/* * Do shell-style pattern matching for ?, \, [], and * characters. * * Written by Rich $alz, Wed Nov 26 19:03:17 EST 1986. * Special thanks to Lars Mathiesen for the ABORT code. * * Bug reports of this modified version should go to * * harald@os2point.ping.de * harald@sesam.com * Fido: 2:2448/434 */ #undef STANDALONE #include #include /* ** Match text and p, return 1, 0, or -1. */ static int DoMatch(char *text, char *p) { register char last; register int matched; register int reverse; for ( ; *p; text++, p++) { if (*text == '\0' && *p != '*') return -1; switch (*p) { case '\\': /* Literal match with following character. */ p++; /* fall */ default: if (*text != *p) return 0; continue; case '?': /* Match anything. */ continue; case '*': while (*++p == '*') /* * Consecutive stars act just like one. */ continue; if (*p == '\0') /* * Trailing star matches everything. */ return 1; while (*text) if ((matched = DoMatch(text++, p)) != 0) return matched; return -1; case '[': reverse = p[1] == '^' ? 1 : 0; if (reverse) /* * Inverted character class. */ p++; matched = 0; if (p[1] == ']' || p[1] == '-') if (*++p == *text) matched = 1; for (last = *p; *++p && *p != ']'; last = *p) if (*p == '-' && p[1] != ']') { if(*text <= *++p && *text >= last) matched = 1; } else if(*text == *p) matched = 1; if (matched == reverse) return 0; continue; } } return *text == '\0'; } /************************************************************************/ /* User-level routine. Returns 1 or 0. */ /************************************************************************/ int wildmat(char *text, char *p) { if(p[0] == '*' && p[1] == '\0') return 1; return(DoMatch(text, p) == 1); } /************************************************************************/ /* */ /************************************************************************/ int ngmatch(char *group, char *list) { int result = 0; char *cp; if(*list == '\0') return(1); while(*list) { if((cp = strchr(list, ',')) != NULL) *cp = '\0'; if(*list == '!') { if(wildmat(group, list + 1)) { result = 0; if(cp) *cp = ','; break; } } else result |= wildmat(group, list); if(cp) *cp++ = ','; else break; list = cp; } return(result); } #ifdef STANDALONE /************************************************************************/ /* */ /************************************************************************/ int main(int argc, char *argv[]) { if(argc < 3) printf("Usage: %s ", argv[0]); else { printf("Test if '%s' in '%s'\n", argv[1], argv[2]); switch(ngmatch(argv[1], argv[2])) { case -1: puts("No match, aborted"); break; case 0: puts("No match"); break; case 1: puts("Match"); break; } } return(0); } #endif