/* * pattern matching function for filenames. Each occurrence of the * * pattern causes a recursion level. */ static int match(const char *name, const Char *pat, const Char *patend, int m_not) { int ok, negate_range; Char c; while (pat < patend) { size_t lwk; __Char wc, wk; c = *pat; /* Only for M_MASK bits */ pat += One_Char_mbtowc(&wc, pat, MB_LEN_MAX); lwk = one_mbtowc(&wk, name, MB_LEN_MAX); switch (c & M_MASK) { case M_ALL: while (pat < patend && (*pat & M_MASK) == M_ALL) /* eat consecutive '*' */ pat += One_Char_mbtowc(&wc, pat, MB_LEN_MAX); if (pat == patend) return (1); while (!match(name, pat, patend, m_not)) { if (*name == EOS) return (0); name += lwk; lwk = one_mbtowc(&wk, name, MB_LEN_MAX); } return (1); case M_ONE: if (*name == EOS) return (0); name += lwk; break; case M_SET: ok = 0; if (*name == EOS) return (0); name += lwk; if ((negate_range = ((*pat & M_MASK) == m_not)) != 0) ++pat; while ((*pat & M_MASK) != M_END) { pat += One_Char_mbtowc(&wc, pat, MB_LEN_MAX); if ((*pat & M_MASK) == M_RNG) { __Char wc2; pat++; pat += One_Char_mbtowc(&wc2, pat, MB_LEN_MAX); if (globcharcoll(wc, wk, 0) <= 0 && globcharcoll(wk, wc2, 0) <= 0) ok = 1; } else if (wc == wk) ok = 1; } pat += One_Char_mbtowc(&wc, pat, MB_LEN_MAX); if (ok == negate_range) return (0); break; default: if (*name == EOS || samecase(wk) != samecase(wc)) return (0); name += lwk; break; } } return (*name == EOS); }
/* t_pmatch(): * Return 2 on exact match, * Return 1 on substring match. * Return 0 on no match. * *estr will point to the end of the longest exact or substring match. */ int t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs) { Char stringc, patternc, rangec; int match, negate_range; const Char *pestr, *nstring; for (nstring = string;; string = nstring) { stringc = *nstring++ & TRIM; patternc = *pattern++ & TRIM; switch (patternc) { case '\0': *estr = string; return (stringc == '\0' ? 2 : 1); case '?': if (stringc == 0) return (0); break; case '*': if (!*pattern) { *estr = Strend(string); return (2); } pestr = NULL; for (;;) { switch(t_pmatch(string, pattern, estr, cs)) { case 0: break; case 1: pestr = *estr;/*FIXME: does not guarantee longest match */ break; case 2: return 2; default: abort(); /* Cannot happen */ } stringc = *string++ & TRIM; if (!stringc) break; } if (pestr) { *estr = pestr; return 1; } else return 0; case '[': match = 0; if ((negate_range = (*pattern == '^')) != 0) pattern++; while ((rangec = *pattern++ & TRIM) != '\0') { if (rangec == ']') break; if (match) continue; if (*pattern == '-' && pattern[1] != ']') { Char rangec2; pattern++; rangec2 = *pattern++ & TRIM; match = (globcharcoll(stringc, rangec2, 0) <= 0 && globcharcoll(rangec, stringc, 0) <= 0); } else match = (stringc == rangec); } if (rangec == '\0') stderror(ERR_NAME | ERR_MISSING, ']'); if ((!match) && (stringc == '\0')) return (0); if (match == negate_range) return (0); break; default: if (cs ? patternc != stringc : Tolower(patternc) != Tolower(stringc)) return (0); break; } } }