fnmatch.c

Go to the documentation of this file.
00001 /* Copyright (C) 1991 Free Software Foundation, Inc.
00002 This file is part of the GNU C Library.
00003 
00004 The GNU C Library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Library General Public License as
00006 published by the Free Software Foundation; either version 2 of the
00007 License, or (at your option) any later version.
00008 
00009 The GNU C Library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Library General Public License for more details.
00013 
00014 You should have received a copy of the GNU Library General Public
00015 License along with the GNU C Library; see the file COPYING.LIB.  If
00016 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
00017 Cambridge, MA 02139, USA.  */
00018 
00019 /*  */
00020 #include <errno.h>
00021 #include <fnmatch.h>
00022 
00023 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
00024 extern int errno;
00025 #endif
00026 
00027 /* Match STRING against the filename pattern PATTERN, returning zero if
00028    it matches, nonzero if not.  */
00029 
00030 #ifdef __STDC__
00031 int
00032 fnmatch(char *pattern, char *string, int flags)
00033 #else
00034 int fnmatch(pattern, string, flags)
00035   char *pattern;
00036   char *string;
00037   int   flags;
00038 #endif
00039 {
00040   register char *p = pattern, *n = string;
00041   register char c;
00042 
00043   if ((flags & ~__FNM_FLAGS) != 0)
00044     {
00045       errno = EINVAL;
00046       return -1;
00047     }
00048 
00049   while ((c = *p++) != '\0')
00050     switch (c)
00051       {
00052       case '?':
00053         if (*n == '\0')
00054           return FNM_NOMATCH;
00055         else if ((flags & FNM_PATHNAME) && *n == '/')
00056           return FNM_NOMATCH;
00057         else if ((flags & FNM_PERIOD) && *n == '.' &&
00058                  (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00059           return FNM_NOMATCH;
00060         else
00061           ++n;
00062         break;
00063 
00064       case '\\':
00065         if (!(flags & FNM_NOESCAPE))
00066           c = *p++;
00067         if (*n++ != c)
00068           return FNM_NOMATCH;
00069         break;
00070 
00071       case '*':
00072         if ((flags & FNM_PERIOD) && *n == '.' &&
00073             (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00074           return FNM_NOMATCH;
00075 
00076         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
00077           if (((flags & FNM_PATHNAME) && *n == '/') ||
00078               (c == '?' && *n == '\0'))
00079             return FNM_NOMATCH;
00080 
00081         if (c == '\0')
00082           return 0;
00083 
00084         {
00085           char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
00086           for (--p; *n != '\0'; ++n)
00087             if ((c == '[' || *n == c1) &&
00088                 fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
00089               return 0;
00090           return FNM_NOMATCH;
00091         }
00092 
00093       case '[':
00094         {
00095           /* Nonzero if this if the sense of
00096              the character class is inverted.  */
00097           register int not;
00098 
00099           if (*n == '\0')
00100             return FNM_NOMATCH;
00101 
00102           if ((flags & FNM_PERIOD) && *n == '.' &&
00103               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
00104             return FNM_NOMATCH;
00105 
00106           not = *p == '!';
00107           if (not)
00108             ++p;
00109 
00110           c = *p++;
00111           for (;;)
00112             {
00113               register char cstart = c, cend = c;
00114 
00115               if (!(flags & FNM_NOESCAPE) && c == '\\')
00116                 cstart = cend = *p++;
00117 
00118               if (c == '\0')
00119                 /* [ (unterminated) loses.  */
00120                 return FNM_NOMATCH;
00121 
00122               c = *p++;
00123               if ((flags & FNM_PATHNAME) && c == '/')
00124                 /* [/] can never match.  */
00125                 return FNM_NOMATCH;
00126 
00127               if (c == '-')
00128                 {
00129                   cend = *p++;
00130                   if (!(flags & FNM_NOESCAPE) && cend == '\\')
00131                     cend = *p++;
00132                   if (cend == '\0')
00133                     return FNM_NOMATCH;
00134                   c = *p++;
00135                 }
00136               if (*n >= cstart && *n <= cend)
00137                 goto matched;
00138 
00139               if (c == ']')
00140                 break;
00141             }
00142           if (!not)
00143             return FNM_NOMATCH;
00144           break;
00145 
00146         matched:;
00147           /* Skip the rest of the [...] that already matched.  */
00148           while (c != ']')
00149             {
00150               if (c == '\0')
00151                 /* [... (unterminated) loses.  */
00152                 return FNM_NOMATCH;
00153 
00154               c = *p++;
00155               if (!(flags & FNM_NOESCAPE) && c == '\\')
00156                 /* 1003.2d11 is unclear if this is right.  %%% */
00157                 ++p;
00158             }
00159           if (not)
00160             return FNM_NOMATCH;
00161 
00162           ++n;
00163         }
00164         break;
00165 
00166       default:
00167         if (c != *n++)
00168           return FNM_NOMATCH;
00169       }
00170 
00171   if (*n == '\0')
00172     return 0;
00173 
00174   return FNM_NOMATCH;
00175 }
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3