This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Cast to signed before negating, to avoid compiler warnings
[perl5.git] / pp_ctl.c
index c358734..692fdeb 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -43,13 +43,20 @@ PP(pp_wantarray)
     dVAR;
     dSP;
     I32 cxix;
+    const PERL_CONTEXT *cx;
     EXTEND(SP, 1);
 
-    cxix = dopoptosub(cxstack_ix);
-    if (cxix < 0)
+    if (PL_op->op_private & OPpOFFBYONE) {
+       if (!(cx = caller_cx(1,NULL))) RETPUSHUNDEF;
+    }
+    else {
+      cxix = dopoptosub(cxstack_ix);
+      if (cxix < 0)
        RETPUSHUNDEF;
+      cx = &cxstack[cxix];
+    }
 
-    switch (cxstack[cxix].blk_gimme) {
+    switch (cx->blk_gimme) {
     case G_ARRAY:
        RETPUSHYES;
     case G_SCALAR:
@@ -298,6 +305,13 @@ PP(pp_substcont)
        s -= RX_GOFS(rx);
 
        /* Are we done */
+       /* I believe that we can't set REXEC_SCREAM here if
+          SvSCREAM(cx->sb_targ) is true because SvPVX(cx->sb_targ) isn't always
+          equal to s.  [See the comment before Perl_re_intuit_start(), which is
+          called from Perl_regexec_flags(), which says that it should be when
+          SvSCREAM() is true.]  s, cx->sb_strend and orig will be consistent
+          with SvPVX(cx->sb_targ), as substconst doesn't modify cx->sb_targ
+          during the match.  */
        if (CxONCE(cx) || s < orig ||
                !CALLREGEXEC(rx, s, cx->sb_strend, orig,
                             (s == m) + RX_GOFS(rx), cx->sb_targ, NULL,
@@ -305,7 +319,7 @@ PP(pp_substcont)
                              ? (REXEC_IGNOREPOS|REXEC_NOT_FIRST)
                              : (REXEC_COPY_STR|REXEC_IGNOREPOS|REXEC_NOT_FIRST))))
        {
-           SV * const targ = cx->sb_targ;
+           SV *targ = cx->sb_targ;
 
            assert(cx->sb_strend >= s);
            if(cx->sb_strend > s) {
@@ -317,27 +331,32 @@ PP(pp_substcont)
            if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
                cx->sb_rxtainted |= SUBST_TAINT_PAT;
 
+           if (pm->op_pmflags & PMf_NONDESTRUCT) {
+               PUSHs(dstr);
+               /* From here on down we're using the copy, and leaving the
+                  original untouched.  */
+               targ = dstr;
+           }
+           else {
 #ifdef PERL_OLD_COPY_ON_WRITE
-           if (SvIsCOW(targ)) {
-               sv_force_normal_flags(targ, SV_COW_DROP_PV);
-           } else
+               if (SvIsCOW(targ)) {
+                   sv_force_normal_flags(targ, SV_COW_DROP_PV);
+               } else
 #endif
-           {
-               SvPV_free(targ);
-           }
-           SvPV_set(targ, SvPVX(dstr));
-           SvCUR_set(targ, SvCUR(dstr));
-           SvLEN_set(targ, SvLEN(dstr));
-           if (DO_UTF8(dstr))
-               SvUTF8_on(targ);
-           SvPV_set(dstr, NULL);
-
-           if (pm->op_pmflags & PMf_NONDESTRUCT)
-               PUSHs(targ);
-           else
+               {
+                   SvPV_free(targ);
+               }
+               SvPV_set(targ, SvPVX(dstr));
+               SvCUR_set(targ, SvCUR(dstr));
+               SvLEN_set(targ, SvLEN(dstr));
+               if (DO_UTF8(dstr))
+                   SvUTF8_on(targ);
+               SvPV_set(dstr, NULL);
+
                mPUSHi(saviters - 1);
 
-           (void)SvPOK_only_UTF8(targ);
+               (void)SvPOK_only_UTF8(targ);
+           }
 
            /* update the taint state of various various variables in
             * preparation for final exit.
@@ -384,7 +403,8 @@ PP(pp_substcont)
     }
     cx->sb_s = RX_OFFS(rx)[0].end + orig;
     { /* Update the pos() information. */
-       SV * const sv = cx->sb_targ;
+       SV * const sv
+           = (pm->op_pmflags & PMf_NONDESTRUCT) ? cx->sb_dstr : cx->sb_targ;
        MAGIC *mg;
        SvUPGRADE(sv, SVt_PVMG);
        if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) {
@@ -414,7 +434,8 @@ PP(pp_substcont)
 
        if (cx->sb_iters > 1 && (cx->sb_rxtainted & 
                        (SUBST_TAINT_STR|SUBST_TAINT_PAT|SUBST_TAINT_REPL)))
-           SvTAINTED_on(cx->sb_targ);
+           SvTAINTED_on((pm->op_pmflags & PMf_NONDESTRUCT)
+                        ? cx->sb_dstr : cx->sb_targ);
        TAINT_NOT;
     }
     rxres_save(&cx->sb_rxres, rx);
@@ -1455,6 +1476,20 @@ Perl_is_lvalue_sub(pTHX)
        return 0;
 }
 
+/* only used by PUSHSUB */
+I32
+Perl_was_lvalue_sub(pTHX)
+{
+    dVAR;
+    const I32 cxix = dopoptosub(cxstack_ix-1);
+    assert(cxix >= 0);  /* We should only be called from inside subs */
+
+    if (CxLVAL(cxstack + cxix) && CvLVALUE(cxstack[cxix].blk_sub.cv))
+       return CxLVAL(cxstack + cxix);
+    else
+       return 0;
+}
+
 STATIC I32
 S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock)
 {
@@ -1622,8 +1657,8 @@ Perl_qerror(pTHX_ SV *err)
 
     if (PL_in_eval) {
        if (PL_in_eval & EVAL_KEEPERR) {
-               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %s",
-                              SvPV_nolen_const(err));
+               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
+                                                    SVfARG(err));
        }
        else
            sv_catsv(ERRSV, err);
@@ -1728,20 +1763,21 @@ Perl_die_unwind(pTHX_ SV *msv)
            PL_curcop = oldcop;
 
            if (optype == OP_REQUIRE) {
-                const char* const msg = SvPVx_nolen_const(exceptsv);
                 (void)hv_store(GvHVn(PL_incgv),
-                               SvPVX_const(namesv), SvCUR(namesv),
+                               SvPVX_const(namesv),
+                               SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)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 */
-               Perl_croak(aTHX_ "%sCompilation failed in require",
-                          *msg ? msg : "Unknown error\n");
+               Perl_croak(aTHX_ "%"SVf"Compilation failed in require",
+                          SVfARG(exceptsv ? exceptsv : newSVpvs_flags("Unknown error\n",
+                                                                    SVs_TEMP)));
            }
            if (in_eval & EVAL_KEEPERR) {
-               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %s",
-                              SvPV_nolen_const(exceptsv));
+               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
+                              SVfARG(exceptsv));
            }
            else {
                sv_setsv(ERRSV, exceptsv);
@@ -1834,13 +1870,17 @@ PP(pp_caller)
     register const PERL_CONTEXT *cx;
     const PERL_CONTEXT *dbcx;
     I32 gimme;
-    const char *stashname;
+    const HEK *stash_hek;
     I32 count = 0;
+    bool has_arg = MAXARG && TOPs;
 
-    if (MAXARG)
+    if (MAXARG) {
+      if (has_arg)
        count = POPi;
+      else (void)POPs;
+    }
 
-    cx = caller_cx(count, &dbcx);
+    cx = caller_cx(count + !!(PL_op->op_private & OPpOFFBYONE), &dbcx);
     if (!cx) {
        if (GIMME != G_ARRAY) {
            EXTEND(SP, 1);
@@ -1849,14 +1889,14 @@ PP(pp_caller)
        RETURN;
     }
 
-    stashname = CopSTASHPV(cx->blk_oldcop);
+    stash_hek = HvNAME_HEK((HV*)CopSTASH(cx->blk_oldcop));
     if (GIMME != G_ARRAY) {
         EXTEND(SP, 1);
-       if (!stashname)
+       if (!stash_hek)
            PUSHs(&PL_sv_undef);
        else {
            dTARGET;
-           sv_setpv(TARG, stashname);
+           sv_sethek(TARG, stash_hek);
            PUSHs(TARG);
        }
        RETURN;
@@ -1864,13 +1904,16 @@ PP(pp_caller)
 
     EXTEND(SP, 11);
 
-    if (!stashname)
+    if (!stash_hek)
        PUSHs(&PL_sv_undef);
-    else
-       mPUSHs(newSVpv(stashname, 0));
+    else {
+       dTARGET;
+       sv_sethek(TARG, stash_hek);
+       PUSHTARG;
+    }
     mPUSHs(newSVpv(OutCopFILE(cx->blk_oldcop), 0));
     mPUSHi((I32)CopLINE(cx->blk_oldcop));
-    if (!MAXARG)
+    if (!has_arg)
        RETURN;
     if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
        GV * const cvgv = CvGV(dbcx->blk_sub.cv);
@@ -1922,8 +1965,7 @@ PP(pp_caller)
        AV * const ary = cx->blk_sub.argarray;
        const int off = AvARRAY(ary) - AvALLOC(ary);
 
-       if (!PL_dbargs)
-           Perl_init_dbargs(aTHX);
+       Perl_init_dbargs(aTHX);
 
        if (AvMAX(PL_dbargs) < AvFILLp(ary) + off)
            av_extend(PL_dbargs, AvFILLp(ary) + off);
@@ -1969,7 +2011,8 @@ PP(pp_reset)
 {
     dVAR;
     dSP;
-    const char * const tmps = (MAXARG < 1) ? (const char *)"" : POPpconstx;
+    const char * const tmps =
+       (MAXARG < 1 || (!TOPs && !POPs)) ? (const char *)"" : POPpconstx;
     sv_reset(tmps, CopSTASH(PL_curcop));
     PUSHs(&PL_sv_yes);
     RETURN;
@@ -2036,6 +2079,79 @@ PP(pp_dbstate)
        return NORMAL;
 }
 
+STATIC SV **
+S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 flags)
+{
+    PERL_ARGS_ASSERT_ADJUST_STACK_ON_LEAVE;
+
+    if (gimme == G_SCALAR) {
+       if (MARK < SP)
+           *++newsp = (SvFLAGS(*SP) & flags) ? *SP : sv_mortalcopy(*SP);
+       else {
+           /* MEXTEND() only updates MARK, so reuse it instead of newsp. */
+           MARK = newsp;
+           MEXTEND(MARK, 1);
+           *++MARK = &PL_sv_undef;
+           return MARK;
+       }
+    }
+    else if (gimme == G_ARRAY) {
+       /* in case LEAVE wipes old return values */
+       while (++MARK <= SP) {
+           if (SvFLAGS(*MARK) & flags)
+               *++newsp = *MARK;
+           else {
+               *++newsp = sv_mortalcopy(*MARK);
+               TAINT_NOT;      /* Each item is independent */
+           }
+       }
+       /* When this function was called with MARK == newsp, we reach this
+        * point with SP == newsp. */
+    }
+
+    return newsp;
+}
+
+PP(pp_enter)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    I32 gimme = GIMME_V;
+
+    ENTER_with_name("block");
+
+    SAVETMPS;
+    PUSHBLOCK(cx, CXt_BLOCK, SP);
+
+    RETURN;
+}
+
+PP(pp_leave)
+{
+    dVAR; dSP;
+    register PERL_CONTEXT *cx;
+    SV **newsp;
+    PMOP *newpm;
+    I32 gimme;
+
+    if (PL_op->op_flags & OPf_SPECIAL) {
+       cx = &cxstack[cxstack_ix];
+       cx->blk_oldpm = PL_curpm;       /* fake block should preserve $1 et al */
+    }
+
+    POPBLOCK(cx,newpm);
+
+    gimme = OP_GIMME(PL_op, (cxstack_ix >= 0) ? gimme : G_SCALAR);
+
+    TAINT_NOT;
+    SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+    PL_curpm = newpm;  /* Don't pop $1 et al till now */
+
+    LEAVE_with_name("block");
+
+    RETURN;
+}
+
 PP(pp_enteriter)
 {
     dVAR; dSP; dMARK;
@@ -2189,21 +2305,7 @@ PP(pp_leaveloop)
     newsp = PL_stack_base + cx->blk_loop.resetsp;
 
     TAINT_NOT;
-    if (gimme == G_VOID)
-       NOOP;
-    else if (gimme == G_SCALAR) {
-       if (mark < SP)
-           *++newsp = sv_mortalcopy(*SP);
-       else
-           *++newsp = &PL_sv_undef;
-    }
-    else {
-       while (mark < SP) {
-           *++newsp = sv_mortalcopy(*++mark);
-           TAINT_NOT;          /* Each item is independent */
-       }
-    }
-    SP = newsp;
+    SP = adjust_stack_on_leave(newsp, SP, MARK, gimme, 0);
     PUTBACK;
 
     POPLOOP(cx);       /* Stack values are safe: release loop vars ... */
@@ -2217,10 +2319,41 @@ PP(pp_leaveloop)
 
 STATIC void
 S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
-                       PERL_CONTEXT *cx)
+                       PERL_CONTEXT *cx, PMOP *newpm)
 {
+    const bool ref = !!(CxLVAL(cx) & OPpENTERSUB_INARGS);
     if (gimme == G_SCALAR) {
+       if (CxLVAL(cx) && !ref) {     /* Leave it as it is if we can. */
+           SV *sv;
+           const char *what = NULL;
+           if (MARK < SP) {
+               assert(MARK+1 == SP);
+               if ((SvPADTMP(TOPs) ||
+                    (SvFLAGS(TOPs) & (SVf_READONLY | SVf_FAKE))
+                      == SVf_READONLY
+                   ) &&
+                   !SvSMAGICAL(TOPs)) {
+                   what =
+                       SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef"
+                       : "a readonly value" : "a temporary";
+               }
+               else goto copy_sv;
+           }
+           else {
+               /* sub:lvalue{} will take us here. */
+               what = "undef";
+           }
+           LEAVE;
+           cxstack_ix--;
+           POPSUB(cx,sv);
+           PL_curpm = newpm;
+           LEAVESUB(sv);
+           Perl_croak(aTHX_
+                     "Can't return %s from lvalue subroutine", what
+           );
+       }
        if (MARK < SP) {
+             copy_sv:
                if (cx->blk_sub.cv && CvDEPTH(cx->blk_sub.cv) > 1) {
                        *++newsp = SvREFCNT_inc(*SP);
                        FREETMPS;
@@ -2228,39 +2361,55 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
                }
                else
                    *++newsp =
-                       (!CxLVAL(cx) || CxLVAL(cx) & OPpENTERSUB_INARGS) &&
                        !SvTEMP(*SP)
                          ? sv_2mortal(SvREFCNT_inc_simple_NN(*SP))
                          : *SP;
        }
-       else
+       else {
+           EXTEND(newsp,1);
            *++newsp = &PL_sv_undef;
-       if (CxLVAL(cx) & OPpENTERSUB_DEREF) {
+       }
+       if (CxLVAL(cx) & OPpDEREF) {
            SvGETMAGIC(TOPs);
            if (!SvOK(TOPs)) {
-               U8 deref_type;
-               if (cx->blk_sub.retop->op_type == OP_RV2SV)
-                   deref_type = OPpDEREF_SV;
-               else if (cx->blk_sub.retop->op_type == OP_RV2AV)
-                   deref_type = OPpDEREF_AV;
-               else {
-                   assert(cx->blk_sub.retop->op_type == OP_RV2HV);
-                   deref_type = OPpDEREF_HV;
-               }
-               vivify_ref(TOPs, deref_type);
+               TOPs = vivify_ref(TOPs, CxLVAL(cx) & OPpDEREF);
            }
        }
     }
     else if (gimme == G_ARRAY) {
-       assert (!(CxLVAL(cx) & OPpENTERSUB_DEREF));
-       if (!CxLVAL(cx) || CxLVAL(cx) & OPpENTERSUB_INARGS)
+       assert (!(CxLVAL(cx) & OPpDEREF));
+       if (ref || !CxLVAL(cx))
            while (++MARK <= SP)
                *++newsp =
                     SvTEMP(*MARK)
                       ? *MARK
-                      : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
+                      : ref && SvFLAGS(*MARK) & SVs_PADTMP
+                          ? sv_mortalcopy(*MARK)
+                          : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
        else while (++MARK <= SP) {
-           *++newsp = *MARK;
+           if (*MARK != &PL_sv_undef
+                   && (SvPADTMP(*MARK)
+                      || (SvFLAGS(*MARK) & (SVf_READONLY|SVf_FAKE))
+                            == SVf_READONLY
+                      )
+           ) {
+                   SV *sv;
+                   /* Might be flattened array after $#array =  */
+                   PUTBACK;
+                   LEAVE;
+                   cxstack_ix--;
+                   POPSUB(cx,sv);
+                   PL_curpm = newpm;
+                   LEAVESUB(sv);
+                   Perl_croak(aTHX_
+                       "Can't return a %s from lvalue subroutine",
+                       SvREADONLY(TOPs) ? "readonly value" : "temporary");
+           }
+           else
+               *++newsp =
+                   SvTEMP(*MARK)
+                      ? *MARK
+                      : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
        }
     }
     PL_stack_sp = newsp;
@@ -2273,7 +2422,6 @@ PP(pp_return)
     bool popsub2 = FALSE;
     bool clear_errsv = FALSE;
     bool lval = FALSE;
-    bool gmagic = FALSE;
     I32 gimme;
     SV **newsp;
     PMOP *newpm;
@@ -2316,7 +2464,6 @@ PP(pp_return)
        popsub2 = TRUE;
        lval = !!CvLVALUE(cx->blk_sub.cv);
        retop = cx->blk_sub.retop;
-       gmagic = CxLVAL(cx) & OPpENTERSUB_DEREF;
        cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
        break;
     case CXt_EVAL:
@@ -2332,7 +2479,8 @@ PP(pp_return)
        {
            /* Unassume the success we assumed earlier. */
            (void)hv_delete(GvHVn(PL_incgv),
-                           SvPVX_const(namesv), SvCUR(namesv),
+                           SvPVX_const(namesv),
+                            SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
                            G_DISCARD);
            DIE(aTHX_ "%"SVf" did not return a true value", SVfARG(namesv));
        }
@@ -2346,7 +2494,7 @@ PP(pp_return)
     }
 
     TAINT_NOT;
-    if (lval) S_return_lvalues(aTHX_ MARK, SP, newsp, gimme, cx);
+    if (lval) S_return_lvalues(aTHX_ MARK, SP, newsp, gimme, cx, newpm);
     else {
       if (gimme == G_SCALAR) {
        if (MARK < SP) {
@@ -2362,12 +2510,10 @@ PP(pp_return)
                        FREETMPS;
                        *++newsp = sv_mortalcopy(sv);
                        SvREFCNT_dec(sv);
-                       if (gmagic) SvGETMAGIC(sv);
                    }
                }
                else if (SvTEMP(*SP) && SvREFCNT(*SP) == 1) {
                    *++newsp = *SP;
-                   if (gmagic) SvGETMAGIC(*SP);
                }
                else
                    *++newsp = sv_mortalcopy(*SP);
@@ -2410,7 +2556,6 @@ PP(pp_return)
 PP(pp_leavesublv)
 {
     dVAR; dSP;
-    SV **mark;
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
@@ -2422,156 +2567,10 @@ PP(pp_leavesublv)
 
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
-    assert(CvLVALUE(cx->blk_sub.cv));
 
     TAINT_NOT;
 
-    if (CxLVAL(cx) & OPpENTERSUB_INARGS) {
-       /* We are an argument to a function or grep().
-        * This kind of lvalueness was legal before lvalue
-        * subroutines too, so be backward compatible:
-        * cannot report errors.  */
-
-       /* Scalar context *is* possible, on the LHS of ->. */
-       if (gimme == G_SCALAR)
-           goto rvalue;
-       if (gimme == G_ARRAY) {
-           mark = newsp + 1;
-           if (!CvLVALUE(cx->blk_sub.cv))
-               goto rvalue_array;
-           EXTEND_MORTAL(SP - newsp);
-           for (mark = newsp + 1; mark <= SP; mark++) {
-               if (SvTEMP(*mark))
-                   NOOP;
-               else if (SvFLAGS(*mark) & SVs_PADTMP)
-                   *mark = sv_mortalcopy(*mark);
-               else {
-                   /* Can be a localized value subject to deletion. */
-                   PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   SvREFCNT_inc_void(*mark);
-               }
-           }
-       }
-    }
-    else if (CxLVAL(cx)) {     /* Leave it as it is if we can. */
-       if (gimme == G_SCALAR) {
-           MARK = newsp + 1;
-           EXTEND_MORTAL(1);
-           if (MARK == SP) {
-               if ((SvPADTMP(TOPs) ||
-                    (SvFLAGS(TOPs) & (SVf_READONLY | SVf_FAKE))
-                      == SVf_READONLY
-                   ) &&
-                   !SvSMAGICAL(TOPs)) {
-                   LEAVE;
-                   cxstack_ix--;
-                   POPSUB(cx,sv);
-                   PL_curpm = newpm;
-                   LEAVESUB(sv);
-                   DIE(aTHX_ "Can't return %s from lvalue subroutine",
-                       SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef"
-                       : "a readonly value" : "a temporary");
-               }
-               else {                  /* Can be a localized value
-                                        * subject to deletion. */
-                   PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   SvREFCNT_inc_void(*mark);
-               }
-           }
-           else {
-               /* sub:lvalue{} will take us here.
-                  Presumably the case of a non-empty array never happens.
-                */
-               LEAVE;
-               cxstack_ix--;
-               POPSUB(cx,sv);
-               PL_curpm = newpm;
-               LEAVESUB(sv);
-               DIE(aTHX_ "%s",
-                   (MARK > SP
-                     ? "Can't return undef from lvalue subroutine"
-                     : "Array returned from lvalue subroutine in scalar "
-                       "context"
-                   )
-               );
-           }
-           SP = MARK;
-       }
-       else if (gimme == G_ARRAY) {
-           EXTEND_MORTAL(SP - newsp);
-           for (mark = newsp + 1; mark <= SP; mark++) {
-               if (*mark != &PL_sv_undef
-                   && (SvPADTMP(*mark)
-                      || (SvFLAGS(*mark) & (SVf_READONLY|SVf_FAKE))
-                            == SVf_READONLY
-                      )
-               ) {
-                   /* Might be flattened array after $#array =  */
-                   PUTBACK;
-                   LEAVE;
-                   cxstack_ix--;
-                   POPSUB(cx,sv);
-                   PL_curpm = newpm;
-                   LEAVESUB(sv);
-                   DIE(aTHX_ "Can't return a %s from lvalue subroutine",
-                       SvREADONLY(TOPs) ? "readonly value" : "temporary");
-               }
-               else {
-                   /* Can be a localized value subject to deletion. */
-                   PL_tmps_stack[++PL_tmps_ix] = *mark;
-                   SvREFCNT_inc_void(*mark);
-               }
-           }
-       }
-    }
-    else {
-       if (gimme == G_SCALAR) {
-         rvalue:
-           MARK = newsp + 1;
-           if (MARK <= SP) {
-               if (cx->blk_sub.cv && CvDEPTH(cx->blk_sub.cv) > 1) {
-                       *MARK = SvREFCNT_inc(TOPs);
-                       FREETMPS;
-                       sv_2mortal(*MARK);
-               }
-               else
-                   *MARK = SvTEMP(TOPs)
-                             ? TOPs
-                             : sv_2mortal(SvREFCNT_inc_simple_NN(TOPs));
-           }
-           else {
-               MEXTEND(MARK, 0);
-               *MARK = &PL_sv_undef;
-           }
-           SP = MARK;
-       }
-       else if (gimme == G_ARRAY) {
-         rvalue_array:
-           for (MARK = newsp + 1; MARK <= SP; MARK++) {
-               if (!SvTEMP(*MARK))
-                   *MARK = sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
-           }
-       }
-    }
-
-    if (CxLVAL(cx) & OPpENTERSUB_DEREF) {
-       assert(gimme == G_SCALAR);
-       SvGETMAGIC(TOPs);
-       if (!SvOK(TOPs)) {
-           U8 deref_type;
-           if (cx->blk_sub.retop->op_type == OP_RV2SV)
-               deref_type = OPpDEREF_SV;
-           else if (cx->blk_sub.retop->op_type == OP_RV2AV)
-               deref_type = OPpDEREF_AV;
-           else {
-               assert(cx->blk_sub.retop->op_type == OP_RV2HV);
-               deref_type = OPpDEREF_HV;
-           }
-           vivify_ref(TOPs, deref_type);
-       }
-    }
-
-    PUTBACK;
+    S_return_lvalues(aTHX_ newsp, SP, newsp, gimme, cx, newpm);
 
     LEAVE;
     cxstack_ix--;
@@ -2639,21 +2638,8 @@ PP(pp_last)
     }
 
     TAINT_NOT;
-    if (gimme == G_SCALAR) {
-       if (MARK < SP)
-           *++newsp = ((pop2 == CXt_SUB) && SvTEMP(*SP))
-                       ? *SP : sv_mortalcopy(*SP);
-       else
-           *++newsp = &PL_sv_undef;
-    }
-    else if (gimme == G_ARRAY) {
-       while (++MARK <= SP) {
-           *++newsp = ((pop2 == CXt_SUB) && SvTEMP(*MARK))
-                       ? *MARK : sv_mortalcopy(*MARK);
-           TAINT_NOT;          /* Each item is independent */
-       }
-    }
-    SP = newsp;
+    SP = adjust_stack_on_leave(newsp, SP, MARK, gimme,
+                               pop2 == CXt_SUB ? SVs_TEMP : 0);
     PUTBACK;
 
     LEAVE;
@@ -2832,8 +2818,9 @@ PP(pp_goto)
                    /* autoloaded stub? */
                    if (cv != GvCV(gv) && (cv = GvCV(gv)))
                        goto retry;
-                   autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv),
-                                         GvNAMELEN(gv), FALSE);
+                   autogv = gv_autoload_pvn(GvSTASH(gv), GvNAME(gv),
+                                         GvNAMELEN(gv),
+                                          GvNAMEUTF8(gv) ? SVf_UTF8 : 0);
                    if (autogv && (cv = GvCV(autogv)))
                        goto retry;
                    tmpstr = sv_newmortal();
@@ -2936,6 +2923,7 @@ PP(pp_goto)
                        sub_crush_depth(cv);
                    pad_push(padlist, CvDEPTH(cv));
                }
+               PL_curcop = cx->blk_oldcop;
                SAVECOMPPAD();
                PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));
                if (CxHASARGS(cx))
@@ -3149,6 +3137,9 @@ PP(pp_exit)
 
     if (MAXARG < 1)
        anum = 0;
+    else if (!TOPs) {
+       anum = 0; (void)POPs;
+    }
     else {
        anum = SvIVx(POPs);
 #ifdef VMS
@@ -3487,6 +3478,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     CvEVAL_on(PL_compcv);
     assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL);
     cxstack[cxstack_ix].blk_eval.cv = PL_compcv;
+    cxstack[cxstack_ix].blk_gimme = gimme;
 
     CvOUTSIDE_SEQ(PL_compcv) = seq;
     CvOUTSIDE(PL_compcv) = MUTABLE_CV(SvREFCNT_inc_simple(outside));
@@ -3523,7 +3515,6 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
 
     PL_eval_root = NULL;
     PL_curcop = &PL_compiling;
-    CopARYBASE_set(PL_curcop, 0);
     if (saveop && (saveop->op_type != OP_REQUIRE) && (saveop->op_flags & OPf_SPECIAL))
        PL_in_eval |= EVAL_KEEPERR;
     else
@@ -3538,11 +3529,12 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
 
     if (yystatus || PL_parser->error_count || !PL_eval_root) {
        SV **newsp;                     /* Used by POPBLOCK. */
-       PERL_CONTEXT *cx = NULL;
+       PERL_CONTEXT *cx;
        I32 optype;                     /* Used by POPEVAL. */
-       SV *namesv = NULL;
-       const char *msg;
+       SV *namesv;
 
+       cx = NULL;
+       namesv = NULL;
        PERL_UNUSED_VAR(newsp);
        PERL_UNUSED_VAR(optype);
 
@@ -3564,7 +3556,6 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
        if (yystatus != 3)
            LEAVE_with_name("eval"); /* pp_entereval knows about this LEAVE.  */
 
-       msg = SvPVx_nolen_const(ERRSV);
        if (in_require) {
            if (!cx) {
                /* If cx is still NULL, it means that we didn't go in the
@@ -3574,21 +3565,26 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
                namesv = cx->blk_eval.old_namesv;
            }
            (void)hv_store(GvHVn(PL_incgv),
-                          SvPVX_const(namesv), SvCUR(namesv),
+                          SvPVX_const(namesv),
+                           SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
                           &PL_sv_undef, 0);
-           Perl_croak(aTHX_ "%sCompilation failed in require",
-                      *msg ? msg : "Unknown error\n");
+           Perl_croak(aTHX_ "%"SVf"Compilation failed in require",
+                      SVfARG(ERRSV
+                                ? ERRSV
+                                : newSVpvs_flags("Unknown error\n", SVs_TEMP)));
        }
        else if (startop) {
            if (yystatus != 3) {
                POPBLOCK(cx,PL_curpm);
                POPEVAL(cx);
            }
-           Perl_croak(aTHX_ "%sCompilation failed in regexp",
-                      (*msg ? msg : "Unknown error\n"));
+           Perl_croak(aTHX_ "%"SVf"Compilation failed in regexp",
+                      SVfARG(ERRSV
+                                ? ERRSV
+                                : newSVpvs_flags("Unknown error\n", SVs_TEMP)));
        }
        else {
-           if (!*msg) {
+           if (!*(SvPVx_nolen_const(ERRSV))) {
                sv_setpvs(ERRSV, "Compilation error");
            }
        }
@@ -3602,15 +3598,6 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     } else
        SAVEFREEOP(PL_eval_root);
 
-    /* Set the context for this new optree.
-     * Propagate the context from the eval(). */
-    if ((gimme & G_WANT) == G_VOID)
-       scalarvoid(PL_eval_root);
-    else if ((gimme & G_WANT) == G_ARRAY)
-       list(PL_eval_root);
-    else
-       scalar(PL_eval_root);
-
     DEBUG_x(dump_eval());
 
     /* Register with debugger: */
@@ -3656,7 +3643,7 @@ S_check_type_and_open(pTHX_ SV *name)
     }
 
 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
-    return PerlIO_openn(aTHX_ NULL, PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
+    return PerlIO_openn(aTHX_ ":", PERL_SCRIPT_MODE, -1, 0, 0, NULL, 1, &name);
 #else
     return PerlIO_open(p, PERL_SCRIPT_MODE);
 #endif
@@ -4197,14 +4184,14 @@ PP(pp_entereval)
     SAVECOMPILEWARNINGS();
     PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
     cophh_free(CopHINTHASH_get(&PL_compiling));
-    if (Perl_fetch_cop_label(aTHX_ PL_curcop, NULL, NULL)) {
+    if (Perl_cop_fetch_label(aTHX_ PL_curcop, 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
            = cophh_copy(PL_curcop->cop_hints_hash->refcounted_he_next);
        /* Check the assumption that this removed the label.  */
-       assert(Perl_fetch_cop_label(aTHX_ &PL_compiling, NULL, NULL) == NULL);
+       assert(Perl_cop_fetch_label(aTHX_ &PL_compiling, NULL, NULL) == NULL);
     }
     else
        PL_compiling.cop_hints_hash = cophh_copy(PL_curcop->cop_hints_hash);
@@ -4258,7 +4245,6 @@ PP(pp_entereval)
 PP(pp_leaveeval)
 {
     dVAR; dSP;
-    register SV **mark;
     SV **newsp;
     PMOP *newpm;
     I32 gimme;
@@ -4275,31 +4261,8 @@ PP(pp_leaveeval)
     retop = cx->blk_eval.retop;
 
     TAINT_NOT;
-    if (gimme == G_VOID)
-       MARK = newsp;
-    else if (gimme == G_SCALAR) {
-       MARK = newsp + 1;
-       if (MARK <= SP) {
-           if (SvFLAGS(TOPs) & 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 */
-       for (mark = newsp + 1; mark <= SP; mark++) {
-           if (!(SvFLAGS(*mark) & SVs_TEMP)) {
-               *mark = sv_mortalcopy(*mark);
-               TAINT_NOT;      /* Each item is independent */
-           }
-       }
-    }
+    SP = adjust_stack_on_leave((gimme == G_VOID) ? SP : newsp, SP, newsp,
+                               gimme, SVs_TEMP);
     PL_curpm = newpm;  /* Don't pop $1 et al till now */
 
 #ifdef DEBUGGING
@@ -4312,7 +4275,8 @@ PP(pp_leaveeval)
     {
        /* Unassume the success we assumed earlier. */
        (void)hv_delete(GvHVn(PL_incgv),
-                       SvPVX_const(namesv), SvCUR(namesv),
+                       SvPVX_const(namesv),
+                        SvUTF8(namesv) ? -(I32)SvCUR(namesv) : (I32)SvCUR(namesv),
                        G_DISCARD);
        retop = Perl_die(aTHX_ "%"SVf" did not return a true value",
                               SVfARG(namesv));
@@ -4396,33 +4360,7 @@ PP(pp_leavetry)
     PERL_UNUSED_VAR(optype);
 
     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 */
-           }
-       }
-    }
+    SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
     PL_curpm = newpm;  /* Don't pop $1 et al till now */
 
     LEAVE_with_name("eval_scope");
@@ -4439,6 +4377,7 @@ PP(pp_entergiven)
     ENTER_with_name("given");
     SAVETMPS;
 
+    SAVECLEARSV(PAD_SVl(PL_op->op_targ));
     sv_setsv_mg(PAD_SV(PL_op->op_targ), POPs);
 
     PUSHBLOCK(cx, CXt_GIVEN, SP);
@@ -4460,33 +4399,7 @@ PP(pp_leavegiven)
     assert(CxTYPE(cx) == CXt_GIVEN);
 
     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 */
-           }
-       }
-    }
+    SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
     PL_curpm = newpm;  /* Don't pop $1 et al till now */
 
     LEAVE_with_name("given");
@@ -4542,14 +4455,14 @@ S_destroy_matcher(pTHX_ PMOP *matcher)
 PP(pp_smartmatch)
 {
     DEBUG_M(Perl_deb(aTHX_ "Starting smart match resolution\n"));
-    return do_smartmatch(NULL, NULL);
+    return do_smartmatch(NULL, NULL, 0);
 }
 
 /* This version of do_smartmatch() implements the
  * table of smart matches that is found in perlsyn.
  */
 STATIC OP *
-S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
+S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
 {
     dVAR;
     dSP;
@@ -4561,7 +4474,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
     /* Take care only to invoke mg_get() once for each argument.
      * Currently we do this by copying the SV if it's magical. */
     if (d) {
-       if (SvGMAGICAL(d))
+       if (!copied && SvGMAGICAL(d))
            d = sv_mortalcopy(d);
     }
     else
@@ -4872,7 +4785,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
                        
                        PUTBACK;
                        DEBUG_M(Perl_deb(aTHX_ "        recursively comparing array element...\n"));
-                       (void) do_smartmatch(seen_this, seen_other);
+                       (void) do_smartmatch(seen_this, seen_other, 0);
                        SPAGAIN;
                        DEBUG_M(Perl_deb(aTHX_ "        recursion finished\n"));
                        
@@ -4934,7 +4847,7 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other)
                    PUTBACK;
                    /* infinite recursion isn't supposed to happen here */
                    DEBUG_M(Perl_deb(aTHX_ "        recursively testing array element...\n"));
-                   (void) do_smartmatch(NULL, NULL);
+                   (void) do_smartmatch(NULL, NULL, 1);
                    SPAGAIN;
                    DEBUG_M(Perl_deb(aTHX_ "        recursion finished\n"));
                    if (SvTRUEx(POPs))
@@ -5036,7 +4949,7 @@ PP(pp_enterwhen)
     if ((0 == (PL_op->op_flags & OPf_SPECIAL)) && !SvTRUEx(POPs))
        RETURNOP(cLOGOP->op_other->op_next);
 
-    ENTER_with_name("eval");
+    ENTER_with_name("when");
     SAVETMPS;
 
     PUSHBLOCK(cx, CXt_WHEN, SP);
@@ -5048,43 +4961,71 @@ PP(pp_enterwhen)
 PP(pp_leavewhen)
 {
     dVAR; dSP;
+    I32 cxix;
     register PERL_CONTEXT *cx;
-    I32 gimme __attribute__unused__;
+    I32 gimme;
     SV **newsp;
     PMOP *newpm;
 
+    cxix = dopoptogiven(cxstack_ix);
+    if (cxix < 0)
+       DIE(aTHX_ "Can't use when() outside a topicalizer");
+
     POPBLOCK(cx,newpm);
     assert(CxTYPE(cx) == CXt_WHEN);
 
-    SP = newsp;
-    PUTBACK;
-
+    TAINT_NOT;
+    SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
     PL_curpm = newpm;   /* pop $1 et al */
 
-    LEAVE_with_name("eval");
-    return NORMAL;
+    LEAVE_with_name("when");
+
+    if (cxix < cxstack_ix)
+        dounwind(cxix);
+
+    cx = &cxstack[cxix];
+
+    if (CxFOREACH(cx)) {
+       /* clear off anything above the scope we're re-entering */
+       I32 inner = PL_scopestack_ix;
+
+       TOPBLOCK(cx);
+       if (PL_scopestack_ix < inner)
+           leave_scope(PL_scopestack[PL_scopestack_ix]);
+       PL_curcop = cx->blk_oldcop;
+
+       return cx->blk_loop.my_op->op_nextop;
+    }
+    else
+       RETURNOP(cx->blk_givwhen.leave_op);
 }
 
 PP(pp_continue)
 {
-    dVAR;   
+    dVAR; dSP;
     I32 cxix;
     register PERL_CONTEXT *cx;
-    I32 inner;
+    I32 gimme;
+    SV **newsp;
+    PMOP *newpm;
+
+    PERL_UNUSED_VAR(gimme);
     
     cxix = dopoptowhen(cxstack_ix); 
     if (cxix < 0)   
        DIE(aTHX_ "Can't \"continue\" outside a when block");
+
     if (cxix < cxstack_ix)
         dounwind(cxix);
     
-    /* clear off anything above the scope we're re-entering */
-    inner = PL_scopestack_ix;
-    TOPBLOCK(cx);
-    if (PL_scopestack_ix < inner)
-        leave_scope(PL_scopestack[PL_scopestack_ix]);
-    PL_curcop = cx->blk_oldcop;
-    return cx->blk_givwhen.leave_op;
+    POPBLOCK(cx,newpm);
+    assert(CxTYPE(cx) == CXt_WHEN);
+
+    SP = newsp;
+    PL_curpm = newpm;   /* pop $1 et al */
+
+    LEAVE_with_name("when");
+    RETURNOP(cx->blk_givwhen.leave_op->op_next);
 }
 
 PP(pp_break)
@@ -5092,34 +5033,22 @@ PP(pp_break)
     dVAR;   
     I32 cxix;
     register PERL_CONTEXT *cx;
-    I32 inner;
-    dSP;
 
     cxix = dopoptogiven(cxstack_ix); 
-    if (cxix < 0) {
-       if (PL_op->op_flags & OPf_SPECIAL)
-           DIE(aTHX_ "Can't use when() outside a topicalizer");
-       else
-           DIE(aTHX_ "Can't \"break\" outside a given block");
-    }
-    if (CxFOREACH(&cxstack[cxix]) && (0 == (PL_op->op_flags & OPf_SPECIAL)))
+    if (cxix < 0)
+       DIE(aTHX_ "Can't \"break\" outside a given block");
+
+    cx = &cxstack[cxix];
+    if (CxFOREACH(cx))
        DIE(aTHX_ "Can't \"break\" in a loop topicalizer");
 
     if (cxix < cxstack_ix)
         dounwind(cxix);
-    
-    /* clear off anything above the scope we're re-entering */
-    inner = PL_scopestack_ix;
+
+    /* Restore the sp at the time we entered the given block */
     TOPBLOCK(cx);
-    if (PL_scopestack_ix < inner)
-        leave_scope(PL_scopestack[PL_scopestack_ix]);
-    PL_curcop = cx->blk_oldcop;
 
-    if (CxFOREACH(cx))
-       return (cx)->blk_loop.my_op->op_nextop;
-    else
-       /* RETURNOP calls PUTBACK which restores the old old sp */
-       RETURNOP(cx->blk_givwhen.leave_op);
+    return cx->blk_givwhen.leave_op;
 }
 
 static MAGIC *