fix bug in backtracking optimizer (from Makoto Ishisone
Gurusamy Sarathy [Sat, 19 Feb 2000 17:33:59 +0000 (17:33 +0000)]
<ishisone@sra.co.jp>)

p4raw-id: //depot/perl@5151

regexec.c
t/op/pat.t

index e63fa6f..f9f2cc0 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -3045,8 +3045,14 @@ 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) == SEOL))
+                   (!PL_multiline  || OP(next) == SEOL || OP(next) == EOS)) {
                    ln = n;                     /* why back off? */
+                   /* ...because $ and \Z can match before *and* after
+                      newline at the end.  Consider "\n\n" =~ /\n+\Z\n/.
+                      We should back off by one in this case. */
+                   if (UCHARAT(PL_reginput - 1) == '\n' && OP(next) != EOS)
+                       ln--;
+               }
                REGCP_SET;
                if (paren) {
                    while (n >= ln) {
index 439796d..142b82e 100755 (executable)
@@ -4,7 +4,7 @@
 # the format supported by op/regexp.t.  If you want to add a test
 # that does fit that format, add it to op/re_tests, not here.
 
-print "1..207\n";
+print "1..210\n";
 
 BEGIN {
     chdir 't' if -d 't';
@@ -978,3 +978,16 @@ $test++;
 print "not " if "@b" ne "@c";
 print "ok $test\n";
 $test++;
+
+# see if backtracking optimization works correctly
+"\n\n" =~ /\n  $ \n/x or print "not ";
+print "ok $test\n";
+$test++;
+
+"\n\n" =~ /\n* $ \n/x or print "not ";
+print "ok $test\n";
+$test++;
+
+"\n\n" =~ /\n+ $ \n/x or print "not ";
+print "ok $test\n";
+$test++;