X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regexec.c;h=5d31d735ff8b3bcfbc6c5d9cccc9e6a1d52dd738;hb=e83d9f5fdfd68dcd19d64ef68af2ecaf1caa2cd3;hp=94bace1e039d60f98c6d15fa28c1de1982b68e6a;hpb=85fbaab29c398adbb5b4445d3ed41e0a96364ce4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regexec.c b/regexec.c index 94bace1..5d31d73 100644 --- a/regexec.c +++ b/regexec.c @@ -2,7 +2,11 @@ */ /* - * "One Ring to rule them all, One Ring to find them..." + * One Ring to rule them all, One Ring to find them + & + * [p.v of _The Lord of the Rings_, opening poem] + * [p.50 of _The Lord of the Rings_, I/iii: "The Shadow of the Past"] + * [p.254 of _The Lord of the Rings_, II/ii: "The Council of Elrond"] */ /* This file contains functions for executing a regular expression. See @@ -1003,15 +1007,16 @@ Perl_re_intuit_start(pTHX_ REGEXP * const rx, SV *sv, char *strpos, #define REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc, uscan, len, \ uvc, charid, foldlen, foldbuf, uniflags) STMT_START { \ + UV uvc_unfolded = 0; \ switch (trie_type) { \ case trie_utf8_fold: \ if ( foldlen>0 ) { \ - uvc = utf8n_to_uvuni( uscan, UTF8_MAXLEN, &len, uniflags ); \ + uvc_unfolded = uvc = utf8n_to_uvuni( uscan, UTF8_MAXLEN, &len, uniflags ); \ foldlen -= len; \ uscan += len; \ len=0; \ } else { \ - uvc = utf8n_to_uvuni( (U8*)uc, UTF8_MAXLEN, &len, uniflags ); \ + uvc_unfolded = uvc = utf8n_to_uvuni( (U8*)uc, UTF8_MAXLEN, &len, uniflags ); \ uvc = to_uni_fold( uvc, foldbuf, &foldlen ); \ foldlen -= UNISKIP( uvc ); \ uscan = foldbuf + UNISKIP( uvc ); \ @@ -1050,6 +1055,9 @@ uvc, charid, foldlen, foldbuf, uniflags) STMT_START { \ charid = (U16)SvIV(*svpp); \ } \ } \ + if (!charid && trie_type == trie_utf8_fold && !UTF) { \ + charid = trie->charmap[uvc_unfolded]; \ + } \ } STMT_END #define REXEC_FBC_EXACTISH_CHECK(CoNd) \ @@ -1726,28 +1734,6 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, return s; } -static void -S_swap_match_buff (pTHX_ regexp *prog) -{ - regexp_paren_pair *t; - - PERL_ARGS_ASSERT_SWAP_MATCH_BUFF; - - if (!prog->swap) { - /* We have to be careful. If the previous successful match - was from this regex we don't want a subsequent paritally - successful match to clobber the old results. - So when we detect this possibility we add a swap buffer - to the re, and switch the buffer each match. If we fail - we switch it back, otherwise we leave it swapped. - */ - Newxz(prog->swap, (prog->nparens + 1), regexp_paren_pair); - } - t = prog->swap; - prog->swap = prog->offs; - prog->offs = t; -} - /* - regexec_flags - match a regexp against a string @@ -1777,7 +1763,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre I32 multiline; RXi_GET_DECL(prog,progi); regmatch_info reginfo; /* create some info to pass to regtry etc */ - bool swap_on_fail = 0; + regexp_paren_pair *swap = NULL; GET_RE_DEBUG_FLAGS_DECL; PERL_ARGS_ASSERT_REGEXEC_FLAGS; @@ -1855,9 +1841,16 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre reginfo.ganch = strbeg; } if (PL_curpm && (PM_GETRE(PL_curpm) == rx)) { - swap_on_fail = 1; - swap_match_buff(prog); /* do we need a save destructor here for - eval dies? */ + /* We have to be careful. If the previous successful match + was from this regex we don't want a subsequent partially + successful match to clobber the old results. + So when we detect this possibility we add a swap buffer + to the re, and switch the buffer each match. If we fail + we switch it back, otherwise we leave it swapped. + */ + swap = prog->offs; + /* do we need a save destructor here for eval dies? */ + Newxz(prog->offs, (prog->nparens + 1), regexp_paren_pair); } if (!(flags & REXEC_CHECKED) && (prog->check_substr != NULL || prog->check_utf8 != NULL)) { re_scream_pos_data d; @@ -2156,6 +2149,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre goto phooey; got_it: + Safefree(swap); RX_MATCH_TAINTED_set(rx, PL_reg_flags & RF_tainted); if (PL_reg_eval_set) @@ -2201,10 +2195,12 @@ phooey: PL_colors[4], PL_colors[5])); if (PL_reg_eval_set) restore_pos(aTHX_ prog); - if (swap_on_fail) + if (swap) { /* we failed :-( roll it back */ - swap_match_buff(prog); - + Safefree(prog->offs); + prog->offs = swap; + } + return 0; } @@ -2246,7 +2242,7 @@ S_regtry(pTHX_ regmatch_info *reginfo, char **startpos) /* Make $_ available to executed code. */ if (reginfo->sv != DEFSV) { SAVE_DEFSV; - DEFSV = reginfo->sv; + DEFSV_set(reginfo->sv); } if (!(SvTYPE(reginfo->sv) >= SVt_PVMG && SvMAGIC(reginfo->sv) @@ -2586,7 +2582,7 @@ S_debug_start_match(pTHX_ const REGEXP *prog, const bool do_utf8, reginitcolors(); { RE_PV_QUOTED_DECL(s0, utf8_pat, PERL_DEBUG_PAD_ZERO(0), - RX_PRECOMP(prog), RX_PRELEN(prog), 60); + RX_PRECOMP_const(prog), RX_PRELEN(prog), 60); RE_PV_QUOTED_DECL(s1, do_utf8, PERL_DEBUG_PAD_ZERO(1), start, end - start, 60); @@ -2681,7 +2677,7 @@ S_reg_check_named_buff_matched(pTHX_ const regexp *rex, const regnode *scan) { I32 n; RXi_GET_DECL(rex,rexi); - SV *sv_dat=(SV*)rexi->data->data[ ARG( scan ) ]; + SV *sv_dat= MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); I32 *nums=(I32*)SvPVX(sv_dat); PERL_ARGS_ASSERT_REG_CHECK_NAMED_BUFF_MATCHED; @@ -2833,6 +2829,11 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) state_num = OP(scan); reenter_switch: + + assert(PL_reglastparen == &rex->lastparen); + assert(PL_reglastcloseparen == &rex->lastcloseparen); + assert(PL_regoffs == rex->offs); + switch (state_num) { case BOL: if (locinput == PL_bostr) @@ -2999,7 +3000,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) if ( got_wordnum ) { if ( ! ST.accepted ) { ENTER; - /* SAVETMPS; */ /* XXX is this necessary? dmq */ + SAVETMPS; /* XXX is this necessary? dmq */ bufflen = TRIE_INITAL_ACCEPT_BUFFLEN; sv_accept_buff=newSV(bufflen * sizeof(reg_trie_accepted) - 1); @@ -3099,7 +3100,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) /* only one choice left - just continue */ DEBUG_EXECUTE_r({ AV *const trie_words - = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET]; + = MUTABLE_AV(rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET]); SV ** const tmp = av_fetch( trie_words, ST.accept_buff[ 0 ].wordnum-1, 0 ); SV *sv= tmp ? sv_newmortal() : NULL; @@ -3181,7 +3182,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) DEBUG_EXECUTE_r({ AV *const trie_words - = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET]; + = MUTABLE_AV(rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET]); SV ** const tmp = av_fetch( trie_words, ST.accept_buff[ best ].wordnum - 1, 0 ); regnode *nextop=(!ST.jump || !ST.jump[ST.accept_buff[best].wordnum]) ? @@ -3218,6 +3219,9 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) } /* NOTREACHED */ case TRIE_next: + /* we dont want to throw this away, see bug 57042*/ + if (oreplsv != GvSV(PL_replgv)) + sv_setsv(oreplsv, GvSV(PL_replgv)); FREETMPS; LEAVE; sayYES; @@ -3700,6 +3704,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) OP_4tree * const oop = PL_op; COP * const ocurcop = PL_curcop; PAD *old_comppad; + char *saved_regeol = PL_regeol; n = ARG(scan); PL_op = (OP_4tree*)rexi->data->data[n]; @@ -3725,6 +3730,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) PL_op = oop; PAD_RESTORE_LOCAL(old_comppad); PL_curcop = ocurcop; + PL_regeol = saved_regeol; if (!logical) { /* /(?{...})/ */ sv_setsv(save_scalar(PL_replgv), ret); @@ -3797,7 +3803,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) /* This isn't a first class regexp. Instead, it's caching a regexp onto an existing, Perl visible scalar. */ - sv_magic(ret, (SV*) rx, PERL_MAGIC_qr, 0, 0); + sv_magic(ret, MUTABLE_SV(rx), PERL_MAGIC_qr, 0, 0); } PL_regsize = osize; } @@ -3878,9 +3884,12 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) regcpblow(ST.cp); cur_eval = ST.prev_eval; cur_curlyx = ST.prev_curlyx; - + + /* rex was changed so update the pointer in PL_reglastparen and PL_reglastcloseparen */ PL_reglastparen = &rex->lastparen; PL_reglastcloseparen = &rex->lastcloseparen; + /* also update PL_regoffs */ + PL_regoffs = rex->offs; /* XXXX This is too dramatic a measure... */ PL_reg_maxiter = 0; @@ -3896,6 +3905,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) SETREX(rex_sv,ST.prev_rex); rex = (struct regexp *)SvANY(rex_sv); rexi = RXi_GET(rex); + /* rex was changed so update the pointer in PL_reglastparen and PL_reglastcloseparen */ PL_reglastparen = &rex->lastparen; PL_reglastcloseparen = &rex->lastcloseparen; @@ -4343,7 +4353,7 @@ NULL case CUTGROUP: PL_reginput = locinput; sv_yes_mark = st->u.mark.mark_name = scan->flags ? NULL : - (SV*)rexi->data->data[ ARG( scan ) ]; + MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); PUSH_STATE_GOTO(CUTGROUP_next,next); /* NOTREACHED */ case CUTGROUP_next_fail: @@ -4391,7 +4401,7 @@ NULL case CURLYM: /* /A{m,n}B/ where A is fixed-length */ /* This is an optimisation of CURLYX that enables us to push - * only a single backtracking state, no matter now many matches + * only a single backtracking state, no matter how many matches * there are in {m,n}. It relies on the pattern being constant * length, with no parens to influence future backrefs */ @@ -4458,8 +4468,11 @@ NULL cur_eval->u.eval.close_paren == (U32)ST.me->flags) goto fake_end; - if ( ST.count < (ST.minmod ? ARG1(ST.me) : ARG2(ST.me)) ) - goto curlym_do_A; /* try to match another A */ + { + I32 max = (ST.minmod ? ARG1(ST.me) : ARG2(ST.me)); + if ( max == REG_INFTY || ST.count < max ) + goto curlym_do_A; /* try to match another A */ + } goto curlym_do_B; /* try to match B */ case CURLYM_A_fail: /* just failed to match an A */ @@ -4551,7 +4564,8 @@ NULL case CURLYM_B_fail: /* just failed to match a B */ REGCP_UNWIND(ST.cp); if (ST.minmod) { - if (ST.count == ARG2(ST.me) /* max */) + I32 max = ARG2(ST.me); + if (max != REG_INFTY && ST.count == max) sayNO; goto curlym_do_A; /* try to match a further A */ } @@ -4898,6 +4912,11 @@ NULL cur_curlyx = cur_eval->u.eval.prev_curlyx; ReREFCNT_inc(rex_sv); st->u.eval.cp = regcppush(0); /* Save *all* the positions. */ + + /* rex was changed so update the pointer in PL_reglastparen and PL_reglastcloseparen */ + PL_reglastparen = &rex->lastparen; + PL_reglastcloseparen = &rex->lastcloseparen; + REGCP_SET(st->u.eval.lastcp); PL_reginput = locinput; @@ -4979,6 +4998,8 @@ NULL do_ifmatch: ST.me = scan; ST.logical = logical; + logical = 0; /* XXX: reset state of logical once it has been saved into ST */ + /* execute body of (?...A) */ PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan))); /* NOTREACHED */ @@ -5018,7 +5039,7 @@ NULL case PRUNE: PL_reginput = locinput; if (!scan->flags) - sv_yes_mark = sv_commit = (SV*)rexi->data->data[ ARG( scan ) ]; + sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); PUSH_STATE_GOTO(COMMIT_next,next); /* NOTREACHED */ case COMMIT_next_fail: @@ -5032,7 +5053,7 @@ NULL case MARKPOINT: ST.prev_mark = mark_state; ST.mark_name = sv_commit = sv_yes_mark - = (SV*)rexi->data->data[ ARG( scan ) ]; + = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); mark_state = st; ST.mark_loc = PL_reginput = locinput; PUSH_YES_STATE_GOTO(MARKPOINT_next,next); @@ -5073,7 +5094,7 @@ NULL otherwise do nothing. Meaning we need to scan */ regmatch_state *cur = mark_state; - SV *find = (SV*)rexi->data->data[ ARG( scan ) ]; + SV *find = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]); while (cur) { if ( sv_eq( cur->u.mark.mark_name, @@ -5685,8 +5706,8 @@ Perl_regclass_swash(pTHX_ const regexp *prog, register const regnode* node, bool const U32 n = ARG(node); if (data->what[n] == 's') { - SV * const rv = (SV*)data->data[n]; - AV * const av = (AV*)SvRV((SV*)rv); + SV * const rv = MUTABLE_SV(data->data[n]); + AV * const av = MUTABLE_AV(SvRV(rv)); SV **const ary = AvARRAY(av); SV **a, **b; @@ -5762,7 +5783,14 @@ S_reginclass(pTHX_ const regexp *prog, register const regnode *n, register const SV * const sw = regclass_swash(prog, n, TRUE, 0, (SV**)&av); if (sw) { - if (swash_fetch(sw, p, do_utf8)) + U8 * utf8_p; + if (do_utf8) { + utf8_p = (U8 *) p; + } else { + STRLEN len = 1; + utf8_p = bytes_to_utf8(p, &len); + } + if (swash_fetch(sw, utf8_p, 1)) match = TRUE; else if (flags & ANYOF_FOLD) { if (!match && lenp && av) { @@ -5771,8 +5799,7 @@ S_reginclass(pTHX_ const regexp *prog, register const regnode *n, register const SV* const sv = *av_fetch(av, i, FALSE); STRLEN len; const char * const s = SvPV_const(sv, len); - - if (len <= plen && memEQ(s, (char*)p, len)) { + if (len <= plen && memEQ(s, (char*)utf8_p, len)) { *lenp = len; match = TRUE; break; @@ -5781,13 +5808,16 @@ S_reginclass(pTHX_ const regexp *prog, register const regnode *n, register const } if (!match) { U8 tmpbuf[UTF8_MAXBYTES_CASE+1]; - STRLEN tmplen; - to_utf8_fold(p, tmpbuf, &tmplen); - if (swash_fetch(sw, tmpbuf, do_utf8)) + STRLEN tmplen; + to_utf8_fold(utf8_p, tmpbuf, &tmplen); + if (swash_fetch(sw, tmpbuf, 1)) match = TRUE; } } + + /* If we allocated a string above, free it */ + if (! do_utf8) Safefree(utf8_p); } } if (match && lenp && *lenp == 0)