home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / rc / part04 / match.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  1.9 KB  |  103 lines

  1. /* match.c: pattern matching routines */
  2.  
  3. #include "rc.h"
  4. #include "utils.h"
  5. #include "match.h"
  6.  
  7. static int rangematch(char *, char);
  8.  
  9. /*
  10.    match() matches a single pattern against a single string.
  11. */
  12.  
  13. boolean match(char *p, char *m, char *s) {
  14.     int i = 0;
  15.     int j;
  16.  
  17.     if (m == NULL)
  18.         return streq(p, s);
  19.  
  20.     while(1) {
  21.         if (p[i] == '\0')
  22.             return *s == '\0';
  23.         else if (m[i]) {
  24.             switch (p[i++]) {
  25.             case '?':
  26.                 if (*s++ == '\0')
  27.                     return FALSE;
  28.                 break;
  29.             case '*':
  30.                 /* collapse multiple stars */
  31.                 while (p[i] == '*' && m[i] == 1)
  32.                     i++;
  33.  
  34.                 /* star at end of pattern? */
  35.                 if (p[i] == '\0')
  36.                     return TRUE;
  37.  
  38.                 while (*s != '\0')
  39.                     if (match(p + i, m + i, s++))
  40.                         return TRUE;
  41.                 return FALSE;
  42.             case '[':
  43.                 if (*s == '\0' || ((j = rangematch(p + i, *s++)) < 0))
  44.                     return FALSE;
  45.                 i += j;
  46.                 break;
  47.             default:
  48.                 fprint(2,"%c is not a metacharacter\n", p[i-1]);
  49.                 return FALSE;
  50.             }
  51.         } else if (p[i++] != *s++) {
  52.                 return FALSE;
  53.         }
  54.     }
  55. }
  56.  
  57. /*
  58.    From the ed(1) man pages (on ranges):
  59.  
  60.     The `-' is treated as an ordinary character if it occurs first
  61.     (or first after an initial ^) or last in the string.
  62.  
  63.     The right square bracket does not terminate the enclosed string
  64.     if it is the first character (after an initial `^', if any), in
  65.     the bracketed string.
  66.  
  67.    rangematch() matches a single character against a class, and returns
  68.    an integer offset to the end of the range on success, or -1 on
  69.    failure.
  70. */
  71.  
  72. static int rangematch(char *p, char c) {
  73.     char *orig = p;
  74.     boolean neg = (*p == '~');
  75.     boolean matched = FALSE;
  76.  
  77.     if (neg)
  78.         p++;
  79.  
  80.     if (*p == ']') {
  81.         p++;
  82.         matched = (c == ']');
  83.     }
  84.  
  85.     for (; *p != ']'; p++) {
  86.         if (*p == '\0')
  87.             return -1;    /* bad syntax */
  88.         if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */
  89.             if (c >= *p)
  90.                 matched |= (c <= p[2]);
  91.             p += 2;
  92.         } else {
  93.             matched |= (*p == c);
  94.         }
  95.     }
  96.  
  97.     if (matched ^ neg)
  98.         return p - orig + 1; /* skip the right-bracket */
  99.     else
  100.         return -1;
  101. }
  102.  
  103.