X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regexec.c;h=bc8da6e24b54c962b64291ebfc1b13b66bffc83e;hb=efdc43f5015438920ce11f05539e55cb02940377;hp=2b7ae4a44514bc59c2663bc3f9545546fd8bd57d;hpb=288b8c02c5ee89a2978a1b9e56ed255c53beb793;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regexec.c b/regexec.c index 2b7ae4a..bc8da6e 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 @@ -56,7 +60,8 @@ **** Alterations to Henry's code are... **** **** Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - **** 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others + **** 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + **** 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. @@ -237,9 +242,10 @@ S_regcppop(pTHX_ const regexp *rex) dVAR; U32 i; char *input; - GET_RE_DEBUG_FLAGS_DECL; + PERL_ARGS_ASSERT_REGCPPOP; + /* Pop REGCP_OTHER_ELEMS before the parentheses loop starts. */ i = SSPOPINT; assert(i == SAVEt_REGCONTEXT); /* Check that the magic cookie is there. */ @@ -314,6 +320,8 @@ Perl_pregexec(pTHX_ REGEXP * const prog, char* stringarg, register char *strend, /* minend: end of match must be >=minend after stringarg. */ /* nosave: For optimizations. */ { + PERL_ARGS_ASSERT_PREGEXEC; + return regexec_flags(prog, stringarg, strend, strbeg, minend, screamer, NULL, nosave ? 0 : REXEC_COPY_STR); @@ -392,16 +400,17 @@ Perl_re_intuit_start(pTHX_ REGEXP * const rx, SV *sv, char *strpos, #ifdef DEBUGGING const char * const i_strpos = strpos; #endif - GET_RE_DEBUG_FLAGS_DECL; + PERL_ARGS_ASSERT_RE_INTUIT_START; + RX_MATCH_UTF8_set(rx,do_utf8); - if (prog->extflags & RXf_UTF8) { + if (RX_UTF8(rx)) { PL_reg_flags |= RF_utf8; } DEBUG_EXECUTE_r( - debug_start_match(prog, do_utf8, strpos, strend, + debug_start_match(rx, do_utf8, strpos, strend, sv ? "Guessing start of match in sv for" : "Guessing start of match in string for"); ); @@ -998,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 ); \ @@ -1045,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) \ @@ -1181,6 +1194,8 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, register I32 tmp = 1; /* Scratch variable? */ register const bool do_utf8 = PL_reg_match_utf8; RXi_GET_DECL(prog,progi); + + PERL_ARGS_ASSERT_FIND_BYCLASS; /* We know what class it must start with. */ switch (OP(c)) { @@ -1509,7 +1524,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, = (reg_ac_data*)progi->data->data[ ARG( c ) ]; reg_trie_data *trie = (reg_trie_data*)progi->data->data[ aho->trie ]; - HV *widecharmap = (HV*) progi->data->data[ aho->trie + 1 ]; + HV *widecharmap = MUTABLE_HV(progi->data->data[ aho->trie + 1 ]); const char *last_start = strend - trie->minlen; #ifdef DEBUGGING @@ -1720,9 +1735,12 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, } static void -S_swap_match_buff (pTHX_ regexp *prog) { +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 @@ -1768,9 +1786,9 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre RXi_GET_DECL(prog,progi); regmatch_info reginfo; /* create some info to pass to regtry etc */ bool swap_on_fail = 0; - GET_RE_DEBUG_FLAGS_DECL; + PERL_ARGS_ASSERT_REGEXEC_FLAGS; PERL_UNUSED_ARG(data); /* Be paranoid... */ @@ -1784,7 +1802,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre RX_MATCH_UTF8_set(rx, do_utf8); DEBUG_EXECUTE_r( - debug_start_match(prog, do_utf8, startpos, strend, + debug_start_match(rx, do_utf8, startpos, strend, "Matching"); ); @@ -1806,7 +1824,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre PL_reg_eval_set = 0; PL_reg_maxiter = 0; - if (prog->extflags & RXf_UTF8) + if (RX_UTF8(rx)) PL_reg_flags |= RF_utf8; /* Mark beginning of line for ^ and lookbehind. */ @@ -2150,8 +2168,8 @@ got_it: if (PL_reg_eval_set) restore_pos(aTHX_ prog); - if (prog->paren_names) - (void)hv_iterinit(prog->paren_names); + if (RXp_PAREN_NAMES(prog)) + (void)hv_iterinit(RXp_PAREN_NAMES(prog)); /* make sure $`, $&, $', and $digit will work later */ if ( !(flags & REXEC_NOT_FIRST) ) { @@ -2211,6 +2229,9 @@ S_regtry(pTHX_ regmatch_info *reginfo, char **startpos) regexp *const prog = (struct regexp *)SvANY(rx); RXi_GET_DECL(prog,progi); GET_RE_DEBUG_FLAGS_DECL; + + PERL_ARGS_ASSERT_REGTRY; + reginfo->cutpoint=NULL; if ((prog->extflags & RXf_EVAL_SEEN) && !PL_reg_eval_set) { @@ -2233,7 +2254,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) @@ -2255,15 +2276,24 @@ S_regtry(pTHX_ regmatch_info *reginfo, char **startpos) Newxz(PL_reg_curpm, 1, PMOP); #ifdef USE_ITHREADS { - SV* const repointer = newSViv(0); - /* so we know which PL_regex_padav element is PL_reg_curpm */ - SvFLAGS(repointer) |= SVf_BREAK; - av_push(PL_regex_padav,repointer); + SV* const repointer = &PL_sv_undef; + /* this regexp is also owned by the new PL_reg_curpm, which + will try to free it. */ + av_push(PL_regex_padav, repointer); PL_reg_curpm->op_pmoffset = av_len(PL_regex_padav); PL_regex_pad = AvARRAY(PL_regex_padav); } #endif } +#ifdef USE_ITHREADS + /* It seems that non-ithreads works both with and without this code. + So for efficiency reasons it seems best not to have the code + compiled when it is not needed. */ + /* This is safe against NULLs: */ + ReREFCNT_dec(PM_GETRE(PL_reg_curpm)); + /* PM_reg_curpm owns a reference to this regexp. */ + ReREFCNT_inc(rx); +#endif PM_SETRE(PL_reg_curpm, rx); PL_reg_oldcurpm = PL_curpm; PL_curpm = PL_reg_curpm; @@ -2553,15 +2583,18 @@ regmatch(), slabs allocated since entry are freed. #ifdef DEBUGGING STATIC void -S_debug_start_match(pTHX_ const regexp *prog, const bool do_utf8, +S_debug_start_match(pTHX_ const REGEXP *prog, const bool do_utf8, const char *start, const char *end, const char *blurb) { - const bool utf8_pat= prog->extflags & RXf_UTF8 ? 1 : 0; + const bool utf8_pat = RX_UTF8(prog) ? 1 : 0; + + PERL_ARGS_ASSERT_DEBUG_START_MATCH; + if (!PL_colorset) reginitcolors(); { RE_PV_QUOTED_DECL(s0, utf8_pat, PERL_DEBUG_PAD_ZERO(0), - RXp_PRECOMP(prog), RXp_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); @@ -2600,6 +2633,8 @@ S_dump_exec_pos(pTHX_ const char *locinput, ? (5 + taill) - l : locinput - loc_bostr; int pref0_len; + PERL_ARGS_ASSERT_DUMP_EXEC_POS; + while (do_utf8 && UTF8_IS_CONTINUATION(*(U8*)(locinput - pref_len))) pref_len++; pref0_len = pref_len - (locinput - loc_reg_starttry); @@ -2650,11 +2685,15 @@ 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(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; + for ( n=0; n= nums[n] && PL_regoffs[nums[n]].end != -1) @@ -2698,16 +2737,12 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) dVAR; register const bool do_utf8 = PL_reg_match_utf8; const U32 uniflags = UTF8_ALLOW_DEFAULT; - REGEXP *rex_sv = reginfo->prog; regexp *rex = (struct regexp *)SvANY(rex_sv); RXi_GET_DECL(rex,rexi); - I32 oldsave; - /* the current state. This is a cached copy of PL_regmatch_state */ register regmatch_state *st; - /* cache heavy used fields of st in registers */ register regnode *scan; register regnode *next; @@ -2722,13 +2757,11 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) const U32 max_nochange_depth = (3 * rex->nparens > MAX_RECURSE_EVAL_NOCHANGE_DEPTH) ? 3 * rex->nparens : MAX_RECURSE_EVAL_NOCHANGE_DEPTH; - regmatch_state *yes_state = NULL; /* state to pop to on success of subpattern */ /* mark_state piggy backs on the yes_state logic so that when we unwind the stack on success we can update the mark_state as we go */ regmatch_state *mark_state = NULL; /* last mark state we have seen */ - regmatch_state *cur_eval = NULL; /* most recent EVAL_AB state */ struct regmatch_state *cur_curlyx = NULL; /* most recent curlyx */ U32 state_num; @@ -2741,10 +2774,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) during a successfull match */ U32 lastopen = 0; /* last open we saw */ bool has_cutgroup = RX_HAS_CUTGROUP(rex) ? 1 : 0; - SV* const oreplsv = GvSV(PL_replgv); - - /* these three flags are set by various ops to signal information to * the very next op. They have a useful lifetime of exactly one loop * iteration, and are not preserved or restored by state pushes/pops @@ -2759,11 +2789,12 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) false: plain (?=foo) true: used as a condition: (?(?=foo)) */ - #ifdef DEBUGGING GET_RE_DEBUG_FLAGS_DECL; #endif + PERL_ARGS_ASSERT_REGMATCH; + DEBUG_OPTIMISE_r( DEBUG_EXECUTE_r({ PerlIO_printf(Perl_debug_log,"regmatch start\n"); })); @@ -2919,7 +2950,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) /* what trie are we using right now */ reg_trie_data * const trie = (reg_trie_data*)rexi->data->data[ ARG( scan ) ]; - HV * widecharmap = (HV *)rexi->data->data[ ARG( scan ) + 1 ]; + HV * widecharmap = MUTABLE_HV(rexi->data->data[ ARG( scan ) + 1 ]); U32 state = trie->startstate; if (trie->bitmap && trie_type != trie_utf8_fold && @@ -2976,7 +3007,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); @@ -3076,7 +3107,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; @@ -3158,7 +3189,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]) ? @@ -3195,6 +3226,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; @@ -3633,7 +3667,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) #define ST st->u.eval { SV *ret; - SV *re_sv; + REGEXP *re_sv; regexp *re; regexp_internal *rei; regnode *startpoint; @@ -3720,13 +3754,13 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) SV *const sv = SvRV(ret); if (SvTYPE(sv) == SVt_REGEXP) { - rx = sv; + rx = (REGEXP*) sv; } else if (SvSMAGICAL(sv)) { mg = mg_find(sv, PERL_MAGIC_qr); assert(mg); } } else if (SvTYPE(ret) == SVt_REGEXP) { - rx = ret; + rx = (REGEXP*) ret; } else if (SvSMAGICAL(ret)) { if (SvGMAGICAL(ret)) { /* I don't believe that there is ever qr magic @@ -3745,8 +3779,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) } if (mg) { - rx = mg->mg_obj; /*XXX:dmq*/ - assert(re); + rx = (REGEXP *) mg->mg_obj; /*XXX:dmq*/ + assert(rx); } if (rx) { rx = reg_temp_copy(rx); @@ -3755,7 +3789,18 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) U32 pm_flags = 0; const I32 osize = PL_regsize; - if (DO_UTF8(ret)) pm_flags |= RXf_UTF8; + if (DO_UTF8(ret)) { + assert (SvUTF8(ret)); + } else if (SvUTF8(ret)) { + /* Not doing UTF-8, despite what the SV says. Is + this only if we're trapped in use 'bytes'? */ + /* Make a copy of the octet sequence, but without + the flag on, as the compiler now honours the + SvUTF8 flag on ret. */ + STRLEN len; + const char *const p = SvPV(ret, len); + ret = newSVpvn_flags(p, len, SVs_TEMP); + } rx = CALLREGCOMP(ret, pm_flags); if (!(SvFLAGS(ret) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY @@ -3763,7 +3808,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, rx, PERL_MAGIC_qr, 0, 0); + sv_magic(ret, MUTABLE_SV(rx), PERL_MAGIC_qr, 0, 0); } PL_regsize = osize; } @@ -3775,7 +3820,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) re->sublen = rex->sublen; rei = RXi_GET(re); DEBUG_EXECUTE_r( - debug_start_match(re, do_utf8, locinput, PL_regeol, + debug_start_match(re_sv, do_utf8, locinput, PL_regeol, "Matching embedded"); ); startpoint = rei->program + 1; @@ -3796,8 +3841,12 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) PL_regoffs = re->offs; /* essentially NOOP on GOSUB */ - *PL_reglastparen = 0; - *PL_reglastcloseparen = 0; + /* see regtry, specifically PL_reglast(?:close)?paren is a pointer! (i dont know why) :dmq */ + PL_reglastparen = &re->lastparen; + PL_reglastcloseparen = &re->lastcloseparen; + re->lastparen = 0; + re->lastcloseparen = 0; + PL_reginput = locinput; PL_regsize = 0; @@ -3805,7 +3854,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) PL_reg_maxiter = 0; ST.toggle_reg_flags = PL_reg_flags; - if (re->extflags & RXf_UTF8) + if (RX_UTF8(re_sv)) PL_reg_flags |= RF_utf8; else PL_reg_flags &= ~RF_utf8; @@ -3840,6 +3889,10 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) regcpblow(ST.cp); cur_eval = ST.prev_eval; cur_curlyx = ST.prev_curlyx; + + PL_reglastparen = &rex->lastparen; + PL_reglastcloseparen = &rex->lastcloseparen; + /* XXXX This is too dramatic a measure... */ PL_reg_maxiter = 0; if ( nochange_depth ) @@ -3854,6 +3907,9 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog) SETREX(rex_sv,ST.prev_rex); rex = (struct regexp *)SvANY(rex_sv); rexi = RXi_GET(rex); + PL_reglastparen = &rex->lastparen; + PL_reglastcloseparen = &rex->lastcloseparen; + PL_reginput = locinput; REGCP_UNWIND(ST.lastcp); regcppop(rex); @@ -4298,7 +4354,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: @@ -4934,6 +4990,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 */ @@ -4973,7 +5031,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: @@ -4987,7 +5045,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); @@ -5028,7 +5086,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, @@ -5317,6 +5375,8 @@ S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max, int depth) PERL_UNUSED_ARG(depth); #endif + PERL_ARGS_ASSERT_REGREPEAT; + scan = PL_reginput; if (max == REG_INFTY) max = I32_MAX; @@ -5632,12 +5692,14 @@ Perl_regclass_swash(pTHX_ const regexp *prog, register const regnode* node, bool RXi_GET_DECL(prog,progi); const struct reg_data * const data = prog ? progi->data : NULL; + PERL_ARGS_ASSERT_REGCLASS_SWASH; + if (data && data->count) { 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; @@ -5688,6 +5750,8 @@ S_reginclass(pTHX_ const regexp *prog, register const regnode *n, register const STRLEN len = 0; STRLEN plen; + PERL_ARGS_ASSERT_REGINCLASS; + if (do_utf8 && !UTF8_IS_INVARIANT(c)) { c = utf8n_to_uvchr(p, UTF8_MAXBYTES, &len, (UTF8_ALLOW_DEFAULT & UTF8_ALLOW_ANYUV) | UTF8_CHECK_ONLY); @@ -5711,7 +5775,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) { @@ -5720,8 +5791,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; @@ -5730,10 +5800,10 @@ 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; } } @@ -5805,6 +5875,9 @@ STATIC U8 * S_reghop3(U8 *s, I32 off, const U8* lim) { dVAR; + + PERL_ARGS_ASSERT_REGHOP3; + if (off >= 0) { while (off-- && s < lim) { /* XXX could check well-formedness here */ @@ -5833,6 +5906,9 @@ STATIC U8 * S_reghop4(U8 *s, I32 off, const U8* llim, const U8* rlim) { dVAR; + + PERL_ARGS_ASSERT_REGHOP4; + if (off >= 0) { while (off-- && s < rlim) { /* XXX could check well-formedness here */ @@ -5857,6 +5933,9 @@ STATIC U8 * S_reghopmaybe3(U8* s, I32 off, const U8* lim) { dVAR; + + PERL_ARGS_ASSERT_REGHOPMAYBE3; + if (off >= 0) { while (off-- && s < lim) { /* XXX could check well-formedness here */ @@ -5904,6 +5983,9 @@ STATIC void S_to_utf8_substr(pTHX_ register regexp *prog) { int i = 1; + + PERL_ARGS_ASSERT_TO_UTF8_SUBSTR; + do { if (prog->substrs->data[i].substr && !prog->substrs->data[i].utf8_substr) { @@ -5933,6 +6015,9 @@ S_to_byte_substr(pTHX_ register regexp *prog) { dVAR; int i = 1; + + PERL_ARGS_ASSERT_TO_BYTE_SUBSTR; + do { if (prog->substrs->data[i].utf8_substr && !prog->substrs->data[i].substr) {