SvREFCNT_inc_void(cx->blk_format.dfoutgv)
/* Restore old @_ */
-#define POP_SAVEARRAY() \
+#define POP_SAVEARRAY(cx) \
STMT_START { \
AV *av = GvAV(PL_defgv); \
GvAV(PL_defgv) = cx->blk_sub.savearray; \
assert(AvARRAY(MUTABLE_AV( \
PadlistARRAY(CvPADLIST(cx->blk_sub.cv))[ \
CvDEPTH(cx->blk_sub.cv)])) == PL_curpad); \
- POP_SAVEARRAY(); \
- /* abandon @_ if it got reified */ \
+ POP_SAVEARRAY(cx); \
av = MUTABLE_AV(PAD_SVl(0)); \
if (UNLIKELY(AvREAL(av))) \
+ /* abandon @_ if it got reified */ \
clear_defarray(av, 0); \
else { \
CLEAR_ARGARRAY(av); \
PUSHLOOP_FOR_setpad(cx);
#define POPLOOP(cx) \
- if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { \
+ if ( CxTYPE(cx) == CXt_LOOP_ARY \
+ || CxTYPE(cx) == CXt_LOOP_LAZYSV) \
+ { \
+ /* Free ary or cur. This assumes that state_u.ary.ary \
+ * aligns with state_u.lazysv.cur. See cx_dup() */ \
SV *sv = cx->blk_loop.state_u.lazysv.cur; \
cx->blk_loop.state_u.lazysv.cur = NULL; \
SvREFCNT_dec_NN(sv); \
- sv = cx->blk_loop.state_u.lazysv.end; \
- cx->blk_loop.state_u.lazysv.end = NULL; \
- SvREFCNT_dec_NN(sv); \
+ if (CxTYPE(cx) == CXt_LOOP_LAZYSV) { \
+ sv = cx->blk_loop.state_u.lazysv.end; \
+ cx->blk_loop.state_u.lazysv.end = NULL; \
+ SvREFCNT_dec_NN(sv); \
+ } \
} \
- else if (CxTYPE(cx) == CXt_LOOP_ARY) { \
- AV *av = cx->blk_loop.state_u.ary.ary; \
- cx->blk_loop.state_u.ary.ary = NULL; \
- SvREFCNT_dec(av); \
- } \
if (cx->cx_type & (CXp_FOR_PAD|CXp_FOR_GV)) { \
SV *cursv; \
SV **svp = (cx)->blk_loop.itervar_u.svp; \
PL_tmps_floor = PL_tmps_ix; \
CX_DEBUG(cx, "PUSH");
+#define _POPBLOCK_COMMON(cx) \
+ PL_markstack_ptr = PL_markstack + cx->blk_oldmarksp, \
+ PL_scopestack_ix = cx->blk_oldscopesp, \
+ PL_curpm = cx->blk_oldpm,
+
/* Exit a block (RETURN and LAST). */
#define POPBLOCK(cx) \
CX_DEBUG(cx, "POP"); \
- PL_curcop = cx->blk_oldcop, \
- PL_markstack_ptr = PL_markstack + cx->blk_oldmarksp, \
- PL_scopestack_ix = cx->blk_oldscopesp, \
+ _POPBLOCK_COMMON(cx) \
/* LEAVE_SCOPE() should have made this true. /(?{})/ cheats
* and leaves a CX entry lying around for repeated use, so
* skip for multicall */ \
assert( (CxTYPE(cx) == CXt_SUB && CxMULTICALL(cx)) \
|| PL_savestack_ix == cx->blk_oldsaveix); \
+ PL_curcop = cx->blk_oldcop, \
PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; \
- PL_curpm = cx->blk_oldpm;
-/* Continue a block elsewhere (NEXT and REDO). */
+/* Continue a block elsewhere (e.g. NEXT, REDO, GOTO).
+ * Whereas POPBLOCK restores the state to the point just before PUSHBLOCK
+ * was called, TOPBLOCK restores it to the point just *after* PUSHBLOCK
+ * was called. */
#define TOPBLOCK(cx) \
- cx = CX_CUR(); \
CX_DEBUG(cx, "TOP"); \
- PL_stack_sp = PL_stack_base + cx->blk_oldsp, \
- PL_markstack_ptr = PL_markstack + cx->blk_oldmarksp, \
- PL_scopestack_ix = cx->blk_oldscopesp, \
- PL_curpm = cx->blk_oldpm;
+ _POPBLOCK_COMMON(cx) \
+ PL_stack_sp = PL_stack_base + cx->blk_oldsp;
/* substitution context */
struct subst {
U8 sbu_rflags;
U16 sbu_rxtainted;
I32 sbu_oldsaveix; /* same as blku_oldsaveix */
- /* all the fields above must be aligned with same-sized fields as blku * */
+ /* all the fields above must be aligned with same-sized fields as blk_u */
SSize_t sbu_iters;
SSize_t sbu_maxiters;
char * sbu_orig;
/* be careful of the ordering of these five. Macros like CxTYPE_is_LOOP,
* CxFOREACH compare ranges */
-#define CXt_LOOP_PLAIN 4 /* {} */
-#define CXt_LOOP_LAZYIV 5 /* for (1..9) {} */
-#define CXt_LOOP_LAZYSV 6 /* for ('a'..'z') {} */
+#define CXt_LOOP_ARY 4 /* for (@ary) {} */
+#define CXt_LOOP_LAZYSV 5 /* for ('a'..'z') {} */
+#define CXt_LOOP_LAZYIV 6 /* for (1..9) {} */
#define CXt_LOOP_LIST 7 /* for (1,2,3) {} */
-#define CXt_LOOP_ARY 8 /* for (@ary) {} */
+#define CXt_LOOP_PLAIN 8 /* {} */
#define CXt_SUB 9
#define CXt_FORMAT 10
#define CXp_TRYBLOCK 0x40 /* eval{}, not eval'' or similar */
/* private flags for CXt_LOOP */
+
+/* this is only set in conjunction with CXp_FOR_GV */
#define CXp_FOR_DEF 0x10 /* foreach using $_ */
+/* these 3 are mutually exclusive */
#define CXp_FOR_LVREF 0x20 /* foreach using \$var */
#define CXp_FOR_GV 0x40 /* foreach using package var */
#define CXp_FOR_PAD 0x80 /* foreach using lexical var */
+
#define CxPADLOOP(c) ((c)->cx_type & CXp_FOR_PAD)
/* private flags for CXt_SUBST */
#define CXp_ONCE 0x10 /* What was sbu_once in struct subst */
#define CxTYPE(c) ((c)->cx_type & CXTYPEMASK)
-#define CxTYPE_is_LOOP(c) ( CxTYPE(cx) >= CXt_LOOP_PLAIN \
- && CxTYPE(cx) <= CXt_LOOP_ARY)
+#define CxTYPE_is_LOOP(c) ( CxTYPE(cx) >= CXt_LOOP_ARY \
+ && CxTYPE(cx) <= CXt_LOOP_PLAIN)
#define CxMULTICALL(c) ((c)->cx_type & CXp_MULTICALL)
#define CxREALEVAL(c) (((c)->cx_type & (CXTYPEMASK|CXp_REAL)) \
== (CXt_EVAL|CXp_REAL))
#define CxTRYBLOCK(c) (((c)->cx_type & (CXTYPEMASK|CXp_TRYBLOCK)) \
== (CXt_EVAL|CXp_TRYBLOCK))
-#define CxFOREACH(c) ( CxTYPE(cx) >= CXt_LOOP_LAZYSV \
- && CxTYPE(cx) <= CXt_LOOP_ARY)
+#define CxFOREACH(c) ( CxTYPE(cx) >= CXt_LOOP_ARY \
+ && CxTYPE(cx) <= CXt_LOOP_LIST)
#define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc()))