5762859 [rkeene@sledge /home/rkeene/devel/backuppcd/all/backuppcd-200601171056]$ cat -n fnmatch.c
  1 /* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
  2    This file is part of the GNU C Library.
  3 
  4    This library is free software; you can redistribute it and/or
  5    modify it under the terms of the GNU Library General Public License as
  6    published by the Free Software Foundation; either version 2 of the
  7    License, or (at your option) any later version.
  8 
  9    This library is distributed in the hope that it will be useful,
 10    but WITHOUT ANY WARRANTY; without even the implied warranty of
 11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12    Library General Public License for more details.
 13 
 14    You should have received a copy of the GNU Library General Public
 15    License along with this library; see the file COPYING.LIB.  If not,
 16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17    Boston, MA 02111-1307, USA.  */
 18 
 19 #if HAVE_CONFIG_H
 20 # include <config.h>
 21 #endif
 22 
 23 /* Enable GNU extensions in fnmatch.h.  */
 24 #ifndef _GNU_SOURCE
 25 # define _GNU_SOURCE    1
 26 #endif
 27 
 28 #include <errno.h>
 29 #include <fnmatch.h>
 30 #include <ctype.h>
 31 
 32 #if HAVE_STRING_H || defined _LIBC
 33 # include <string.h>
 34 #else
 35 # include <strings.h>
 36 #endif
 37 
 38 #if defined STDC_HEADERS || defined _LIBC
 39 # include <stdlib.h>
 40 #endif
 41 
 42 /* For platform which support the ISO C amendement 1 functionality we
 43    support user defined character classes.  */
 44 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 45 /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
 46 # include <wchar.h>
 47 # include <wctype.h>
 48 #endif
 49 
 50 /* Comment out all this code if we are using the GNU C Library, and are not
 51    actually compiling the library itself.  This code is part of the GNU C
 52    Library, but also included in many other GNU distributions.  Compiling
 53    and linking in this code is a waste when using the GNU C library
 54    (especially if it is a shared library).  Rather than having every GNU
 55    program understand `configure --with-gnu-libc' and omit the object files,
 56    it is simpler to just do this in the source for each such file.  */
 57 
 58 #if defined _LIBC || !defined __GNU_LIBRARY__
 59 
 60 
 61 # if defined STDC_HEADERS || !defined isascii
 62 #  define ISASCII(c) 1
 63 # else
 64 #  define ISASCII(c) isascii(c)
 65 # endif
 66 
 67 # ifdef isblank
 68 #  define ISBLANK(c) (ISASCII (c) && isblank (c))
 69 # else
 70 #  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
 71 # endif
 72 # ifdef isgraph
 73 #  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
 74 # else
 75 #  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
 76 # endif
 77 
 78 # define ISPRINT(c) (ISASCII (c) && isprint (c))
 79 # define ISDIGIT(c) (ISASCII (c) && isdigit (c))
 80 # define ISALNUM(c) (ISASCII (c) && isalnum (c))
 81 # define ISALPHA(c) (ISASCII (c) && isalpha (c))
 82 # define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
 83 # define ISLOWER(c) (ISASCII (c) && islower (c))
 84 # define ISPUNCT(c) (ISASCII (c) && ispunct (c))
 85 # define ISSPACE(c) (ISASCII (c) && isspace (c))
 86 # define ISUPPER(c) (ISASCII (c) && isupper (c))
 87 # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
 88 
 89 # define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
 90 
 91 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 92 /* The GNU C library provides support for user-defined character classes
 93    and the functions from ISO C amendement 1.  */
 94 #  ifdef CHARCLASS_NAME_MAX
 95 #   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
 96 #  else
 97 /* This shouldn't happen but some implementation might still have this
 98    problem.  Use a reasonable default value.  */
 99 #   define CHAR_CLASS_MAX_LENGTH 256
100 #  endif
101 
102 #  ifdef _LIBC
103 #   define IS_CHAR_CLASS(string) __wctype (string)
104 #  else
105 #   define IS_CHAR_CLASS(string) wctype (string)
106 #  endif
107 # else
108 #  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
109 
110 #  define IS_CHAR_CLASS(string)                           \
111    (STREQ (string, "alpha") || STREQ (string, "upper")                \
112     || STREQ (string, "lower") || STREQ (string, "digit")             \
113     || STREQ (string, "alnum") || STREQ (string, "xdigit")            \
114     || STREQ (string, "space") || STREQ (string, "print")             \
115     || STREQ (string, "punct") || STREQ (string, "graph")             \
116     || STREQ (string, "cntrl") || STREQ (string, "blank"))
117 # endif
118 
119 /* Avoid depending on library functions or files
120    whose names are inconsistent.  */
121 
122 # if !defined _LIBC && !defined getenv
123 extern char *getenv ();
124 # endif
125 
126 # ifndef errno
127 extern int errno;
128 # endif
129 
130 /* This function doesn't exist on most systems.  */
131 
132 # if !defined HAVE___STRCHRNUL && !defined _LIBC
133 static char *
134 __strchrnul (s, c)
135      const char *s;
136      int c;
137 {
138   char *result = strchr (s, c);
139   if (result == NULL)
140     result = strchr (s, '\0');
141   return result;
142 }
143 # endif
144 
145 # ifndef internal_function
146 /* Inside GNU libc we mark some function in a special way.  In other
147    environments simply ignore the marking.  */
148 #  define internal_function
149 # endif
150 
151 /* Match STRING against the filename pattern PATTERN, returning zero if
152    it matches, nonzero if not.  */
153 static int internal_fnmatch __P ((const char *pattern, const char *string,
154                   int no_leading_period, int flags))
155      internal_function;
156 static int
157 internal_function
158 internal_fnmatch (pattern, string, no_leading_period, flags)
159      const char *pattern;
160      const char *string;
161      int no_leading_period;
162      int flags;
163 {
164   register const char *p = pattern, *n = string;
165   register unsigned char c;
166 
167 /* Note that this evaluates C many times.  */
168 # ifdef _LIBC
169 #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
170 # else
171 #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
172 # endif
173 
174   while ((c = *p++) != '\0')
175     {
176       c = FOLD (c);
177 
178       switch (c)
179     {
180     case '?':
181       if (*n == '\0')
182         return FNM_NOMATCH;
183       else if (*n == '/' && (flags & FNM_FILE_NAME))
184         return FNM_NOMATCH;
185       else if (*n == '.' && no_leading_period
186            && (n == string
187                || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
188         return FNM_NOMATCH;
189       break;
190 
191     case '\\':
192       if (!(flags & FNM_NOESCAPE))
193         {
194           c = *p++;
195           if (c == '\0')
196         /* Trailing \ loses.  */
197         return FNM_NOMATCH;
198           c = FOLD (c);
199         }
200       if (FOLD ((unsigned char) *n) != c)
201         return FNM_NOMATCH;
202       break;
203 
204     case '*':
205       if (*n == '.' && no_leading_period
206           && (n == string
207           || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
208         return FNM_NOMATCH;
209 
210       for (c = *p++; c == '?' || c == '*'; c = *p++)
211         {
212           if (*n == '/' && (flags & FNM_FILE_NAME))
213         /* A slash does not match a wildcard under FNM_FILE_NAME.  */
214         return FNM_NOMATCH;
215           else if (c == '?')
216         {
217           /* A ? needs to match one character.  */
218           if (*n == '\0')
219             /* There isn't another character; no match.  */
220             return FNM_NOMATCH;
221           else
222             /* One character of the string is consumed in matching
223                this ? wildcard, so *??? won't match if there are
224                less than three characters.  */
225             ++n;
226         }
227         }
228 
229       if (c == '\0')
230         /* The wildcard(s) is/are the last element of the pattern.
231            If the name is a file name and contains another slash
232            this does mean it cannot match.  */
233         return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
234             ? FNM_NOMATCH : 0);
235       else
236         {
237           const char *endp;
238 
239           endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
240 
241           if (c == '[')
242         {
243           int flags2 = ((flags & FNM_FILE_NAME)
244                 ? flags : (flags & ~FNM_PERIOD));
245 
246           for (--p; n < endp; ++n)
247             if (internal_fnmatch (p, n,
248                       (no_leading_period
249                        && (n == string
250                            || (n[-1] == '/'
251                            && (flags
252                                & FNM_FILE_NAME)))),
253                       flags2)
254             == 0)
255               return 0;
256         }
257           else if (c == '/' && (flags & FNM_FILE_NAME))
258         {
259           while (*n != '\0' && *n != '/')
260             ++n;
261           if (*n == '/'
262               && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
263                         flags) == 0))
264             return 0;
265         }
266           else
267         {
268           int flags2 = ((flags & FNM_FILE_NAME)
269                 ? flags : (flags & ~FNM_PERIOD));
270 
271           if (c == '\\' && !(flags & FNM_NOESCAPE))
272             c = *p;
273           c = FOLD (c);
274           for (--p; n < endp; ++n)
275             if (FOLD ((unsigned char) *n) == c
276             && (internal_fnmatch (p, n,
277                           (no_leading_period
278                            && (n == string
279                            || (n[-1] == '/'
280                                && (flags
281                                & FNM_FILE_NAME)))),
282                           flags2) == 0))
283               return 0;
284         }
285         }
286 
287       /* If we come here no match is possible with the wildcard.  */
288       return FNM_NOMATCH;
289 
290     case '[':
291       {
292         /* Nonzero if the sense of the character class is inverted.  */
293         static int posixly_correct;
294         register int not;
295         char cold;
296 
297         if (posixly_correct == 0)
298           posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
299 
300         if (*n == '\0')
301           return FNM_NOMATCH;
302 
303         if (*n == '.' && no_leading_period && (n == string
304                            || (n[-1] == '/'
305                                && (flags
306                                & FNM_FILE_NAME))))
307           return FNM_NOMATCH;
308 
309         if (*n == '/' && (flags & FNM_FILE_NAME))
310           /* `/' cannot be matched.  */
311           return FNM_NOMATCH;
312 
313         not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
314         if (not)
315           ++p;
316 
317         c = *p++;
318         for (;;)
319           {
320         unsigned char fn = FOLD ((unsigned char) *n);
321 
322         if (!(flags & FNM_NOESCAPE) && c == '\\')
323           {
324             if (*p == '\0')
325               return FNM_NOMATCH;
326             c = FOLD ((unsigned char) *p);
327             ++p;
328 
329             if (c == fn)
330               goto matched;
331           }
332         else if (c == '[' && *p == ':')
333           {
334             /* Leave room for the null.  */
335             char str[CHAR_CLASS_MAX_LENGTH + 1];
336             size_t c1 = 0;
337 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
338             wctype_t wt;
339 # endif
340             const char *startp = p;
341 
342             for (;;)
343               {
344             if (c1 == CHAR_CLASS_MAX_LENGTH)
345               /* The name is too long and therefore the pattern
346                  is ill-formed.  */
347               return FNM_NOMATCH;
348 
349             c = *++p;
350             if (c == ':' && p[1] == ']')
351               {
352                 p += 2;
353                 break;
354               }
355             if (c < 'a' || c >= 'z')
356               {
357                 /* This cannot possibly be a character class name.
358                    Match it as a normal range.  */
359                 p = startp;
360                 c = '[';
361                 goto normal_bracket;
362               }
363             str[c1++] = c;
364               }
365             str[c1] = '\0';
366 
367 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
368             wt = IS_CHAR_CLASS (str);
369             if (wt == 0)
370               /* Invalid character class name.  */
371               return FNM_NOMATCH;
372 
373             if (__iswctype (__btowc ((unsigned char) *n), wt))
374               goto matched;
375 # else
376             if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
377             || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
378             || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
379             || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
380             || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
381             || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
382             || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
383             || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
384             || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
385             || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
386             || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
387             || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
388               goto matched;
389 # endif
390           }
391         else if (c == '\0')
392           /* [ (unterminated) loses.  */
393           return FNM_NOMATCH;
394         else
395           {
396           normal_bracket:
397             if (FOLD (c) == fn)
398               goto matched;
399 
400             cold = c;
401             c = *p++;
402 
403             if (c == '-' && *p != ']')
404               {
405             /* It is a range.  */
406             unsigned char cend = *p++;
407             if (!(flags & FNM_NOESCAPE) && cend == '\\')
408               cend = *p++;
409             if (cend == '\0')
410               return FNM_NOMATCH;
411 
412             if (cold <= fn && fn <= FOLD (cend))
413               goto matched;
414 
415             c = *p++;
416               }
417           }
418 
419         if (c == ']')
420           break;
421           }
422 
423         if (!not)
424           return FNM_NOMATCH;
425         break;
426 
427       matched:
428         /* Skip the rest of the [...] that already matched.  */
429         while (c != ']')
430           {
431         if (c == '\0')
432           /* [... (unterminated) loses.  */
433           return FNM_NOMATCH;
434 
435         c = *p++;
436         if (!(flags & FNM_NOESCAPE) && c == '\\')
437           {
438             if (*p == '\0')
439               return FNM_NOMATCH;
440             /* XXX 1003.2d11 is unclear if this is right.  */
441             ++p;
442           }
443         else if (c == '[' && *p == ':')
444           {
445             do
446               if (*++p == '\0')
447             return FNM_NOMATCH;
448             while (*p != ':' || p[1] == ']');
449             p += 2;
450             c = *p;
451           }
452           }
453         if (not)
454           return FNM_NOMATCH;
455       }
456       break;
457 
458     default:
459       if (c != FOLD ((unsigned char) *n))
460         return FNM_NOMATCH;
461     }
462 
463       ++n;
464     }
465 
466   if (*n == '\0')
467     return 0;
468 
469   if ((flags & FNM_LEADING_DIR) && *n == '/')
470     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
471     return 0;
472 
473   return FNM_NOMATCH;
474 
475 # undef FOLD
476 }
477 
478 
479 int
480 fnmatch (pattern, string, flags)
481      const char *pattern;
482      const char *string;
483      int flags;
484 {
485   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
486 }
487 
488 #endif  /* _LIBC or not __GNU_LIBRARY__.  */
5762860 [rkeene@sledge /home/rkeene/devel/backuppcd/all/backuppcd-200601171056]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2005-08-23 22:36:09