/* cop.h
*
- * Copyright (c) 1991-1999, Larry Wall
+ * Copyright (c) 1991-2000, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
(void)SvREFCNT_inc(cx->blk_sub.dfoutgv)
#ifdef USE_THREADS
-#define POPSAVEARRAY() NOOP
+# define POP_SAVEARRAY() NOOP
#else
-#define POPSAVEARRAY() \
+# define POP_SAVEARRAY() \
STMT_START { \
SvREFCNT_dec(GvAV(PL_defgv)); \
GvAV(PL_defgv) = cx->blk_sub.savearray; \
} STMT_END
#endif /* USE_THREADS */
+#ifdef USE_ITHREADS
+ /* junk in @_ spells trouble when cloning CVs, so don't leave any */
+# define CLEAR_ARGARRAY() av_clear(cx->blk_sub.argarray)
+#else
+# define CLEAR_ARGARRAY() NOOP
+#endif /* USE_ITHREADS */
+
+
#define POPSUB(cx,sv) \
STMT_START { \
if (cx->blk_sub.hasargs) { \
- POPSAVEARRAY(); \
+ POP_SAVEARRAY(); \
/* abandon @_ if it got reified */ \
if (AvREAL(cx->blk_sub.argarray)) { \
SSize_t fill = AvFILLp(cx->blk_sub.argarray); \
AvFLAGS(cx->blk_sub.argarray) = AVf_REIFY; \
PL_curpad[0] = (SV*)cx->blk_sub.argarray; \
} \
+ else { \
+ CLEAR_ARGARRAY(); \
+ } \
} \
sv = (SV*)cx->blk_sub.cv; \
if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth)) \
struct block_eval {
I32 old_in_eval;
I32 old_op_type;
- char * old_name;
+ SV * old_namesv;
OP * old_eval_root;
SV * cur_text;
};
#define PUSHEVAL(cx,n,fgv) \
+ 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_name = n; \
+ cx->blk_eval.old_namesv = (n ? newSVpv(n,0) : Nullsv); \
cx->blk_eval.old_eval_root = PL_eval_root; \
- cx->blk_eval.cur_text = PL_linestr;
+ cx->blk_eval.cur_text = PL_linestr; \
+ } STMT_END
#define POPEVAL(cx) \
+ STMT_START { \
PL_in_eval = cx->blk_eval.old_in_eval; \
optype = cx->blk_eval.old_op_type; \
- PL_eval_root = cx->blk_eval.old_eval_root;
+ PL_eval_root = cx->blk_eval.old_eval_root; \
+ if (cx->blk_eval.old_namesv) \
+ sv_2mortal(cx->blk_eval.old_namesv); \
+ } STMT_END
/* loop context */
struct block_loop {
OP * redo_op;
OP * next_op;
OP * last_op;
+#ifdef USE_ITHREADS
+ void * iterdata;
+#else
SV ** itervar;
+#endif
SV * itersave;
SV * iterlval;
AV * iterary;
IV itermax;
};
-#define PUSHLOOP(cx, ivar, s) \
+#ifdef USE_ITHREADS
+# define CxITERVAR(c) \
+ ((c)->blk_loop.iterdata \
+ ? (CxPADLOOP(cx) \
+ ? &PL_curpad[(PADOFFSET)(c)->blk_loop.iterdata] \
+ : &GvSV((GV*)(c)->blk_loop.iterdata)) \
+ : (SV**)NULL)
+# define CX_ITERDATA_SET(cx,idata) \
+ if ((cx->blk_loop.iterdata = (idata))) \
+ cx->blk_loop.itersave = SvREFCNT_inc(*CxITERVAR(cx));
+#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));
+#endif
+
+#define PUSHLOOP(cx, dat, s) \
cx->blk_loop.label = PL_curcop->cop_label; \
cx->blk_loop.resetsp = s - PL_stack_base; \
cx->blk_loop.redo_op = cLOOP->op_redoop; \
cx->blk_loop.next_op = cLOOP->op_nextop; \
cx->blk_loop.last_op = cLOOP->op_lastop; \
- if (cx->blk_loop.itervar = (ivar)) \
- cx->blk_loop.itersave = SvREFCNT_inc(*cx->blk_loop.itervar);\
cx->blk_loop.iterlval = Nullsv; \
cx->blk_loop.iterary = Nullav; \
- cx->blk_loop.iterix = -1;
+ cx->blk_loop.iterix = -1; \
+ CX_ITERDATA_SET(cx,dat);
#define POPLOOP(cx) \
SvREFCNT_dec(cx->blk_loop.iterlval); \
- if (cx->blk_loop.itervar) { \
- sv_2mortal(*(cx->blk_loop.itervar)); \
- *(cx->blk_loop.itervar) = cx->blk_loop.itersave; \
+ if (CxITERVAR(cx)) { \
+ SV **s_v_p = CxITERVAR(cx); \
+ sv_2mortal(*s_v_p); \
+ *s_v_p = cx->blk_loop.itersave; \
} \
if (cx->blk_loop.iterary && cx->blk_loop.iterary != PL_curstack)\
SvREFCNT_dec(cx->blk_loop.iterary);
#define CXt_LOOP 3
#define CXt_SUBST 4
#define CXt_BLOCK 5
+#define CXt_FORMAT 6
/* private flags for CXt_EVAL */
#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_PADVAR 0x00000100 /* itervar lives on pad, iterdata
+ has pad offset; if not set,
+ iterdata holds GV* */
+# define CxPADLOOP(c) (((c)->cx_type & (CXt_LOOP|CXp_PADVAR)) \
+ == (CXt_LOOP|CXp_PADVAR))
+#endif
#define CxTYPE(c) ((c)->cx_type & CXTYPEMASK)
-#define CxREALEVAL(c) (((c)->cx_type & (CXt_EVAL|CXp_REAL)) == (CXt_EVAL|CXp_REAL))
+#define CxREALEVAL(c) (((c)->cx_type & (CXt_EVAL|CXp_REAL)) \
+ == (CXt_EVAL|CXp_REAL))
+#define CxTRYBLOCK(c) (((c)->cx_type & (CXt_EVAL|CXp_TRYBLOCK)) \
+ == (CXt_EVAL|CXp_TRYBLOCK))
#define CXINC (cxstack_ix < cxstack_max ? ++cxstack_ix : (cxstack_ix = cxinc()))
/* "gimme" values */
+
+/*
+=for apidoc AmU||G_SCALAR
+Used to indicate scalar context. See C<GIMME_V>, C<GIMME>, and
+L<perlcall>.
+
+=for apidoc AmU||G_ARRAY
+Used to indicate array context. See C<GIMME_V>, C<GIMME> and
+L<perlcall>.
+
+=for apidoc AmU||G_VOID
+Used to indicate void context. See C<GIMME_V> and L<perlcall>.
+
+=for apidoc AmU||G_DISCARD
+Indicates that arguments returned from a callback should be discarded. See
+L<perlcall>.
+
+=for apidoc AmU||G_EVAL
+
+Used to force a Perl C<eval> wrapper around a callback. See
+L<perlcall>.
+
+=for apidoc AmU||G_NOARGS
+
+Indicates that no arguments are being sent to a callback. See
+L<perlcall>.
+
+=cut
+*/
+
#define G_SCALAR 0
#define G_ARRAY 1
#define G_VOID 128 /* skip this bit when adding flags below */