diff options
-rw-r--r-- | cop.h | 15 | ||||
-rw-r--r-- | pp_ctl.c | 15 |
2 files changed, 25 insertions, 5 deletions
@@ -836,12 +836,23 @@ struct block_loop { /* given/when context */ struct block_givwhen { OP *leave_op; + SV *defsv_save; /* the original $_ */ }; -#define PUSHGIVEN(cx) \ +#define PUSHWHEN(cx) \ cx->blk_givwhen.leave_op = cLOGOP->op_other; -#define PUSHWHEN PUSHGIVEN +#define PUSHGIVEN(cx, orig_var) \ + PUSHWHEN(cx); \ + cx->blk_givwhen.defsv_save = orig_var; + +#define POPWHEN(cx) \ + NOOP; + +#define POPGIVEN(cx) \ + SvREFCNT_dec(GvSV(PL_defgv)); \ + GvSV(PL_defgv) = cx->blk_givwhen.defsv_save; + /* context common to subroutines, evals and loops */ struct block { @@ -1528,6 +1528,12 @@ Perl_dounwind(pTHX_ I32 cxix) case CXt_LOOP_PLAIN: POPLOOP(cx); break; + case CXt_WHEN: + POPWHEN(cx); + break; + case CXt_GIVEN: + POPGIVEN(cx); + break; case CXt_NULL: break; case CXt_FORMAT: @@ -4409,16 +4415,17 @@ PP(pp_entergiven) dSP; PERL_CONTEXT *cx; const I32 gimme = GIMME_V; + SV *origsv = DEFSV; + SV *newsv = POPs; ENTER_with_name("given"); SAVETMPS; assert(!PL_op->op_targ); /* used to be set for lexical $_ */ - SAVE_DEFSV; - DEFSV_set(POPs); + GvSV(PL_defgv) = SvREFCNT_inc(newsv); PUSHBLOCK(cx, CXt_GIVEN, SP); - PUSHGIVEN(cx); + PUSHGIVEN(cx, origsv); RETURN; } @@ -4433,6 +4440,7 @@ PP(pp_leavegiven) PERL_UNUSED_CONTEXT; POPBLOCK(cx,newpm); + POPGIVEN(cx); assert(CxTYPE(cx) == CXt_GIVEN); SP = (gimme == G_VOID) @@ -5020,6 +5028,7 @@ PP(pp_leavewhen) POPBLOCK(cx,newpm); assert(CxTYPE(cx) == CXt_WHEN); + POPWHEN(cx); SP = (gimme == G_VOID) ? newsp |