/***************************************************************** | amatch - match a string against a wildcard pattern |---------------------------------------------------------------- | Compares a data string against a test pattern using Bourne shell | wildcard rules (*not* regular expression rules). | | This routine is ugly and not well structured. | | Author: Bill Davidsen (davidsen@crdos1.crd.ge.com) Mar 24, 1985 | with helpful suggestions from Andy Robinson |---------------------------------------------------------------- | Copyright: | Copyright (c) 1985, 1989 by Bill Davidsen. This program may be | freely given, bartered, traded or sold by anyone for any | purpose. The supplier assumes all risk for any consequences of | malfunction. All other rights reserved. |---------------------------------------------------------------- | Arguments: | 1 - address of wildcard pattern | 2 - address of string to test ****************************************************************/ #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif int amatch(register char *ts, register char *cs) { int low, hi, notf; while (1) { /* keep going until done */ if (*cs == '\0') { /* out of string */ for (; *ts == '*'; ++ts) ; /* get rid of extra '*' */ return(*ts == '\0'); } switch (*ts) { case '\0': return(FALSE); case '[': /* the hardest case (see '*' below) */ /* is the not flag set? */ if (notf = (*(ts + 1) == '!')) ++ts; /* ! flag set */ /* loop through the bracket */ while (*++ts != ']' && *ts != '\0') { if (*ts == '-') { /* a range of values */ /* get lower limit */ if ((*--ts == '[' || *ts == '!') && *(ts - 1) != '\\') low = '\0'; else low = *ts; /* get upper limit */ if (*(ts += 2) == ']' || *ts == '\0') { hi = '\377'; --ts; } else { if (*ts == '\\' && *++ts == '\0') { --ts; hi = '\377'; } else hi = *ts; } /* and compare */ if (*cs > (char) low && *cs <= (char) hi) goto foo; continue; /* in bracket loop */ } /* process wildcard */ if (*ts == '\\' && *++ts == '\0') break; /* bump and check for \0 */ /* check if they are the same */ if (*cs == *ts) goto foo; } /* while */ /* get here if no match (out of ts or reached ]) */ if (!notf) return(FALSE); if (*ts) ++ts; break; /* come here if a match */ foo: if (notf) return(FALSE); ++ts; while (*ts != '\0' && *ts++ != ']') ; /* get to end of bracket */ break; case '*': /* a chicken way out! my only recursive part */ while (*++ts == '*') ; /* get rid of extra '*' */ if (!*ts) /* trailing '*' matches anything */ return(TRUE); do if (amatch(ts, cs)) return(TRUE); while (*++cs); return(*ts == '\0'); case '?': /* just bump the pointers */ ++ts; break; case '\\': /* this drops through to next one */ ++ts; default: /* if they ain't the same here forget it */ if (*cs != *ts++) return(FALSE); } /* switch */ ++cs; } /* while (1) */ } /* match */ /***************************************************************** | test program for amatch |---------------------------------------------------------------- | Reads patterns and paths until none given. ****************************************************************/ #ifdef TEST #include static void getline(char *buffer, int len); void main(void) { char data[80], pattern[80]; int match; do { /* read wildcard patterns */ printf("Enter pattern: "); getline(pattern, 80); if (strlen(pattern)) { /* read test cases */ do { printf(" Enter test data: "); getline(data, 80); if (strlen(data)) { match = amatch(pattern, data); printf("\t%s\n", (match ? "YES" : "NO")); } } while (strlen(data)); } } while (strlen(pattern)); } static void getline(char *buffer, int len) { fgets(buffer, len, stdin); len = strlen(buffer) - 1; if (buffer[len] == '\n') buffer[len] = 0; } #endif