static int wsinglematch (lua_WChar c, const lua_WChar *p, const lua_WChar *ep) { switch (*p) { case '.': return 1; /* matches any char */ case WL_ESC: return wmatch_class(c, *(p+1)); case '[': return wmatchbracketclass(c, p, ep-1); default: return (*p == c); } }
static const lua_WChar *wmatch (WMatchState *ms, const lua_WChar *s, const lua_WChar *p) { init: /* using goto's to optimize tail recursion */ switch (*p) { case '(': { /* start capture */ if (*(p+1) == ')') /* position capture? */ return wstart_capture(ms, s, p+2, CAP_POSITION); else return wstart_capture(ms, s, p+1, CAP_UNFINISHED); } case ')': { /* end capture */ return wend_capture(ms, s, p+1); } case WL_ESC: { switch (*(p+1)) { case 'b': { /* balanced string? */ s = wmatchbalance(ms, s, p+2); if (s == NULL) return NULL; p+=4; goto init; /* else return wmatch(ms, s, p+4); */ } case 'f': { /* frontier? */ const lua_WChar *ep; lua_WChar previous; p += 2; if (*p != '[') luaL_error(ms->L, "missing " LUA_QL("[") " after " LUA_QL("%%f") " in pattern"); ep = wclassend(ms, p); /* points to what is next */ previous = (s == ms->src_init) ? '\0' : *(s-1); if (wmatchbracketclass(previous, p, ep-1) || !wmatchbracketclass(*s, p, ep-1)) return NULL; p=ep; goto init; /* else return wmatch(ms, s, ep); */ } default: { if (iswdigit(*(p+1))) { /* capture results (%0-%9)? */ s = wmatch_capture(ms, s, *(p+1)); if (s == NULL) return NULL; p+=2; goto init; /* else return wmatch(ms, s, p+2) */ } goto dflt; /* case default */ } } } case '\0': { /* end of pattern */ return s; /* wmatch succeeded */ } case '$': { if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ return (s == ms->src_end) ? s : NULL; /* check end of string */ else goto dflt; } default: dflt: { /* it is a pattern item */ const lua_WChar *ep = wclassend(ms, p); /* points to what is next */ int m = s<ms->src_end && wsinglematch(*s, p, ep); switch (*ep) { case '?': { /* optional */ const lua_WChar *res; if (m && ((res=wmatch(ms, s+1, ep+1)) != NULL)) return res; p=ep+1; goto init; /* else return wmatch(ms, s, ep+1); */ } case '*': { /* 0 or more repetitions */ return wmax_expand(ms, s, p, ep); } case '+': { /* 1 or more repetitions */ return (m ? wmax_expand(ms, s+1, p, ep) : NULL); } case '-': { /* 0 or more repetitions (minimum) */ return wmin_expand(ms, s, p, ep); } default: { if (!m) return NULL; s++; p=ep; goto init; /* else return wmatch(ms, s+1, ep); */ } } } } }