home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / ccmd / wild.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  6.3 KB  |  237 lines

  1. /*
  2.  Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  the City of New York.  Permission is granted to any individual or
  4.  institution to use, copy, or redistribute this software so long as it
  5.  is not sold for profit, provided this copyright notice is retained.
  6.  
  7.  Author: Howie Kaye
  8. */
  9.  
  10. #define TRUE 1
  11. #define FALSE 0
  12. #define NULL 0
  13.  
  14. #ifdef MSDOS
  15. #include <ctype.h>
  16. #define uncase(x) tolower(x)        /* XXX */
  17. #else
  18. #define uncase(x) (x)
  19. #endif
  20.  
  21. /*
  22.  * pattern matcher.
  23.  * matches patterns with wildcards of:
  24.  * '*' = matches any string
  25.  * '?' = any char
  26.  * '[abc-h]' = any include character or range
  27.  * '{abc,def}' = any included string.  these may include any other wildcard
  28.  */
  29. static
  30. match(pattern,string) char *pattern,*string; {
  31.   char *psave,*ssave;            /* back up pointers for failure */
  32.   psave = ssave = NULL;            /* initially no value */
  33.   while (1) {                /* skip first */
  34.     for (; uncase(*pattern) == uncase(*string); pattern++,string++)  
  35.       if (*string == '\0') {        /* end of strings, succeed */
  36.     return(1);
  37.       }
  38.     if ((*string != '\0') && (*pattern == '{')) { /* a "{"...try to match it */
  39.       if (do_curly(pattern,&string)) {    /* the curly routine checks the rest */
  40.     return(TRUE);            /* of the string too */
  41.       }
  42.       else {
  43.     if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  44.                     /* ...have seen a star */
  45.       string = ++ssave;        /* skip 1 char from string */
  46.       pattern = psave;        /* and back up pattern */
  47.     }
  48.     else {
  49.       return(0);            /* '{' didn't match.   fail. */
  50.     }
  51.       }
  52.     }
  53.     else if ((*string != '\0') && (*pattern == '[')) { /* a '[' */
  54.       if (do_list(*string,pattern)) {    /* try to match the list */
  55.     while (*pattern != ']' && *pattern != '\0') { /* and skip past it */
  56.       pattern++;
  57.     } 
  58.     if (*pattern == ']') pattern++;
  59.     ++string;            /* and the string */
  60.       }
  61.       else {
  62.     if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  63.                     /* ...have seen a star */
  64.       string = ++ssave;        /* skip 1 char from string */
  65.       pattern = psave;        /* and back up pattern */
  66.     }
  67.     else {
  68.       return(0);            /* no match.  fail */
  69.     }
  70.       }
  71.     } else if (*string != '\0' && *pattern == '?') {
  72.       ++pattern;            /* '?', let it match */
  73.       ++string;
  74.     } else if (*pattern == '*') {    /* '*' ... */
  75.         psave = ++pattern;        /* remember where we saw it */
  76.         ssave = string;            /* let it match 0 chars */
  77.     } else if (ssave != NULL && *ssave != '\0') { /* if not at end  */
  78.                     /* ...have seen a star */
  79.       string = ++ssave;            /* skip 1 char from string */
  80.       pattern = psave;            /* and back up pattern */
  81.     } else {
  82.         return(0);            /* otherwise just fail */
  83.     }
  84.   }
  85. }
  86.  
  87.  
  88. char *nextchr();
  89.  
  90. /*
  91.  * match patterns in square brackets
  92.  */
  93. static
  94. do_list(chr,pattern) char chr, *pattern; {
  95.   int inverse = 0;            /* test if a "not'ed" pattern */
  96.   int match=0;
  97.   int range[128],i,checked;
  98.   char lower, upper;
  99.  
  100.   for (i = 0; i < 128; i++) range[i] = 0;
  101.   pattern++;                /* pass '[' */
  102.   if (*pattern == '^') {        /* check for negation */
  103.     inverse = TRUE;
  104.     pattern++;                /* and skip past it */
  105.   }
  106.   
  107.   while(*pattern != ']' && *pattern != '\0') {
  108.     pattern = nextchr(pattern,&lower,&upper); /* fill in chars */
  109.     for(i = uncase(lower); i <= uncase(upper); i++){/* over possible ranges */
  110.       range[i] = 1;
  111.     }
  112.     pattern++;
  113.   }
  114.   return(inverse ^ range[uncase(chr)]);    /* return match based on inverse */
  115. }
  116.  
  117. /*
  118.  * get next range of chars out of bracket'ed list
  119.  * returns upper and lower bound in lower and upper
  120.  * if not a range, lower == upper
  121.  */
  122.  
  123. static
  124. char *
  125. nextchr(pattern,lower,upper) char *pattern; char *lower,*upper; {
  126.   if (*pattern == '\\') {        /* a quoted char */
  127.     pattern++;
  128.   }
  129.   *lower = *pattern;            /* get first char */
  130.   *upper = *lower;            /* assume not a range */
  131.   if (pattern[1] == '-') {        /* wrong. */
  132.     pattern+=2;                /* skip the dash. */
  133.     if (*pattern == '\\') {        /* check for quote again */
  134.       pattern++;
  135.     }
  136.     *upper = *pattern;            /* get the upper limit */
  137.   }
  138.   return(pattern);            /* return updated pattern pointer */
  139. }
  140.  
  141. char *get_curly_token();
  142.  
  143. /*
  144.  * match inside curly braces
  145.  */
  146.  
  147. do_curly(pattern,string) char *pattern,**string; {
  148.   char current[300],*p;        /* big buffer,  */
  149.   int last = FALSE;
  150.   int complete;
  151.   int count;
  152.   int maxlen;
  153.  
  154.   count = 0;
  155.   pattern++;
  156.   maxlen = 0;
  157.   while(1) {                /* get next token from in braces */
  158.     pattern = get_curly_token(pattern,current);
  159.     if (match(current,*string)) {    /* if a match return success */
  160.       return(TRUE);
  161.     }
  162.     if (*pattern == '\0' || *pattern == '}') /* otherwise, keep */
  163.       break;
  164.     pattern++;                /* going to next token */
  165.   }
  166.   return(FALSE);            /* failure */
  167. }
  168.  
  169. /*
  170.  * get the next token in curly braces, and append the end of the string 
  171.  * to it.
  172.  */
  173. char *
  174. get_curly_token(pattern,current) char *pattern,*current; {
  175.   char *p = pattern;
  176.   char *cp = current,*xp;
  177.   int leftcount = 1;
  178.   int commacount = 0;
  179.  
  180.   while(leftcount > 0) {        /* make sure braces match correctly */
  181.     switch(*p) {
  182.     case '{':                /* if a char is an open brace */
  183.       leftcount++;            /* count it */
  184.       break;
  185.     case '}':                /* likewise a close brace */
  186.       leftcount--;
  187.       break;
  188.     case ',':                /* a "," in the current set of braces*/
  189.       if (leftcount == 1)
  190.     commacount = 1;            /* note end of token */
  191.       break;
  192.     }
  193.     if (!leftcount || commacount || *p == '\0') { /* token ended */
  194.       strncpy(cp,pattern,p-pattern);    /* copy token */
  195.       cp[p-pattern] = '\0';        /* tie it off */
  196.       xp = p;                /* save pointer */
  197.       if (leftcount == 0) xp++;        /* if the close brace, pass it */
  198.       while(leftcount > 0) {        /* then scan to end of pattern */
  199.     if (*xp == '{') leftcount++;
  200.     else if (*xp == '}') leftcount--;
  201.     else if (*xp == '\0') break;
  202.     xp++;
  203.       }
  204.       strcat(cp,xp);            /* append the rest of the string */
  205.       return(p);            /* return pointer to end of token */
  206.     }
  207.     p++;                /* otherwise, keep traversing string */
  208.   }
  209. }
  210.  
  211. /*
  212.  * pattern match
  213.  * if partial, append a "*" to the pattern
  214.  * if *.* in msdos, then match
  215.  * otherwise, try to match
  216.  */
  217.  
  218. fmatch(string,pattern,partial) char *string,*pattern; int partial; {
  219.   int ret;
  220.   char temp[30];
  221.   char *pat = temp;
  222.   if (strlen(pattern)+2 > 29)
  223.       pat = (char *)malloc(strlen(pattern)+2);
  224.   strcpy(pat,pattern);
  225.   if (partial) strcat(pat,"*");
  226. #ifdef MSDOS
  227.   if (!strcmp(pat,"*.*")) 
  228.     ret = TRUE;
  229.   else
  230. #endif
  231.   ret = match(pat,string);
  232.   if (pat != temp)
  233.       free(pat);
  234.   return(ret);
  235. }
  236.  
  237.