ref: c05151aa1b7ac81866cf937c973e7038035dfe53
dir: /plan9/glob.c/
#include <stdio.h> #include "../linux/glob.h" /* Like glob_match, but match PATTERN against any final segment of TEXT. */ static int glob_match_after_star(char *pattern, char *text) { register char *p = pattern, *t = text; register char c, c1; while ((c = *p++) == '?' || c == '*') if (c == '?' && *t++ == '\0') return 0; if (c == '\0') return 1; if (c == '\\') c1 = *p; else c1 = c; while (1) { if ((c == '[' || *t == c1) && glob_match(p - 1, t)) return 1; if (*t++ == '\0') return 0; } } /* Return nonzero if PATTERN has any special globbing chars in it. */ static int glob_pattern_p(char *pattern) { register char *p = pattern; register char c; int open = 0; while ((c = *p++) != '\0') switch (c) { case '?': case '*': return 1; case '[': /* Only accept an open brace if there is a close */ open++; /* brace to match it. Bracket expressions must be */ continue; /* complete, according to Posix.2 */ case ']': if (open) return 1; continue; case '\\': if (*p++ == '\0') return 0; } return 0; } /* Match the pattern PATTERN against the string TEXT; return 1 if it matches, 0 otherwise. A match means the entire string TEXT is used up in matching. In the pattern string, `*' matches any sequence of characters, `?' matches any character, [SET] matches any character in the specified set, [!SET] matches any character not in the specified set. A set is composed of characters or ranges; a range looks like character hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the set of characters allowed in C identifiers. Any other character in the pattern must be matched exactly. To suppress the special syntactic significance of any of `[]*?!-\', and match the character exactly, precede it with a `\'. */ int glob_match(char *pattern, char *text) { register char *p = pattern, *t = text; register char c; while ((c = *p++) != '\0') switch (c) { case '?': if (*t == '\0') return 0; else ++t; break; case '\\': if (*p++ != *t++) return 0; break; case '*': return glob_match_after_star(p, t); case '[': { register char c1 = *t++; int invert; if (!c1) return (0); invert = ((*p == '!') || (*p == '^')); if (invert) p++; c = *p++; while (1) { register char cstart = c, cend = c; if (c == '\\') { cstart = *p++; cend = cstart; } if (c == '\0') return 0; c = *p++; if (c == '-' && *p != ']') { cend = *p++; if (cend == '\\') cend = *p++; if (cend == '\0') return 0; c = *p++; } if (c1 >= cstart && c1 <= cend) goto match; if (c == ']') break; } if (!invert) return 0; break; match: /* Skip the rest of the [...] construct that already matched. */ while (c != ']') { if (c == '\0') return 0; c = *p++; if (c == '\0') return 0; else if (c == '\\') ++p; } if (invert) return 0; break; } default: if (c != *t++) return 0; } return *t == '\0'; }