X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/faf11cac614129491d0258772ee4e6f8a3fb39e8..e4a054ea0a8cd1ea68a25b95ec3055e51df2d6d4:/regexec.c diff --git a/regexec.c b/regexec.c index bdc05af..6a7f064 100644 --- a/regexec.c +++ b/regexec.c @@ -5,6 +5,17 @@ * "One Ring to rule them all, One Ring to find them..." */ +/* This file contains functions for executing a regular expression. See + * also regcomp.c which funnily enough, contains functions for compiling + * a regular expression. + * + * This file is also copied at build time to ext/re/re_exec.c, where + * it's built with -DPERL_EXT_RE_BUILD -DPERL_EXT_RE_DEBUG -DPERL_EXT. + * This causes the main functions to be compiled under new names and with + * debugging support added, which makes "use re 'debug'" work. + + */ + /* NOTE: this is derived from Henry Spencer's regexp code, and should not * confused with the original package (see point 3 below). Thanks, Henry! */ @@ -67,7 +78,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, 2004, 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. @@ -86,6 +98,7 @@ #define RF_warned 2 /* warned about big count? */ #define RF_evaled 4 /* Did an EVAL with setting? */ #define RF_utf8 8 /* String contains multibyte chars? */ +#define RF_false 16 /* odd number of nested negatives */ #define UTF ((PL_reg_flags & RF_utf8) != 0) @@ -171,7 +184,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]); @@ -396,10 +409,12 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, I32 ml_anch; register char *other_last = Nullch; /* other substr checked before this */ char *check_at = Nullch; /* check substr found at this pos */ + I32 multiline = prog->reganch & PMf_MULTILINE; #ifdef DEBUGGING 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, @@ -456,7 +471,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, if (prog->reganch & ROPT_ANCH) { /* Match at beg-of-str or after \n */ ml_anch = !( (prog->reganch & ROPT_ANCH_SINGLE) || ( (prog->reganch & ROPT_ANCH_BOL) - && !PL_multiline ) ); /* Check after \n? */ + && !multiline ) ); /* Check after \n? */ if (!ml_anch) { if ( !(prog->reganch & (ROPT_ANCH_GPOS /* Checked by the caller */ @@ -541,17 +556,20 @@ 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; } else if (prog->reganch & ROPT_CANY_SEEN) s = fbm_instr((U8*)(s + start_shift), (U8*)(strend - end_shift), - check, PL_multiline ? FBMrf_MULTILINE : 0); + check, multiline ? FBMrf_MULTILINE : 0); else s = fbm_instr(HOP3(s, start_shift, strend), HOP3(strend, -end_shift, strbeg), - check, PL_multiline ? FBMrf_MULTILINE : 0); + check, multiline ? FBMrf_MULTILINE : 0); /* Update the count-of-usability, remove useless subpatterns, unshift s. */ @@ -595,7 +613,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, t = s - prog->check_offset_max; if (s - strpos > prog->check_offset_max /* signed-corrected t > strpos */ - && (!(prog->reganch & ROPT_UTF8) + && (!do_utf8 || ((t = reghopmaybe3_c(s, -(prog->check_offset_max), strpos)) && t > strpos))) /* EMPTY */; @@ -620,7 +638,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, HOP3(HOP3(last1, prog->anchored_offset, strend) + SvCUR(must), -(SvTAIL(must)!=0), strbeg), must, - PL_multiline ? FBMrf_MULTILINE : 0 + multiline ? FBMrf_MULTILINE : 0 ); DEBUG_r(PerlIO_printf(Perl_debug_log, "%s anchored substr `%s%.*s%s'%s", @@ -681,7 +699,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, s = fbm_instr((unsigned char*)s, (unsigned char*)last + SvCUR(must) - (SvTAIL(must)!=0), - must, PL_multiline ? FBMrf_MULTILINE : 0); + must, multiline ? FBMrf_MULTILINE : 0); DEBUG_r(PerlIO_printf(Perl_debug_log, "%s floating substr `%s%.*s%s'%s", (s ? "Found" : "Contradicts"), PL_colors[0], @@ -715,7 +733,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos, t = s - prog->check_offset_max; if (s - strpos > prog->check_offset_max /* signed-corrected t > strpos */ - && (!(prog->reganch & ROPT_UTF8) + && (!do_utf8 || ((t = reghopmaybe3_c(s, -prog->check_offset_max, strpos)) && t > strpos))) { /* Fixed substring is found far enough so that the match @@ -848,10 +866,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 @@ -950,6 +965,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta I32 doevery = (prog->reganch & ROPT_SKIP) == 0; char *m; STRLEN ln; + STRLEN lnc; + register STRLEN uskip; unsigned int c1; unsigned int c2; char *e; @@ -959,25 +976,40 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta /* We know what class it must start with. */ switch (OP(c)) { case ANYOF: - while (s < strend) { - STRLEN skip = do_utf8 ? UTF8SKIP(s) : 1; - - if (do_utf8 ? - reginclass(c, (U8*)s, 0, do_utf8) : - REGINCLASS(c, (U8*)s) || - (ANYOF_FOLD_SHARP_S(c, s, strend) && - /* The assignment of 2 is intentional: - * for the sharp s, the skip is 2. */ - (skip = SHARP_S_SKIP) - )) { - if (tmp && (norun || regtry(prog, s))) - goto got_it; - else - tmp = doevery; - } - else - tmp = 1; - s += skip; + if (do_utf8) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { + if ((ANYOF_FLAGS(c) & ANYOF_UNICODE) || + !UTF8_IS_INVARIANT((U8)s[0]) ? + reginclass(c, (U8*)s, 0, do_utf8) : + REGINCLASS(c, (U8*)s)) { + if (tmp && (norun || regtry(prog, s))) + goto got_it; + else + tmp = doevery; + } + else + tmp = 1; + s += uskip; + } + } + else { + while (s < strend) { + STRLEN skip = 1; + + if (REGINCLASS(c, (U8*)s) || + (ANYOF_FOLD_SHARP_S(c, s, strend) && + /* The assignment of 2 is intentional: + * for the folded sharp s, the skip is 2. */ + (skip = SHARP_S_SKIP))) { + if (tmp && (norun || regtry(prog, s))) + goto got_it; + else + tmp = doevery; + } + else + tmp = 1; + s += skip; + } } break; case CANY: @@ -990,10 +1022,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } break; case EXACTF: - m = STRING(c); - ln = STR_LEN(c); + m = STRING(c); + ln = STR_LEN(c); /* length to match in octets/bytes */ + lnc = (I32) ln; /* length to match in characters */ if (UTF) { STRLEN ulen1, ulen2; + U8 *sm = (U8 *) m; U8 tmpbuf1[UTF8_MAXLEN_UCLC+1]; U8 tmpbuf2[UTF8_MAXLEN_UCLC+1]; @@ -1004,6 +1038,11 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta 0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY); c2 = utf8n_to_uvchr(tmpbuf2, UTF8_MAXLEN_UCLC, 0, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY); + lnc = 0; + while (sm < ((U8 *) m + ln)) { + lnc++; + sm += UTF8SKIP(sm); + } } else { c1 = *(U8*)m; @@ -1011,12 +1050,13 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } goto do_exactf; case EXACTFL: - m = STRING(c); - ln = STR_LEN(c); + m = STRING(c); + ln = STR_LEN(c); + lnc = (I32) ln; c1 = *(U8*)m; c2 = PL_fold_locale[c1]; do_exactf: - e = HOP3c(strend, -(I32)ln, s); + e = HOP3c(strend, -((I32)lnc), s); if (norun && e < s) e = s; /* Due to minlen logic of intuit() */ @@ -1039,6 +1079,8 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta STRLEN len, foldlen; if (c1 == c2) { + /* Upper and lower of 1st char are equal - + * probably not a "letter". */ while (s <= e) { c = utf8n_to_uvchr((U8*)s, UTF8_MAXLEN, &len, ckWARN(WARN_UTF8) ? @@ -1143,7 +1185,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta tmp = ((OP(c) == BOUND ? isALNUM_uni(tmp) : isALNUM_LC_uvchr(UNI_TO_NATIVE(tmp))) != 0); LOAD_UTF8_CHARCLASS(alnum,"a"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (tmp == !(OP(c) == BOUND ? swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) : isALNUM_LC_utf8((U8*)s))) @@ -1152,7 +1194,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta if ((norun || regtry(prog, s))) goto got_it; } - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1186,14 +1228,14 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta tmp = ((OP(c) == NBOUND ? isALNUM_uni(tmp) : isALNUM_LC_uvchr(UNI_TO_NATIVE(tmp))) != 0); LOAD_UTF8_CHARCLASS(alnum,"a"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (tmp == !(OP(c) == NBOUND ? swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) : isALNUM_LC_utf8((U8*)s))) tmp = !tmp; else if ((norun || regtry(prog, s))) goto got_it; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1215,7 +1257,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case ALNUM: if (do_utf8) { LOAD_UTF8_CHARCLASS(alnum,"a"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1224,7 +1266,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1244,7 +1286,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case ALNUML: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (isALNUM_LC_utf8((U8*)s)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1253,7 +1295,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1273,7 +1315,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NALNUM: if (do_utf8) { LOAD_UTF8_CHARCLASS(alnum,"a"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1282,7 +1324,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1302,7 +1344,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NALNUML: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!isALNUM_LC_utf8((U8*)s)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1311,7 +1353,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1331,7 +1373,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case SPACE: if (do_utf8) { LOAD_UTF8_CHARCLASS(space," "); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1340,7 +1382,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1360,7 +1402,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case SPACEL: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (*s == ' ' || isSPACE_LC_utf8((U8*)s)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1369,7 +1411,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1389,7 +1431,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NSPACE: if (do_utf8) { LOAD_UTF8_CHARCLASS(space," "); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!(*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8))) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1398,7 +1440,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1418,7 +1460,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NSPACEL: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!(*s == ' ' || isSPACE_LC_utf8((U8*)s))) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1427,7 +1469,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1447,7 +1489,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case DIGIT: if (do_utf8) { LOAD_UTF8_CHARCLASS(digit,"0"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1456,7 +1498,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1476,7 +1518,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case DIGITL: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (isDIGIT_LC_utf8((U8*)s)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1485,7 +1527,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1505,7 +1547,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NDIGIT: if (do_utf8) { LOAD_UTF8_CHARCLASS(digit,"0"); - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1514,7 +1556,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1534,7 +1576,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta case NDIGITL: PL_reg_flags |= RF_tainted; if (do_utf8) { - while (s < strend) { + while (s + (uskip = UTF8SKIP(s)) <= strend) { if (!isDIGIT_LC_utf8((U8*)s)) { if (tmp && (norun || regtry(prog, s))) goto got_it; @@ -1543,7 +1585,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, char *strend, char *sta } else tmp = 1; - s += UTF8SKIP(s); + s += uskip; } } else { @@ -1593,10 +1635,12 @@ 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); + I32 multiline = prog->reganch & PMf_MULTILINE; #ifdef DEBUGGING 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; @@ -1708,7 +1752,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * if (prog->reganch & (ROPT_ANCH & ~ROPT_ANCH_GPOS)) { if (s == startpos && regtry(prog, startpos)) goto got_it; - else if (PL_multiline || (prog->reganch & ROPT_IMPLICIT) + else if (multiline || (prog->reganch & ROPT_IMPLICIT) || (prog->reganch & ROPT_ANCH_MBOL)) /* XXXX SBOL? */ { char *end; @@ -1842,7 +1886,10 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * end_shift, &scream_pos, 0)) : (s = fbm_instr((unsigned char*)HOP3(s, back_min, strend), (unsigned char*)strend, must, - PL_multiline ? FBMrf_MULTILINE : 0))) ) { + 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); @@ -1882,9 +1929,12 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * goto phooey; } else if ((c = prog->regstclass)) { - if (minlen && PL_regkind[(U8)OP(prog->regstclass)] != EXACT) + if (minlen) { + I32 op = (U8)OP(prog->regstclass); /* don't bother with what can't match */ - strend = HOPc(strend, -(minlen - 1)); + if (PL_regkind[op] != EXACT && op != CANY) + strend = HOPc(strend, -(minlen - 1)); + } DEBUG_r({ SV *prop = sv_newmortal(); char *s0; @@ -1926,6 +1976,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; @@ -1934,7 +1987,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char * if (SvTAIL(float_real)) { if (memEQ(strend - len + 1, little, len - 1)) last = strend - len + 1; - else if (!PL_multiline) + else if (!multiline) last = memEQ(strend - len, little, len) ? strend - len : Nullch; else @@ -1993,17 +2046,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; @@ -2054,8 +2118,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_5005THREADS */ - SAVESPTR(DEFSV); + SAVE_DEFSV; DEFSV = PL_reg_sv; } @@ -2093,6 +2156,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 @@ -2107,6 +2173,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos) PL_reglastparen = &prog->lastparen; PL_reglastcloseparen = &prog->lastcloseparen; prog->lastparen = 0; + prog->lastcloseparen = 0; PL_regsize = 0; DEBUG_r(PL_reg_starttry = startpos); if (PL_reg_start_tmpl <= prog->nparens) { @@ -2269,17 +2336,17 @@ S_regmatch(pTHX_ regnode *prog) regprop(prop, scan); { char *s0 = - do_utf8 ? + do_utf8 && OP(scan) != CANY ? pv_uni_display(dsv0, (U8*)(locinput - pref_len), pref0_len, 60, UNI_DISPLAY_REGEX) : locinput - pref_len; int len0 = do_utf8 ? strlen(s0) : pref0_len; - char *s1 = do_utf8 ? + char *s1 = do_utf8 && OP(scan) != CANY ? pv_uni_display(dsv1, (U8*)(locinput - pref_len + pref0_len), pref_len - pref0_len, 60, UNI_DISPLAY_REGEX) : locinput - pref_len + pref0_len; int len1 = do_utf8 ? strlen(s1) : pref_len - pref0_len; - char *s2 = do_utf8 ? + char *s2 = do_utf8 && OP(scan) != CANY ? pv_uni_display(dsv2, (U8*)locinput, PL_regeol - locinput, 60, UNI_DISPLAY_REGEX) : locinput; @@ -2310,8 +2377,7 @@ S_regmatch(pTHX_ regnode *prog) switch (OP(scan)) { case BOL: - if (locinput == PL_bostr || (PL_multiline && - (nextchr || locinput < PL_regeol) && locinput[-1] == '\n') ) + if (locinput == PL_bostr) { /* regtill = regbol; */ break; @@ -2333,12 +2399,8 @@ S_regmatch(pTHX_ regnode *prog) break; sayNO; case EOL: - if (PL_multiline) - goto meol; - else goto seol; case MEOL: - meol: if ((nextchr || locinput < PL_regeol) && nextchr != '\n') sayNO; break; @@ -2791,13 +2853,14 @@ S_regmatch(pTHX_ regnode *prog) dSP; OP_4tree *oop = PL_op; COP *ocurcop = PL_curcop; - SV **ocurpad = PL_curpad; + PAD *old_comppad; SV *ret; + struct regexp *oreg = PL_reg_re; n = ARG(scan); PL_op = (OP_4tree*)PL_regdata->data[n]; DEBUG_r( PerlIO_printf(Perl_debug_log, " re_eval 0x%"UVxf"\n", PTR2UV(PL_op)) ); - PL_curpad = AvARRAY((AV*)PL_regdata->data[n + 2]); + PAD_SAVE_LOCAL(old_comppad, (PAD*)PL_regdata->data[n + 2]); PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr; { @@ -2805,7 +2868,7 @@ S_regmatch(pTHX_ regnode *prog) CALLRUNOPS(aTHX); /* Scalar context. */ SPAGAIN; if (SP == before) - ret = Nullsv; /* protect against empty (?{}) blocks. */ + ret = &PL_sv_undef; /* protect against empty (?{}) blocks. */ else { ret = POPs; PUTBACK; @@ -2813,7 +2876,7 @@ S_regmatch(pTHX_ regnode *prog) } PL_op = oop; - PL_curpad = ocurpad; + PAD_RESTORE_LOCAL(old_comppad); PL_curcop = ocurcop; if (logical) { if (logical == 2) { /* Postponed subexpression. */ @@ -2821,13 +2884,18 @@ S_regmatch(pTHX_ regnode *prog) MAGIC *mg = Null(MAGIC*); re_cc_state state; CHECKPOINT cp, lastcp; - - if(SvROK(ret) || SvRMAGICAL(ret)) { - SV *sv = SvROK(ret) ? SvRV(ret) : ret; - - if(SvMAGICAL(sv)) - mg = mg_find(sv, PERL_MAGIC_qr); + int toggleutf; + register SV *sv; + + 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); @@ -2841,9 +2909,11 @@ S_regmatch(pTHX_ regnode *prog) I32 onpar = PL_regnpar; Zero(&pm, 1, PMOP); + 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; @@ -2873,6 +2943,9 @@ S_regmatch(pTHX_ regnode *prog) *PL_reglastcloseparen = 0; PL_reg_call_cc = &state; PL_reginput = locinput; + toggleutf = ((PL_reg_flags & RF_utf8) != 0) ^ + ((re->reganch & ROPT_UTF8) != 0); + if (toggleutf) PL_reg_flags ^= RF_utf8; /* XXXX This is too dramatic a measure... */ PL_reg_maxiter = 0; @@ -2887,6 +2960,7 @@ S_regmatch(pTHX_ regnode *prog) PL_regcc = state.cc; PL_reg_re = state.re; cache_re(PL_reg_re); + if (toggleutf) PL_reg_flags ^= RF_utf8; /* XXXX This is too dramatic a measure... */ PL_reg_maxiter = 0; @@ -2903,6 +2977,7 @@ S_regmatch(pTHX_ regnode *prog) PL_regcc = state.cc; PL_reg_re = state.re; cache_re(PL_reg_re); + if (toggleutf) PL_reg_flags ^= RF_utf8; /* XXXX This is too dramatic a measure... */ PL_reg_maxiter = 0; @@ -2913,8 +2988,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: @@ -3147,7 +3224,10 @@ S_regmatch(pTHX_ regnode *prog) "%*s already tried at this position...\n", REPORT_CODE_OFF+PL_regindent*2, "") ); - sayNO_SILENT; + if (PL_reg_flags & RF_false) + sayYES; + else + sayNO_SILENT; } PL_reg_poscache[o] |= (1<= ln || (n == REG_INFTY && ln > 0 && l)) { /* ln overflow ? */ + while (n >= ln || (n == REG_INFTY && ln > 0)) { /* ln overflow ? */ /* If it could work, try it. */ if (c1 == -1000 || UCHARAT(PL_reginput) == c1 || @@ -3392,13 +3451,6 @@ S_regmatch(pTHX_ regnode *prog) } else { n = regrepeat_hard(scan, n, &l); - /* if we matched something zero-length we don't need to - backtrack, unless the minimum count is zero and we - are capturing the result - in that case the capture - being defined or not may affect later execution - */ - if (n != 0 && l == 0 && !(paren && ln == 0)) - ln = n; /* don't backtrack */ locinput = PL_reginput; DEBUG_r( PerlIO_printf(Perl_debug_log, @@ -3415,19 +3467,8 @@ S_regmatch(pTHX_ regnode *prog) if (! HAS_TEXT(text_node)) c1 = c2 = -1000; else { if (PL_regkind[(U8)OP(text_node)] == REF) { - I32 n, ln; - n = ARG(text_node); /* which paren pair */ - ln = PL_regstartp[n]; - /* assume yes if we haven't seen CLOSEn */ - if ( - (I32)*PL_reglastparen < n || - ln == -1 || - ln == PL_regendp[n] - ) { - c1 = c2 = -1000; - goto assume_ok_REG; - } - c1 = *(PL_bostr + ln); + c1 = c2 = -1000; + goto assume_ok_REG; } else { c1 = (U8)*STRING(text_node); } @@ -3524,19 +3565,8 @@ S_regmatch(pTHX_ regnode *prog) if (! HAS_TEXT(text_node)) c1 = c2 = -1000; else { if (PL_regkind[(U8)OP(text_node)] == REF) { - I32 n, ln; - n = ARG(text_node); /* which paren pair */ - ln = PL_regstartp[n]; - /* assume yes if we haven't seen CLOSEn */ - if ( - (I32)*PL_reglastparen < n || - ln == -1 || - ln == PL_regendp[n] - ) { - c1 = c2 = -1000; - goto assume_ok_easy; - } - s = (U8*)PL_bostr + ln; + c1 = c2 = -1000; + goto assume_ok_easy; } else { s = (U8*)STRING(text_node); } @@ -3682,14 +3712,14 @@ S_regmatch(pTHX_ regnode *prog) /* If it could work, try it. */ if (c == (UV)c1 || c == (UV)c2) { - TRYPAREN(paren, n, PL_reginput); + TRYPAREN(paren, ln, PL_reginput); REGCP_UNWIND(lastcp); } } /* If it could work, try it. */ else if (c1 == -1000) { - TRYPAREN(paren, n, PL_reginput); + TRYPAREN(paren, ln, PL_reginput); REGCP_UNWIND(lastcp); } /* Couldn't or didn't -- move forward. */ @@ -3707,7 +3737,7 @@ S_regmatch(pTHX_ regnode *prog) n = regrepeat(scan, n); locinput = PL_reginput; if (ln < n && PL_regkind[(U8)OP(next)] == EOL && - ((!PL_multiline && OP(next) != MEOL) || + (OP(next) != MEOL || OP(next) == SEOL || OP(next) == EOS)) { ln = n; /* why back off? */ @@ -3830,6 +3860,7 @@ S_regmatch(pTHX_ regnode *prog) } else PL_reginput = locinput; + PL_reg_flags ^= RF_false; goto do_ifmatch; case IFMATCH: n = 1; @@ -3845,6 +3876,8 @@ S_regmatch(pTHX_ regnode *prog) do_ifmatch: inner = NEXTOPER(NEXTOPER(scan)); if (regmatch(inner) != n) { + if (n == 0) + PL_reg_flags ^= RF_false; say_no: if (logical) { logical = 0; @@ -3854,6 +3887,8 @@ S_regmatch(pTHX_ regnode *prog) else sayNO; } + if (n == 0) + PL_reg_flags ^= RF_false; say_yes: if (logical) { logical = 0; @@ -4220,7 +4255,7 @@ S_regrepeat(pTHX_ regnode *p, I32 max) /* - regrepeat_hard - repeatedly match something, report total lenth and length * - * The repeater is supposed to have constant length. + * The repeater is supposed to have constant non-zero length. */ STATIC I32 @@ -4331,13 +4366,12 @@ S_reginclass(pTHX_ register regnode *n, register U8* p, STRLEN* lenp, register b char flags = ANYOF_FLAGS(n); bool match = FALSE; UV c = *p; - STRLEN len = 1; + STRLEN len = 0; STRLEN plen; - c = (do_utf8 && !UTF8_IS_INVARIANT(c)) ? - utf8n_to_uvchr(p, UTF8_MAXLEN, &len, - ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY) : - NATIVE_TO_UTF(c); + if (do_utf8 && !UTF8_IS_INVARIANT(c)) + c = utf8n_to_uvchr(p, UTF8_MAXLEN, &len, + ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY); plen = lenp ? *lenp : UNISKIP(NATIVE_TO_UNI(c)); if (do_utf8 || (flags & ANYOF_UNICODE)) { @@ -4518,6 +4552,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;