Diff for /gforth/engine/fnmatch.c between versions 1.1 and 1.2

version 1.1, 2000/07/01 20:48:53 version 1.2, 2000/07/02 08:27:20
Line 1 Line 1
 /* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.  /* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.  
   
    This library is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or modify
    modify it under the terms of the GNU Library General Public License as     it under the terms of the GNU General Public License as published by
    published by the Free Software Foundation; either version 2 of the     the Free Software Foundation; either version 2, or (at your option)
    License, or (at your option) any later version.     any later version.
   
    This library is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    Library General Public License for more details.     GNU General Public License for more details.
   
    You should have received a copy of the GNU Library General Public    You should have received a copy of the GNU General Public License
    License along with this library; see the file COPYING.LIB.  If not,    along with this program; if not, write to the Free Software Foundation,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    Boston, MA 02111-1307, USA.  */  
   
 #if HAVE_CONFIG_H  #if HAVE_CONFIG_H
 # include <config.h>  # include <config.h>
Line 29 Line 27
 #include <fnmatch.h>  #include <fnmatch.h>
 #include <ctype.h>  #include <ctype.h>
   
 #if HAVE_STRING_H || defined _LIBC  
 # include <string.h>  
 #else  
 # include <strings.h>  
 #endif  
   
 #if defined STDC_HEADERS || defined _LIBC  
 # include <stdlib.h>  
 #endif  
   
 /* For platform which support the ISO C amendement 1 functionality we  
    support user defined character classes.  */  
 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)  
 /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */  
 # include <wchar.h>  
 # include <wctype.h>  
 #endif  
   
 /* Comment out all this code if we are using the GNU C Library, and are not  /* Comment out all this code if we are using the GNU C Library, and are not
    actually compiling the library itself.  This code is part of the GNU C     actually compiling the library itself.  This code is part of the GNU C
Line 64 Line 45
 #  define ISASCII(c) isascii(c)  #  define ISASCII(c) isascii(c)
 # endif  # endif
   
 #ifdef isblank  # define ISUPPER(c) (ISASCII (c) && isupper (c))
 # define ISBLANK(c) (ISASCII (c) && isblank (c))  
 #else  
 # define ISBLANK(c) ((c) == ' ' || (c) == '\t')  
 #endif  
 #ifdef isgraph  
 # define ISGRAPH(c) (ISASCII (c) && isgraph (c))  
 #else  
 # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))  
 #endif  
   
 #define ISPRINT(c) (ISASCII (c) && isprint (c))  
 #define ISDIGIT(c) (ISASCII (c) && isdigit (c))  
 #define ISALNUM(c) (ISASCII (c) && isalnum (c))  
 #define ISALPHA(c) (ISASCII (c) && isalpha (c))  
 #define ISCNTRL(c) (ISASCII (c) && iscntrl (c))  
 #define ISLOWER(c) (ISASCII (c) && islower (c))  
 #define ISPUNCT(c) (ISASCII (c) && ispunct (c))  
 #define ISSPACE(c) (ISASCII (c) && isspace (c))  
 #define ISUPPER(c) (ISASCII (c) && isupper (c))  
 #define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))  
   
 # define STREQ(s1, s2) ((strcmp (s1, s2) == 0))  
   
 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)  
 /* The GNU C library provides support for user-defined character classes  
    and the functions from ISO C amendement 1.  */  
 #  ifdef CHARCLASS_NAME_MAX  
 #   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX  
 #  else  
 /* This shouldn't happen but some implementation might still have this  
    problem.  Use a reasonable default value.  */  
 #   define CHAR_CLASS_MAX_LENGTH 256  
 #  endif  
   
 #  ifdef _LIBC  
 #   define IS_CHAR_CLASS(string) __wctype (string)  
 #  else  
 #   define IS_CHAR_CLASS(string) wctype (string)  
 #  endif  
 # else  
 #  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */  
   
 #  define IS_CHAR_CLASS(string)                                               \  
    (STREQ (string, "alpha") || STREQ (string, "upper")                        \  
     || STREQ (string, "lower") || STREQ (string, "digit")                     \  
     || STREQ (string, "alnum") || STREQ (string, "xdigit")                    \  
     || STREQ (string, "space") || STREQ (string, "print")                     \  
     || STREQ (string, "punct") || STREQ (string, "graph")                     \  
     || STREQ (string, "cntrl") || STREQ (string, "blank"))  
 # endif  
   
 /* Avoid depending on library functions or files  
    whose names are inconsistent.  */  
   
 # if !defined _LIBC && !defined getenv  
 extern char *getenv ();  
 # endif  
   
 # ifndef errno  # ifndef errno
 extern int errno;  extern int errno;
Line 129  extern int errno; Line 54  extern int errno;
   
 /* Match STRING against the filename pattern PATTERN, returning zero if  /* Match STRING against the filename pattern PATTERN, returning zero if
    it matches, nonzero if not.  */     it matches, nonzero if not.  */
 static int  int
 #ifdef _LIBC  fnmatch (const char *pattern, const char *string, int flags)
 internal_function  
 #endif  
 internal_fnmatch (const char *pattern, const char *string,  
                   int no_leading_period, int flags)  
 {  {
   register const char *p = pattern, *n = string;    register const char *p = pattern, *n = string;
   register unsigned char c;    register char c;
   
 /* Note that this evaluates C many times.  */  /* Note that this evaluates C many times.  */
 # ifdef _LIBC  # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
 #  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))  
 # else  
 #  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))  
 # endif  
   
   while ((c = *p++) != '\0')    while ((c = *p++) != '\0')
     {      {
Line 155  internal_fnmatch (const char *pattern, c Line 72  internal_fnmatch (const char *pattern, c
         case '?':          case '?':
           if (*n == '\0')            if (*n == '\0')
             return FNM_NOMATCH;              return FNM_NOMATCH;
           else if (*n == '/' && (flags & FNM_FILE_NAME))            else if ((flags & FNM_FILE_NAME) && *n == '/')
             return FNM_NOMATCH;              return FNM_NOMATCH;
           else if (*n == '.' && no_leading_period            else if ((flags & FNM_PERIOD) && *n == '.' &&
                    && (n == string                     (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
                        || (n[-1] == '/' && (flags & FNM_FILE_NAME))))  
             return FNM_NOMATCH;              return FNM_NOMATCH;
           break;            break;
   
Line 172  internal_fnmatch (const char *pattern, c Line 88  internal_fnmatch (const char *pattern, c
                 return FNM_NOMATCH;                  return FNM_NOMATCH;
               c = FOLD (c);                c = FOLD (c);
             }              }
           if (FOLD ((unsigned char) *n) != c)            if (FOLD (*n) != c)
             return FNM_NOMATCH;              return FNM_NOMATCH;
           break;            break;
   
         case '*':          case '*':
           if (*n == '.' && no_leading_period            if ((flags & FNM_PERIOD) && *n == '.' &&
               && (n == string                (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
                   || (n[-1] == '/' && (flags & FNM_FILE_NAME))))  
             return FNM_NOMATCH;              return FNM_NOMATCH;
   
           for (c = *p++; c == '?' || c == '*'; c = *p++)            for (c = *p++; c == '?' || c == '*'; c = *p++)
             {              {
               if (*n == '/' && (flags & FNM_FILE_NAME))                if ((flags & FNM_FILE_NAME) && *n == '/')
                 /* A slash does not match a wildcard under FNM_FILE_NAME.  */                  /* A slash does not match a wildcard under FNM_FILE_NAME.  */
                 return FNM_NOMATCH;                  return FNM_NOMATCH;
               else if (c == '?')                else if (c == '?')
Line 202  internal_fnmatch (const char *pattern, c Line 117  internal_fnmatch (const char *pattern, c
             }              }
   
           if (c == '\0')            if (c == '\0')
             /* The wildcard(s) is/are the last element of the pattern.              return 0;
                If the name is a file name and contains another slash  
                this does mean it cannot match.  If the FNM_LEADING_DIR  
                flag is set and exactly one slash is following, we have  
                a match.  */  
             {  
               int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;  
   
               if (flags & FNM_FILE_NAME)  
                 {  
                   const char *slashp = strchr (n, '/');  
   
                   if (flags & FNM_LEADING_DIR)  
                     {  
                       if (slashp != NULL  
                           && strchr (slashp + 1, '/') == NULL)  
                         result = 0;  
                     }  
                   else  
                     {  
                       if (slashp == NULL)  
                         result = 0;  
                     }  
                 }  
   
               return result;  
             }  
           else  
             {  
               const char *endp;  
   
               endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');  
   
               if (c == '[')  
                 {  
                   int flags2 = ((flags & FNM_FILE_NAME)  
                                 ? flags : (flags & ~FNM_PERIOD));  
   
                   for (--p; n < endp; ++n)  
                     if (internal_fnmatch (p, n,  
                                           (no_leading_period  
                                            && (n == string  
                                                || (n[-1] == '/'  
                                                    && (flags  
                                                        & FNM_FILE_NAME)))),  
                                           flags2)  
                         == 0)  
                       return 0;  
                 }  
               else if (c == '/' && (flags & FNM_FILE_NAME))  
                 {  
                   while (*n != '\0' && *n != '/')  
                     ++n;  
                   if (*n == '/'  
                       && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,  
                                             flags) == 0))  
                     return 0;  
                 }  
               else  
                 {  
                   int flags2 = ((flags & FNM_FILE_NAME)  
                                 ? flags : (flags & ~FNM_PERIOD));  
   
                   if (c == '\\' && !(flags & FNM_NOESCAPE))            {
                     c = *p;              char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
                   c = FOLD (c);              c1 = FOLD (c1);
                   for (--p; n < endp; ++n)              for (--p; *n != '\0'; ++n)
                     if (FOLD ((unsigned char) *n) == c                if ((c == '[' || FOLD (*n) == c1) &&
                         && (internal_fnmatch (p, n,                    fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
                                               (no_leading_period                  return 0;
                                                && (n == string              return FNM_NOMATCH;
                                                    || (n[-1] == '/'            }
                                                        && (flags  
                                                            & FNM_FILE_NAME)))),  
                                               flags2) == 0))  
                       return 0;  
                 }  
             }  
   
           /* If we come here no match is possible with the wildcard.  */  
           return FNM_NOMATCH;  
   
         case '[':          case '[':
           {            {
             /* Nonzero if the sense of the character class is inverted.  */              /* Nonzero if the sense of the character class is inverted.  */
             static int posixly_correct;  
             register int not;              register int not;
             char cold;  
   
             if (posixly_correct == 0)  
               posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;  
   
             if (*n == '\0')              if (*n == '\0')
               return FNM_NOMATCH;                return FNM_NOMATCH;
   
             if (*n == '.' && no_leading_period && (n == string              if ((flags & FNM_PERIOD) && *n == '.' &&
                                                    || (n[-1] == '/'                  (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
                                                        && (flags  
                                                            & FNM_FILE_NAME))))  
               return FNM_NOMATCH;  
   
             if (*n == '/' && (flags & FNM_FILE_NAME))  
               /* `/' cannot be matched.  */  
               return FNM_NOMATCH;                return FNM_NOMATCH;
   
             not = (*p == '!' || (posixly_correct < 0 && *p == '^'));              not = (*p == '!' || *p == '^');
             if (not)              if (not)
               ++p;                ++p;
   
             c = *p++;              c = *p++;
             for (;;)              for (;;)
               {                {
                 unsigned char fn = FOLD ((unsigned char) *n);                  register char cstart = c, cend = c;
   
                 if (!(flags & FNM_NOESCAPE) && c == '\\')                  if (!(flags & FNM_NOESCAPE) && c == '\\')
                   {                    {
                     if (*p == '\0')                      if (*p == '\0')
                       return FNM_NOMATCH;                        return FNM_NOMATCH;
                     c = FOLD ((unsigned char) *p);                      cstart = cend = *p++;
                     ++p;  
   
                     if (c == fn)  
                       goto matched;  
                   }                    }
                 else if (c == '[' && *p == ':')  
                   {  
                     /* Leave room for the null.  */  
                     char str[CHAR_CLASS_MAX_LENGTH + 1];  
                     size_t c1 = 0;  
 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)  
                     wctype_t wt;  
 # endif  
                     const char *startp = p;  
   
                     for (;;)                  cstart = cend = FOLD (cstart);
                       {  
                         if (c1 == CHAR_CLASS_MAX_LENGTH)  
                           /* The name is too long and therefore the pattern  
                              is ill-formed.  */  
                           return FNM_NOMATCH;  
   
                         c = *++p;  
                         if (c == ':' && p[1] == ']')  
                           {  
                             p += 2;  
                             break;  
                           }  
                         if (c < 'a' || c >= 'z')  
                           {  
                             /* This cannot possibly be a character class name.  
                                Match it as a normal range.  */  
                             p = startp;  
                             c = '[';  
                             goto normal_bracket;  
                           }  
                         str[c1++] = c;  
                       }  
                     str[c1] = '\0';  
   
 # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)  
                     wt = IS_CHAR_CLASS (str);  
                     if (wt == 0)  
                       /* Invalid character class name.  */  
                       return FNM_NOMATCH;  
   
                     if (__iswctype (__btowc ((unsigned char) *n), wt))                  if (c == '\0')
                       goto matched;  
 # else  
                     if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))  
                         || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))  
                         || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))  
                         || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))  
                         || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))  
                         || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))  
                         || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))  
                         || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))  
                         || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))  
                         || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))  
                         || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))  
                         || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))  
                       goto matched;  
 # endif  
                   }  
                 else if (c == '\0')  
                   /* [ (unterminated) loses.  */                    /* [ (unterminated) loses.  */
                   return FNM_NOMATCH;                    return FNM_NOMATCH;
                 else  
                   {  
                     c = FOLD (c);  
                   normal_bracket:  
                     if (c == fn)  
                       goto matched;  
   
                     cold = c;                  c = *p++;
                     c = *p++;                  c = FOLD (c);
   
                     if (c == '-' && *p != ']')                  if ((flags & FNM_FILE_NAME) && c == '/')
                       {                    /* [/] can never match.  */
                         /* It is a range.  */                    return FNM_NOMATCH;
                         char lo[2];  
                         char fc[2];  
                         unsigned char cend = *p++;  
                         if (!(flags & FNM_NOESCAPE) && cend == '\\')  
                           cend = *p++;  
                         if (cend == '\0')  
                           return FNM_NOMATCH;  
   
                         lo[0] = cold;  
                         lo[1] = '\0';  
                         fc[0] = fn;  
                         fc[1] = '\0';  
                         if (strcoll (lo, fc) <= 0)  
                           {  
                             char hi[2];  
                             hi[0] = FOLD (cend);  
                             hi[1] = '\0';  
                             if (strcoll (fc, hi) <= 0)  
                               goto matched;  
                           }  
   
                         c = *p++;                  if (c == '-' && *p != ']')
                       }                    {
                       cend = *p++;
                       if (!(flags & FNM_NOESCAPE) && cend == '\\')
                         cend = *p++;
                       if (cend == '\0')
                         return FNM_NOMATCH;
                       cend = FOLD (cend);
   
                       c = *p++;
                   }                    }
   
                   if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
                     goto matched;
   
                 if (c == ']')                  if (c == ']')
                   break;                    break;
               }                }
   
             if (!not)              if (!not)
               return FNM_NOMATCH;                return FNM_NOMATCH;
             break;              break;
   
           matched:            matched:;
             /* Skip the rest of the [...] that already matched.  */              /* Skip the rest of the [...] that already matched.  */
             while (c != ']')              while (c != ']')
               {                {
Line 450  internal_fnmatch (const char *pattern, c Line 208  internal_fnmatch (const char *pattern, c
                     /* XXX 1003.2d11 is unclear if this is right.  */                      /* XXX 1003.2d11 is unclear if this is right.  */
                     ++p;                      ++p;
                   }                    }
                 else if (c == '[' && *p == ':')  
                   {  
                     do  
                       if (*++p == '\0')  
                         return FNM_NOMATCH;  
                     while (*p != ':' || p[1] == ']');  
                     p += 2;  
                     c = *p;  
                   }  
               }                }
             if (not)              if (not)
               return FNM_NOMATCH;                return FNM_NOMATCH;
Line 466  internal_fnmatch (const char *pattern, c Line 215  internal_fnmatch (const char *pattern, c
           break;            break;
   
         default:          default:
           if (c != FOLD ((unsigned char) *n))            if (c != FOLD (*n))
             return FNM_NOMATCH;              return FNM_NOMATCH;
         }          }
   
Line 485  internal_fnmatch (const char *pattern, c Line 234  internal_fnmatch (const char *pattern, c
 # undef FOLD  # undef FOLD
 }  }
   
   
 int  
 fnmatch (pattern, string, flags)  
      const char *pattern;  
      const char *string;  
      int flags;  
 {  
   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);  
 }  
   
 #endif  /* _LIBC or not __GNU_LIBRARY__.  */  #endif  /* _LIBC or not __GNU_LIBRARY__.  */

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>