home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / f / futi14as.zip / GLOBMAT.C < prev    next >
C/C++ Source or Header  |  1990-07-21  |  4KB  |  200 lines

  1. /* File-name wildcard pattern matching for GNU.
  2.    Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program 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
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* To whomever it may concern: I have never seen the code which most
  19.    Unix programs use to perform this function.  I wrote this from scratch
  20.    based on specifications for the pattern matching.  --RMS.  */
  21.  
  22. static int glob_match_after_star ();
  23.  
  24. /* Return nonzero if PATTERN has any special globbing chars in it.  */
  25.  
  26. int
  27. glob_pattern_p (pattern)
  28.      char *pattern;
  29. {
  30.   register char *p = pattern;
  31.   register char c;
  32.  
  33.   while ((c = *p++) != '\0')
  34.     switch (c)
  35.       {
  36.       case '?':
  37.       case '[':
  38.       case '*':
  39.     return 1;
  40.  
  41.       case '\\':
  42.     if (*p++ == '\0')
  43.       return 0;
  44.       }
  45.  
  46.   return 0;
  47. }
  48.  
  49.  
  50. /* Match the pattern PATTERN against the string TEXT;
  51.    return 1 if it matches, 0 otherwise.
  52.  
  53.    A match means the entire string TEXT is used up in matching.
  54.  
  55.    In the pattern string, `*' matches any sequence of characters,
  56.    `?' matches any character, [SET] matches any character in the specified set,
  57.    [!SET] matches any character not in the specified set.
  58.  
  59.    A set is composed of characters or ranges; a range looks like
  60.    character hyphen character (as in 0-9 or A-Z).
  61.    [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
  62.    Any other character in the pattern must be matched exactly.
  63.  
  64.    To suppress the special syntactic significance of any of `[]*?!-\',
  65.    and match the character exactly, precede it with a `\'.
  66.  
  67.    If DOT_SPECIAL is nonzero,
  68.    `*' and `?' do not match `.' at the beginning of TEXT.  */
  69.  
  70. int
  71. glob_match (pattern, text, dot_special)
  72.      char *pattern, *text;
  73.      int dot_special;
  74. {
  75.   register char *p = pattern, *t = text;
  76.   register char c;
  77.  
  78.   while ((c = *p++) != '\0')
  79.     switch (c)
  80.       {
  81.       case '?':
  82.     if (*t == '\0' || (dot_special && t == text && *t == '.'))
  83.       return 0;
  84.     else
  85.       ++t;
  86.     break;
  87.  
  88.       case '\\':
  89.     if (*p++ != *t++)
  90.       return 0;
  91.     break;
  92.  
  93.       case '*':
  94.     if (dot_special && t == text && *t == '.')
  95.       return 0;
  96.     return glob_match_after_star (p, t);
  97.  
  98.       case '[':
  99.     {
  100.       register char c1 = *t++;
  101.       int invert;
  102.  
  103.       if (c1 == '\0')
  104.         return 0;
  105.  
  106.       invert = (*p == '!');
  107.  
  108.       if (invert)
  109.         p++;
  110.  
  111.       c = *p++;
  112.       while (1)
  113.         {
  114.           register char cstart = c, cend = c;
  115.  
  116.           if (c == '\\')
  117.         {
  118.           cstart = *p++;
  119.           cend = cstart;
  120.         }
  121.  
  122.           if (cstart == '\0')
  123.         return 0;    /* Missing ']'. */
  124.  
  125.           c = *p++;
  126.  
  127.           if (c == '-')
  128.         {
  129.           cend = *p++;
  130.           if (cend == '\\')
  131.             cend = *p++;
  132.           if (cend == '\0')
  133.             return 0;
  134.           c = *p++;
  135.         }
  136.           if (c1 >= cstart && c1 <= cend)
  137.         goto match;
  138.           if (c == ']')
  139.         break;
  140.         }
  141.       if (!invert)
  142.         return 0;
  143.       break;
  144.  
  145.     match:
  146.       /* Skip the rest of the [...] construct that already matched.  */
  147.       while (c != ']')
  148.         {
  149.           if (c == '\0')
  150.         return 0;
  151.           c = *p++;
  152.           if (c == '\0')
  153.         return 0;
  154.           if (c == '\\')
  155.         p++;
  156.         }
  157.       if (invert)
  158.         return 0;
  159.       break;
  160.     }
  161.  
  162.       default:
  163.     if (c != *t++)
  164.       return 0;
  165.       }
  166.  
  167.   return *t == '\0';
  168. }
  169.  
  170. /* Like glob_match, but match PATTERN against any final segment of TEXT.  */
  171.  
  172. static int
  173. glob_match_after_star (pattern, text)
  174.      char *pattern, *text;
  175. {
  176.   register char *p = pattern, *t = text;
  177.   register char c, c1;
  178.  
  179.   while ((c = *p++) == '?' || c == '*')
  180.     if (c == '?' && *t++ == '\0')
  181.       return 0;
  182.  
  183.   if (c == '\0')
  184.     return 1;
  185.  
  186.   if (c == '\\')
  187.     c1 = *p;
  188.   else
  189.     c1 = c;
  190.  
  191.   --p;
  192.   while (1)
  193.     {
  194.       if ((c == '[' || *t == c1) && glob_match (p, t, 0))
  195.     return 1;
  196.       if (*t++ == '\0')
  197.     return 0;
  198.     }
  199. }
  200.