This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge branch 'vincent/rvalue_stmt_given' into blead
authorVincent Pit <perl@profvince.com>
Wed, 19 May 2010 20:59:58 +0000 (22:59 +0200)
committerVincent Pit <perl@profvince.com>
Wed, 19 May 2010 20:59:58 +0000 (22:59 +0200)
1  2 
op.c
pod/perlsyn.pod
pp_ctl.c

diff --combined op.c
--- 1/op.c
--- 2/op.c
+++ b/op.c
@@@ -562,7 -562,6 +562,7 @@@ Perl_op_clear(pTHX_ OP *o
            o->op_targ = 0;
            goto retry;
        }
 +    case OP_ENTERTRY:
      case OP_ENTEREVAL:        /* Was holding hints. */
        o->op_targ = 0;
        break;
@@@ -924,25 -923,28 +924,28 @@@ Perl_scalar(pTHX_ OP *o
      case OP_LEAVETRY:
        kid = cLISTOPo->op_first;
        scalar(kid);
-       while ((kid = kid->op_sibling)) {
-           if (kid->op_sibling)
-               scalarvoid(kid);
-           else
+       kid = kid->op_sibling;
+     do_kids:
+       while (kid) {
+           OP *sib = kid->op_sibling;
+           if (sib && kid->op_type != OP_LEAVEWHEN) {
+               if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) {
+                   scalar(kid);
+                   scalarvoid(sib);
+                   break;
+               } else
+                   scalarvoid(kid);
+           } else
                scalar(kid);
+           kid = sib;
        }
        PL_curcop = &PL_compiling;
        break;
      case OP_SCOPE:
      case OP_LINESEQ:
      case OP_LIST:
-       for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) {
-           if (kid->op_sibling)
-               scalarvoid(kid);
-           else
-               scalar(kid);
-       }
-       PL_curcop = &PL_compiling;
-       break;
+       kid = cLISTOPo->op_first;
+       goto do_kids;
      case OP_SORT:
        Perl_ck_warner(aTHX_ packWARN(WARN_VOID), "Useless use of sort in scalar context");
        break;
@@@ -986,7 -988,7 +989,7 @@@ Perl_scalarvoid(pTHX_ OP *o
      want = o->op_flags & OPf_WANT;
      if ((want && want != OPf_WANT_SCALAR)
         || (PL_parser && PL_parser->error_count)
-        || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE)
+        || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE || o->op_type == OP_LEAVEWHEN)
      {
        return o;
      }
@@@ -1297,24 -1299,27 +1300,27 @@@ Perl_list(pTHX_ OP *o
      case OP_LEAVETRY:
        kid = cLISTOPo->op_first;
        list(kid);
-       while ((kid = kid->op_sibling)) {
-           if (kid->op_sibling)
-               scalarvoid(kid);
-           else
+       kid = kid->op_sibling;
+     do_kids:
+       while (kid) {
+           OP *sib = kid->op_sibling;
+           if (sib && kid->op_type != OP_LEAVEWHEN) {
+               if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) {
+                   list(kid);
+                   scalarvoid(sib);
+                   break;
+               } else
+                   scalarvoid(kid);
+           } else
                list(kid);
+           kid = sib;
        }
        PL_curcop = &PL_compiling;
        break;
      case OP_SCOPE:
      case OP_LINESEQ:
-       for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) {
-           if (kid->op_sibling)
-               scalarvoid(kid);
-           else
-               list(kid);
-       }
-       PL_curcop = &PL_compiling;
-       break;
+       kid = cLISTOPo->op_first;
+       goto do_kids;
      }
      return o;
  }
@@@ -5282,11 -5287,14 +5288,11 @@@ S_looks_like_bool(pTHX_ const OP *o
             && looks_like_bool(cLOGOPo->op_first->op_sibling));
  
        case OP_NULL:
 +      case OP_SCALAR:
            return (
                o->op_flags & OPf_KIDS
            && looks_like_bool(cUNOPo->op_first));
  
 -        case OP_SCALAR:
 -            return looks_like_bool(cUNOPo->op_first);
 -
 -
        case OP_ENTERSUB:
  
        case OP_NOT:    case OP_XOR:
@@@ -5712,9 -5720,7 +5718,9 @@@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o
                 )&& !attrs) {
                if (CvFLAGS(PL_compcv)) {
                    /* might have had built-in attrs applied */
 -                  CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS);
 +                  if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv) && ckWARN(WARN_MISC))
 +                      Perl_warner(aTHX_ packWARN(WARN_MISC), "lvalue attribute ignored after the subroutine has been defined");
 +                  CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS & ~CVf_LVALUE);
                }
                /* just a "sub foo;" when &foo is already defined */
                SAVEFREESV(PL_compcv);
                    && block->op_type != OP_NULL
  #endif
        ) {
 +          cv_flags_t existing_builtin_attrs = CvFLAGS(cv) & CVf_BUILTIN_ATTRS;
            cv_undef(cv);
 -          CvFLAGS(cv) = CvFLAGS(PL_compcv);
 +          CvFLAGS(cv) = CvFLAGS(PL_compcv) | existing_builtin_attrs;
            if (!CvWEAKOUTSIDE(cv))
                SvREFCNT_dec(CvOUTSIDE(cv));
            CvOUTSIDE(cv) = CvOUTSIDE(PL_compcv);
@@@ -7746,14 -7751,8 +7752,14 @@@ Perl_ck_shift(pTHX_ OP *o
      PERL_ARGS_ASSERT_CK_SHIFT;
  
      if (!(o->op_flags & OPf_KIDS)) {
 -      OP *argop = newUNOP(OP_RV2AV, 0,
 -          scalar(newGVOP(OP_GV, 0, CvUNIQUE(PL_compcv) ? PL_argvgv : PL_defgv)));
 +      OP *argop;
 +
 +      if (!CvUNIQUE(PL_compcv)) {
 +          o->op_flags |= OPf_SPECIAL;
 +          return o;
 +      }
 +
 +      argop = newUNOP(OP_RV2AV, 0, scalar(newGVOP(OP_GV, 0, PL_argvgv)));
  #ifdef PERL_MAD
        OP * const oldo = o;
        o = newUNOP(type, 0, scalar(argop));
@@@ -8373,7 -8372,6 +8379,7 @@@ Perl_ck_each(pTHX_ OP *o
     container of the rep_op var */
  STATIC OP *
  S_opt_scalarhv(pTHX_ OP *rep_op) {
 +    dVAR;
      UNOP *unop;
  
      PERL_ARGS_ASSERT_OPT_SCALARHV;
@@@ -8684,7 -8682,7 +8690,7 @@@ Perl_peep(pTHX_ register OP *o
              ){        
                  OP * nop = o;
                  OP * lop = o;
 -                if (!(nop->op_flags && OPf_WANT_VOID)) {
 +                if (!((nop->op_flags & OPf_WANT) == OPf_WANT_VOID)) {
                      while (nop && nop->op_next) {
                          switch (nop->op_next->op_type) {
                              case OP_NOT:
                          }
                      }            
                  }
 -                if (lop->op_flags && OPf_WANT_VOID) {
 +                if ((lop->op_flags & OPf_WANT) == OPf_WANT_VOID) {
                      if (fop->op_type == OP_PADHV || fop->op_type == OP_RV2HV) 
                          cLOGOP->op_first = opt_scalarhv(fop);
                      if (sop && (sop->op_type == OP_PADHV || sop->op_type == OP_RV2HV)) 
diff --combined pod/perlsyn.pod
@@@ -228,9 -228,6 +228,9 @@@ The following compound statements may b
      if (EXPR) BLOCK
      if (EXPR) BLOCK else BLOCK
      if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
 +    unless (EXPR) BLOCK
 +    unless (EXPR) BLOCK else BLOCK
 +    unless (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
      LABEL while (EXPR) BLOCK
      LABEL while (EXPR) BLOCK continue BLOCK
      LABEL until (EXPR) BLOCK
@@@ -255,11 -252,7 +255,11 @@@ all do the same thing
  The C<if> statement is straightforward.  Because BLOCKs are always
  bounded by curly brackets, there is never any ambiguity about which
  C<if> an C<else> goes with.  If you use C<unless> in place of C<if>,
 -the sense of the test is reversed.
 +the sense of the test is reversed. Like C<if>, C<unless> can be followed
 +by C<else>. C<unless> can even be followed by one or more C<elsif>
 +statements, though you may want to think twice before using that particular
 +language construct, as everyone reading your code will have to think at least
 +twice before they can understand what's going on.
  
  The C<while> statement executes the block as long as the expression is
  L<true|/"Truth and Falsehood">.
@@@ -674,6 -667,42 +674,42 @@@ case to the next
        default    { say '$foo does not contain a y' }
      }
  
+ =head3 Return value
+ When a C<given> statement is also a valid expression (e.g.
+ when it's the last statement of a block), it returns :
+ =over 4
+ =item *
+ An empty list as soon as an explicit C<break> is encountered.
+ =item *
+ The value of the last evaluated expression of the successful
+ C<when>/C<default> clause, if there's one.
+ =item *
+ The value of the last evaluated expression of the C<given> block if no
+ condition was true.
+ =back
+ Note that, unlike C<if> and C<unless>, both C<when> and C<default> always
+ themselves return an empty list.
+     my $price = do { given ($item) {
+       when ([ 'pear', 'apple' ]) { 1 }
+       break when 'vote';      # My vote cannot be bought
+         1e10  when /Mona Lisa/;
+         'unknown';
+     } };
+ C<given> blocks can't currently be used as proper expressions. This
+ may be addressed in a future version of perl.
  =head3 Switching in a loop
  
  Instead of using C<given()>, you can use a C<foreach()> loop.
diff --combined pp_ctl.c
+++ b/pp_ctl.c
@@@ -155,20 -155,19 +155,20 @@@ PP(pp_regcomp
           ly this hack can be replaced with the approach described at
           http://www.nntp.perl.org/group/perl.perl5.porters/2007/03
           /msg122415.html some day. */
 -      OP *matchop = pm->op_next;
 -      SV *lhs;
 -      const bool was_tainted = PL_tainted;
 -      if (matchop->op_flags & OPf_STACKED)
 +      if(pm->op_type == OP_MATCH) {
 +       SV *lhs;
 +       const bool was_tainted = PL_tainted;
 +       if (pm->op_flags & OPf_STACKED)
            lhs = TOPs;
 -      else if (matchop->op_private & OPpTARGET_MY)
 -          lhs = PAD_SV(matchop->op_targ);
 -      else lhs = DEFSV;
 -      SvGETMAGIC(lhs);
 -      /* Restore the previous value of PL_tainted (which may have been
 -         modified by get-magic), to avoid incorrectly setting the
 -         RXf_TAINTED flag further down. */
 -      PL_tainted = was_tainted;
 +       else if (pm->op_private & OPpTARGET_MY)
 +          lhs = PAD_SV(pm->op_targ);
 +       else lhs = DEFSV;
 +       SvGETMAGIC(lhs);
 +       /* Restore the previous value of PL_tainted (which may have been
 +          modified by get-magic), to avoid incorrectly setting the
 +          RXf_TAINTED flag further down. */
 +       PL_tainted = was_tainted;
 +      }
  
        re = reg_temp_copy(NULL, re);
        ReREFCNT_dec(PM_GETRE(pm));
@@@ -264,9 -263,6 +264,9 @@@ PP(pp_substcont
      register REGEXP * const rx = cx->sb_rx;
      SV *nsv = NULL;
      REGEXP *old = PM_GETRE(pm);
 +
 +    PERL_ASYNC_CHECK();
 +
      if(old != rx) {
        if(old)
            ReREFCNT_dec(old);
        if (cx->sb_iters > cx->sb_maxiters)
            DIE(aTHX_ "Substitution loop");
  
 +      SvGETMAGIC(TOPs); /* possibly clear taint on $1 etc: #67962 */
 +
        if (!(cx->sb_rxtainted & 2) && SvTAINTED(TOPs))
            cx->sb_rxtainted |= 2;
 -      sv_catsv(dstr, POPs);
 +      sv_catsv_nomg(dstr, POPs);
        /* XXX: adjust for positive offsets of \G for instance s/(.)\G//g with positive pos() */
        s -= RX_GOFS(rx);
  
@@@ -1342,11 -1336,11 +1342,11 @@@ S_dopoptolabel(pTHX_ const char *label
          {
            const char *cx_label = CxLABEL(cx);
            if (!cx_label || strNE(label, cx_label) ) {
 -              DEBUG_l(Perl_deb(aTHX_ "(Skipping label #%ld %s)\n",
 +              DEBUG_l(Perl_deb(aTHX_ "(poptolabel(): skipping label at cx=%ld %s)\n",
                        (long)i, cx_label));
                continue;
            }
 -          DEBUG_l( Perl_deb(aTHX_ "(Found label #%ld %s)\n", (long)i, label));
 +          DEBUG_l( Perl_deb(aTHX_ "(poptolabel(): found label at cx=%ld %s)\n", (long)i, label));
            return i;
          }
        }
@@@ -1415,7 -1409,7 +1415,7 @@@ S_dopoptosub_at(pTHX_ const PERL_CONTEX
        case CXt_EVAL:
        case CXt_SUB:
        case CXt_FORMAT:
 -          DEBUG_l( Perl_deb(aTHX_ "(Found sub #%ld)\n", (long)i));
 +          DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i));
            return i;
        }
      }
@@@ -1433,7 -1427,7 +1433,7 @@@ S_dopoptoeval(pTHX_ I32 startingblock
        default:
            continue;
        case CXt_EVAL:
 -          DEBUG_l( Perl_deb(aTHX_ "(Found eval #%ld)\n", (long)i));
 +          DEBUG_l( Perl_deb(aTHX_ "(dopoptoeval(): found eval at cx=%ld)\n", (long)i));
            return i;
        }
      }
@@@ -1462,7 -1456,7 +1462,7 @@@ S_dopoptoloop(pTHX_ I32 startingblock
        case CXt_LOOP_LAZYSV:
        case CXt_LOOP_FOR:
        case CXt_LOOP_PLAIN:
 -          DEBUG_l( Perl_deb(aTHX_ "(Found loop #%ld)\n", (long)i));
 +          DEBUG_l( Perl_deb(aTHX_ "(dopoptoloop(): found loop at cx=%ld)\n", (long)i));
            return i;
        }
      }
@@@ -1480,7 -1474,7 +1480,7 @@@ S_dopoptogiven(pTHX_ I32 startingblock
        default:
            continue;
        case CXt_GIVEN:
 -          DEBUG_l( Perl_deb(aTHX_ "(Found given #%ld)\n", (long)i));
 +          DEBUG_l( Perl_deb(aTHX_ "(dopoptogiven(): found given at cx=%ld)\n", (long)i));
            return i;
        case CXt_LOOP_PLAIN:
            assert(!CxFOREACHDEF(cx));
        case CXt_LOOP_LAZYSV:
        case CXt_LOOP_FOR:
            if (CxFOREACHDEF(cx)) {
 -              DEBUG_l( Perl_deb(aTHX_ "(Found foreach #%ld)\n", (long)i));
 +              DEBUG_l( Perl_deb(aTHX_ "(dopoptogiven(): found foreach at cx=%ld)\n", (long)i));
                return i;
            }
        }
@@@ -1508,7 -1502,7 +1508,7 @@@ S_dopoptowhen(pTHX_ I32 startingblock
        default:
            continue;
        case CXt_WHEN:
 -          DEBUG_l( Perl_deb(aTHX_ "(Found when #%ld)\n", (long)i));
 +          DEBUG_l( Perl_deb(aTHX_ "(dopoptowhen(): found when at cx=%ld)\n", (long)i));
            return i;
        }
      }
@@@ -1524,7 -1518,8 +1524,7 @@@ Perl_dounwind(pTHX_ I32 cxix
      while (cxstack_ix > cxix) {
        SV *sv;
          register PERL_CONTEXT *cx = &cxstack[cxstack_ix];
 -      DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n",
 -                            (long) cxstack_ix, PL_block_type[CxTYPE(cx)]));
 +      DEBUG_CX("UNWIND");                                             \
        /* Note: we don't need to restore the base context info till the end. */
        switch (CxTYPE(cx)) {
        case CXt_SUBST:
@@@ -1572,17 -1567,48 +1572,17 @@@ Perl_qerror(pTHX_ SV *err
  }
  
  void
 -Perl_die_where(pTHX_ SV *msv)
 +Perl_die_unwind(pTHX_ SV *msv)
  {
      dVAR;
 +    SV *exceptsv = sv_mortalcopy(msv);
 +    U8 in_eval = PL_in_eval;
 +    PERL_ARGS_ASSERT_DIE_UNWIND;
  
 -    if (PL_in_eval) {
 +    if (in_eval) {
        I32 cxix;
        I32 gimme;
  
 -      if (msv) {
 -          if (PL_in_eval & EVAL_KEEPERR) {
 -                static const char prefix[] = "\t(in cleanup) ";
 -              SV * const err = ERRSV;
 -              const char *e = NULL;
 -              if (!SvPOK(err))
 -                  sv_setpvs(err,"");
 -              else if (SvCUR(err) >= sizeof(prefix)+SvCUR(msv)-1) {
 -                  STRLEN len;
 -                  STRLEN msglen;
 -                  const char* message = SvPV_const(msv, msglen);
 -                  e = SvPV_const(err, len);
 -                  e += len - msglen;
 -                  if (*e != *message || strNE(e,message))
 -                      e = NULL;
 -              }
 -              if (!e) {
 -                  STRLEN start;
 -                  SvGROW(err, SvCUR(err)+sizeof(prefix)+SvCUR(msv));
 -                  sv_catpvn(err, prefix, sizeof(prefix)-1);
 -                  sv_catsv(err, msv);
 -                  start = SvCUR(err)-SvCUR(msv)-sizeof(prefix)+1;
 -                  Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "%s",
 -                                 SvPVX_const(err)+start);
 -              }
 -          }
 -          else {
 -              STRLEN msglen;
 -              const char* message = SvPV_const(msv, msglen);
 -              sv_setpvn(ERRSV, message, msglen);
 -              SvFLAGS(ERRSV) |= SvFLAGS(msv) & SVf_UTF8;
 -          }
 -      }
 -
        while ((cxix = dopoptoeval(cxstack_ix)) < 0
               && PL_curstackinfo->si_prev)
        {
  
        if (cxix >= 0) {
            I32 optype;
 +          SV *namesv;
            register PERL_CONTEXT *cx;
            SV **newsp;
  
            POPBLOCK(cx,PL_curpm);
            if (CxTYPE(cx) != CXt_EVAL) {
                STRLEN msglen;
 -              const char* message = SvPVx_const( msv ? msv : ERRSV, msglen);
 +              const char* message = SvPVx_const(exceptsv, msglen);
                PerlIO_write(Perl_error_log, (const char *)"panic: die ", 11);
                PerlIO_write(Perl_error_log, message, msglen);
                my_exit(1);
            }
            POPEVAL(cx);
 +          namesv = cx->blk_eval.old_namesv;
  
            if (gimme == G_SCALAR)
                *++newsp = &PL_sv_undef;
            PL_curcop = cx->blk_oldcop;
  
            if (optype == OP_REQUIRE) {
 -                const char* const msg = SvPVx_nolen_const(ERRSV);
 -              SV * const nsv = cx->blk_eval.old_namesv;
 -                (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv),
 +                const char* const msg = SvPVx_nolen_const(exceptsv);
 +                (void)hv_store(GvHVn(PL_incgv),
 +                               SvPVX_const(namesv), SvCUR(namesv),
                                 &PL_sv_undef, 0);
 +              /* note that unlike pp_entereval, pp_require isn't
 +               * supposed to trap errors. So now that we've popped the
 +               * EVAL that pp_require pushed, and processed the error
 +               * message, rethrow the error */
                DIE(aTHX_ "%sCompilation failed in require",
                    *msg ? msg : "Unknown error\n");
            }
 +          if (in_eval & EVAL_KEEPERR) {
 +              Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %s",
 +                             SvPV_nolen_const(exceptsv));
 +          }
 +          else {
 +              sv_setsv(ERRSV, exceptsv);
 +          }
            assert(CxTYPE(cx) == CXt_EVAL);
 +          PL_restartjmpenv = cx->blk_eval.cur_top_env;
            PL_restartop = cx->blk_eval.retop;
            JMPENV_JUMP(3);
            /* NOTREACHED */
        }
      }
  
 -    write_to_stderr( msv ? msv : ERRSV );
 +    write_to_stderr(exceptsv);
      my_failure_exit();
      /* NOTREACHED */
  }
@@@ -1852,8 -1864,6 +1852,8 @@@ PP(pp_dbstate
      PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
      FREETMPS;
  
 +    PERL_ASYNC_CHECK();
 +
      if (PL_op->op_flags & OPf_SPECIAL /* breakpoint */
            || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace))
      {
            /* don't do recursive DB::DB call */
            return NORMAL;
  
 -      ENTER_with_name("sub");
 +      ENTER;
        SAVETMPS;
  
        SAVEI32(PL_debug);
            (void)(*CvXSUB(cv))(aTHX_ cv);
            CvDEPTH(cv)--;
            FREETMPS;
 -          LEAVE_with_name("sub");
 +          LEAVE;
            return NORMAL;
        }
        else {
@@@ -2101,7 -2111,6 +2101,7 @@@ PP(pp_return
      SV **newsp;
      PMOP *newpm;
      I32 optype = 0;
 +    SV *namesv;
      SV *sv;
      OP *retop = NULL;
  
        if (!(PL_in_eval & EVAL_KEEPERR))
            clear_errsv = TRUE;
        POPEVAL(cx);
 +      namesv = cx->blk_eval.old_namesv;
        retop = cx->blk_eval.retop;
        if (CxTRYBLOCK(cx))
            break;
            (MARK == SP || (gimme == G_SCALAR && !SvTRUE(*SP))) )
        {
            /* Unassume the success we assumed earlier. */
 -          SV * const nsv = cx->blk_eval.old_namesv;
 -          (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD);
 -          DIE(aTHX_ "%"SVf" did not return a true value", SVfARG(nsv));
 +          (void)hv_delete(GvHVn(PL_incgv),
 +                          SvPVX_const(namesv), SvCUR(namesv),
 +                          G_DISCARD);
 +          DIE(aTHX_ "%"SVf" did not return a true value", SVfARG(namesv));
        }
        break;
      case CXt_FORMAT:
@@@ -2552,7 -2559,7 +2552,7 @@@ PP(pp_goto
                PUSHMARK(mark);
                PUTBACK;
                (void)(*CvXSUB(cv))(aTHX_ cv);
 -              LEAVE_with_name("sub");
 +              LEAVE;
                return retop;
            }
            else {
      else
        label = cPVOP->op_pv;
  
 +    PERL_ASYNC_CHECK();
 +
      if (label && *label) {
        OP *gotoprobe = NULL;
        bool leaving_eval = FALSE;
@@@ -2825,20 -2830,6 +2825,20 @@@ S_save_lines(pTHX_ AV *array, SV *sv
      }
  }
  
 +/*
 +=for apidoc docatch
 +
 +Check for the cases 0 or 3 of cur_env.je_ret, only used inside an eval context.
 +
 +0 is used as continue inside eval,
 +
 +3 is used for a die caught by an inner eval - continue inner loop
 +
 +See cop.h: je_mustcatch, when set at any runlevel to TRUE, means eval ops must
 +establish a local jmpenv to handle exception traps.
 +
 +=cut
 +*/
  STATIC OP *
  S_docatch(pTHX_ OP *o)
  {
        break;
      case 3:
        /* die caught by an inner eval - continue inner loop */
 -
 -      /* NB XXX we rely on the old popped CxEVAL still being at the top
 -       * of the stack; the way die_where() currently works, this
 -       * assumption is valid. In theory The cur_top_env value should be
 -       * returned in another global, the way retop (aka PL_restartop)
 -       * is. */
 -      assert(CxTYPE(&cxstack[cxstack_ix+1]) == CXt_EVAL);
 -
 -      if (PL_restartop
 -          && cxstack[cxstack_ix+1].blk_eval.cur_top_env == PL_top_env)
 -      {
 +      if (PL_restartop && PL_restartjmpenv == PL_top_env) {
 +          PL_restartjmpenv = NULL;
            PL_op = PL_restartop;
            PL_restartop = 0;
            goto redo_body;
      return NULL;
  }
  
 +/* James Bond: Do you expect me to talk?
 +   Auric Goldfinger: No, Mr. Bond. I expect you to die.
 +
 +   This code is an ugly hack, doesn't work with lexicals in subroutines that are
 +   called more than once, and is only used by regcomp.c, for (?{}) blocks.
 +
 +   Currently it is not used outside the core code. Best if it stays that way.
 +*/
  OP *
  Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp)
  /* sv Text to convert to OP tree. */
  /* startop op_free() this to undo. */
  /* code Short string id of the caller. */
  {
 -    /* FIXME - how much of this code is common with pp_entereval?  */
      dVAR; dSP;                                /* Make POPBLOCK work. */
      PERL_CONTEXT *cx;
      SV **newsp;
@@@ -3025,35 -3018,6 +3025,35 @@@ Perl_find_runcv(pTHX_ U32 *db_seqp
  }
  
  
 +/* Run yyparse() in a setjmp wrapper. Returns:
 + *   0: yyparse() successful
 + *   1: yyparse() failed
 + *   3: yyparse() died
 + */
 +STATIC int
 +S_try_yyparse(pTHX)
 +{
 +    int ret;
 +    dJMPENV;
 +
 +    assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL);
 +    JMPENV_PUSH(ret);
 +    switch (ret) {
 +    case 0:
 +      ret = yyparse() ? 1 : 0;
 +      break;
 +    case 3:
 +      break;
 +    default:
 +      JMPENV_POP;
 +      JMPENV_JUMP(ret);
 +      /* NOTREACHED */
 +    }
 +    JMPENV_POP;
 +    return ret;
 +}
 +
 +
  /* Compile a require/do, an eval '', or a /(?{...})/.
   * In the last case, startop is non-null, and contains the address of
   * a pointer that should be set to the just-compiled code.
@@@ -3068,10 -3032,8 +3068,10 @@@ S_doeval(pTHX_ int gimme, OP** startop
  {
      dVAR; dSP;
      OP * const saveop = PL_op;
 +    bool in_require = (saveop && saveop->op_type == OP_REQUIRE);
 +    int yystatus;
  
 -    PL_in_eval = ((saveop && saveop->op_type == OP_REQUIRE)
 +    PL_in_eval = (in_require
                  ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL))
                  : EVAL_INEVAL);
  
        PL_in_eval |= EVAL_KEEPERR;
      else
        CLEAR_ERRSV();
 -    if (yyparse() || PL_parser->error_count || !PL_eval_root) {
 +
 +    /* note that yyparse() may raise an exception, e.g. C<BEGIN{die}>,
 +     * so honour CATCH_GET and trap it here if necessary */
 +
 +    yystatus = (!in_require && CATCH_GET) ? S_try_yyparse(aTHX) : yyparse();
 +
 +    if (yystatus || PL_parser->error_count || !PL_eval_root) {
        SV **newsp;                     /* Used by POPBLOCK. */
 -      PERL_CONTEXT *cx = &cxstack[cxstack_ix];
 -      I32 optype = 0;                 /* Might be reset by POPEVAL. */
 +      PERL_CONTEXT *cx = NULL;
 +      I32 optype;                     /* Used by POPEVAL. */
 +      SV *namesv = NULL;
        const char *msg;
  
 +      PERL_UNUSED_VAR(newsp);
 +      PERL_UNUSED_VAR(optype);
 +
 +      /* note that if yystatus == 3, then the EVAL CX block has already
 +       * been popped, and various vars restored */
        PL_op = saveop;
 -      if (PL_eval_root) {
 -          op_free(PL_eval_root);
 -          PL_eval_root = NULL;
 -      }
 -      SP = PL_stack_base + POPMARK;           /* pop original mark */
 -      if (!startop) {
 -          POPBLOCK(cx,PL_curpm);
 -          POPEVAL(cx);
 +      if (yystatus != 3) {
 +          if (PL_eval_root) {
 +              op_free(PL_eval_root);
 +              PL_eval_root = NULL;
 +          }
 +          SP = PL_stack_base + POPMARK;       /* pop original mark */
 +          if (!startop) {
 +              POPBLOCK(cx,PL_curpm);
 +              POPEVAL(cx);
 +              namesv = cx->blk_eval.old_namesv;
 +          }
        }
        lex_end();
 -      LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE.  */
 +      if (yystatus != 3)
 +          LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE.  */
  
        msg = SvPVx_nolen_const(ERRSV);
 -      if (optype == OP_REQUIRE) {
 -          const SV * const nsv = cx->blk_eval.old_namesv;
 -          (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv),
 -                          &PL_sv_undef, 0);
 +      if (in_require) {
 +          if (!cx) {
 +              /* If cx is still NULL, it means that we didn't go in the
 +               * POPEVAL branch. */
 +              cx = &cxstack[cxstack_ix];
 +              assert(CxTYPE(cx) == CXt_EVAL);
 +              namesv = cx->blk_eval.old_namesv;
 +          }
 +          (void)hv_store(GvHVn(PL_incgv),
 +                         SvPVX_const(namesv), SvCUR(namesv),
 +                         &PL_sv_undef, 0);
            Perl_croak(aTHX_ "%sCompilation failed in require",
                       *msg ? msg : "Unknown error\n");
        }
        else if (startop) {
 -          POPBLOCK(cx,PL_curpm);
 -          POPEVAL(cx);
 +          if (yystatus != 3) {
 +              POPBLOCK(cx,PL_curpm);
 +              POPEVAL(cx);
 +          }
            Perl_croak(aTHX_ "%sCompilation failed in regexp",
                       (*msg ? msg : "Unknown error\n"));
        }
                sv_setpvs(ERRSV, "Compilation error");
            }
        }
 -      PERL_UNUSED_VAR(newsp);
        PUSHs(&PL_sv_undef);
        PUTBACK;
        return FALSE;
@@@ -3337,21 -3275,21 +3337,21 @@@ PP(pp_require
                        SVfARG(vnormal(PL_patchlevel)));
                }
                else { /* probably 'use 5.10' or 'use 5.8' */
 -                  SV * hintsv = newSV(0);
 +                  SV *hintsv;
                    I32 second = 0;
  
                    if (av_len(lav)>=1) 
                        second = SvIV(*av_fetch(lav,1,0));
  
                    second /= second >= 600  ? 100 : 10;
 -                  hintsv = Perl_newSVpvf(aTHX_ "v%d.%d.%d",
 -                      (int)first, (int)second,0);
 +                  hintsv = Perl_newSVpvf(aTHX_ "v%d.%d.0",
 +                                         (int)first, (int)second);
                    upg_version(hintsv, TRUE);
  
                    DIE(aTHX_ "Perl %"SVf" required (did you mean %"SVf"?)"
                        "--this is only %"SVf", stopped",
                        SVfARG(vnormal(req)),
 -                      SVfARG(vnormal(hintsv)),
 +                      SVfARG(vnormal(sv_2mortal(hintsv))),
                        SVfARG(vnormal(PL_patchlevel)));
                }
            }
@@@ -3798,18 -3736,7 +3798,18 @@@ PP(pp_entereval
      if (PL_compiling.cop_hints_hash) {
        Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
      }
 -    PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash;
 +    if (Perl_fetch_cop_label(aTHX_ PL_curcop->cop_hints_hash, NULL, NULL)) {
 +      /* The label, if present, is the first entry on the chain. So rather
 +         than writing a blank label in front of it (which involves an
 +         allocation), just use the next entry in the chain.  */
 +      PL_compiling.cop_hints_hash
 +          = PL_curcop->cop_hints_hash->refcounted_he_next;
 +      /* Check the assumption that this removed the label.  */
 +      assert(Perl_fetch_cop_label(aTHX_ PL_compiling.cop_hints_hash, NULL,
 +                                  NULL) == NULL);
 +    }
 +    else
 +      PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash;
      if (PL_compiling.cop_hints_hash) {
        HINTS_REFCNT_LOCK;
        PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
@@@ -3867,11 -3794,9 +3867,11 @@@ PP(pp_leaveeval
      OP *retop;
      const U8 save_flags = PL_op -> op_flags;
      I32 optype;
 +    SV *namesv;
  
      POPBLOCK(cx,newpm);
      POPEVAL(cx);
 +    namesv = cx->blk_eval.old_namesv;
      retop = cx->blk_eval.retop;
  
      TAINT_NOT;
        !(gimme == G_SCALAR ? SvTRUE(*SP) : SP > newsp))
      {
        /* Unassume the success we assumed earlier. */
 -      SV * const nsv = cx->blk_eval.old_namesv;
 -      (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD);
 -      retop = Perl_die(aTHX_ "%"SVf" did not return a true value", SVfARG(nsv));
 -      /* die_where() did LEAVE, or we won't be here */
 +      (void)hv_delete(GvHVn(PL_incgv),
 +                      SvPVX_const(namesv), SvCUR(namesv),
 +                      G_DISCARD);
 +      retop = Perl_die(aTHX_ "%"SVf" did not return a true value",
 +                             SVfARG(namesv));
 +      /* die_unwind() did LEAVE, or we won't be here */
      }
      else {
        LEAVE_with_name("eval");
@@@ -4059,14 -3982,38 +4059,38 @@@ PP(pp_leavegiven
      POPBLOCK(cx,newpm);
      assert(CxTYPE(cx) == CXt_GIVEN);
  
-     SP = newsp;
-     PUTBACK;
-     PL_curpm = newpm;   /* pop $1 et al */
+     TAINT_NOT;
+     if (gimme == G_VOID)
+       SP = newsp;
+     else if (gimme == G_SCALAR) {
+       register SV **mark;
+       MARK = newsp + 1;
+       if (MARK <= SP) {
+           if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
+               *MARK = TOPs;
+           else
+               *MARK = sv_mortalcopy(TOPs);
+       }
+       else {
+           MEXTEND(mark,0);
+           *MARK = &PL_sv_undef;
+       }
+       SP = MARK;
+     }
+     else {
+       /* in case LEAVE wipes old return values */
+       register SV **mark;
+       for (mark = newsp + 1; mark <= SP; mark++) {
+           if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) {
+               *mark = sv_mortalcopy(*mark);
+               TAINT_NOT;      /* Each item is independent */
+           }
+       }
+     }
+     PL_curpm = newpm; /* Don't pop $1 et al till now */
  
      LEAVE_with_name("given");
-     return NORMAL;
+     RETURN;
  }
  
  /* Helper routines used by pp_smartmatch */
@@@ -4606,9 -4553,10 +4630,10 @@@ PP(pp_enterwhen
         fails, we don't want to push a context and then
         pop it again right away, so we skip straight
         to the op that follows the leavewhen.
+        RETURNOP calls PUTBACK which restores the stack pointer after the POPs.
      */
      if ((0 == (PL_op->op_flags & OPf_SPECIAL)) && !SvTRUEx(POPs))
-       return cLOGOP->op_other->op_next;
+       RETURNOP(cLOGOP->op_other->op_next);
  
      ENTER_with_name("eval");
      SAVETMPS;
@@@ -4667,7 -4615,8 +4692,8 @@@ PP(pp_break
      I32 cxix;
      register PERL_CONTEXT *cx;
      I32 inner;
-     
+     dSP;
      cxix = dopoptogiven(cxstack_ix); 
      if (cxix < 0) {
        if (PL_op->op_flags & OPf_SPECIAL)
      if (CxFOREACH(cx))
        return CX_LOOP_NEXTOP_GET(cx);
      else
-       return cx->blk_givwhen.leave_op;
+       /* RETURNOP calls PUTBACK which restores the old old sp */
+       RETURNOP(cx->blk_givwhen.leave_op);
  }
  
  STATIC OP *