| 570 | |
| 571 | |
| 572 | static const char *match (MatchState *ms, const char *s, const char *p) { |
| 573 | if (l_unlikely(ms->matchdepth-- == 0)) |
| 574 | luaL_error(ms->L, "pattern too complex"); |
| 575 | init: /* using goto to optimize tail recursion */ |
| 576 | if (p != ms->p_end) { /* end of pattern? */ |
| 577 | switch (*p) { |
| 578 | case '(': { /* start capture */ |
| 579 | if (*(p + 1) == ')') /* position capture? */ |
| 580 | s = start_capture(ms, s, p + 2, CAP_POSITION); |
| 581 | else |
| 582 | s = start_capture(ms, s, p + 1, CAP_UNFINISHED); |
| 583 | break; |
| 584 | } |
| 585 | case ')': { /* end capture */ |
| 586 | s = end_capture(ms, s, p + 1); |
| 587 | break; |
| 588 | } |
| 589 | case '$': { |
| 590 | if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ |
| 591 | goto dflt; /* no; go to default */ |
| 592 | s = (s == ms->src_end) ? s : NULL; /* check end of string */ |
| 593 | break; |
| 594 | } |
| 595 | case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ |
| 596 | switch (*(p + 1)) { |
| 597 | case 'b': { /* balanced string? */ |
| 598 | s = matchbalance(ms, s, p + 2); |
| 599 | if (s != NULL) { |
| 600 | p += 4; goto init; /* return match(ms, s, p + 4); */ |
| 601 | } /* else fail (s == NULL) */ |
| 602 | break; |
| 603 | } |
| 604 | case 'f': { /* frontier? */ |
| 605 | const char *ep; char previous; |
| 606 | p += 2; |
| 607 | if (l_unlikely(*p != '[')) |
| 608 | luaL_error(ms->L, "missing '[' after '%%f' in pattern"); |
| 609 | ep = classend(ms, p); /* points to what is next */ |
| 610 | previous = (s == ms->src_init) ? '\0' : *(s - 1); |
| 611 | if (!matchbracketclass(cast_uchar(previous), p, ep - 1) && |
| 612 | matchbracketclass(cast_uchar(*s), p, ep - 1)) { |
| 613 | p = ep; goto init; /* return match(ms, s, ep); */ |
| 614 | } |
| 615 | s = NULL; /* match failed */ |
| 616 | break; |
| 617 | } |
| 618 | case '0': case '1': case '2': case '3': |
| 619 | case '4': case '5': case '6': case '7': |
| 620 | case '8': case '9': { /* capture results (%0-%9)? */ |
| 621 | s = match_capture(ms, s, cast_uchar(*(p + 1))); |
| 622 | if (s != NULL) { |
| 623 | p += 2; goto init; /* return match(ms, s, p + 2) */ |
| 624 | } |
| 625 | break; |
| 626 | } |
| 627 | default: goto dflt; |
| 628 | } |
| 629 | break; |
no test coverage detected