/* * p m a t c h . c */ /*)LIBRARY */ #ifdef DOCUMENTATION title pmatch Pattern Match -- Unix File Conventions index Pattern match -- Unix file conventions synopsis int pmatch(string, pattern) char *string; /* What to look for */ char *pattern; /* Pattern to match */ description pmatch() returns TRUE if the string argument is matched by the pattern argument. The pattern follows Unix filename conventions: .lm +8 * matches any (even null) string ? matches any single (non-null) byte [class] defines a class of characters. A class consists of either a list of valid characters or pairs of characters separated by '-' defining a range. \ uses the next character literally; same as '\\' at pattern end. .lm -8 Note that upper- and lower-case are distinct. bugs author Martin Minow, taken from various Unix utilities. #endif /* *)EDITLEVEL=02 * Edit History * 0.1 09-Dec-81 MM Initial edit */ #define EOS 0 #define FALSE 0 #define TRUE 1 int pmatch(string, pattern) char *string; /* What to look for */ char *pattern; /* May have class indicator */ /* * Recursive routine to match "string" against "pattern". * Returns TRUE if successful, FALSE if failure. * * pattern follows Unix pattern match conventions: * * matches any (even null) string * ? matches any single (non-null) byte * [class] defines a class of characters. A class consists of * either a list of valid characters or pairs of characters * separated by '-' defining a range. * \ uses the next character literally (== '\\' at pattern end). * Upper and lower case are distinct. */ { register int classchar; /* Current class character */ register int stringchar; /* Current string character */ register int flag; /* Class found flag */ int pattchar; /* Current pattern character */ int prevclass; /* Previous char. for [a-z] */ for (;;++string, ++pattern) { stringchar = *string; /* Initialize -- get string */ switch ((pattchar = *pattern)) { case EOS: /* End of pattern */ return (stringchar == EOS); case '*': /* Always advance */ if (*++pattern == EOS) return (TRUE); return (match1(string, pattern)); case '\\': /* Quote next */ if (pattern[1] != EOS) pattchar = *++pattern; default: /* Match exact */ if (stringchar != pattchar) return (FALSE); break; /* Advance */ case '?': /* Match any single byte */ if (stringchar != EOS) break; /* Gotcha, advance */ return (FALSE); case '[': /* Match a class */ prevclass = 32767; /* Big start now */ flag = 0; /* No success yet */ while ((classchar = *++pattern) != EOS) { switch (classchar) { case ']': if (flag != FALSE) goto classok; return (FALSE); case '-': classchar = pattern[1]; flag |= (prevclass <= stringchar) && (stringchar <= classchar); } prevclass = classchar; if (stringchar == classchar) flag++; } return (FALSE); } classok: ; } } static int match1(string, pattern) register char *string; char *pattern; /* * Advance the string (after '*' in the pattern) */ { while(*string != EOS) { if (pmatch(string, pattern)) return (TRUE); string++; } return (FALSE); }