X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fregex%2Ffnmatch.c;h=978fff884239b27b2256ee28a7bdf3bec022c310;hb=fe5e72ae782238038ba4eaa3e1889e7bd16fecec;hp=ffd3ea0d74fd27396e08ad2554b58b72ae7206bf;hpb=45b38550eec7de580d790440154791c67cae8475;p=musl diff --git a/src/regex/fnmatch.c b/src/regex/fnmatch.c index ffd3ea0d..978fff88 100644 --- a/src/regex/fnmatch.c +++ b/src/regex/fnmatch.c @@ -18,8 +18,9 @@ #include #include #include +#include "locale_impl.h" -#define END -1 +#define END 0 #define UNMATCHABLE -2 #define BRACKET -3 #define QUESTION -4 @@ -53,7 +54,7 @@ static int pat_next(const char *pat, size_t m, size_t *step, int flags) return END; } *step = 1; - if (pat[0]=='\\' && !(flags & FNM_NOESCAPE)) { + if (pat[0]=='\\' && pat[1] && !(flags & FNM_NOESCAPE)) { *step = 2; pat++; esc = 1; @@ -97,7 +98,13 @@ escaped: return pat[0]; } -static int match_bracket(const char *p, int k) +static int casefold(int k) +{ + int c = towupper(k); + return c == k ? towlower(k) : c; +} + +static int match_bracket(const char *p, int k, int kfold) { wchar_t wc; int inv = 0; @@ -119,7 +126,10 @@ static int match_bracket(const char *p, int k) wchar_t wc2; int l = mbtowc(&wc2, p+1, 4); if (l < 0) return 0; - if (wc<=wc2 && (unsigned)k-wc <= wc2-wc) return !inv; + if (wc <= wc2) + if ((unsigned)k-wc <= wc2-wc || + (unsigned)kfold-wc <= wc2-wc) + return !inv; p += l-1; continue; } @@ -132,7 +142,9 @@ static int match_bracket(const char *p, int k) char buf[16]; memcpy(buf, p0, p-1-p0); buf[p-1-p0] = 0; - if (iswctype(k, wctype(buf))) return !inv; + if (iswctype(k, wctype(buf)) || + iswctype(kfold, wctype(buf))) + return !inv; } continue; } @@ -143,7 +155,7 @@ static int match_bracket(const char *p, int k) if (l < 0) return 0; p += l-1; } - if (wc==k) return !inv; + if (wc==k || wc==kfold) return !inv; } return inv; } @@ -153,7 +165,7 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n const char *p, *ptail, *endpat; const char *s, *stail, *endstr; size_t pinc, sinc, tailcnt=0; - int c, k; + int c, k, kfold; if (flags & FNM_PERIOD) { if (*str == '.' && *pat != '.') @@ -173,10 +185,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n return (c==END) ? 0 : FNM_NOMATCH; str += sinc; n -= sinc; + kfold = flags & FNM_CASEFOLD ? casefold(k) : k; if (c == BRACKET) { - if (!match_bracket(pat, k)) + if (!match_bracket(pat, k, kfold)) return FNM_NOMATCH; - } else if (c != QUESTION && k != c) { + } else if (c != QUESTION && k != c && kfold != c) { return FNM_NOMATCH; } pat+=pinc; @@ -217,7 +230,7 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n * On illegal sequences we may get it wrong, but in that case * we necessarily have a matching failure anyway. */ for (s=endstr; s>str && tailcnt; tailcnt--) { - if (s[-1] < 128U) s--; + if (s[-1] < 128U || MB_CUR_MAX==1) s--; else while ((unsigned char)*--s-0x80U<0x40 && s>str); } if (tailcnt) return FNM_NOMATCH; @@ -233,10 +246,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n break; } s += sinc; + kfold = flags & FNM_CASEFOLD ? casefold(k) : k; if (c == BRACKET) { - if (!match_bracket(p-pinc, k)) + if (!match_bracket(p-pinc, k, kfold)) return FNM_NOMATCH; - } else if (c != QUESTION && k != c) { + } else if (c != QUESTION && k != c && kfold != c) { return FNM_NOMATCH; } } @@ -261,10 +275,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n k = str_next(s, endstr-s, &sinc); if (!k) return FNM_NOMATCH; + kfold = flags & FNM_CASEFOLD ? casefold(k) : k; if (c == BRACKET) { - if (!match_bracket(p-pinc, k)) + if (!match_bracket(p-pinc, k, kfold)) break; - } else if (c != QUESTION && k != c) { + } else if (c != QUESTION && k != c && kfold != c) { break; } s += sinc; @@ -288,12 +303,19 @@ int fnmatch(const char *pat, const char *str, int flags) if (flags & FNM_PATHNAME) for (;;) { for (s=str; *s && *s!='/'; s++); for (p=pat; (c=pat_next(p, -1, &inc, flags))!=END && c!='/'; p+=inc); - if (*s && *p!=*s) return FNM_NOMATCH; + if (c!=*s && (!*s || !(flags & FNM_LEADING_DIR))) + return FNM_NOMATCH; if (fnmatch_internal(pat, p-pat, str, s-str, flags)) return FNM_NOMATCH; - if (!*s && c==END) return 0; + if (!c) return 0; str = s+1; - pat = p+1; + pat = p+inc; + } else if (flags & FNM_LEADING_DIR) { + for (s=str; *s; s++) { + if (*s != '/') continue; + if (!fnmatch_internal(pat, -1, str, s-str, flags)) + return 0; + } } return fnmatch_internal(pat, -1, str, -1, flags); }