| 363 | |
| 364 | |
| 365 | static const char *match (MatchState *ms, const char *s, const char *p) { |
| 366 | init: /* using goto's to optimize tail recursion */ |
| 367 | switch (*p) { |
| 368 | case '(': { /* start capture */ |
| 369 | if (*(p+1) == ')') /* position capture? */ |
| 370 | return start_capture(ms, s, p+2, CAP_POSITION); |
| 371 | else |
| 372 | return start_capture(ms, s, p+1, CAP_UNFINISHED); |
| 373 | } |
| 374 | case ')': { /* end capture */ |
| 375 | return end_capture(ms, s, p+1); |
| 376 | } |
| 377 | case L_ESC: { |
| 378 | switch (*(p+1)) { |
| 379 | case 'b': { /* balanced string? */ |
| 380 | s = matchbalance(ms, s, p+2); |
| 381 | if (s == NULL) return NULL; |
| 382 | p+=4; goto init; /* else return match(ms, s, p+4); */ |
| 383 | } |
| 384 | case 'f': { /* frontier? */ |
| 385 | const char *ep; char previous; |
| 386 | p += 2; |
| 387 | if (*p != '[') |
| 388 | luaL_error(ms->L, "missing " LUA_QL("[") " after " |
| 389 | LUA_QL("%%f") " in pattern"); |
| 390 | ep = classend(ms, p); /* points to what is next */ |
| 391 | previous = (s == ms->src_init) ? '\0' : *(s-1); |
| 392 | if (matchbracketclass(uchar(previous), p, ep-1) || |
| 393 | !matchbracketclass(uchar(*s), p, ep-1)) return NULL; |
| 394 | p=ep; goto init; /* else return match(ms, s, ep); */ |
| 395 | } |
| 396 | default: { |
| 397 | if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ |
| 398 | s = match_capture(ms, s, uchar(*(p+1))); |
| 399 | if (s == NULL) return NULL; |
| 400 | p+=2; goto init; /* else return match(ms, s, p+2) */ |
| 401 | } |
| 402 | goto dflt; /* case default */ |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | case '\0': { /* end of pattern */ |
| 407 | return s; /* match succeeded */ |
| 408 | } |
| 409 | case '$': { |
| 410 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ |
| 411 | return (s == ms->src_end) ? s : NULL; /* check end of string */ |
| 412 | else goto dflt; |
| 413 | } |
| 414 | default: dflt: { /* it is a pattern item */ |
| 415 | const char *ep = classend(ms, p); /* points to what is next */ |
| 416 | int m = s<ms->src_end && singlematch(uchar(*s), p, ep); |
| 417 | switch (*ep) { |
| 418 | case '?': { /* optional */ |
| 419 | const char *res; |
| 420 | if (m && ((res=match(ms, s+1, ep+1)) != NULL)) |
| 421 | return res; |
| 422 | p=ep+1; goto init; /* else return match(ms, s, ep+1); */ |
no test coverage detected