X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/893ef8be9f45dd692c68d41339f2da7a26431833..a74ff37d56a36f313c3eec2c8f99167b0c7a28d9:/regexec.c diff --git a/regexec.c b/regexec.c index 6386d41..432764b 100644 --- a/regexec.c +++ b/regexec.c @@ -288,7 +288,6 @@ static regmatch_state * S_push_slab(pTHX); STATIC CHECKPOINT S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen) { - dVAR; const int retval = PL_savestack_ix; const int paren_elems_to_push = (maxopenparen - parenfloor) * REGCP_PAREN_ELEMS; @@ -300,8 +299,9 @@ S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen) PERL_ARGS_ASSERT_REGCPPUSH; if (paren_elems_to_push < 0) - Perl_croak(aTHX_ "panic: paren_elems_to_push, %i < 0, maxopenparen: %i parenfloor: %i REGCP_PAREN_ELEMS: %i", - paren_elems_to_push, maxopenparen, parenfloor, REGCP_PAREN_ELEMS); + Perl_croak(aTHX_ "panic: paren_elems_to_push, %i < 0, maxopenparen: %i parenfloor: %i REGCP_PAREN_ELEMS: %u", + (int)paren_elems_to_push, (int)maxopenparen, + (int)parenfloor, (unsigned)REGCP_PAREN_ELEMS); if ((elems_shifted >> SAVE_TIGHT_SHIFT) != total_elems) Perl_croak(aTHX_ "panic: paren_elems_to_push offset %"UVuf @@ -368,7 +368,6 @@ S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen) STATIC void S_regcppop(pTHX_ regexp *rex, U32 *maxopenparen_p) { - dVAR; UV i; U32 paren; GET_RE_DEBUG_FLAGS_DECL; @@ -541,7 +540,11 @@ S_isFOO_utf8_lc(pTHX_ const U8 classnum, const U8* character) below 256 */ } - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + /* Some compilers/linters detect that this spot cannot be reached + * (because all code paths above already did return), while some + * others throw a fit unless we have a return at the end. */ + assert(0); return FALSE; } @@ -648,7 +651,6 @@ Perl_re_intuit_start(pTHX_ const U32 flags, re_scream_pos_data *data) { - dVAR; struct regexp *const prog = ReANY(rx); SSize_t start_shift = prog->check_offset_min; /* Should be nonnegative! */ @@ -1504,10 +1506,14 @@ STMT_START { } \ } STMT_END -#define REXEC_FBC_EXACTISH_SCAN(CoNd) \ +#define DUMP_EXEC_POS(li,s,doutf8) \ + dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \ + startpos, doutf8) + +#define REXEC_FBC_EXACTISH_SCAN(COND) \ STMT_START { \ while (s <= e) { \ - if ( (CoNd) \ + if ( (COND) \ && (ln == 1 || folder(s, pat_string, ln)) \ && (reginfo->intuit || regtry(reginfo, &s)) )\ goto got_it; \ @@ -1515,148 +1521,199 @@ STMT_START { \ } \ } STMT_END -#define REXEC_FBC_UTF8_SCAN(CoDe) \ +#define REXEC_FBC_UTF8_SCAN(CODE) \ STMT_START { \ while (s < strend) { \ - CoDe \ + CODE \ s += UTF8SKIP(s); \ } \ } STMT_END -#define REXEC_FBC_SCAN(CoDe) \ +#define REXEC_FBC_SCAN(CODE) \ STMT_START { \ while (s < strend) { \ - CoDe \ + CODE \ s++; \ } \ } STMT_END -#define REXEC_FBC_UTF8_CLASS_SCAN(CoNd) \ -REXEC_FBC_UTF8_SCAN( \ - if (CoNd) { \ - if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \ - goto got_it; \ - else \ - tmp = doevery; \ - } \ - else \ - tmp = 1; \ +#define REXEC_FBC_UTF8_CLASS_SCAN(COND) \ +REXEC_FBC_UTF8_SCAN( /* Loops while (s < strend) */ \ + if (COND) { \ + if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \ + goto got_it; \ + else \ + tmp = doevery; \ + } \ + else \ + tmp = 1; \ ) -#define REXEC_FBC_CLASS_SCAN(CoNd) \ -REXEC_FBC_SCAN( \ - if (CoNd) { \ - if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \ - goto got_it; \ - else \ - tmp = doevery; \ - } \ - else \ - tmp = 1; \ +#define REXEC_FBC_CLASS_SCAN(COND) \ +REXEC_FBC_SCAN( /* Loops while (s < strend) */ \ + if (COND) { \ + if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \ + goto got_it; \ + else \ + tmp = doevery; \ + } \ + else \ + tmp = 1; \ ) -#define REXEC_FBC_TRYIT \ -if ((reginfo->intuit || regtry(reginfo, &s))) \ - goto got_it - -#define REXEC_FBC_CSCAN(CoNdUtF8,CoNd) \ +#define REXEC_FBC_CSCAN(CONDUTF8,COND) \ if (utf8_target) { \ - REXEC_FBC_UTF8_CLASS_SCAN(CoNdUtF8); \ + REXEC_FBC_UTF8_CLASS_SCAN(CONDUTF8); \ } \ else { \ - REXEC_FBC_CLASS_SCAN(CoNd); \ + REXEC_FBC_CLASS_SCAN(COND); \ } - -#define DUMP_EXEC_POS(li,s,doutf8) \ - dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \ - startpos, doutf8) - -#define UTF8_NOLOAD(TEST_NON_UTF8, IF_SUCCESS, IF_FAIL) \ - tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n'; \ - tmp = TEST_NON_UTF8(tmp); \ - REXEC_FBC_UTF8_SCAN( \ - if (tmp == ! TEST_NON_UTF8((U8) *s)) { \ - tmp = !tmp; \ - IF_SUCCESS; \ - } \ - else { \ - IF_FAIL; \ - } \ - ); \ - -#define UTF8_LOAD(TeSt1_UtF8, TeSt2_UtF8, IF_SUCCESS, IF_FAIL) \ - if (s == reginfo->strbeg) { \ - tmp = '\n'; \ - } \ - else { \ - U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg); \ - tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r, \ +/* The three macros below are slightly different versions of the same logic. + * + * The first is for /a and /aa when the target string is UTF-8. This can only + * match ascii, but it must advance based on UTF-8. The other two handle the + * non-UTF-8 and the more generic UTF-8 cases. In all three, we are looking + * for the boundary (or non-boundary) between a word and non-word character. + * The utf8 and non-utf8 cases have the same logic, but the details must be + * different. Find the "wordness" of the character just prior to this one, and + * compare it with the wordness of this one. If they differ, we have a + * boundary. At the beginning of the string, pretend that the previous + * character was a new-line. + * + * All these macros uncleanly have side-effects with each other and outside + * variables. So far it's been too much trouble to clean-up + * + * TEST_NON_UTF8 is the macro or function to call to test if its byte input is + * a word character or not. + * IF_SUCCESS is code to do if it finds that we are at a boundary between + * word/non-word + * IF_FAIL is code to do if we aren't at a boundary between word/non-word + * + * Exactly one of the two IF_FOO parameters is a no-op, depending on whether we + * are looking for a boundary or for a non-boundary. If we are looking for a + * boundary, we want IF_FAIL to be the no-op, and for IF_SUCCESS to go out and + * see if this tentative match actually works, and if so, to quit the loop + * here. And vice-versa if we are looking for a non-boundary. + * + * 'tmp' below in the next three macros in the REXEC_FBC_SCAN and + * REXEC_FBC_UTF8_SCAN loops is a loop invariant, a bool giving the return of + * TEST_NON_UTF8(s-1). To see this, note that that's what it is defined to be + * at entry to the loop, and to get to the IF_FAIL branch, tmp must equal + * TEST_NON_UTF8(s), and in the opposite branch, IF_SUCCESS, tmp is that + * complement. But in that branch we complement tmp, meaning that at the + * bottom of the loop tmp is always going to be equal to TEST_NON_UTF8(s), + * which means at the top of the loop in the next iteration, it is + * TEST_NON_UTF8(s-1) */ +#define FBC_UTF8_A(TEST_NON_UTF8, IF_SUCCESS, IF_FAIL) \ + tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n'; \ + tmp = TEST_NON_UTF8(tmp); \ + REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */ \ + if (tmp == ! TEST_NON_UTF8((U8) *s)) { \ + tmp = !tmp; \ + IF_SUCCESS; /* Is a boundary if values for s-1 and s differ */ \ + } \ + else { \ + IF_FAIL; \ + } \ + ); \ + +/* Like FBC_UTF8_A, but TEST_UV is a macro which takes a UV as its input, and + * TEST_UTF8 is a macro that for the same input code points returns identically + * to TEST_UV, but takes a pointer to a UTF-8 encoded string instead */ +#define FBC_UTF8(TEST_UV, TEST_UTF8, IF_SUCCESS, IF_FAIL) \ + if (s == reginfo->strbeg) { \ + tmp = '\n'; \ + } \ + else { /* Back-up to the start of the previous character */ \ + U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg); \ + tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r, \ 0, UTF8_ALLOW_DEFAULT); \ - } \ - tmp = TeSt1_UtF8; \ - LOAD_UTF8_CHARCLASS_ALNUM(); \ - REXEC_FBC_UTF8_SCAN( \ - if (tmp == ! (TeSt2_UtF8)) { \ - tmp = !tmp; \ - IF_SUCCESS; \ - } \ - else { \ - IF_FAIL; \ - } \ - ); \ + } \ + tmp = TEST_UV(tmp); \ + LOAD_UTF8_CHARCLASS_ALNUM(); \ + REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */ \ + if (tmp == ! (TEST_UTF8((U8 *) s))) { \ + tmp = !tmp; \ + IF_SUCCESS; \ + } \ + else { \ + IF_FAIL; \ + } \ + ); -/* The only difference between the BOUND and NBOUND cases is that - * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in - * NBOUND. This is accomplished by passing it in either the if or else clause, - * with the other one being empty */ -#define FBC_BOUND(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \ - FBC_BOUND_COMMON(UTF8_LOAD(TEST1_UTF8, TEST2_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER) - -#define FBC_BOUND_NOLOAD(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \ - FBC_BOUND_COMMON(UTF8_NOLOAD(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER) - -#define FBC_NBOUND(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \ - FBC_BOUND_COMMON(UTF8_LOAD(TEST1_UTF8, TEST2_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT) - -#define FBC_NBOUND_NOLOAD(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \ - FBC_BOUND_COMMON(UTF8_NOLOAD(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT) - - -/* Common to the BOUND and NBOUND cases. Unfortunately the UTF8 tests need to - * be passed in completely with the variable name being tested, which isn't - * such a clean interface, but this is easier to read than it was before. We - * are looking for the boundary (or non-boundary between a word and non-word - * character. The utf8 and non-utf8 cases have the same logic, but the details - * must be different. Find the "wordness" of the character just prior to this - * one, and compare it with the wordness of this one. If they differ, we have - * a boundary. At the beginning of the string, pretend that the previous - * character was a new-line */ +/* Like the above two macros. UTF8_CODE is the complete code for handling + * UTF-8. Common to the BOUND and NBOUND cases, set-up by the FBC_BOUND, etc + * macros below */ #define FBC_BOUND_COMMON(UTF8_CODE, TEST_NON_UTF8, IF_SUCCESS, IF_FAIL) \ if (utf8_target) { \ - UTF8_CODE \ + UTF8_CODE \ } \ else { /* Not utf8 */ \ tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n'; \ tmp = TEST_NON_UTF8(tmp); \ - REXEC_FBC_SCAN( \ + REXEC_FBC_SCAN( /* advances s while s < strend */ \ if (tmp == ! TEST_NON_UTF8((U8) *s)) { \ - tmp = !tmp; \ IF_SUCCESS; \ + tmp = !tmp; \ } \ else { \ IF_FAIL; \ } \ ); \ } \ - if ((!prog->minlen && tmp) && (reginfo->intuit || regtry(reginfo, &s))) \ - goto got_it; + /* Here, things have been set up by the previous code so that tmp is the \ + * return of TEST_NON_UTF(s-1) or TEST_UTF8(s-1) (depending on the \ + * utf8ness of the target). We also have to check if this matches against \ + * the EOS, which we treat as a \n (which is the same value in both UTF-8 \ + * or non-UTF8, so can use the non-utf8 test condition even for a UTF-8 \ + * string */ \ + if (tmp == ! TEST_NON_UTF8('\n')) { \ + IF_SUCCESS; \ + } \ + else { \ + IF_FAIL; \ + } + +/* This is the macro to use when we want to see if something that looks like it + * could match, actually does, and if so exits the loop */ +#define REXEC_FBC_TRYIT \ + if ((reginfo->intuit || regtry(reginfo, &s))) \ + goto got_it + +/* The only difference between the BOUND and NBOUND cases is that + * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in + * NBOUND. This is accomplished by passing it as either the if or else clause, + * with the other one being empty (PLACEHOLDER is defined as empty). + * + * The TEST_FOO parameters are for operating on different forms of input, but + * all should be ones that return identically for the same underlying code + * points */ +#define FBC_BOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \ + FBC_BOUND_COMMON( \ + FBC_UTF8(TEST_UV, TEST_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), \ + TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER) + +#define FBC_BOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \ + FBC_BOUND_COMMON( \ + FBC_UTF8_A(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), \ + TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER) + +#define FBC_NBOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \ + FBC_BOUND_COMMON( \ + FBC_UTF8(TEST_UV, TEST_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), \ + TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT) + +#define FBC_NBOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \ + FBC_BOUND_COMMON( \ + FBC_UTF8_A(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), \ + TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT) + /* We know what class REx starts with. Try to find this position... */ /* if reginfo->intuit, its a dryrun */ /* annoyingly all the vars in this routine have different names from their counterparts in regmatch. /grrr */ - STATIC char * S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *strend, regmatch_info *reginfo) @@ -1845,45 +1902,30 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, } break; } + case BOUNDL: - FBC_BOUND(isWORDCHAR_LC, - isWORDCHAR_LC_uvchr(tmp), - isWORDCHAR_LC_utf8((U8*)s)); + FBC_BOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8); break; case NBOUNDL: - FBC_NBOUND(isWORDCHAR_LC, - isWORDCHAR_LC_uvchr(tmp), - isWORDCHAR_LC_utf8((U8*)s)); + FBC_NBOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8); break; case BOUND: - FBC_BOUND(isWORDCHAR, - isWORDCHAR_uni(tmp), - cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target))); + FBC_BOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8); break; case BOUNDA: - FBC_BOUND_NOLOAD(isWORDCHAR_A, - isWORDCHAR_A(tmp), - isWORDCHAR_A((U8*)s)); + FBC_BOUND_A(isWORDCHAR_A, isWORDCHAR_A, isWORDCHAR_A); break; case NBOUND: - FBC_NBOUND(isWORDCHAR, - isWORDCHAR_uni(tmp), - cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target))); + FBC_NBOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8); break; case NBOUNDA: - FBC_NBOUND_NOLOAD(isWORDCHAR_A, - isWORDCHAR_A(tmp), - isWORDCHAR_A((U8*)s)); + FBC_NBOUND_A(isWORDCHAR_A, isWORDCHAR_A, isWORDCHAR_A); break; case BOUNDU: - FBC_BOUND(isWORDCHAR_L1, - isWORDCHAR_uni(tmp), - cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target))); + FBC_BOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8); break; case NBOUNDU: - FBC_NBOUND(isWORDCHAR_L1, - isWORDCHAR_uni(tmp), - cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target))); + FBC_NBOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8); break; case LNBREAK: REXEC_FBC_CSCAN(is_LNBREAK_utf8_safe(s, strend), @@ -2258,7 +2300,6 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, break; default: Perl_croak(aTHX_ "panic: unknown regstclass %d", (int)OP(c)); - break; } return 0; got_it: @@ -2433,7 +2474,6 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend, /* flags: For optimizations. See REXEC_* in regexp.h */ { - dVAR; struct regexp *const prog = ReANY(rx); char *s; regnode *c; @@ -2455,7 +2495,6 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend, /* Be paranoid... */ if (prog == NULL || stringarg == NULL) { Perl_croak(aTHX_ "NULL regexp parameter"); - return 0; } DEBUG_EXECUTE_r( @@ -3155,7 +3194,6 @@ phooey: STATIC I32 /* 0 failure, 1 success */ S_regtry(pTHX_ regmatch_info *reginfo, char **startposp) { - dVAR; CHECKPOINT lastcp; REGEXP *const rx = reginfo->prog; regexp *const prog = ReANY(rx); @@ -3526,7 +3564,7 @@ S_dump_exec_pos(pTHX_ const char *locinput, * or 0 if non of the buffers matched. */ STATIC I32 -S_reg_check_named_buff_matched(pTHX_ const regexp *rex, const regnode *scan) +S_reg_check_named_buff_matched(const regexp *rex, const regnode *scan) { I32 n; RXi_GET_DECL(rex,rexi); @@ -3602,8 +3640,8 @@ S_setup_EXACTISH_ST_c1_c2(pTHX_ const regnode * const text_node, int *c1p, const bool utf8_target = reginfo->is_utf8_target; - UV c1 = CHRTEST_NOT_A_CP_1; - UV c2 = CHRTEST_NOT_A_CP_2; + UV c1 = (UV)CHRTEST_NOT_A_CP_1; + UV c2 = (UV)CHRTEST_NOT_A_CP_2; bool use_chrtest_void = FALSE; const bool is_utf8_pat = reginfo->is_utf8_pat; @@ -4005,12 +4043,15 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) st->u.keeper.val = rex->offs[0].start; rex->offs[0].start = locinput - reginfo->strbeg; PUSH_STATE_GOTO(KEEPS_next, next, locinput); - assert(0); /*NOTREACHED*/ + /* NOTREACHED */ + assert(0); + case KEEPS_next_fail: /* rollback the start point change */ rex->offs[0].start = st->u.keeper.val; sayNO_SILENT; - assert(0); /*NOTREACHED*/ + /* NOTREACHED */ + assert(0); case MEOL: /* /..$/m */ if (!NEXTCHR_IS_EOS && nextchr != '\n') @@ -4061,7 +4102,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) REPORT_CODE_OFF+depth*2, "", PL_colors[4], PL_colors[5]) ); sayNO_SILENT; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } /* FALLTHROUGH */ case TRIE: /* (ab|cd) */ @@ -4248,7 +4290,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) ); goto trie_first_try; /* jump into the fail handler */ }} - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case TRIE_next_fail: /* we failed - try next alternative */ { @@ -4362,7 +4405,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) if (ST.accepted > 1 || has_cutgroup) { PUSH_STATE_GOTO(TRIE_next, scan, (char*)uc); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } /* only one choice left - just continue */ DEBUG_EXECUTE_r({ @@ -4386,7 +4430,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) locinput = (char*)uc; continue; /* execute rest of RE */ - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } #undef ST @@ -4618,7 +4663,6 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) break; default: Perl_croak(aTHX_ "panic: Unexpected FLAGS %u in op %u", FLAGS(scan), OP(scan)); - break; } } /* Note requires that all BOUNDs be lower than all NBOUNDs in @@ -5196,7 +5240,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) /* and then jump to the code we share with EVAL */ goto eval_recurse_doit; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case EVAL: /* /(?{A})B/ /(??{A})B/ and /(?(?{A})X|Y)B/ */ if (cur_eval && cur_eval->locinput==locinput) { @@ -5285,7 +5330,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) assert(o->op_targ == OP_LEAVE); o = cUNOPo->op_first; assert(o->op_type == OP_ENTER); - o = o->op_sibling; + o = OP_SIBLING(o); } if (o->op_type != OP_STUB) { @@ -5477,7 +5522,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) cur_eval = st; /* now continue from first node in postoned RE */ PUSH_YES_STATE_GOTO(EVAL_AB, startpoint, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } case EVAL_AB: /* cleanup after a successful (??{A})B */ @@ -5586,7 +5632,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog) } } goto fake_end; - /*NOTREACHED*/ + /* NOTREACHED */ case GROUPP: /* (?(1)) */ n = ARG(scan); /* which paren pair */ @@ -5736,19 +5782,22 @@ NULL ST.lastloc = NULL; /* this will be updated by WHILEM */ PUSH_YES_STATE_GOTO(CURLYX_end, PREVOPER(next), locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } case CURLYX_end: /* just finished matching all of A*B */ cur_curlyx = ST.prev_curlyx; sayYES; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case CURLYX_end_fail: /* just failed to match all of A*B */ regcpblow(ST.cp); cur_curlyx = ST.prev_curlyx; sayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); #undef ST @@ -5758,11 +5807,14 @@ NULL { /* see the discussion above about CURLYX/WHILEM */ I32 n; - int min = ARG1(cur_curlyx->u.curlyx.me); - int max = ARG2(cur_curlyx->u.curlyx.me); - regnode *A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS; + int min, max; + regnode *A; assert(cur_curlyx); /* keep Coverity happy */ + + min = ARG1(cur_curlyx->u.curlyx.me); + max = ARG2(cur_curlyx->u.curlyx.me); + A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS; n = ++cur_curlyx->u.curlyx.count; /* how many A's matched */ ST.save_lastloc = cur_curlyx->u.curlyx.lastloc; ST.cache_offset = 0; @@ -5783,7 +5835,8 @@ NULL REGCP_SET(ST.lastcp); PUSH_STATE_GOTO(WHILEM_A_pre, A, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } /* If degenerate A matches "", assume A done. */ @@ -5895,7 +5948,8 @@ NULL REGCP_SET(ST.lastcp); PUSH_YES_STATE_GOTO(WHILEM_B_min, ST.save_curlyx->u.curlyx.B, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } /* Prefer A over B for maximal matching. */ @@ -5906,24 +5960,28 @@ NULL cur_curlyx->u.curlyx.lastloc = locinput; REGCP_SET(ST.lastcp); PUSH_STATE_GOTO(WHILEM_A_max, A, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } goto do_whilem_B_max; } - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case WHILEM_B_min: /* just matched B in a minimal match */ case WHILEM_B_max: /* just matched B in a maximal match */ cur_curlyx = ST.save_curlyx; sayYES; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case WHILEM_B_max_fail: /* just failed to match B in a maximal match */ cur_curlyx = ST.save_curlyx; cur_curlyx->u.curlyx.lastloc = ST.save_lastloc; cur_curlyx->u.curlyx.count--; CACHEsayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case WHILEM_A_min_fail: /* just failed to match A in a minimal match */ /* FALLTHROUGH */ @@ -5933,7 +5991,8 @@ NULL cur_curlyx->u.curlyx.lastloc = ST.save_lastloc; cur_curlyx->u.curlyx.count--; CACHEsayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case WHILEM_A_max_fail: /* just failed to match A in a maximal match */ REGCP_UNWIND(ST.lastcp); @@ -5959,7 +6018,8 @@ NULL cur_curlyx = cur_curlyx->u.curlyx.prev_curlyx; PUSH_YES_STATE_GOTO(WHILEM_B_max, ST.save_curlyx->u.curlyx.B, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case WHILEM_B_min_fail: /* just failed to match B in a minimal match */ cur_curlyx = ST.save_curlyx; @@ -5993,7 +6053,8 @@ NULL PUSH_STATE_GOTO(WHILEM_A_min, /*A*/ NEXTOPER(ST.save_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); #undef ST #define ST st->u.branch @@ -6018,13 +6079,15 @@ NULL } else { PUSH_STATE_GOTO(BRANCH_next, scan, locinput); } - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case CUTGROUP: /* /(*THEN)/ */ sv_yes_mark = st->u.mark.mark_name = scan->flags ? NULL : MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); PUSH_STATE_GOTO(CUTGROUP_next, next, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case CUTGROUP_next_fail: do_cutgroup = 1; @@ -6032,11 +6095,13 @@ NULL if (st->u.mark.mark_name) sv_commit = st->u.mark.mark_name; sayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case BRANCH_next: sayYES; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case BRANCH_next_fail: /* that branch failed; try the next, if any */ if (do_cutgroup) { @@ -6058,7 +6123,8 @@ NULL sayNO_SILENT; } continue; /* execute next BRANCH[J] op */ - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case MINMOD: /* next op will be non-greedy, e.g. A*? */ minmod = 1; @@ -6102,7 +6168,8 @@ NULL curlym_do_A: /* execute the A in /A{m,n}B/ */ PUSH_YES_STATE_GOTO(CURLYM_A, ST.A, locinput); /* match A */ - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case CURLYM_A: /* we've just matched an A */ ST.count++; @@ -6152,6 +6219,7 @@ NULL /* calculate c1 and c2 for possible match of 1st char * following curly */ ST.c1 = ST.c2 = CHRTEST_VOID; + assert(ST.B); if (HAS_TEXT(ST.B) || JUMPABLE(ST.B)) { regnode *text_node = ST.B; if (! HAS_TEXT(text_node)) @@ -6237,7 +6305,8 @@ NULL } PUSH_STATE_GOTO(CURLYM_B, ST.B, locinput); /* match B */ - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case CURLYM_B_fail: /* just failed to match a B */ REGCP_UNWIND(ST.cp); @@ -6415,8 +6484,8 @@ NULL REGCP_SET(ST.cp); goto curly_try_B_max; } - assert(0); /* NOTREACHED */ - + /* NOTREACHED */ + assert(0); case CURLY_B_min_known_fail: /* failed to find B in a non-greedy match where c1,c2 valid */ @@ -6491,8 +6560,8 @@ NULL } PUSH_STATE_GOTO(CURLY_B_min_known, ST.B, locinput); } - assert(0); /* NOTREACHED */ - + /* NOTREACHED */ + assert(0); case CURLY_B_min_fail: /* failed to find B in a non-greedy match where c1,c2 invalid */ @@ -6524,8 +6593,8 @@ NULL } } sayNO; - assert(0); /* NOTREACHED */ - + /* NOTREACHED */ + assert(0); curly_try_B_max: /* a successful greedy match: now try to match B */ @@ -6555,7 +6624,8 @@ NULL if (ST.c1 == CHRTEST_VOID || could_match) { CURLY_SETPAREN(ST.paren, ST.count); PUSH_STATE_GOTO(CURLY_B_max, ST.B, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } } /* FALLTHROUGH */ @@ -6674,7 +6744,8 @@ NULL /* execute body of (?...A) */ PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan)), newstart); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } case IFMATCH_A_fail: /* body of (?...A) failed */ @@ -6714,7 +6785,8 @@ NULL if (!scan->flags) sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); PUSH_STATE_GOTO(COMMIT_next, next, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case COMMIT_next_fail: no_final = 1; @@ -6722,7 +6794,8 @@ NULL case OPFAIL: /* (*FAIL) */ sayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); #define ST st->u.mark case MARKPOINT: /* (*MARK:foo) */ @@ -6732,12 +6805,14 @@ NULL mark_state = st; ST.mark_loc = locinput; PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case MARKPOINT_next: mark_state = ST.prev_mark; sayYES; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case MARKPOINT_next_fail: if (popmark && sv_eq(ST.mark_name,popmark)) @@ -6758,7 +6833,8 @@ NULL sv_yes_mark = mark_state ? mark_state->u.mark.mark_name : NULL; sayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); case SKIP: /* (*SKIP) */ if (scan->flags) { @@ -6803,7 +6879,8 @@ NULL } no_final = 1; sayNO; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); #undef ST case LNBREAK: /* \R */ @@ -6837,7 +6914,8 @@ NULL /* switch break jumps here */ scan = next; /* prepare to execute the next op and ... */ continue; /* ... jump back to the top, reusing st */ - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); push_yes_state: /* push a state that backtracks on success */ @@ -6880,7 +6958,8 @@ NULL locinput = pushinput; st = newst; continue; - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } } @@ -6889,7 +6968,7 @@ NULL * the terminating point. */ Perl_croak(aTHX_ "corrupted regexp pointers"); - /*NOTREACHED*/ + /* NOTREACHED */ sayNO; yes: @@ -7037,7 +7116,6 @@ STATIC I32 S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p, regmatch_info *const reginfo, I32 max, int depth) { - dVAR; char *scan; /* Pointer to current position in target string */ I32 c; char *loceol = reginfo->strend; /* local version */ @@ -7517,7 +7595,8 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p, default: Perl_croak(aTHX_ "panic: regrepeat() called with unrecognized node type %d='%s'", OP(p), PL_reg_name[OP(p)]); - assert(0); /* NOTREACHED */ + /* NOTREACHED */ + assert(0); } @@ -7578,7 +7657,6 @@ Perl__get_regclass_nonbitmap_data(pTHX_ const regexp *prog, * swash are returned (in a printable form). * Tied intimately to how regcomp.c sets up the data structure */ - dVAR; SV *sw = NULL; SV *si = NULL; /* Input swash initialization string */ SV* invlist = NULL; @@ -7650,7 +7728,7 @@ Perl__get_regclass_nonbitmap_data(pTHX_ const regexp *prog, /* If requested, return a printable version of what this swash matches */ if (listsvp) { - SV* matches_string = newSVpvn("", 0); + SV* matches_string = newSVpvs(""); /* The swash should be used, if possible, to get the data, as it * contains the resolved data. But this function can be called at @@ -7841,8 +7919,6 @@ S_reghop3(U8 *s, SSize_t off, const U8* lim) * 'off' >= 0, backwards if negative. But don't go outside of position * 'lim', which better be < s if off < 0 */ - dVAR; - PERL_ARGS_ASSERT_REGHOP3; if (off >= 0) { @@ -7867,8 +7943,6 @@ S_reghop3(U8 *s, SSize_t off, const U8* lim) STATIC U8 * S_reghop4(U8 *s, SSize_t off, const U8* llim, const U8* rlim) { - dVAR; - PERL_ARGS_ASSERT_REGHOP4; if (off >= 0) { @@ -7896,8 +7970,6 @@ S_reghop4(U8 *s, SSize_t off, const U8* llim, const U8* rlim) STATIC U8 * S_reghopmaybe3(U8* s, SSize_t off, const U8* lim) { - dVAR; - PERL_ARGS_ASSERT_REGHOPMAYBE3; if (off >= 0) { @@ -8014,7 +8086,6 @@ S_setup_eval_state(pTHX_ regmatch_info *const reginfo) static void S_cleanup_regmatch_info_aux(pTHX_ void *arg) { - dVAR; regmatch_info_aux *aux = (regmatch_info_aux *) arg; regmatch_info_aux_eval *eval_state = aux->info_aux_eval; regmatch_slab *s; @@ -8106,7 +8177,6 @@ S_to_byte_substr(pTHX_ regexp *prog) /* Converts substr fields in prog from UTF-8 to bytes, calling fbm_compile * on the converted value; returns FALSE if can't be converted. */ - dVAR; int i = 1; PERL_ARGS_ASSERT_TO_BYTE_SUBSTR;