home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / diff_2_2.lha / diff-2.2 / fnmatch.c < prev    next >
C/C++ Source or Header  |  1993-04-16  |  4KB  |  178 lines

  1. /* Copyright (C) 1991, 1992 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. #ifndef AMIGA
  20. #include <fnmatch.h>
  21. #else /* AMIGA */
  22. #include "fnmatch.h"
  23. #endif /* !AMIGA */
  24.  
  25. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  26. extern int errno;
  27. #endif
  28.  
  29. /* Match STRING against the filename pattern PATTERN, returning zero if
  30.    it matches, nonzero if not.  */
  31. int
  32. fnmatch (pattern, string, flags)
  33.      const char *pattern;
  34.      const char *string;
  35.      int flags;
  36. {
  37.   register const char *p = pattern, *n = string;
  38.   register char c;
  39.  
  40.   if ((flags & ~__FNM_FLAGS) != 0)
  41.     {
  42.       errno = EINVAL;
  43.       return -1;
  44.     }
  45.  
  46.   while ((c = *p++) != '\0')
  47.     {
  48.       switch (c)
  49.     {
  50.     case '?':
  51.       if (*n == '\0')
  52.         return FNM_NOMATCH;
  53.       else if ((flags & FNM_PATHNAME) && *n == '/')
  54.         return FNM_NOMATCH;
  55.       else if ((flags & FNM_PERIOD) && *n == '.' &&
  56.            (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  57.         return FNM_NOMATCH;
  58.       break;
  59.  
  60.     case '\\':
  61.       if (!(flags & FNM_NOESCAPE))
  62.         c = *p++;
  63.       if (*n != c)
  64.         return FNM_NOMATCH;
  65.       break;
  66.  
  67.     case '*':
  68.       if ((flags & FNM_PERIOD) && *n == '.' &&
  69.           (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
  70.         return FNM_NOMATCH;
  71.  
  72.       for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
  73.         if (((flags & FNM_PATHNAME) && *n == '/') ||
  74.         (c == '?' && *n == '\0'))
  75.           return FNM_NOMATCH;
  76.  
  77.       if (c == '\0')
  78.         return 0;
  79.  
  80.       {
  81.         char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
  82.         for (--p; *n != '\0'; ++n)
  83.           if ((c == '[' || *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_PATHNAME) && 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.         if (c == '\0')
  114.           /* [ (unterminated) loses.  */
  115.           return FNM_NOMATCH;
  116.  
  117.         c = *p++;
  118.  
  119.         if ((flags & FNM_PATHNAME) && c == '/')
  120.           /* [/] can never match.  */
  121.           return FNM_NOMATCH;
  122.  
  123.         if (c == '-' && *p != ']')
  124.           {
  125.             cend = *p++;
  126.             if (!(flags & FNM_NOESCAPE) && cend == '\\')
  127.               cend = *p++;
  128.             if (cend == '\0')
  129.               return FNM_NOMATCH;
  130.             c = *p++;
  131.           }
  132.  
  133.         if (*n >= cstart && *n <= cend)
  134.           goto matched;
  135.  
  136.         if (c == ']')
  137.           break;
  138.           }
  139.         if (!not)
  140.           return FNM_NOMATCH;
  141.         break;
  142.  
  143.       matched:;
  144.         /* Skip the rest of the [...] that already matched.  */
  145.         while (c != ']')
  146.           {
  147.         if (c == '\0')
  148.           /* [... (unterminated) loses.  */
  149.           return FNM_NOMATCH;
  150.  
  151.         c = *p++;
  152.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  153.           /* 1003.2d11 is unclear if this is right.  %%% */
  154.           ++p;
  155.           }
  156.         if (not)
  157.           return FNM_NOMATCH;
  158.       }
  159.       break;
  160.  
  161.     default:
  162.       if (c != *n)
  163.         return FNM_NOMATCH;
  164.     }
  165.  
  166.       ++n;
  167.     }
  168.  
  169.   if (*n == '\0')
  170.     return 0;
  171.  
  172.   if ((flags & FNM_LEADING_DIR) && *n == '/')
  173.     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
  174.     return 0;
  175.  
  176.   return FNM_NOMATCH;
  177. }
  178.