source: trunk/third/gnome-vfs/libgnomevfs/fnmatch.c @ 17128

Revision 17128, 5.2 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17127, which included commits to RCS files with non-trunk default branches.
Line 
1/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
17 */
18
19/*
20 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
21 * file for a list of people on the GTK+ Team.  See the ChangeLog
22 * files for a list of changes.  These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24 */
25
26#include <config.h>
27#include "fnmatch.h"
28
29/* Added for GTK. We need to make sure that all constants are defined
30 * to properly compile this file.
31 */
32#ifndef _GNU_SOURCE
33#define _GNU_SOURCE
34#endif
35
36#include <errno.h>
37#include <ctype.h>
38
39
40/* Comment out all this code if we are using the GNU C Library, and are not
41   actually compiling the library itself.  This code is part of the GNU C
42   Library, but also included in many other GNU distributions.  Compiling
43   and linking in this code is a waste when using the GNU C library
44   (especially if it is a shared library).  Rather than having every GNU
45   program understand `configure --with-gnu-libc' and omit the object files,
46   it is simpler to just do this in the source for each such file.  */
47
48#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
49
50
51#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
52extern int errno;
53#endif
54
55/* Match STRING against the filename pattern PATTERN, returning zero if
56   it matches, nonzero if not.  */
57int
58fnmatch (pattern, string, flags)
59     const char *pattern;
60     const char *string;
61     int flags;
62{
63  register const char *p = pattern, *n = string;
64  register char c;
65
66/* Note that this evalutes C many times.  */
67#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper ((unsigned char)(c)) ? tolower ((unsigned char)(c)) : (c))
68
69  while ((c = *p++) != '\0')
70    {
71      c = FOLD (c);
72
73      switch (c)
74        {
75        case '?':
76          if (*n == '\0')
77            return FNM_NOMATCH;
78          else if ((flags & FNM_FILE_NAME) && *n == '/')
79            return FNM_NOMATCH;
80          else if ((flags & FNM_PERIOD) && *n == '.' &&
81                   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
82            return FNM_NOMATCH;
83          break;
84
85        case '\\':
86          if (!(flags & FNM_NOESCAPE))
87            {
88              c = *p++;
89              c = FOLD (c);
90            }
91          if (FOLD (*n) != c)
92            return FNM_NOMATCH;
93          break;
94
95        case '*':
96          if ((flags & FNM_PERIOD) && *n == '.' &&
97              (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
98            return FNM_NOMATCH;
99
100          for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
101            if (((flags & FNM_FILE_NAME) && *n == '/') ||
102                (c == '?' && *n == '\0'))
103              return FNM_NOMATCH;
104
105          if (c == '\0')
106            return 0;
107
108          {
109            char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
110            c1 = FOLD (c1);
111            for (--p; *n != '\0'; ++n)
112              if ((c == '[' || FOLD (*n) == c1) &&
113                  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
114                return 0;
115            return FNM_NOMATCH;
116          }
117
118        case '[':
119          {
120            /* Nonzero if the sense of the character class is inverted.  */
121            register int not;
122
123            if (*n == '\0')
124              return FNM_NOMATCH;
125
126            if ((flags & FNM_PERIOD) && *n == '.' &&
127                (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
128              return FNM_NOMATCH;
129
130            not = (*p == '!' || *p == '^');
131            if (not)
132              ++p;
133
134            c = *p++;
135            for (;;)
136              {
137                register char cstart = c, cend = c;
138
139                if (!(flags & FNM_NOESCAPE) && c == '\\')
140                  cstart = cend = *p++;
141
142                cstart = cend = FOLD (cstart);
143
144                if (c == '\0')
145                  /* [ (unterminated) loses.  */
146                  return FNM_NOMATCH;
147
148                c = *p++;
149                c = FOLD (c);
150
151                if ((flags & FNM_FILE_NAME) && c == '/')
152                  /* [/] can never match.  */
153                  return FNM_NOMATCH;
154
155                if (c == '-' && *p != ']')
156                  {
157                    cend = *p++;
158                    if (!(flags & FNM_NOESCAPE) && cend == '\\')
159                      cend = *p++;
160                    if (cend == '\0')
161                      return FNM_NOMATCH;
162                    cend = FOLD (cend);
163
164                    c = *p++;
165                  }
166
167                if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
168                  goto matched;
169
170                if (c == ']')
171                  break;
172              }
173            if (!not)
174              return FNM_NOMATCH;
175            break;
176
177          matched:;
178            /* Skip the rest of the [...] that already matched.  */
179            while (c != ']')
180              {
181                if (c == '\0')
182                  /* [... (unterminated) loses.  */
183                  return FNM_NOMATCH;
184
185                c = *p++;
186                if (!(flags & FNM_NOESCAPE) && c == '\\')
187                  /* XXX 1003.2d11 is unclear if this is right.  */
188                  ++p;
189              }
190            if (not)
191              return FNM_NOMATCH;
192          }
193          break;
194
195        default:
196          if (c != FOLD (*n))
197            return FNM_NOMATCH;
198        }
199
200      ++n;
201    }
202
203  if (*n == '\0')
204    return 0;
205
206  if ((flags & FNM_LEADING_DIR) && *n == '/')
207    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
208    return 0;
209
210  return FNM_NOMATCH;
211}
212
213#endif  /* _LIBC or not __GNU_LIBRARY__.  */
Note: See TracBrowser for help on using the repository browser.