home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / tcl / expect / expect-4.7 / lib_string.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-20  |  3.8 KB  |  173 lines

  1. #define FALSE 0
  2. #define TRUE 1
  3.  
  4. /* The following functions implement expect's glob-style string matching */
  5. /* Exp_StringMatch allow's implements the unanchored front (or conversely */
  6. /* the '^') feature.  Exp_StringMatch2 does the rest of the work. */
  7. int    /* returns # of chars that matched */
  8. Exp_StringMatch(string, pattern,offset)
  9. char *string;
  10. char *pattern;
  11. int *offset;    /* offset from beginning of string where pattern matches */
  12. {
  13.     char *s;
  14.     int sm;    /* count of chars matched or -1 */
  15.     int caret = FALSE;
  16.  
  17.     *offset = 0;
  18.  
  19.     if (pattern[0] == '^') {
  20.         caret = TRUE;
  21.         pattern++;
  22.     }
  23.  
  24.     sm = Exp_StringMatch2(string,pattern);
  25.     if (sm >= 0) return(sm);
  26.  
  27.     if (caret) return(-1);
  28.  
  29.     if (pattern[0] == '*') return(-1);
  30.  
  31.     for (s = string;*s;s++) {
  32.          sm = Exp_StringMatch2(s,pattern);
  33.         if (sm != -1) {
  34.             *offset = s-string;
  35.             return(sm);
  36.         }
  37.     }
  38.     return(-1);
  39. }
  40.  
  41. /* Exp_StringMatch2 --
  42.  
  43. Like Tcl_StringMatch except that
  44. 1) returns number of characters matched, -1 if failed.
  45.     (Can return 0 on patterns like "" or "$")
  46. 2) does not require pattern to match to end of string
  47. 3) Original code is stolen from Tcl_StringMatch
  48. */
  49.  
  50. int Exp_StringMatch2(string,pattern)
  51.     register char *string;    /* String. */
  52.     register char *pattern;    /* Pattern, which may contain
  53.                  * special characters. */
  54. {
  55.     char c2;
  56.     int match = 0;    /* # of chars matched */
  57.  
  58.     while (1) {
  59.     /* See if we're at the end of both the pattern and the string.
  60.      * If so, we succeeded.  If we're at the end of the pattern
  61.      * but not at the end of the string, we failed.
  62.      */
  63.     
  64.     if (*pattern == 0) {
  65.         /* removed test for end of string - DEL */
  66.         return match;
  67.     }
  68.  
  69.     if ((*string == 0) && (*pattern != '*')) {
  70.         return -1;
  71.     }
  72.  
  73.     /* Check for a "*" as the next pattern character.  It matches
  74.      * any substring.  We handle this by calling ourselves
  75.      * recursively for each postfix of string, until either we
  76.      * match or we reach the end of the string.
  77.      */
  78.     
  79.     if (*pattern == '*') {
  80.         pattern += 1;
  81.         if (*pattern == 0) {
  82.         return(strlen(string)+match); /* DEL */
  83.         }
  84.         while (*string != 0) {
  85.         int rc;                    /* DEL */
  86.  
  87.         if (-1 != (rc = Exp_StringMatch2(string, pattern))) {
  88.             return rc+match;        /* DEL */
  89.         }
  90.         string += 1;
  91.         match++;                /* DEL */
  92.         }
  93.         if (*pattern == '$') return 0;    /* handle *$ */
  94.         return -1;                    /* DEL */
  95.     }
  96.     
  97.     /* Check for a "?" as the next pattern character.  It matches
  98.      * any single character.
  99.      */
  100.  
  101.     if (*pattern == '?') {
  102.         goto thisCharOK;
  103.     }
  104.  
  105.     /* Check for a "[" as the next pattern character.  It is followed
  106.      * by a list of characters that are acceptable, or by a range
  107.      * (two characters separated by "-").
  108.      */
  109.     
  110.     if (*pattern == '[') {
  111.         pattern += 1;
  112.         while (1) {
  113.         if ((*pattern == ']') || (*pattern == 0)) {
  114.             return 0;
  115.         }
  116.         if (*pattern == *string) {
  117.             break;
  118.         }
  119.         if (pattern[1] == '-') {
  120.             c2 = pattern[2];
  121.             if (c2 == 0) {
  122.             return -1;        /* DEL */
  123.             }
  124.             if ((*pattern <= *string) && (c2 >= *string)) {
  125.             break;
  126.             }
  127.             if ((*pattern >= *string) && (c2 <= *string)) {
  128.             break;
  129.             }
  130.             pattern += 2;
  131.         }
  132.         pattern += 1;
  133.         }
  134.         while ((*pattern != ']') && (*pattern != 0)) {
  135.         pattern += 1;
  136.         }
  137.         goto thisCharOK;
  138.     }
  139.     
  140.     /* If the last pattern character is '$', verify that the entire
  141.      * string has been matched. - DEL 
  142.      */
  143.  
  144.     if ((*pattern == '$') && (pattern[1] == 0)) {
  145.         if (*string == 0) return(0);
  146.         else return(-1);        
  147.     }
  148.  
  149.     /* If the next pattern character is '/', just strip off the '/'
  150.      * so we do exact matching on the character that follows.
  151.      */
  152.     
  153.     if (*pattern == '\\') {
  154.         pattern += 1;
  155.         if (*pattern == 0) {
  156.         return -1;
  157.         }
  158.     }
  159.  
  160.     /* There's no special character.  Just make sure that the next
  161.      * characters of each string match.
  162.      */
  163.     
  164.     if (*pattern != *string) {
  165.         return -1;
  166.     }
  167.  
  168.     thisCharOK: pattern += 1;
  169.     string += 1;
  170.     match++;
  171.     }
  172. }
  173.