Update.
authorUlrich Drepper <drepper@redhat.com>
Mon, 26 Apr 1999 23:21:01 +0000 (23:21 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 26 Apr 1999 23:21:01 +0000 (23:21 +0000)
1999-04-26  Ulrich Drepper  <drepper@cygnus.com>

* posix/fnmatch.c (internal_fnmatch): Renamed from fnmatch.  Take
extra parameter.  Fix several more bugs involving wildcard and
ranges.
(fnmatch): New function.  Call internal_fnmatch.

* posix/testfnm.c: More test cases.

ChangeLog
posix/fnmatch.c
posix/testfnm.c

index 95f538e..feee823 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+1999-04-26  Ulrich Drepper  <drepper@cygnus.com>
+
+       * posix/fnmatch.c (internal_fnmatch): Renamed from fnmatch.  Take
+       extra parameter.  Fix several more bugs involving wildcard and
+       ranges.
+       (fnmatch): New function.  Call internal_fnmatch.
+
+       * posix/testfnm.c: More test cases.
+
 1999-04-03  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
 
        * manual/install.texi (Configuring and compiling): Explain that
index e0ff2c3..d31c375 100644 (file)
@@ -129,11 +129,10 @@ extern int errno;
 
 /* Match STRING against the filename pattern PATTERN, returning zero if
    it matches, nonzero if not.  */
-int
-fnmatch (pattern, string, flags)
-     const char *pattern;
-     const char *string;
-     int flags;
+static int
+internal_function
+internal_fnmatch (const char *pattern, const char *string,
+                 int no_leading_period, int flags)
 {
   register const char *p = pattern, *n = string;
   register unsigned char c;
@@ -156,8 +155,7 @@ fnmatch (pattern, string, flags)
            return FNM_NOMATCH;
          else if (*n == '/' && (flags & FNM_FILE_NAME))
            return FNM_NOMATCH;
-         else if (*n == '.' && (flags & FNM_PERIOD) &&
-                  (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+         else if (*n == '.' && no_leading_period)
            return FNM_NOMATCH;
          break;
 
@@ -175,8 +173,7 @@ fnmatch (pattern, string, flags)
          break;
 
        case '*':
-         if (*n == '.' && (flags & FNM_PERIOD) &&
-             (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+         if (*n == '.' && no_leading_period)
            return FNM_NOMATCH;
 
          for (c = *p++; c == '?' || c == '*'; c = *p++)
@@ -214,9 +211,22 @@ fnmatch (pattern, string, flags)
              if (c == '[')
                {
                  for (--p; n < endp; ++n)
-                   if (fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+                   if (internal_fnmatch (p, n,
+                                         (n == string) && no_leading_period,
+                                         ((flags & FNM_FILE_NAME)
+                                          ? flags : (flags & ~FNM_PERIOD)))
+                       == 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
                {
                  if (c == '\\' && !(flags & FNM_NOESCAPE))
@@ -224,7 +234,13 @@ fnmatch (pattern, string, flags)
                  c = FOLD (c);
                  for (--p; n < endp; ++n)
                    if (FOLD ((unsigned char) *n) == c
-                       && fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+                       && (internal_fnmatch (p, n,
+                                             ((n == string)
+                                              && no_leading_period),
+                                             ((flags & FNM_FILE_NAME)
+                                              ? flags
+                                              : (flags & ~FNM_PERIOD)))
+                           == 0))
                      return 0;
                }
            }
@@ -245,8 +261,7 @@ fnmatch (pattern, string, flags)
            if (*n == '\0')
              return FNM_NOMATCH;
 
-           if (*n == '.' && (flags & FNM_PERIOD) &&
-               (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+           if (*n == '.' && no_leading_period)
              return FNM_NOMATCH;
 
            if (*n == '/' && (flags & FNM_FILE_NAME))
@@ -294,7 +309,15 @@ fnmatch (pattern, string, flags)
                            p += 2;
                            break;
                          }
-                       str[c1++] = 'c';
+                       if (c < 'a' || c >= 'z')
+                         {
+                           /* This cannot possibly be a character class name.
+                              Match it as a normal range.  */
+                           --p;
+                           c = '[';
+                           goto normal_bracket;
+                         }
+                       str[c1++] = c;
                      }
                    str[c1] = '\0';
 
@@ -325,26 +348,31 @@ fnmatch (pattern, string, flags)
                else if (c == '\0')
                  /* [ (unterminated) loses.  */
                  return FNM_NOMATCH;
-               else if (FOLD (c) == fn)
-                 goto matched;
-
-               cold = c;
-               c = *p++;
-
-               if (c == '-' && *p != ']')
+               else
                  {
-                   /* It is a range.  */
-                   unsigned char cend = *p++;
-                   if (!(flags & FNM_NOESCAPE) && cend == '\\')
-                     cend = *p++;
-                   if (cend == '\0')
-                     return FNM_NOMATCH;
-
-                   if (cold <= fn && fn <= FOLD (cend))
+                 normal_bracket:
+                   if (FOLD (c) == fn)
                      goto matched;
 
+                   cold = c;
                    c = *p++;
+
+                   if (c == '-' && *p != ']')
+                     {
+                       /* It is a range.  */
+                       unsigned char cend = *p++;
+                       if (!(flags & FNM_NOESCAPE) && cend == '\\')
+                         cend = *p++;
+                       if (cend == '\0')
+                         return FNM_NOMATCH;
+
+                       if (cold <= fn && fn <= FOLD (cend))
+                         goto matched;
+
+                       c = *p++;
+                     }
                  }
+
                if (c == ']')
                  break;
              }
@@ -404,4 +432,14 @@ fnmatch (pattern, string, flags)
 # 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__.  */
index b43f953..5a6c7e1 100644 (file)
@@ -15,7 +15,38 @@ struct {
   { "a/b", "[a-z]/[a-z]", 0, 0 },
   { "a/b", "*", FNM_FILE_NAME, FNM_NOMATCH },
   { "a/b", "*[/]b", FNM_FILE_NAME, FNM_NOMATCH },
-  { "a/b", "*[b]", FNM_FILE_NAME, FNM_NOMATCH }
+  { "a/b", "*[b]", FNM_FILE_NAME, FNM_NOMATCH },
+  { "a/b", "[*]/b", 0, FNM_NOMATCH },
+  { "*/b", "[*]/b", 0, 0 },
+  { "a/b", "[?]/b", 0, FNM_NOMATCH },
+  { "?/b", "[?]/b", 0, 0 },
+  { "a/b", "[[a]/b", 0, 0 },
+  { "[/b", "[[a]/b", 0, 0 },
+  { "a/b", "\\*/b", 0, FNM_NOMATCH },
+  { "*/b", "\\*/b", 0, 0 },
+  { "a/b", "\\?/b", 0, FNM_NOMATCH },
+  { "?/b", "\\?/b", 0, 0 },
+  { "[/b", "[/b", 0, FNM_NOMATCH },
+  { "[/b", "\\[/b", 0, 0 },
+  { "aa/b", "??/b", 0, 0 },
+  { "aa/b", "???b", 0, 0 },
+  { "aa/b", "???b", FNM_PATHNAME, FNM_NOMATCH },
+  { ".a/b", "?a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { "a/.b", "a/?b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { ".a/b", "*a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { "a/.b", "a/*b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { ".a/b", "[.]a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { "a/.b", "a/[.]b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { "a/b", "*/?", FNM_PATHNAME|FNM_PERIOD, 0 },
+  { "a/b", "?/*", FNM_PATHNAME|FNM_PERIOD, 0 },
+  { ".a/b", ".*/?", FNM_PATHNAME|FNM_PERIOD, 0 },
+  { "a/.b", "*/.?", FNM_PATHNAME|FNM_PERIOD, 0 },
+  { "a/.b", "*/*", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
+  { "a/.b", "*?*/*", FNM_PERIOD, 0 },
+  { "a./b", "*[.]/b", FNM_PATHNAME|FNM_PERIOD, 0 },
+  { "a/b", "*[[:alpha:]]/*[[:alnum:]]", FNM_PATHNAME, 0 },
+  { "a/b", "*[![:digit:]]*/[![:d-d]", FNM_PATHNAME, 0 },
+  { "a/[", "*[![:digit:]]*/[![:d-d]", FNM_PATHNAME, FNM_NOMATCH },
 };
 
 int