home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / gnu / tar.txt / tar-1.12 / lib / fnmatch.c < prev    next >
C/C++ Source or Header  |  1997-04-25  |  6KB  |  241 lines

  1. /* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2, or (at your option)
  6.    any later version.
  7.  
  8.    This program 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
  11.    GNU General Public License for more details.
  12.  
  13.   You should have received a copy of the GNU General Public License
  14.   along with this program; if not, write to the Free Software Foundation,
  15.   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  16.  
  17. #if HAVE_CONFIG_H
  18. # include <config.h>
  19. #endif
  20.  
  21. /* Enable GNU extensions in fnmatch.h.  */
  22. #ifndef _GNU_SOURCE
  23. # define _GNU_SOURCE    1
  24. #endif
  25.  
  26. #include <errno.h>
  27. #include <fnmatch.h>
  28. #include <ctype.h>
  29.  
  30.  
  31. /* Comment out all this code if we are using the GNU C Library, and are not
  32.    actually compiling the library itself.  This code is part of the GNU C
  33.    Library, but also included in many other GNU distributions.  Compiling
  34.    and linking in this code is a waste when using the GNU C library
  35.    (especially if it is a shared library).  Rather than having every GNU
  36.    program understand `configure --with-gnu-libc' and omit the object files,
  37.    it is simpler to just do this in the source for each such file.  */
  38.  
  39. #if defined _LIBC || !defined __GNU_LIBRARY__
  40.  
  41.  
  42. # if defined STDC_HEADERS || !defined isascii
  43. #  define ISASCII(c) 1
  44. # else
  45. #  define ISASCII(c) isascii(c)
  46. # endif
  47.  
  48. # define ISUPPER(c) (ISASCII (c) && isupper (c))
  49.  
  50.  
  51. # ifndef errno
  52. extern int errno;
  53. # endif
  54.  
  55. /* Match STRING against the filename pattern PATTERN, returning zero if
  56.    it matches, nonzero if not.  */
  57. int
  58. fnmatch (pattern, string, flags)
  59.      const char *pattern;
  60.      const char *string;
  61.      int flags;
  62. {
  63.   register const char *p = pattern, *n = string;
  64.   register char c;
  65.  
  66. /* Note that this evaluates C many times.  */
  67. # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
  68.  
  69.   while ((c = *p++) != '\0')
  70.     {
  71.       c = FOLD (c);
  72.  
  73.       switch (c)
  74.     {
  75.     case '?':
  76.       if (*n == '\0')
  77.         return FNM_NOMATCH;
  78.       else if ((flags & FNM_FILE_NAME) && *n == '/')
  79.         return FNM_NOMATCH;
  80.       else if ((flags & FNM_PERIOD) && *n == '.' &&
  81.            (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  82.         return FNM_NOMATCH;
  83.       break;
  84.  
  85.     case '\\':
  86.       if (!(flags & FNM_NOESCAPE))
  87.         {
  88.           c = *p++;
  89.           if (c == '\0')
  90.         /* Trailing \ loses.  */
  91.         return FNM_NOMATCH;
  92.           c = FOLD (c);
  93.         }
  94.       if (FOLD (*n) != c)
  95.         return FNM_NOMATCH;
  96.       break;
  97.  
  98.     case '*':
  99.       if ((flags & FNM_PERIOD) && *n == '.' &&
  100.           (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  101.         return FNM_NOMATCH;
  102.  
  103.       for (c = *p++; c == '?' || c == '*'; c = *p++)
  104.         {
  105.           if ((flags & FNM_FILE_NAME) && *n == '/')
  106.         /* A slash does not match a wildcard under FNM_FILE_NAME.  */
  107.         return FNM_NOMATCH;
  108.           else if (c == '?')
  109.         {
  110.           /* A ? needs to match one character.  */
  111.           if (*n == '\0')
  112.             /* There isn't another character; no match.  */
  113.             return FNM_NOMATCH;
  114.           else
  115.             /* One character of the string is consumed in matching
  116.                this ? wildcard, so *??? won't match if there are
  117.                less than three characters.  */
  118.             ++n;
  119.         }
  120.         }
  121.  
  122.       if (c == '\0')
  123.         return 0;
  124.  
  125.       {
  126.         char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
  127.         c1 = FOLD (c1);
  128.         for (--p; *n != '\0'; ++n)
  129.           if ((c == '[' || FOLD (*n) == c1) &&
  130.           fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
  131.         return 0;
  132.         return FNM_NOMATCH;
  133.       }
  134.  
  135.     case '[':
  136.       {
  137.         /* Nonzero if the sense of the character class is inverted.  */
  138.         register int not;
  139.  
  140.         if (*n == '\0')
  141.           return FNM_NOMATCH;
  142.  
  143.         if ((flags & FNM_PERIOD) && *n == '.' &&
  144.         (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
  145.           return FNM_NOMATCH;
  146.  
  147.         not = (*p == '!' || *p == '^');
  148.         if (not)
  149.           ++p;
  150.  
  151.         c = *p++;
  152.         for (;;)
  153.           {
  154.         register char cstart = c, cend = c;
  155.  
  156.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  157.           {
  158.             if (*p == '\0')
  159.               return FNM_NOMATCH;
  160.             cstart = cend = *p++;
  161.           }
  162.  
  163.         cstart = cend = FOLD (cstart);
  164.  
  165.         if (c == '\0')
  166.           /* [ (unterminated) loses.  */
  167.           return FNM_NOMATCH;
  168.  
  169.         c = *p++;
  170.         c = FOLD (c);
  171.  
  172.         if ((flags & FNM_FILE_NAME) && c == '/')
  173.           /* [/] can never match.  */
  174.           return FNM_NOMATCH;
  175.  
  176.         if (c == '-' && *p != ']')
  177.           {
  178.             cend = *p++;
  179.             if (!(flags & FNM_NOESCAPE) && cend == '\\')
  180.               cend = *p++;
  181.             if (cend == '\0')
  182.               return FNM_NOMATCH;
  183.             cend = FOLD (cend);
  184.  
  185.             c = *p++;
  186.           }
  187.  
  188.         if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
  189.           goto matched;
  190.  
  191.         if (c == ']')
  192.           break;
  193.           }
  194.         if (!not)
  195.           return FNM_NOMATCH;
  196.         break;
  197.  
  198.       matched:;
  199.         /* Skip the rest of the [...] that already matched.  */
  200.         while (c != ']')
  201.           {
  202.         if (c == '\0')
  203.           /* [... (unterminated) loses.  */
  204.           return FNM_NOMATCH;
  205.  
  206.         c = *p++;
  207.         if (!(flags & FNM_NOESCAPE) && c == '\\')
  208.           {
  209.             if (*p == '\0')
  210.               return FNM_NOMATCH;
  211.             /* XXX 1003.2d11 is unclear if this is right.  */
  212.             ++p;
  213.           }
  214.           }
  215.         if (not)
  216.           return FNM_NOMATCH;
  217.       }
  218.       break;
  219.  
  220.     default:
  221.       if (c != FOLD (*n))
  222.         return FNM_NOMATCH;
  223.     }
  224.  
  225.       ++n;
  226.     }
  227.  
  228.   if (*n == '\0')
  229.     return 0;
  230.  
  231.   if ((flags & FNM_LEADING_DIR) && *n == '/')
  232.     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
  233.     return 0;
  234.  
  235.   return FNM_NOMATCH;
  236.  
  237. # undef FOLD
  238. }
  239.  
  240. #endif    /* _LIBC or not __GNU_LIBRARY__.  */
  241.