From: Hugo van der Sanden Date: Sun, 14 Apr 2002 16:09:30 +0000 (+0100) Subject: Re: [ID 20020412.005] Dancing ??s X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d65afb4bb3ed16e1305854aa6e047d2d9d4bb0dd;p=p5sagit%2Fp5-mst-13.2.git Re: [ID 20020412.005] Dancing ??s Message-Id: <200204141509.g3EF9UQ18111@crypt.compulink.co.uk> p4raw-id: //depot/perl@15936 --- diff --git a/pod/perlop.pod b/pod/perlop.pod index e842317..6785d24 100644 --- a/pod/perlop.pod +++ b/pod/perlop.pod @@ -841,7 +841,11 @@ that you won't change the variables in the pattern. If you change them, Perl won't even notice. See also L<"qr/STRING/imosx">. If the PATTERN evaluates to the empty string, the last -I matched regular expression is used instead. +I matched regular expression is used instead. In this +case, only the C and C flags on the empty pattern is honoured - +the other flags are taken from the original pattern. If no match has +previously succeeded, this will (silently) act instead as a genuine +empty pattern (which will always match). If the C option is not used, C in list context returns a list consisting of the subexpressions matched by the parentheses in the diff --git a/pp_hot.c b/pp_hot.c index ec18858..3ff6dc6 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -1184,6 +1184,7 @@ PP(pp_match) { dSP; dTARG; register PMOP *pm = cPMOP; + PMOP *dynpm = pm; register char *t; register char *s; char *strend; @@ -1217,6 +1218,7 @@ PP(pp_match) PL_reg_match_utf8 = DO_UTF8(TARG); + /* PMdf_USED is set after a ?? matches once */ if (pm->op_pmdynflags & PMdf_USED) { failure: if (gimme == G_ARRAY) @@ -1224,17 +1226,19 @@ PP(pp_match) RETPUSHNO; } + /* empty pattern special-cased to use last successful pattern if possible */ if (!rx->prelen && PL_curpm) { pm = PL_curpm; rx = PM_GETRE(pm); } + if (rx->minlen > len) - goto failure; + goto failure; truebase = t = s; /* XXXX What part of this is needed with true \G-support? */ - if ((global = pm->op_pmflags & PMf_GLOBAL)) { + if ((global = dynpm->op_pmflags & PMf_GLOBAL)) { rx->startp[0] = -1; if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) { MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global); @@ -1287,8 +1291,8 @@ play_it_again: if (CALLREGEXEC(aTHX_ rx, s, strend, truebase, minmatch, TARG, NULL, r_flags)) { PL_curpm = pm; - if (pm->op_pmflags & PMf_ONCE) - pm->op_pmdynflags |= PMdf_USED; + if (dynpm->op_pmflags & PMf_ONCE) + dynpm->op_pmdynflags |= PMdf_USED; goto gotcha; } else @@ -1325,7 +1329,7 @@ play_it_again: } } if (global) { - if (pm->op_pmflags & PMf_CONTINUE) { + if (dynpm->op_pmflags & PMf_CONTINUE) { MAGIC* mg = 0; if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) mg = mg_find(TARG, PERL_MAGIC_regex_global); @@ -1378,8 +1382,8 @@ yup: /* Confirmed by INTUIT */ RX_MATCH_TAINTED_on(rx); TAINT_IF(RX_MATCH_TAINTED(rx)); PL_curpm = pm; - if (pm->op_pmflags & PMf_ONCE) - pm->op_pmdynflags |= PMdf_USED; + if (dynpm->op_pmflags & PMf_ONCE) + dynpm->op_pmdynflags |= PMdf_USED; if (RX_MATCH_COPIED(rx)) Safefree(rx->subbeg); RX_MATCH_COPIED_off(rx); @@ -1416,7 +1420,7 @@ yup: /* Confirmed by INTUIT */ nope: ret_no: - if (global && !(pm->op_pmflags & PMf_CONTINUE)) { + if (global && !(dynpm->op_pmflags & PMf_CONTINUE)) { if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) { MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global); if (mg) diff --git a/t/op/pat.t b/t/op/pat.t index 2ae16c1..853c59c 100755 --- a/t/op/pat.t +++ b/t/op/pat.t @@ -6,7 +6,7 @@ $| = 1; -print "1..897\n"; +print "1..900\n"; BEGIN { chdir 't' if -d 't'; @@ -2798,3 +2798,28 @@ print "# some Unicode properties\n"; print eval { "a" =~ /\p{qrst} / } ? "not ok $test\n" : "ok $test\n"; $test++; } + +{ + # [ID 20020412.005] wrong pmop flags checked when empty pattern + # requires reuse of last successful pattern + my $test = 898; + $test =~ /\d/; + for (0 .. 1) { + my $match = ?? + 0; + if ($match != $_) { + print "ok $test\n"; + } else { + printf "not ok %s\t# 'match once' %s on %s iteration\n", $test, + $match ? 'succeeded' : 'failed', $_ ? 'second' : 'first'; + } + ++$test; + } + $test =~ /(\d)/; + my $result = join '', $test =~ //g; + if ($result eq $test) { + print "ok $test\n"; + } else { + printf "not ok %s\t# expected '%s', got '%s'\n", $test, $test, $result; + } + ++$test; +}