change#4849 wasn't restoring savestack correctly; make loops that have
Gurusamy Sarathy [Fri, 25 Feb 2000 19:23:58 +0000 (19:23 +0000)]
continue blocks recognizable at run time

p4raw-link: @4849 on //depot/perl: 872465582bf743a066e1240f2c3e941735674827

p4raw-id: //depot/perl@5255

op.c
op.h
pp_ctl.c
t/cmd/while.t

diff --git a/op.c b/op.c
index 04a84b8..6ed38e4 100644 (file)
--- a/op.c
+++ b/op.c
@@ -3764,6 +3764,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
     OP *listop;
     OP *o;
     OP *condop;
+    U8 loopflags = 0;
 
     if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
                 || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
@@ -3796,8 +3797,10 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
        block = scope(block);
     }
 
-    if (cont)
+    if (cont) {
        next = LINKLIST(cont);
+       loopflags |= OPpLOOP_CONTINUE;
+    }
     if (expr) {
        cont = append_elem(OP_LINESEQ, cont, newOP(OP_UNSTACK, 0));
        if ((line_t)whileline != NOLINE) {
@@ -3840,6 +3843,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
 
     loop->op_redoop = redo;
     loop->op_lastop = o;
+    o->op_private |= loopflags;
 
     if (next)
        loop->op_nextop = next;
diff --git a/op.h b/op.h
index 6019486..52b68cb 100644 (file)
--- a/op.h
+++ b/op.h
@@ -139,6 +139,9 @@ Deprecated.  Use C<GIMME_V> instead.
 /* Private for OP_REPEAT */
 #define OPpREPEAT_DOLIST       64      /* List replication. */
 
+/* Private for OP_LEAVELOOP */
+#define OPpLOOP_CONTINUE       64      /* a continue block is present */
+
 /* Private for OP_RV2?V, OP_?ELEM */
 #define OPpDEREF               (32|64) /* Want ref to something: */
 #define OPpDEREF_AV            32      /*   Want ref to AV. */
index 308c824..5523592 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1983,17 +1983,14 @@ PP(pp_next)
     if (cxix < cxstack_ix)
        dounwind(cxix);
 
-    cx = &cxstack[cxstack_ix];
-    {
-       OP *nextop = cx->blk_loop.next_op;
-       /* clean scope, but only if there's no continue block */
-       if (nextop == cUNOPx(cx->blk_loop.last_op)->op_first->op_next) {
-           TOPBLOCK(cx);
-           oldsave = PL_scopestack[PL_scopestack_ix - 1];
-           LEAVE_SCOPE(oldsave);
-       }
-       return nextop;
+    TOPBLOCK(cx);
+
+    /* clean scope, but only if there's no continue block */
+    if (!(cx->blk_loop.last_op->op_private & OPpLOOP_CONTINUE)) {
+       oldsave = PL_scopestack[PL_scopestack_ix - 1];
+       LEAVE_SCOPE(oldsave);
     }
+    return cx->blk_loop.next_op;
 }
 
 PP(pp_redo)
index 46bbdea..ecc15ed 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..19\n";
+print "1..22\n";
 
 open (tmp,'>Cmd_while.tmp') || die "Can't create Cmd_while.tmp.";
 print tmp "tvi925\n";
@@ -160,3 +160,20 @@ print "ok $i\n";
         print "ok $l\n"
     }
 }
+
+$i = 20;
+{
+    while (1) {
+       my $x;
+       print $x if defined $x;
+       $x = "not ";
+       print "ok $i\n"; ++$i;
+       if ($i == 21) {
+           next;
+       }
+       last;
+    }
+    continue {
+        print "ok $i\n"; ++$i;
+    }
+}