Back to index

cell-binutils  2.17cvs20070401
fnmatch.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
00002 
00003 NOTE: This source is derived from an old version taken from the GNU C
00004 Library (glibc).
00005 
00006 This program is free software; you can redistribute it and/or modify it
00007 under the terms of the GNU General Public License as published by the
00008 Free Software Foundation; either version 2, or (at your option) any
00009 later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, 51 Franklin Street - Fifth Floor,
00019 Boston, MA 02110-1301, USA.  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #if defined (CONFIG_BROKETS)
00023 /* We use <config.h> instead of "config.h" so that a compilation
00024    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
00025    (which it would do because it found this file in $srcdir).  */
00026 #include <config.h>
00027 #else
00028 #include "config.h"
00029 #endif
00030 #endif
00031 
00032 
00033 #ifndef _GNU_SOURCE
00034 #define _GNU_SOURCE
00035 #endif
00036 
00037 /* This code to undef const added in libiberty.  */
00038 #ifndef __STDC__
00039 /* This is a separate conditional since some stdc systems
00040    reject `defined (const)'.  */
00041 #ifndef const
00042 #define const
00043 #endif
00044 #endif
00045 
00046 #include <errno.h>
00047 #include <fnmatch.h>
00048 #include <safe-ctype.h>
00049 
00050 /* Comment out all this code if we are using the GNU C Library, and are not
00051    actually compiling the library itself.  This code is part of the GNU C
00052    Library, but also included in many other GNU distributions.  Compiling
00053    and linking in this code is a waste when using the GNU C library
00054    (especially if it is a shared library).  Rather than having every GNU
00055    program understand `configure --with-gnu-libc' and omit the object files,
00056    it is simpler to just do this in the source for each such file.  */
00057 
00058 #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
00059 
00060 
00061 #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
00062 extern int errno;
00063 #endif
00064 
00065 /* Match STRING against the filename pattern PATTERN, returning zero if
00066    it matches, nonzero if not.  */
00067 int
00068 fnmatch (const char *pattern, const char *string, int flags)
00069 {
00070   register const char *p = pattern, *n = string;
00071   register unsigned char c;
00072 
00073 #define FOLD(c)      ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
00074 
00075   while ((c = *p++) != '\0')
00076     {
00077       c = FOLD (c);
00078 
00079       switch (c)
00080        {
00081        case '?':
00082          if (*n == '\0')
00083            return FNM_NOMATCH;
00084          else if ((flags & FNM_FILE_NAME) && *n == '/')
00085            return FNM_NOMATCH;
00086          else if ((flags & FNM_PERIOD) && *n == '.' &&
00087                  (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
00088            return FNM_NOMATCH;
00089          break;
00090 
00091        case '\\':
00092          if (!(flags & FNM_NOESCAPE))
00093            {
00094              c = *p++;
00095              c = FOLD (c);
00096            }
00097          if (FOLD ((unsigned char)*n) != c)
00098            return FNM_NOMATCH;
00099          break;
00100 
00101        case '*':
00102          if ((flags & FNM_PERIOD) && *n == '.' &&
00103              (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
00104            return FNM_NOMATCH;
00105 
00106          for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
00107            if (((flags & FNM_FILE_NAME) && *n == '/') ||
00108               (c == '?' && *n == '\0'))
00109              return FNM_NOMATCH;
00110 
00111          if (c == '\0')
00112            return 0;
00113 
00114          {
00115            unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
00116            c1 = FOLD (c1);
00117            for (--p; *n != '\0'; ++n)
00118              if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
00119                 fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
00120               return 0;
00121            return FNM_NOMATCH;
00122          }
00123 
00124        case '[':
00125          {
00126            /* Nonzero if the sense of the character class is inverted.  */
00127            register int negate;
00128 
00129            if (*n == '\0')
00130              return FNM_NOMATCH;
00131 
00132            if ((flags & FNM_PERIOD) && *n == '.' &&
00133               (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
00134              return FNM_NOMATCH;
00135 
00136            negate = (*p == '!' || *p == '^');
00137            if (negate)
00138              ++p;
00139 
00140            c = *p++;
00141            for (;;)
00142              {
00143               register unsigned char cstart = c, cend = c;
00144 
00145               if (!(flags & FNM_NOESCAPE) && c == '\\')
00146                 cstart = cend = *p++;
00147 
00148               cstart = cend = FOLD (cstart);
00149 
00150               if (c == '\0')
00151                 /* [ (unterminated) loses.  */
00152                 return FNM_NOMATCH;
00153 
00154               c = *p++;
00155               c = FOLD (c);
00156 
00157               if ((flags & FNM_FILE_NAME) && c == '/')
00158                 /* [/] can never match.  */
00159                 return FNM_NOMATCH;
00160 
00161               if (c == '-' && *p != ']')
00162                 {
00163                   cend = *p++;
00164                   if (!(flags & FNM_NOESCAPE) && cend == '\\')
00165                     cend = *p++;
00166                   if (cend == '\0')
00167                     return FNM_NOMATCH;
00168                   cend = FOLD (cend);
00169 
00170                   c = *p++;
00171                 }
00172 
00173               if (FOLD ((unsigned char)*n) >= cstart
00174                   && FOLD ((unsigned char)*n) <= cend)
00175                 goto matched;
00176 
00177               if (c == ']')
00178                 break;
00179              }
00180            if (!negate)
00181              return FNM_NOMATCH;
00182            break;
00183 
00184          matched:;
00185            /* Skip the rest of the [...] that already matched.  */
00186            while (c != ']')
00187              {
00188               if (c == '\0')
00189                 /* [... (unterminated) loses.  */
00190                 return FNM_NOMATCH;
00191 
00192               c = *p++;
00193               if (!(flags & FNM_NOESCAPE) && c == '\\')
00194                 /* XXX 1003.2d11 is unclear if this is right.  */
00195                 ++p;
00196              }
00197            if (negate)
00198              return FNM_NOMATCH;
00199          }
00200          break;
00201 
00202        default:
00203          if (c != FOLD ((unsigned char)*n))
00204            return FNM_NOMATCH;
00205        }
00206 
00207       ++n;
00208     }
00209 
00210   if (*n == '\0')
00211     return 0;
00212 
00213   if ((flags & FNM_LEADING_DIR) && *n == '/')
00214     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
00215     return 0;
00216 
00217   return FNM_NOMATCH;
00218 }
00219 
00220 #endif /* _LIBC or not __GNU_LIBRARY__.  */