X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=regexec.c;h=a7a9a675e0273ccc796849e092a1309b9430b5a7;hb=79316e7384d4e499a91e5690f6fcce22fa852ca5;hp=3f062ed798543c3da58e93521613d9fbe409fc7e;hpb=f31a99c85a958352599ea1e9ed74866c8666a515;p=p5sagit%2Fp5-mst-13.2.git diff --git a/regexec.c b/regexec.c index 3f062ed..a7a9a67 100644 --- a/regexec.c +++ b/regexec.c @@ -80,12 +80,6 @@ #define PERL_IN_REGEXEC_C #include "perl.h" -#ifdef PERL_IN_XSUB_RE -# if defined(PERL_CAPI) || defined(PERL_OBJECT) -# include "XSUB.h" -# endif -#endif - #include "regcomp.h" #define RF_tainted 1 /* tainted information used? */ @@ -107,17 +101,17 @@ */ #define CHR_SVLEN(sv) (UTF ? sv_len_utf8(sv) : SvCUR(sv)) -#define CHR_DIST(a,b) (DO_UTF8(PL_reg_sv) ? utf8_distance(a,b) : a - b) +#define CHR_DIST(a,b) (PL_reg_match_utf8 ? utf8_distance(a,b) : a - b) #define reghop_c(pos,off) ((char*)reghop((U8*)pos, off)) #define reghopmaybe_c(pos,off) ((char*)reghopmaybe((U8*)pos, off)) -#define HOP(pos,off) (DO_UTF8(PL_reg_sv) ? reghop((U8*)pos, off) : (U8*)(pos + off)) -#define HOPMAYBE(pos,off) (DO_UTF8(PL_reg_sv) ? reghopmaybe((U8*)pos, off) : (U8*)(pos + off)) +#define HOP(pos,off) (PL_reg_match_utf8 ? reghop((U8*)pos, off) : (U8*)(pos + off)) +#define HOPMAYBE(pos,off) (PL_reg_match_utf8 ? reghopmaybe((U8*)pos, off) : (U8*)(pos + off)) #define HOPc(pos,off) ((char*)HOP(pos,off)) #define HOPMAYBEc(pos,off) ((char*)HOPMAYBE(pos,off)) #define HOPBACK(pos, off) ( \ - (UTF && DO_UTF8(PL_reg_sv)) \ + (UTF && PL_reg_match_utf8) \ ? reghopmaybe((U8*)pos, -off) \ : (pos - off >= PL_bostr) \ ? (U8*)(pos - off) \ @@ -127,14 +121,29 @@ #define reghop3_c(pos,off,lim) ((char*)reghop3((U8*)pos, off, (U8*)lim)) #define reghopmaybe3_c(pos,off,lim) ((char*)reghopmaybe3((U8*)pos, off, (U8*)lim)) -#define HOP3(pos,off,lim) (DO_UTF8(PL_reg_sv) ? reghop3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off)) -#define HOPMAYBE3(pos,off,lim) (DO_UTF8(PL_reg_sv) ? reghopmaybe3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off)) +#define HOP3(pos,off,lim) (PL_reg_match_utf8 ? reghop3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off)) +#define HOPMAYBE3(pos,off,lim) (PL_reg_match_utf8 ? reghopmaybe3((U8*)pos, off, (U8*)lim) : (U8*)(pos + off)) #define HOP3c(pos,off,lim) ((char*)HOP3(pos,off,lim)) #define HOPMAYBE3c(pos,off,lim) ((char*)HOPMAYBE3(pos,off,lim)) #define LOAD_UTF8_CHARCLASS(a,b) STMT_START { if (!CAT2(PL_utf8_,a)) (void)CAT2(is_utf8_, a)((U8*)b); } STMT_END -static void restore_pos(pTHXo_ void *arg); +/* for use after a quantifier and before an EXACT-like node -- japhy */ +#define JUMPABLE(rn) ( \ + OP(rn) == OPEN || OP(rn) == CLOSE || OP(rn) == EVAL || \ + OP(rn) == SUSPEND || OP(rn) == IFMATCH \ +) + +#define NEAR_EXACT(rn) (PL_regkind[(U8)OP(rn)] == EXACT || JUMPABLE(rn)) + +#define NEXT_IMPT(rn) STMT_START { \ + while (JUMPABLE(rn)) \ + if (OP(rn) == SUSPEND || OP(rn) == IFMATCH) \ + rn = NEXTOPER(NEXTOPER(rn)); \ + else rn += NEXT_OFF(rn); \ +} STMT_END + +static void restore_pos(pTHX_ void *arg); STATIC CHECKPOINT S_regcppush(pTHX_ I32 parenfloor) @@ -374,20 +383,26 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, char *check_at = Nullch; /* check substr found at this pos */ #ifdef DEBUGGING char *i_strpos = strpos; + SV *dsv = sv_2mortal(newSVpvn("", 0)); #endif - DEBUG_r( if (!PL_colorset) reginitcolors() ); - DEBUG_r(PerlIO_printf(Perl_debug_log, - "%sGuessing start of match, REx%s `%s%.60s%s%s' against `%s%.*s%s%s'...\n", - PL_colors[4],PL_colors[5],PL_colors[0], - prog->precomp, - PL_colors[1], - (strlen(prog->precomp) > 60 ? "..." : ""), - PL_colors[0], - (int)(strend - strpos > 60 ? 60 : strend - strpos), - strpos, PL_colors[1], - (strend - strpos > 60 ? "..." : "")) - ); + DEBUG_r({ + char*s = UTF ? sv_uni_display(dsv, sv, 60, 0) : strpos; + int len = UTF ? strlen(s) : strend - strpos; + if (!PL_colorset) + reginitcolors(); + PerlIO_printf(Perl_debug_log, + "%sGuessing start of match, REx%s `%s%.60s%s%s' against `%s%.*s%s%s'...\n", + PL_colors[4],PL_colors[5],PL_colors[0], + prog->precomp, + PL_colors[1], + (strlen(prog->precomp) > 60 ? "..." : ""), + PL_colors[0], + (int)(len > 60 ? 60 : len), + s, PL_colors[1], + (len > 60 ? "..." : "") + ); + }); if (prog->reganch & ROPT_UTF8) PL_reg_flags |= RF_utf8; @@ -878,7 +893,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta unsigned int c2; char *e; register I32 tmp = 1; /* Scratch variable? */ - register bool do_utf8 = DO_UTF8(PL_reg_sv); + register bool do_utf8 = PL_reg_match_utf8; /* We know what class it must start with. */ switch (OP(c)) { @@ -908,8 +923,15 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta m = STRING(c); ln = STR_LEN(c); if (UTF) { - c1 = to_utf8_lower((U8*)m); - c2 = to_utf8_upper((U8*)m); + STRLEN ulen1, ulen2; + U8 tmpbuf1[UTF8_MAXLEN*2+1]; + U8 tmpbuf2[UTF8_MAXLEN*2+1]; + + to_utf8_lower((U8*)m, tmpbuf1, &ulen1); + to_utf8_upper((U8*)m, tmpbuf2, &ulen2); + + c1 = utf8_to_uvuni(tmpbuf1, 0); + c2 = utf8_to_uvuni(tmpbuf2, 0); } else { c1 = *(U8*)m; @@ -1434,6 +1456,9 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * char *scream_olds; SV* oreplsv = GvSV(PL_replgv); bool do_utf8 = DO_UTF8(sv); +#ifdef DEBUGGING + SV *dsv = sv_2mortal(newSVpvn("", 0)); +#endif PL_regcc = 0; @@ -1516,18 +1541,23 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * goto phooey; /* not present */ } - DEBUG_r( if (!PL_colorset) reginitcolors() ); - DEBUG_r(PerlIO_printf(Perl_debug_log, - "%sMatching REx%s `%s%.60s%s%s' against `%s%.*s%s%s'\n", - PL_colors[4],PL_colors[5],PL_colors[0], - prog->precomp, - PL_colors[1], - (strlen(prog->precomp) > 60 ? "..." : ""), - PL_colors[0], - (int)(strend - startpos > 60 ? 60 : strend - startpos), - startpos, PL_colors[1], - (strend - startpos > 60 ? "..." : "")) - ); + DEBUG_r({ + char *s = UTF ? sv_uni_display(dsv, sv, 60, 0) : startpos; + int len = UTF ? strlen(s) : strend - startpos; + if (!PL_colorset) + reginitcolors(); + PerlIO_printf(Perl_debug_log, + "%sMatching REx%s `%s%.60s%s%s' against `%s%.*s%s%s'\n", + PL_colors[4],PL_colors[5],PL_colors[0], + prog->precomp, + PL_colors[1], + (strlen(prog->precomp) > 60 ? "..." : ""), + PL_colors[0], + (int)(len > 60 ? 60 : len), + s, PL_colors[1], + (len > 60 ? "..." : "") + ); + }); /* Simplest case: anchored match need be tried only once. */ /* [unless only anchor is BOL and multiline is set] */ @@ -1697,7 +1727,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * DEBUG_r({ SV *prop = sv_newmortal(); regprop(prop, c); - PerlIO_printf(Perl_debug_log, "Matching stclass `%s' against `%s'\n", SvPVX(prop), s); + PerlIO_printf(Perl_debug_log, "Matching stclass `%s' against `%s'\n", SvPVX(prop), UTF ? sv_uni_display(dsv, sv, 60, 0) : s); }); if (find_byclass(prog, c, s, strend, startpos, 0)) goto got_it; @@ -1775,7 +1805,7 @@ got_it: sv_setsv(oreplsv, GvSV(PL_replgv));/* So that when GvSV(replgv) is restored, the value remains the same. */ - restore_pos(aTHXo_ 0); + restore_pos(aTHX_ 0); } /* make sure $`, $&, $', and $digit will work later */ @@ -1804,7 +1834,7 @@ phooey: DEBUG_r(PerlIO_printf(Perl_debug_log, "%sMatch failed%s\n", PL_colors[4],PL_colors[5])); if (PL_reg_eval_set) - restore_pos(aTHXo_ 0); + restore_pos(aTHX_ 0); return 0; } @@ -1841,7 +1871,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos) if (PL_reg_sv) { /* Make $_ available to executed code. */ if (PL_reg_sv != DEFSV) { - /* SAVE_DEFSV does *not* suffice here for USE_THREADS */ + /* SAVE_DEFSV does *not* suffice here for USE_5005THREADS */ SAVESPTR(DEFSV); DEFSV = PL_reg_sv; } @@ -2009,7 +2039,12 @@ S_regmatch(pTHX_ regnode *prog) #if 0 I32 firstcp = PL_savestack_ix; #endif - register bool do_utf8 = DO_UTF8(PL_reg_sv); + register bool do_utf8 = PL_reg_match_utf8; +#ifdef DEBUGGING + SV *dsv0 = sv_2mortal(newSVpvn("", 0)); + SV *dsv1 = sv_2mortal(newSVpvn("", 0)); + SV *dsv2 = sv_2mortal(newSVpvn("", 0)); +#endif #ifdef DEBUGGING PL_regindent++; @@ -2020,7 +2055,7 @@ S_regmatch(pTHX_ regnode *prog) scan = prog; while (scan != NULL) { - DEBUG_r( { + DEBUG_r( { SV *prop = sv_newmortal(); int docolor = *PL_colors[0]; int taill = (docolor ? 10 : 7); /* 3 chars for "> <" */ @@ -2048,20 +2083,42 @@ S_regmatch(pTHX_ regnode *prog) if (pref0_len > pref_len) pref0_len = pref_len; regprop(prop, scan); - PerlIO_printf(Perl_debug_log, - "%4"IVdf" <%s%.*s%s%s%.*s%s%s%s%.*s%s>%*s|%3"IVdf":%*s%s\n", - (IV)(locinput - PL_bostr), - PL_colors[4], pref0_len, - locinput - pref_len, PL_colors[5], - PL_colors[2], pref_len - pref0_len, - locinput - pref_len + pref0_len, PL_colors[3], - (docolor ? "" : "> <"), - PL_colors[0], l, locinput, PL_colors[1], - 15 - l - pref_len + 1, - "", - (IV)(scan - PL_regprogram), PL_regindent*2, "", - SvPVX(prop)); - } ); + { + char *s0 = + UTF ? + pv_uni_display(dsv0, (U8*)(locinput - pref_len), + pref0_len, 60, 0) : + locinput - pref_len; + int len0 = UTF ? strlen(s0) : pref0_len; + char *s1 = UTF ? + pv_uni_display(dsv1, (U8*)(locinput - pref_len + pref0_len), + pref_len - pref0_len, 60, 0) : + locinput - pref_len + pref0_len; + int len1 = UTF ? strlen(s1) : pref_len - pref0_len; + char *s2 = UTF ? + pv_uni_display(dsv2, (U8*)locinput, + PL_regeol - locinput, 60, 0) : + locinput; + int len2 = UTF ? strlen(s2) : l; + PerlIO_printf(Perl_debug_log, + "%4"IVdf" <%s%.*s%s%s%.*s%s%s%s%.*s%s>%*s|%3"IVdf":%*s%s\n", + (IV)(locinput - PL_bostr), + PL_colors[4], + len0, s0, + PL_colors[5], + PL_colors[2], + len1, s1, + PL_colors[3], + (docolor ? "" : "> <"), + PL_colors[0], + len2, s2, + PL_colors[1], + 15 - l - pref_len + 1, + "", + (IV)(scan - PL_regprogram), PL_regindent*2, "", + SvPVX(prop)); + } + }); next = scan + NEXT_OFF(scan); if (next == scan) @@ -2190,17 +2247,17 @@ S_regmatch(pTHX_ regnode *prog) if (do_utf8) { char *l = locinput; char *e; + STRLEN ulen; + U8 tmpbuf[UTF8_MAXLEN*2+1]; e = s + ln; - c1 = OP(scan) == EXACTF; while (s < e) { - if (l >= PL_regeol) { + if (l >= PL_regeol) sayNO; - } - if ((UTF ? utf8n_to_uvchr((U8*)s, e - s, 0, 0) : *((U8*)s)) != - (c1 ? toLOWER_utf8((U8*)l) : toLOWER_LC_utf8((U8*)l))) - sayNO; - s += UTF ? UTF8SKIP(s) : 1; - l += UTF8SKIP(l); + toLOWER_utf8((U8*)l, tmpbuf, &ulen); + if (memNE(s, tmpbuf, ulen)) + sayNO; + s += UTF8SKIP(s); + l += ulen; } locinput = l; nextchr = UCHARAT(locinput); @@ -2463,23 +2520,18 @@ S_regmatch(pTHX_ regnode *prog) * have to map both upper and title case to lower case. */ if (OP(scan) == REFF) { + STRLEN ulen1, ulen2; + U8 tmpbuf1[UTF8_MAXLEN*2+1]; + U8 tmpbuf2[UTF8_MAXLEN*2+1]; while (s < e) { if (l >= PL_regeol) sayNO; - if (toLOWER_utf8((U8*)s) != toLOWER_utf8((U8*)l)) + toLOWER_utf8((U8*)s, tmpbuf1, &ulen1); + toLOWER_utf8((U8*)l, tmpbuf2, &ulen2); + if (ulen1 != ulen2 || memNE(tmpbuf1, tmpbuf2, ulen1)) sayNO; - s += UTF8SKIP(s); - l += UTF8SKIP(l); - } - } - else { - while (s < e) { - if (l >= PL_regeol) - sayNO; - if (toLOWER_LC_utf8((U8*)s) != toLOWER_LC_utf8((U8*)l)) - sayNO; - s += UTF8SKIP(s); - l += UTF8SKIP(l); + s += ulen1; + l += ulen2; } } locinput = l; @@ -2525,11 +2577,18 @@ S_regmatch(pTHX_ regnode *prog) PL_curpad = AvARRAY((AV*)PL_regdata->data[n + 2]); PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr; - CALLRUNOPS(aTHX); /* Scalar context. */ - SPAGAIN; - ret = POPs; - PUTBACK; - + { + SV **before = SP; + CALLRUNOPS(aTHX); /* Scalar context. */ + SPAGAIN; + if (SP == before) + ret = Nullsv; /* protect against empty (?{}) blocks. */ + else { + ret = POPs; + PUTBACK; + } + } + PL_op = oop; PL_curpad = ocurpad; PL_curcop = ocurcop; @@ -3043,14 +3102,24 @@ S_regmatch(pTHX_ regnode *prog) if (ln && l == 0) n = ln; /* don't backtrack */ locinput = PL_reginput; - if (PL_regkind[(U8)OP(next)] == EXACT) { - c1 = (U8)*STRING(next); - if (OP(next) == EXACTF) - c2 = PL_fold[c1]; - else if (OP(next) == EXACTFL) - c2 = PL_fold_locale[c1]; - else - c2 = c1; + if (NEAR_EXACT(next)) { + regnode *text_node = next; + + if (PL_regkind[(U8)OP(next)] != EXACT) + NEXT_IMPT(text_node); + + if (PL_regkind[(U8)OP(text_node)] != EXACT) { + c1 = c2 = -1000; + } + else { + c1 = (U8)*STRING(text_node); + if (OP(next) == EXACTF) + c2 = PL_fold[c1]; + else if (OP(text_node) == EXACTFL) + c2 = PL_fold_locale[c1]; + else + c2 = c1; + } } else c1 = c2 = -1000; @@ -3102,14 +3171,24 @@ S_regmatch(pTHX_ regnode *prog) (IV) n, (IV)l) ); if (n >= ln) { - if (PL_regkind[(U8)OP(next)] == EXACT) { - c1 = (U8)*STRING(next); - if (OP(next) == EXACTF) - c2 = PL_fold[c1]; - else if (OP(next) == EXACTFL) - c2 = PL_fold_locale[c1]; - else - c2 = c1; + if (NEAR_EXACT(next)) { + regnode *text_node = next; + + if (PL_regkind[(U8)OP(next)] != EXACT) + NEXT_IMPT(text_node); + + if (PL_regkind[(U8)OP(text_node)] != EXACT) { + c1 = c2 = -1000; + } + else { + c1 = (U8)*STRING(text_node); + if (OP(text_node) == EXACTF) + c2 = PL_fold[c1]; + else if (OP(text_node) == EXACTFL) + c2 = PL_fold_locale[c1]; + else + c2 = c1; + } } else c1 = c2 = -1000; @@ -3179,22 +3258,48 @@ S_regmatch(pTHX_ regnode *prog) * Lookahead to avoid useless match attempts * when we know what character comes next. */ - if (PL_regkind[(U8)OP(next)] == EXACT) { - U8 *s = (U8*)STRING(next); - if (!UTF) { - c2 = c1 = *s; - if (OP(next) == EXACTF) - c2 = PL_fold[c1]; - else if (OP(next) == EXACTFL) - c2 = PL_fold_locale[c1]; - } - else { /* UTF */ - if (OP(next) == EXACTF) { - c1 = to_utf8_lower(s); - c2 = to_utf8_upper(s); + + /* + * Used to only do .*x and .*?x, but now it allows + * for )'s, ('s and (?{ ... })'s to be in the way + * of the quantifier and the EXACT-like node. -- japhy + */ + + if (NEAR_EXACT(next)) { + U8 *s; + regnode *text_node = next; + + if (PL_regkind[(U8)OP(next)] != EXACT) + NEXT_IMPT(text_node); + + if (PL_regkind[(U8)OP(text_node)] != EXACT) { + c1 = c2 = -1000; + } + else { + s = (U8*)STRING(text_node); + + if (!UTF) { + c2 = c1 = *s; + if (OP(text_node) == EXACTF) + c2 = PL_fold[c1]; + else if (OP(text_node) == EXACTFL) + c2 = PL_fold_locale[c1]; } - else { - c2 = c1 = utf8_to_uvchr(s, NULL); + else { /* UTF */ + if (OP(text_node) == EXACTF) { + STRLEN ulen1, ulen2; + U8 tmpbuf1[UTF8_MAXLEN*2+1]; + U8 tmpbuf2[UTF8_MAXLEN*2+1]; + + to_utf8_lower((U8*)s, tmpbuf1, &ulen1); + to_utf8_upper((U8*)s, tmpbuf2, &ulen2); + + c1 = utf8_to_uvuni(tmpbuf1, 0); + c2 = utf8_to_uvuni(tmpbuf2, 0); + } + else { + c2 = c1 = utf8_to_uvchr(s, NULL); + } } } } @@ -3234,12 +3339,13 @@ S_regmatch(pTHX_ regnode *prog) /* Find place 'next' could work */ if (!do_utf8) { if (c1 == c2) { - while (locinput <= e && *locinput != c1) + while (locinput <= e && + UCHARAT(locinput) != c1) locinput++; } else { while (locinput <= e - && *locinput != c1 - && *locinput != c2) + && UCHARAT(locinput) != c1 + && UCHARAT(locinput) != c2) locinput++; } count = locinput - old; @@ -3590,7 +3696,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max) register I32 c; register char *loceol = PL_regeol; register I32 hardcount = 0; - register bool do_utf8 = DO_UTF8(PL_reg_sv); + register bool do_utf8 = PL_reg_match_utf8; scan = PL_reginput; if (max != REG_INFTY && max < loceol - scan) @@ -3829,7 +3935,7 @@ S_regrepeat_hard(pTHX_ regnode *p, I32 max, I32 *lp) return 0; start = PL_reginput; - if (DO_UTF8(PL_reg_sv)) { + if (PL_reg_match_utf8) { while (PL_reginput < loceol && (scan = PL_reginput, res = regmatch(p))) { if (!count++) { l = 0; @@ -3926,14 +4032,10 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, register bool do_utf8) if (swash_fetch(sw, p, do_utf8)) match = TRUE; else if (flags & ANYOF_FOLD) { - U8 tmpbuf[UTF8_MAXLEN+1]; - - if (flags & ANYOF_LOCALE) { - PL_reg_flags |= RF_tainted; - uvchr_to_utf8(tmpbuf, toLOWER_LC_utf8(p)); - } - else - uvchr_to_utf8(tmpbuf, toLOWER_utf8(p)); + STRLEN ulen; + U8 tmpbuf[UTF8_MAXLEN*2+1]; + + toLOWER_utf8(p, tmpbuf, &ulen); if (swash_fetch(sw, tmpbuf, do_utf8)) match = TRUE; } @@ -4065,12 +4167,8 @@ S_reghopmaybe3(pTHX_ U8* s, I32 off, U8* lim) return s; } -#ifdef PERL_OBJECT -#include "XSUB.h" -#endif - static void -restore_pos(pTHXo_ void *arg) +restore_pos(pTHX_ void *arg) { if (PL_reg_eval_set) { if (PL_reg_oldsaved) {