Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

fnmatch.c

Go to the documentation of this file.
00001 #include "../rsync.h"
00002 #ifndef HAVE_FNMATCH
00003 
00004 /* ----- THE FOLLOWING UP TO 'END' is glibc-2.1.2 posix/fnmatch.c
00005      except for the parts with '#if 0' */
00006 
00007 /* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
00008    This file is part of the GNU C Library.
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Library General Public License as
00012    published by the Free Software Foundation; either version 2 of the
00013    License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Library General Public License for more details.
00019 
00020    You should have received a copy of the GNU Library General Public
00021    License along with this library; see the file COPYING.LIB.  If not,
00022    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023    Boston, MA 02111-1307, USA.  */
00024 
00025 #if 0   /* header files included better by ../rsync.h */
00026 
00027 #if HAVE_CONFIG_H
00028 # include <config.h>
00029 #endif
00030 
00031 /* Enable GNU extensions in fnmatch.h.  */
00032 #ifndef _GNU_SOURCE
00033 # define _GNU_SOURCE    1
00034 #endif
00035 
00036 #include <errno.h>
00037 #include <fnmatch.h>
00038 #include <ctype.h>
00039 
00040 #if HAVE_STRING_H || defined _LIBC
00041 # include <string.h>
00042 #else
00043 # include <strings.h>
00044 #endif
00045 
00046 #if defined STDC_HEADERS || defined _LIBC
00047 # include <stdlib.h>
00048 #endif
00049 
00050 #endif /* 0 */
00051 /* For platform which support the ISO C amendement 1 functionality we
00052    support user defined character classes.  */
00053 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00054 /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
00055 # include <wchar.h>
00056 # include <wctype.h>
00057 #endif
00058 
00059 /* Comment out all this code if we are using the GNU C Library, and are not
00060    actually compiling the library itself.  This code is part of the GNU C
00061    Library, but also included in many other GNU distributions.  Compiling
00062    and linking in this code is a waste when using the GNU C library
00063    (especially if it is a shared library).  Rather than having every GNU
00064    program understand `configure --with-gnu-libc' and omit the object files,
00065    it is simpler to just do this in the source for each such file.  */
00066 
00067 #if 1
00068 
00069 # if defined STDC_HEADERS || !defined isascii
00070 #  define ISASCII(c) 1
00071 # else
00072 #  define ISASCII(c) isascii(c)
00073 # endif
00074 
00075 #ifdef isblank
00076 # define ISBLANK(c) (ISASCII (c) && isblank (c))
00077 #else
00078 # define ISBLANK(c) ((c) == ' ' || (c) == '\t')
00079 #endif
00080 #ifdef isgraph
00081 # define ISGRAPH(c) (ISASCII (c) && isgraph (c))
00082 #else
00083 # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
00084 #endif
00085 
00086 #define ISPRINT(c) (ISASCII (c) && isprint (c))
00087 #define ISDIGIT(c) (ISASCII (c) && isdigit (c))
00088 #define ISALNUM(c) (ISASCII (c) && isalnum (c))
00089 #define ISALPHA(c) (ISASCII (c) && isalpha (c))
00090 #define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
00091 #define ISLOWER(c) (ISASCII (c) && islower (c))
00092 #define ISPUNCT(c) (ISASCII (c) && ispunct (c))
00093 #define ISSPACE(c) (ISASCII (c) && isspace (c))
00094 #define ISUPPER(c) (ISASCII (c) && isupper (c))
00095 #define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
00096 
00097 # define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
00098 
00099 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00100 /* The GNU C library provides support for user-defined character classes
00101    and the functions from ISO C amendement 1.  */
00102 #  ifdef CHARCLASS_NAME_MAX
00103 #   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
00104 #  else
00105 /* This shouldn't happen but some implementation might still have this
00106    problem.  Use a reasonable default value.  */
00107 #   define CHAR_CLASS_MAX_LENGTH 256
00108 #  endif
00109 
00110 #  ifdef _LIBC
00111 #   define IS_CHAR_CLASS(string) __wctype (string)
00112 #  else
00113 #   define IS_CHAR_CLASS(string) wctype (string)
00114 #  endif
00115 # else
00116 #  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
00117 
00118 #  define IS_CHAR_CLASS(string)                                               \
00119    (STREQ (string, "alpha") || STREQ (string, "upper")                        \
00120     || STREQ (string, "lower") || STREQ (string, "digit")                     \
00121     || STREQ (string, "alnum") || STREQ (string, "xdigit")                    \
00122     || STREQ (string, "space") || STREQ (string, "print")                     \
00123     || STREQ (string, "punct") || STREQ (string, "graph")                     \
00124     || STREQ (string, "cntrl") || STREQ (string, "blank"))
00125 # endif
00126 
00127 /* Avoid depending on library functions or files
00128    whose names are inconsistent.  */
00129 
00130 # if !defined _LIBC && !defined getenv
00131 extern char *getenv ();
00132 # endif
00133 
00134 # ifndef errno
00135 extern int errno;
00136 # endif
00137 
00138 /* Match STRING against the filename pattern PATTERN, returning zero if
00139    it matches, nonzero if not.  */
00140 static int
00141 #ifdef _LIBC
00142 internal_function
00143 #endif
00144 internal_fnmatch (const char *pattern, const char *string,
00145                   int no_leading_period, int flags)
00146 {
00147   register const char *p = pattern, *n = string;
00148   register unsigned char c;
00149 
00150 /* Note that this evaluates C many times.  */
00151 # ifdef _LIBC
00152 #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
00153 # else
00154 #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
00155 # endif
00156 
00157   while ((c = *p++) != '\0')
00158     {
00159       c = FOLD (c);
00160 
00161       switch (c)
00162         {
00163         case '?':
00164           if (*n == '\0')
00165             return FNM_NOMATCH;
00166           else if (*n == '/' && (flags & FNM_FILE_NAME))
00167             return FNM_NOMATCH;
00168           else if (*n == '.' && no_leading_period
00169                    && (n == string
00170                        || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
00171             return FNM_NOMATCH;
00172           break;
00173 
00174         case '\\':
00175           if (!(flags & FNM_NOESCAPE))
00176             {
00177               c = *p++;
00178               if (c == '\0')
00179                 /* Trailing \ loses.  */
00180                 return FNM_NOMATCH;
00181               c = FOLD (c);
00182             }
00183           if (FOLD ((unsigned char) *n) != c)
00184             return FNM_NOMATCH;
00185           break;
00186 
00187         case '*':
00188           if (*n == '.' && no_leading_period
00189               && (n == string
00190                   || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
00191             return FNM_NOMATCH;
00192 
00193           for (c = *p++; c == '?' || c == '*'; c = *p++)
00194             {
00195               if (*n == '/' && (flags & FNM_FILE_NAME))
00196                 /* A slash does not match a wildcard under FNM_FILE_NAME.  */
00197                 return FNM_NOMATCH;
00198               else if (c == '?')
00199                 {
00200                   /* A ? needs to match one character.  */
00201                   if (*n == '\0')
00202                     /* There isn't another character; no match.  */
00203                     return FNM_NOMATCH;
00204                   else
00205                     /* One character of the string is consumed in matching
00206                        this ? wildcard, so *??? won't match if there are
00207                        less than three characters.  */
00208                     ++n;
00209                 }
00210             }
00211 
00212           if (c == '\0')
00213             /* The wildcard(s) is/are the last element of the pattern.
00214                If the name is a file name and contains another slash
00215                this does mean it cannot match.  */
00216             return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
00217                     ? FNM_NOMATCH : 0);
00218           else
00219             {
00220               const char *endp;
00221 
00222 #if 0
00223               endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
00224 #else
00225 /* replace call to internal glibc function with equivalent */
00226               if (!(flags & FNM_FILE_NAME) || ((endp = strchr(n, '/')) == NULL))
00227                 endp = n + strlen(n);
00228 #endif
00229 
00230               if (c == '[')
00231                 {
00232                   int flags2 = ((flags & FNM_FILE_NAME)
00233                                 ? flags : (flags & ~FNM_PERIOD));
00234 
00235                   for (--p; n < endp; ++n)
00236                     if (internal_fnmatch (p, n,
00237                                           (no_leading_period
00238                                            && (n == string
00239                                                || (n[-1] == '/'
00240                                                    && (flags
00241                                                        & FNM_FILE_NAME)))),
00242                                           flags2)
00243                         == 0)
00244                       return 0;
00245                 }
00246               else if (c == '/' && (flags & FNM_FILE_NAME))
00247                 {
00248                   while (*n != '\0' && *n != '/')
00249                     ++n;
00250                   if (*n == '/'
00251                       && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
00252                                             flags) == 0))
00253                     return 0;
00254                 }
00255               else
00256                 {
00257                   int flags2 = ((flags & FNM_FILE_NAME)
00258                                 ? flags : (flags & ~FNM_PERIOD));
00259 
00260                   if (c == '\\' && !(flags & FNM_NOESCAPE))
00261                     c = *p;
00262                   c = FOLD (c);
00263                   for (--p; n < endp; ++n)
00264                     if (FOLD ((unsigned char) *n) == c
00265                         && (internal_fnmatch (p, n,
00266                                               (no_leading_period
00267                                                && (n == string
00268                                                    || (n[-1] == '/'
00269                                                        && (flags
00270                                                            & FNM_FILE_NAME)))),
00271                                               flags2) == 0))
00272                       return 0;
00273                 }
00274             }
00275 
00276           /* If we come here no match is possible with the wildcard.  */
00277           return FNM_NOMATCH;
00278 
00279         case '[':
00280           {
00281             /* Nonzero if the sense of the character class is inverted.  */
00282             static int posixly_correct;
00283             register int not;
00284             char cold;
00285 
00286             if (posixly_correct == 0)
00287               posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
00288 
00289             if (*n == '\0')
00290               return FNM_NOMATCH;
00291 
00292             if (*n == '.' && no_leading_period && (n == string
00293                                                    || (n[-1] == '/'
00294                                                        && (flags
00295                                                            & FNM_FILE_NAME))))
00296               return FNM_NOMATCH;
00297 
00298             if (*n == '/' && (flags & FNM_FILE_NAME))
00299               /* `/' cannot be matched.  */
00300               return FNM_NOMATCH;
00301 
00302             not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
00303             if (not)
00304               ++p;
00305 
00306             c = *p++;
00307             for (;;)
00308               {
00309                 unsigned char fn = FOLD ((unsigned char) *n);
00310 
00311                 if (!(flags & FNM_NOESCAPE) && c == '\\')
00312                   {
00313                     if (*p == '\0')
00314                       return FNM_NOMATCH;
00315                     c = FOLD ((unsigned char) *p);
00316                     ++p;
00317 
00318                     if (c == fn)
00319                       goto matched;
00320                   }
00321                 else if (c == '[' && *p == ':')
00322                   {
00323                     /* Leave room for the null.  */
00324                     char str[CHAR_CLASS_MAX_LENGTH + 1];
00325                     size_t c1 = 0;
00326 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00327                     wctype_t wt;
00328 # endif
00329                     const char *startp = p;
00330 
00331                     for (;;)
00332                       {
00333                         if (c1 == CHAR_CLASS_MAX_LENGTH)
00334                           /* The name is too long and therefore the pattern
00335                              is ill-formed.  */
00336                           return FNM_NOMATCH;
00337 
00338                         c = *++p;
00339                         if (c == ':' && p[1] == ']')
00340                           {
00341                             p += 2;
00342                             break;
00343                           }
00344                         if (c < 'a' || c >= 'z')
00345                           {
00346                             /* This cannot possibly be a character class name.
00347                                Match it as a normal range.  */
00348                             p = startp;
00349                             c = '[';
00350                             goto normal_bracket;
00351                           }
00352                         str[c1++] = c;
00353                       }
00354                     str[c1] = '\0';
00355 
00356 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
00357                     wt = IS_CHAR_CLASS (str);
00358                     if (wt == 0)
00359                       /* Invalid character class name.  */
00360                       return FNM_NOMATCH;
00361 
00362                     if (__iswctype (__btowc ((unsigned char) *n), wt))
00363                       goto matched;
00364 # else
00365                     if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
00366                         || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
00367                         || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
00368                         || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
00369                         || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
00370                         || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
00371                         || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
00372                         || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
00373                         || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
00374                         || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
00375                         || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
00376                         || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
00377                       goto matched;
00378 # endif
00379                   }
00380                 else if (c == '\0')
00381                   /* [ (unterminated) loses.  */
00382                   return FNM_NOMATCH;
00383                 else
00384                   {
00385                   normal_bracket:
00386                     if (FOLD (c) == fn)
00387                       goto matched;
00388 
00389                     cold = c;
00390                     c = *p++;
00391 
00392                     if (c == '-' && *p != ']')
00393                       {
00394                         /* It is a range.  */
00395                         unsigned char cend = *p++;
00396                         if (!(flags & FNM_NOESCAPE) && cend == '\\')
00397                           cend = *p++;
00398                         if (cend == '\0')
00399                           return FNM_NOMATCH;
00400 
00401                         if (cold <= fn && fn <= FOLD (cend))
00402                           goto matched;
00403 
00404                         c = *p++;
00405                       }
00406                   }
00407 
00408                 if (c == ']')
00409                   break;
00410               }
00411 
00412             if (!not)
00413               return FNM_NOMATCH;
00414             break;
00415 
00416           matched:
00417             /* Skip the rest of the [...] that already matched.  */
00418             while (c != ']')
00419               {
00420                 if (c == '\0')
00421                   /* [... (unterminated) loses.  */
00422                   return FNM_NOMATCH;
00423 
00424                 c = *p++;
00425                 if (!(flags & FNM_NOESCAPE) && c == '\\')
00426                   {
00427                     if (*p == '\0')
00428                       return FNM_NOMATCH;
00429                     /* XXX 1003.2d11 is unclear if this is right.  */
00430                     ++p;
00431                   }
00432                 else if (c == '[' && *p == ':')
00433                   {
00434                     do
00435                       if (*++p == '\0')
00436                         return FNM_NOMATCH;
00437                     while (*p != ':' || p[1] == ']');
00438                     p += 2;
00439                     c = *p;
00440                   }
00441               }
00442             if (not)
00443               return FNM_NOMATCH;
00444           }
00445           break;
00446 
00447         default:
00448           if (c != FOLD ((unsigned char) *n))
00449             return FNM_NOMATCH;
00450         }
00451 
00452       ++n;
00453     }
00454 
00455   if (*n == '\0')
00456     return 0;
00457 
00458   if ((flags & FNM_LEADING_DIR) && *n == '/')
00459     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
00460     return 0;
00461 
00462   return FNM_NOMATCH;
00463 
00464 # undef FOLD
00465 }
00466 
00467 
00468 int
00469 fnmatch (pattern, string, flags)
00470      const char *pattern;
00471      const char *string;
00472      int flags;
00473 {
00474   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
00475 }
00476 
00477 #endif  /* _LIBC or not __GNU_LIBRARY__.  */
00478 /* ----- END glibc-2.1.2 posix/fnmatch.c */
00479 
00480 #else   /* HAVE_FNMATCH */
00481 void fnmatch_dummy(void) {}
00482 #endif

Generated on Tue Apr 16 12:37:36 2002 for rsync by doxygen1.2.15