[BACK]Return to fnmatch.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/gen/fnmatch.c between version 1.21 and 1.22

version 1.21, 2005/12/24 21:11:16 version 1.22, 2011/01/31 04:20:50
Line 59  __weak_alias(fnmatch,_fnmatch)
Line 59  __weak_alias(fnmatch,_fnmatch)
   
 #define EOS     '\0'  #define EOS     '\0'
   
 static const char *rangematch __P((const char *, int, int));  
   
 static inline int  static inline int
 foldcase(int ch, int flags)  foldcase(int ch, int flags)
 {  {
   
         if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))          if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))
                 return (tolower(ch));                  return tolower(ch);
         return (ch);          return ch;
 }  }
   
 #define FOLDCASE(ch, flags)     foldcase((unsigned char)(ch), (flags))  #define FOLDCASE(ch, flags)     foldcase((unsigned char)(ch), (flags))
   
 int  static const char *
 fnmatch(pattern, string, flags)  rangematch(const char *pattern, int test, int flags)
         const char *pattern, *string;  {
         int flags;          int negate, ok;
           char c, c2;
   
           _DIAGASSERT(pattern != NULL);
   
           /*
            * A bracket expression starting with an unquoted circumflex
            * character produces unspecified results (IEEE 1003.2-1992,
            * 3.13.2).  This implementation treats it like '!', for
            * consistency with the regular expression syntax.
            * J.T. Conklin (conklin@ngai.kaleida.com)
            */
           if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
                   ++pattern;
   
           for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {
                   if (c == '\\' && !(flags & FNM_NOESCAPE))
                           c = FOLDCASE(*pattern++, flags);
                   if (c == EOS)
                           return NULL;
                   if (*pattern == '-'
                       && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&
                           c2 != ']') {
                           pattern += 2;
                           if (c2 == '\\' && !(flags & FNM_NOESCAPE))
                                   c2 = FOLDCASE(*pattern++, flags);
                           if (c2 == EOS)
                                   return NULL;
                           if (c <= test && test <= c2)
                                   ok = 1;
                   } else if (c == test)
                           ok = 1;
           }
           return ok == negate ? NULL : pattern;
   }
   
   
   static int
   fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
 {  {
         const char *stringstart;          const char *stringstart;
         char c, test;          char c, test;
Line 83  fnmatch(pattern, string, flags)
Line 119  fnmatch(pattern, string, flags)
         _DIAGASSERT(pattern != NULL);          _DIAGASSERT(pattern != NULL);
         _DIAGASSERT(string != NULL);          _DIAGASSERT(string != NULL);
   
           if (recursion-- == 0)
                   return FNM_NORES;
   
         for (stringstart = string;;)          for (stringstart = string;;)
                 switch (c = FOLDCASE(*pattern++, flags)) {                  switch (c = FOLDCASE(*pattern++, flags)) {
                 case EOS:                  case EOS:
                         if ((flags & FNM_LEADING_DIR) && *string == '/')                          if ((flags & FNM_LEADING_DIR) && *string == '/')
                                 return (0);                                  return 0;
                         return (*string == EOS ? 0 : FNM_NOMATCH);                          return *string == EOS ? 0 : FNM_NOMATCH;
                 case '?':                  case '?':
                         if (*string == EOS)                          if (*string == EOS)
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         if (*string == '/' && (flags & FNM_PATHNAME))                          if (*string == '/' && (flags & FNM_PATHNAME))
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         if (*string == '.' && (flags & FNM_PERIOD) &&                          if (*string == '.' && (flags & FNM_PERIOD) &&
                             (string == stringstart ||                              (string == stringstart ||
                             ((flags & FNM_PATHNAME) && *(string - 1) == '/')))                              ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         ++string;                          ++string;
                         break;                          break;
                 case '*':                  case '*':
Line 109  fnmatch(pattern, string, flags)
Line 148  fnmatch(pattern, string, flags)
                         if (*string == '.' && (flags & FNM_PERIOD) &&                          if (*string == '.' && (flags & FNM_PERIOD) &&
                             (string == stringstart ||                              (string == stringstart ||
                             ((flags & FNM_PATHNAME) && *(string - 1) == '/')))                              ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
   
                         /* Optimize for pattern with * at end or before /. */                          /* Optimize for pattern with * at end or before /. */
                         if (c == EOS) {                          if (c == EOS) {
                                 if (flags & FNM_PATHNAME)                                  if (flags & FNM_PATHNAME)
                                         return ((flags & FNM_LEADING_DIR) ||                                          return (flags & FNM_LEADING_DIR) ||
                                             strchr(string, '/') == NULL ?                                              strchr(string, '/') == NULL ?
                                             0 : FNM_NOMATCH);                                              0 : FNM_NOMATCH;
                                 else                                  else
                                         return (0);                                          return 0;
                         } else if (c == '/' && flags & FNM_PATHNAME) {                          } else if (c == '/' && flags & FNM_PATHNAME) {
                                 if ((string = strchr(string, '/')) == NULL)                                  if ((string = strchr(string, '/')) == NULL)
                                         return (FNM_NOMATCH);                                          return FNM_NOMATCH;
                                 break;                                  break;
                         }                          }
   
                         /* General case, use recursion. */                          /* General case, use recursion. */
                         while ((test = FOLDCASE(*string, flags)) != EOS) {                          while ((test = FOLDCASE(*string, flags)) != EOS) {
                                 if (!fnmatch(pattern, string,                                  int e;
                                              flags & ~FNM_PERIOD))                                  switch ((e = fnmatchx(pattern, string,
                                         return (0);                                      flags & ~FNM_PERIOD, recursion))) {
                                   case FNM_NOMATCH:
                                           break;
                                   default:
                                           return e;
                                   }
                                 if (test == '/' && flags & FNM_PATHNAME)                                  if (test == '/' && flags & FNM_PATHNAME)
                                         break;                                          break;
                                 ++string;                                  ++string;
                         }                          }
                         return (FNM_NOMATCH);                          return FNM_NOMATCH;
                 case '[':                  case '[':
                         if (*string == EOS)                          if (*string == EOS)
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         if (*string == '/' && flags & FNM_PATHNAME)                          if (*string == '/' && flags & FNM_PATHNAME)
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         if ((pattern =                          if ((pattern = rangematch(pattern,
                             rangematch(pattern, FOLDCASE(*string, flags),                              FOLDCASE(*string, flags), flags)) == NULL)
                                        flags)) == NULL)                                  return FNM_NOMATCH;
                                 return (FNM_NOMATCH);  
                         ++string;                          ++string;
                         break;                          break;
                 case '\\':                  case '\\':
Line 156  fnmatch(pattern, string, flags)
Line 199  fnmatch(pattern, string, flags)
                         /* FALLTHROUGH */                          /* FALLTHROUGH */
                 default:                  default:
                         if (c != FOLDCASE(*string++, flags))                          if (c != FOLDCASE(*string++, flags))
                                 return (FNM_NOMATCH);                                  return FNM_NOMATCH;
                         break;                          break;
                 }                  }
         /* NOTREACHED */          /* NOTREACHED */
 }  }
   
 static const char *  int
 rangematch(pattern, test, flags)  fnmatch(const char *pattern, const char *string, int flags)
         const char *pattern;  
         int test, flags;  
 {  {
         int negate, ok;          return fnmatchx(pattern, string, flags, 128);
         char c, c2;  
   
         _DIAGASSERT(pattern != NULL);  
   
         /*  
          * A bracket expression starting with an unquoted circumflex  
          * character produces unspecified results (IEEE 1003.2-1992,  
          * 3.13.2).  This implementation treats it like '!', for  
          * consistency with the regular expression syntax.  
          * J.T. Conklin (conklin@ngai.kaleida.com)  
          */  
         if ((negate = (*pattern == '!' || *pattern == '^')) != 0)  
                 ++pattern;  
   
         for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {  
                 if (c == '\\' && !(flags & FNM_NOESCAPE))  
                         c = FOLDCASE(*pattern++, flags);  
                 if (c == EOS)  
                         return (NULL);  
                 if (*pattern == '-'  
                     && (c2 = FOLDCASE(*(pattern+1), flags)) != EOS &&  
                         c2 != ']') {  
                         pattern += 2;  
                         if (c2 == '\\' && !(flags & FNM_NOESCAPE))  
                                 c2 = FOLDCASE(*pattern++, flags);  
                         if (c2 == EOS)  
                                 return (NULL);  
                         if (c <= test && test <= c2)  
                                 ok = 1;  
                 } else if (c == test)  
                         ok = 1;  
         }  
         return (ok == negate ? NULL : pattern);  
 }  }

Legend:
Removed from v.1.21  
changed lines
  Added in v.1.22

CVSweb <webmaster@jp.NetBSD.org>