X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regexec.c;h=db3cecb88482692a579c6f2fb256103e5cb3f387;hb=ca9279baf07d6843f58a31f1ce3ff7dc875faf1a;hp=f91af17d173620e3c7a1ac5a912d65adf85114f6;hpb=388cc4de5f48b02cc9fe9b962f02cf603af02178;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regexec.c b/regexec.c index f91af17..db3cecb 100644 --- a/regexec.c +++ b/regexec.c @@ -67,7 +67,8 @@ * **** Alterations to Henry's code are... **** - **** Copyright (c) 1991-2002, Larry Wall + **** Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + **** 2000, 2001, 2002, 2003, by Larry Wall and others **** **** You may distribute under the terms of either the GNU General Public **** License or the Artistic License, as specified in the README file. @@ -171,7 +172,7 @@ S_regcppush(pTHX_ I32 parenfloor) Perl_croak(aTHX_ "panic: paren_elems_to_push < 0"); #define REGCP_OTHER_ELEMS 6 - SSCHECK(paren_elems_to_push + REGCP_OTHER_ELEMS); + SSGROW(paren_elems_to_push + REGCP_OTHER_ELEMS); for (p = PL_regsize; p > parenfloor; p--) { /* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */ SSPUSHINT(PL_regendp[p]); @@ -400,6 +401,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, char *i_strpos = strpos; SV *dsv = PERL_DEBUG_PAD_ZERO(0); #endif + RX_MATCH_UTF8_set(prog,do_utf8); if (prog->reganch & ROPT_UTF8) { DEBUG_r(PerlIO_printf(Perl_debug_log, @@ -541,6 +543,9 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, start_shift + (s - strbeg), end_shift, pp, 0); else goto fail_finish; + /* we may be pointing at the wrong string */ + if (s && RX_MATCH_COPIED(prog)) + s = strbeg + (s - SvPVX(sv)); if (data) *data->scream_olds = s; } @@ -848,10 +853,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, char *startpos = strbeg; t = s; - if (prog->reganch & ROPT_UTF8) { - PL_regdata = prog->data; - PL_bostr = startpos; - } + cache_re(prog); s = find_byclass(prog, prog->regstclass, s, endpos, startpos, 1); if (!s) { #ifdef DEBUGGING @@ -1612,6 +1614,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * SV *dsv0 = PERL_DEBUG_PAD_ZERO(0); SV *dsv1 = PERL_DEBUG_PAD_ZERO(1); #endif + RX_MATCH_UTF8_set(prog,do_utf8); PL_regcc = 0; @@ -1858,6 +1861,9 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * : (s = fbm_instr((unsigned char*)HOP3(s, back_min, strend), (unsigned char*)strend, must, PL_multiline ? FBMrf_MULTILINE : 0))) ) { + /* we may be pointing at the wrong string */ + if ((flags & REXEC_SCREAM) && RX_MATCH_COPIED(prog)) + s = strbeg + (s - SvPVX(sv)); DEBUG_r( did_match = 1 ); if (HOPc(s, -back_max) > last1) { last1 = HOPc(s, -back_min); @@ -1944,6 +1950,9 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * end_shift, &scream_pos, 1); /* last one */ if (!last) last = scream_olds; /* Only one occurrence. */ + /* we may be pointing at the wrong string */ + else if (RX_MATCH_COPIED(prog)) + s = strbeg + (s - SvPVX(sv)); } else { STRLEN len; @@ -2011,17 +2020,28 @@ got_it: /* make sure $`, $&, $', and $digit will work later */ if ( !(flags & REXEC_NOT_FIRST) ) { - if (RX_MATCH_COPIED(prog)) { - Safefree(prog->subbeg); - RX_MATCH_COPIED_off(prog); - } + RX_MATCH_COPY_FREE(prog); if (flags & REXEC_COPY_STR) { I32 i = PL_regeol - startpos + (stringarg - strbeg); - - s = savepvn(strbeg, i); - prog->subbeg = s; +#ifdef PERL_COPY_ON_WRITE + if ((SvIsCOW(sv) + || (SvFLAGS(sv) & CAN_COW_MASK) == CAN_COW_FLAGS)) { + if (DEBUG_C_TEST) { + PerlIO_printf(Perl_debug_log, + "Copy on write: regexp capture, type %d\n", + (int) SvTYPE(sv)); + } + prog->saved_copy = sv_setsv_cow(prog->saved_copy, sv); + prog->subbeg = SvPVX(prog->saved_copy); + assert (SvPOKp(prog->saved_copy)); + } else +#endif + { + RX_MATCH_COPIED_on(prog); + s = savepvn(strbeg, i); + prog->subbeg = s; + } prog->sublen = i; - RX_MATCH_COPIED_on(prog); } else { prog->subbeg = strbeg; @@ -2111,6 +2131,9 @@ S_regtry(pTHX_ regexp *prog, char *startpos) $` inside (?{}) could fail... */ PL_reg_oldsaved = prog->subbeg; PL_reg_oldsavedlen = prog->sublen; +#ifdef PERL_COPY_ON_WRITE + PL_nrs = prog->saved_copy; +#endif RX_MATCH_COPIED_off(prog); } else @@ -2812,6 +2835,7 @@ S_regmatch(pTHX_ regnode *prog) COP *ocurcop = PL_curcop; PAD *old_comppad; SV *ret; + struct regexp *oreg = PL_reg_re; n = ARG(scan); PL_op = (OP_4tree*)PL_regdata->data[n]; @@ -2841,13 +2865,17 @@ S_regmatch(pTHX_ regnode *prog) re_cc_state state; CHECKPOINT cp, lastcp; int toggleutf; + register SV *sv; - if(SvROK(ret) || SvRMAGICAL(ret)) { - SV *sv = SvROK(ret) ? SvRV(ret) : ret; - - if(SvMAGICAL(sv)) - mg = mg_find(sv, PERL_MAGIC_qr); + if(SvROK(ret) && SvSMAGICAL(sv = SvRV(ret))) + mg = mg_find(sv, PERL_MAGIC_qr); + else if (SvSMAGICAL(ret)) { + if (SvGMAGICAL(ret)) + sv_unmagic(ret, PERL_MAGIC_qr); + else + mg = mg_find(ret, PERL_MAGIC_qr); } + if (mg) { re = (regexp *)mg->mg_obj; (void)ReREFCNT_inc(re); @@ -2864,7 +2892,8 @@ S_regmatch(pTHX_ regnode *prog) if (DO_UTF8(ret)) pm.op_pmdynflags |= PMdf_DYN_UTF8; re = CALLREGCOMP(aTHX_ t, t + len, &pm); if (!(SvFLAGS(ret) - & (SVs_TEMP | SVs_PADTMP | SVf_READONLY))) + & (SVs_TEMP | SVs_PADTMP | SVf_READONLY + | SVs_GMG))) sv_magic(ret,(SV*)ReREFCNT_inc(re), PERL_MAGIC_qr,0,0); PL_regprecomp = oprecomp; @@ -2939,8 +2968,10 @@ S_regmatch(pTHX_ regnode *prog) sw = SvTRUE(ret); logical = 0; } - else + else { sv_setsv(save_scalar(PL_replgv), ret); + cache_re(oreg); + } break; } case OPEN: @@ -4068,26 +4099,8 @@ S_regrepeat(pTHX_ regnode *p, I32 max) case ANYOF: if (do_utf8) { loceol = PL_regeol; - while (hardcount < max && scan < loceol) { - bool cont = FALSE; - if (ANYOF_FLAGS(p) & ANYOF_UNICODE) { - if (reginclass(p, (U8*)scan, 0, do_utf8)) - cont = TRUE; - } - else { - U8 c = (U8)scan[0]; - - if (UTF8_IS_INVARIANT(c)) { - if (ANYOF_BITMAP_TEST(p, c)) - cont = TRUE; - } - else { - if (reginclass(p, (U8*)scan, 0, do_utf8)) - cont = TRUE; - } - } - if (!cont) - break; + while (hardcount < max && scan < loceol && + reginclass(p, (U8*)scan, 0, do_utf8)) { scan += UTF8SKIP(scan); hardcount++; } @@ -4561,6 +4574,9 @@ restore_pos(pTHX_ void *arg) if (PL_reg_oldsaved) { PL_reg_re->subbeg = PL_reg_oldsaved; PL_reg_re->sublen = PL_reg_oldsavedlen; +#ifdef PERL_COPY_ON_WRITE + PL_reg_re->saved_copy = PL_nrs; +#endif RX_MATCH_COPIED_on(PL_reg_re); } PL_reg_magic->mg_len = PL_reg_oldpos;