/* cop.h
*
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others
+ * 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
#ifdef USE_ITHREADS
# define CopFILE(c) ((c)->cop_file)
# define CopFILEGV(c) (CopFILE(c) \
- ? gv_fetchfile(CopFILE(c)) : Nullgv)
+ ? gv_fetchfile(CopFILE(c)) : NULL)
# ifdef NETWARE
# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv))
# endif
# define CopFILESV(c) (CopFILE(c) \
- ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv)
+ ? GvSV(gv_fetchfile(CopFILE(c))) : NULL)
# define CopFILEAV(c) (CopFILE(c) \
- ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav)
+ ? GvAV(gv_fetchfile(CopFILE(c))) : NULL)
+# ifdef DEBUGGING
+# define CopFILEAVx(c) (assert(CopFILE(c)), \
+ GvAV(gv_fetchfile(CopFILE(c))))
+# else
+# define CopFILEAVx(c) (GvAV(gv_fetchfile(CopFILE(c))))
+# endif
# define CopSTASHPV(c) ((c)->cop_stashpv)
# ifdef NETWARE
-# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch))
+# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : NULL))
# else
# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = savesharedpv(pv))
# endif
# define CopSTASH(c) (CopSTASHPV(c) \
- ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv)
-# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME_get(hv) : Nullch)
+ ? gv_stashpv(CopSTASHPV(c),GV_ADD) : NULL)
+# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME_get(hv) : NULL)
# define CopSTASH_eq(c,hv) ((hv) && stashpv_hvname_match(c,hv))
# ifdef NETWARE
# define CopSTASH_free(c) SAVECOPSTASH_FREE(c)
# define CopFILE_free(c) SAVECOPFILE_FREE(c)
# else
# define CopSTASH_free(c) PerlMemShared_free(CopSTASHPV(c))
-# define CopFILE_free(c) (PerlMemShared_free(CopFILE(c)),(CopFILE(c) = Nullch))
+# define CopFILE_free(c) (PerlMemShared_free(CopFILE(c)),(CopFILE(c) = NULL))
# endif
#else
# define CopFILEGV(c) ((c)->cop_filegv)
# define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv))
# define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv))
-# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv)
-# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav)
-# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch)
+# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : NULL)
+# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : NULL)
+# ifdef DEBUGGING
+# define CopFILEAVx(c) (assert(CopFILEGV(c)), GvAV(CopFILEGV(c)))
+# else
+# define CopFILEAVx(c) (GvAV(CopFILEGV(c)))
+# endif
+# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : NULL)
# define CopSTASH(c) ((c)->cop_stash)
# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv))
-# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME_get(CopSTASH(c)) : Nullch)
+# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME_get(CopSTASH(c)) : NULL)
/* cop_stash is not refcounted */
# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD))
# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv))
# define CopSTASH_free(c)
-# define CopFILE_free(c) (SvREFCNT_dec(CopFILEGV(c)),(CopFILEGV(c) = Nullgv))
+# define CopFILE_free(c) (SvREFCNT_dec(CopFILEGV(c)),(CopFILEGV(c) = NULL))
#endif /* USE_ITHREADS */
} \
sv = (SV*)cx->blk_sub.cv; \
if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth)) \
- sv = Nullsv; \
+ sv = NULL; \
} STMT_END
#define LEAVESUB(sv) \
STMT_START { \
cx->blk_eval.old_in_eval = PL_in_eval; \
cx->blk_eval.old_op_type = PL_op->op_type; \
- cx->blk_eval.old_namesv = (n ? newSVpv(n,0) : Nullsv); \
+ cx->blk_eval.old_namesv = (n ? newSVpv(n,0) : NULL); \
cx->blk_eval.old_eval_root = PL_eval_root; \
cx->blk_eval.cur_text = PL_linestr; \
- cx->blk_eval.cv = Nullcv; /* set by doeval(), as applicable */ \
+ cx->blk_eval.cv = NULL; /* set by doeval(), as applicable */ \
cx->blk_eval.retop = Nullop; \
cx->blk_eval.cur_top_env = PL_top_env; \
} STMT_END
if ((cx->blk_loop.iterdata = (idata))) \
cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); \
else \
- cx->blk_loop.itersave = Nullsv;
+ cx->blk_loop.itersave = NULL;
#else
# define CxITERVAR(c) ((c)->blk_loop.itervar)
# define CX_ITERDATA_SET(cx,ivar) \
if ((cx->blk_loop.itervar = (SV**)(ivar))) \
cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx)); \
else \
- cx->blk_loop.itersave = Nullsv;
+ cx->blk_loop.itersave = NULL;
#endif
#define PUSHLOOP(cx, dat, s) \
cx->blk_loop.redo_op = cLOOP->op_redoop; \
cx->blk_loop.next_op = cLOOP->op_nextop; \
cx->blk_loop.last_op = cLOOP->op_lastop; \
- cx->blk_loop.iterlval = Nullsv; \
- cx->blk_loop.iterary = Nullav; \
+ cx->blk_loop.iterlval = NULL; \
+ cx->blk_loop.iterary = NULL; \
cx->blk_loop.iterix = -1; \
CX_ITERDATA_SET(cx,dat);
if (cx->blk_loop.iterary && cx->blk_loop.iterary != PL_curstack)\
SvREFCNT_dec(cx->blk_loop.iterary);
+/* given/when context */
+struct block_givwhen {
+ OP *leave_op;
+};
+
+#define PUSHGIVEN(cx) \
+ cx->blk_givwhen.leave_op = cLOGOP->op_other;
+
+#define PUSHWHEN PUSHGIVEN
+
/* context common to subroutines, evals and loops */
struct block {
I32 blku_oldsp; /* stack pointer to copy stuff down to */
struct block_sub blku_sub;
struct block_eval blku_eval;
struct block_loop blku_loop;
+ struct block_givwhen blku_givwhen;
} blk_u;
};
#define blk_oldsp cx_u.cx_blk.blku_oldsp
#define blk_sub cx_u.cx_blk.blk_u.blku_sub
#define blk_eval cx_u.cx_blk.blk_u.blku_eval
#define blk_loop cx_u.cx_blk.blk_u.blku_loop
+#define blk_givwhen cx_u.cx_blk.blk_u.blku_givwhen
/* Enter a block. */
#define PUSHBLOCK(cx,t,sp) CXINC, cx = &cxstack[cxstack_ix], \
#define CXt_SUBST 4
#define CXt_BLOCK 5
#define CXt_FORMAT 6
+#define CXt_GIVEN 7
+#define CXt_WHEN 8
/* private flags for CXt_SUB and CXt_NULL */
#define CXp_MULTICALL 0x00000400 /* part of a multicall (so don't
#define CXp_REAL 0x00000100 /* truly eval'', not a lookalike */
#define CXp_TRYBLOCK 0x00000200 /* eval{}, not eval'' or similar */
-#ifdef USE_ITHREADS
/* private flags for CXt_LOOP */
+#define CXp_FOREACH 0x00000200 /* a foreach loop */
+#define CXp_FOR_DEF 0x00000400 /* foreach using $_ */
+#ifdef USE_ITHREADS
# define CXp_PADVAR 0x00000100 /* itervar lives on pad, iterdata
has pad offset; if not set,
iterdata holds GV* */
== (CXt_EVAL|CXp_REAL))
#define CxTRYBLOCK(c) (((c)->cx_type & (CXt_EVAL|CXp_TRYBLOCK)) \
== (CXt_EVAL|CXp_TRYBLOCK))
+#define CxFOREACH(c) (((c)->cx_type & (CXt_LOOP|CXp_FOREACH)) \
+ == (CXt_LOOP|CXp_FOREACH))
+#define CxFOREACHDEF(c) (((c)->cx_type & (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))\
+ == (CXt_LOOP|CXp_FOREACH|CXp_FOR_DEF))
#define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc()))
#define dMULTICALL \
SV **newsp; /* set by POPBLOCK */ \
PERL_CONTEXT *cx; \
- CV *cv; \
+ CV *multicall_cv; \
OP *multicall_cop; \
bool multicall_oldcatch; \
U8 hasargs = 0 /* used by PUSHSUB */
-#define PUSH_MULTICALL \
+#define PUSH_MULTICALL(the_cv) \
STMT_START { \
- AV* padlist = CvPADLIST(cv); \
+ CV * const _nOnclAshIngNamE_ = the_cv; \
+ CV * const cv = _nOnclAshIngNamE_; \
+ AV * const padlist = CvPADLIST(cv); \
ENTER; \
multicall_oldcatch = CATCH_GET; \
SAVETMPS; SAVEVPTR(PL_op); \
} \
SAVECOMPPAD(); \
PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); \
+ multicall_cv = cv; \
multicall_cop = CvSTART(cv); \
} STMT_END
#define POP_MULTICALL \
STMT_START { \
- LEAVESUB(cv); \
- CvDEPTH(cv)--; \
+ LEAVESUB(multicall_cv); \
+ CvDEPTH(multicall_cv)--; \
POPBLOCK(cx,PL_curpm); \
CATCH_SET(multicall_oldcatch); \
LEAVE; \