home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / thesrc15.zip / fnmatch.c < prev    next >
C/C++ Source or Header  |  1993-09-01  |  4KB  |  183 lines

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