| 14040 | |
| 14041 | |
| 14042 | static const char *match (MatchState *ms, const char *s, const char *p) { |
| 14043 | init: /* using goto's to optimize tail recursion */ |
| 14044 | switch (*p) { |
| 14045 | case '(': { /* start capture */ |
| 14046 | if (*(p+1) == ')') /* position capture? */ |
| 14047 | return start_capture(ms, s, p+2, CAP_POSITION); |
| 14048 | else |
| 14049 | return start_capture(ms, s, p+1, CAP_UNFINISHED); |
| 14050 | } |
| 14051 | case ')': { /* end capture */ |
| 14052 | return end_capture(ms, s, p+1); |
| 14053 | } |
| 14054 | case L_ESC: { |
| 14055 | switch (*(p+1)) { |
| 14056 | case 'b': { /* balanced string? */ |
| 14057 | s = matchbalance(ms, s, p+2); |
| 14058 | if (s == NULL) return NULL; |
| 14059 | p+=4; goto init; /* else return match(ms, s, p+4); */ |
| 14060 | } |
| 14061 | case 'f': { /* frontier? */ |
| 14062 | const char *ep; char previous; |
| 14063 | p += 2; |
| 14064 | if (*p != '[') |
| 14065 | luaL_error(ms->L, "missing " LUA_QL("[") " after " |
| 14066 | LUA_QL("%%f") " in pattern"); |
| 14067 | ep = classend(ms, p); /* points to what is next */ |
| 14068 | previous = (s == ms->src_init) ? '\0' : *(s-1); |
| 14069 | if (matchbracketclass(uchar(previous), p, ep-1) || |
| 14070 | !matchbracketclass(uchar(*s), p, ep-1)) return NULL; |
| 14071 | p=ep; goto init; /* else return match(ms, s, ep); */ |
| 14072 | } |
| 14073 | default: { |
| 14074 | if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ |
| 14075 | s = match_capture(ms, s, uchar(*(p+1))); |
| 14076 | if (s == NULL) return NULL; |
| 14077 | p+=2; goto init; /* else return match(ms, s, p+2) */ |
| 14078 | } |
| 14079 | goto dflt; /* case default */ |
| 14080 | } |
| 14081 | } |
| 14082 | } |
| 14083 | case '\0': { /* end of pattern */ |
| 14084 | return s; /* match succeeded */ |
| 14085 | } |
| 14086 | case '$': { |
| 14087 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ |
| 14088 | return (s == ms->src_end) ? s : NULL; /* check end of string */ |
| 14089 | else goto dflt; |
| 14090 | } |
| 14091 | default: dflt: { /* it is a pattern item */ |
| 14092 | const char *ep = classend(ms, p); /* points to what is next */ |
| 14093 | int m = s<ms->src_end && singlematch(uchar(*s), p, ep); |
| 14094 | switch (*ep) { |
| 14095 | case '?': { /* optional */ |
| 14096 | const char *res; |
| 14097 | if (m && ((res=match(ms, s+1, ep+1)) != NULL)) |
| 14098 | return res; |
| 14099 | p=ep+1; goto init; /* else return match(ms, s, ep+1); */ |
no test coverage detected