home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / rc / part06 / match.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-30  |  2.1 KB  |  100 lines

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