/* rangematch -- match a character against a character class */ static int rangematch(const char *p, const char *q, char c) { const char *orig = p; Boolean neg; Boolean matched = FALSE; if (*p == '~' && !ISQUOTED(q, 0)) { p++, q++; neg = TRUE; } else neg = FALSE; if (*p == ']' && !ISQUOTED(q, 0)) { p++, q++; matched = (c == ']'); } for (; *p != ']' || ISQUOTED(q, 0); p++, q++) { if (*p == '\0') return RANGE_ERROR; /* bad syntax */ if (p[1] == '-' && !ISQUOTED(q, 1) && ((p[2] != ']' && p[2] != '\0') || ISQUOTED(q, 2))) { /* check for [..-..] but ignore [..-] */ if (c >= *p && c <= p[2]) matched = TRUE; p += 2; q += 2; } else if (*p == c) matched = TRUE; } if (matched ^ neg) return p - orig + 1; /* skip the right-bracket */ else return RANGE_FAIL; }
static List *extractsinglematch(const char *subject, const char *pattern, const char *quoting, List *result) { int i; const char *s; if (!haswild(pattern, quoting) /* no wildcards, so no matches */ || !match(subject, pattern, quoting)) return NULL; for (s = subject, i = 0; pattern[i] != '\0'; s++) { if (ISQUOTED(quoting, i)) i++; else { int c = pattern[i++]; switch (c) { case '*': { const char *begin; if (pattern[i] == '\0') return mklist(mkstr(gcdup(s)), result); for (begin = s;; s++) { const char *q = TAILQUOTE(quoting, i); assert(*s != '\0'); if (match(s, pattern + i, q)) { result = mklist(mkstr(gcndup(begin, s - begin)), result); return haswild(pattern + i, q) ? extractsinglematch(s, pattern + i, q, result) : result; } } } case '[': { int j = rangematch(pattern + i, TAILQUOTE(quoting, i), *s); assert(j != RANGE_FAIL); if (j == RANGE_ERROR) { assert(*s == '['); break; } i += j; } /* FALLTHROUGH */ case '?': result = mklist(mkstr(str("%c", *s)), result); break; default: break; } } } return result; }