home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / gnu / find-3.8-src.lha / src / amiga / find-3.8 / lib / fnmatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-29  |  4.1 KB  |  183 lines

  1. /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of the
  6. License, or (at your option) any later version.
  7.  
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. Library General Public License for more details.
  12.  
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; see the file COPYING.LIB.  If
  15. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16. Cambridge, MA 02139, USA.  */
  17.  
  18. #include <errno.h>
  19. #include <fnmatch.h>
  20. #include <ctype.h>
  21.  
  22. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  23. extern int errno;
  24. #endif
  25.  
  26. /* Match STRING against the filename pattern PATTERN, returning zero if
  27.    it matches, nonzero if not.  */
  28. int
  29. fnmatch (pattern, string, flags)
  30.      const char *pattern;
  31.      const char *string;
  32.      int flags;
  33. {
  34.   register const char *p = pattern, *n = string;
  35.   register char c;
  36.  
  37. /* Note that this evalutes C many times.  */
  38. #define FOLD(c)    ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
  39.  
  40.   while ((c = *p++) != '\0')
  41.     {
  42.       c = FOLD (c);
  43.  
  44.       switch (c)
  45.     {
  46.     case '?':
  47.       if (*n == '\0')
  48.         return FNM_NOMATCH;
  49.       else if ((flags & FNM_FILE_NAME) && *n == '/')
  50.         return FNM_NOMATCH;
  51.       else if ((flags & FNM_PERIOD) && *n == '.' &&
  52.            (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  53.         return FNM_NOMATCH;
  54.       break;
  55.  
  56.     case '\\':
  57.       if (!(flags & FNM_NOESCAPE))
  58.         {
  59.           c = *p++;
  60.           c = FOLD (c);
  61.         }
  62.       if (FOLD (*n) != c)
  63.         return FNM_NOMATCH;
  64.       break;
  65.  
  66.     case '*':
  67.       if ((flags & FNM_PERIOD) && *n == '.' &&
  68.           (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  69.         return FNM_NOMATCH;
  70.  
  71.       for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
  72.         if (((flags & FNM_FILE_NAME) && *n == '/') ||
  73.         (c == '?' && *n == '\0'))
  74.           return FNM_NOMATCH;
  75.  
  76.       if (c == '\0')
  77.         return 0;
  78.  
  79.       {
  80.         char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
  81.         c1 = FOLD (c1);
  82.         for (--p; *n != '\0'; ++n)
  83.           if ((c == '[' || FOLD (*n) == c1) &&
  84.           fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
  85.         return 0;
  86.         return FNM_NOMATCH;
  87.       }
  88.  
  89.     case '[':
  90.       {
  91.         /* Nonzero if the sense of the character class is inverted.  */
  92.         register int not;
  93.  
  94.         if (*n == '\0')
  95.           return FNM_NOMATCH;
  96.  
  97.         if ((flags & FNM_PERIOD) && *n == '.' &&
  98.         (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  99.           return FNM_NOMATCH;
  100.  
  101.         not = (*p == '!' || *p == '^');
  102.         if (not)
  103.           ++p;
  104.  
  105.         c = *p++;
  106.         for (;;)
  107.           {
  108.         register char cstart = c, cend = c;
  109.  
  110.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  111.           cstart = cend = *p++;
  112.  
  113.         cstart = cend = FOLD (cstart);
  114.  
  115.         if (c == '\0')
  116.           /* [ (unterminated) loses.  */
  117.           return FNM_NOMATCH;
  118.  
  119.         c = *p++;
  120.         c = FOLD (c);
  121.  
  122.         if ((flags & FNM_FILE_NAME) && c == '/')
  123.           /* [/] can never match.  */
  124.           return FNM_NOMATCH;
  125.  
  126.         if (c == '-' && *p != ']')
  127.           {
  128.             cend = *p++;
  129.             if (!(flags & FNM_NOESCAPE) && cend == '\\')
  130.               cend = *p++;
  131.             if (cend == '\0')
  132.               return FNM_NOMATCH;
  133.             cend = FOLD (cend);
  134.  
  135.             c = *p++;
  136.           }
  137.  
  138.         if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
  139.           goto matched;
  140.  
  141.         if (c == ']')
  142.           break;
  143.           }
  144.         if (!not)
  145.           return FNM_NOMATCH;
  146.         break;
  147.  
  148.       matched:;
  149.         /* Skip the rest of the [...] that already matched.  */
  150.         while (c != ']')
  151.           {
  152.         if (c == '\0')
  153.           /* [... (unterminated) loses.  */
  154.           return FNM_NOMATCH;
  155.  
  156.         c = *p++;
  157.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  158.           /* XXX 1003.2d11 is unclear if this is right.  */
  159.           ++p;
  160.           }
  161.         if (not)
  162.           return FNM_NOMATCH;
  163.       }
  164.       break;
  165.  
  166.     default:
  167.       if (c != FOLD (*n))
  168.         return FNM_NOMATCH;
  169.     }
  170.  
  171.       ++n;
  172.     }
  173.  
  174.   if (*n == '\0')
  175.     return 0;
  176.  
  177.   if ((flags & FNM_LEADING_DIR) && *n == '/')
  178.     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
  179.     return 0;
  180.  
  181.   return FNM_NOMATCH;
  182. }
  183.