-/***********************************************************
+/* pp.h
*
- * $Header: /usr/src/local/lwall/perl5/RCS/pp.h,v 4.1 92/08/07 18:26:20 lwall Exp Locker: lwall $
+ * Copyright (c) 1991-1994, Larry Wall
*
- * Description:
- * Push/Pop code defs.
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file.
*
- * Standards:
- *
- * Created:
- * Mon Jun 15 16:47:20 1992
- *
- * Author:
- * Larry Wall <lwall@netlabs.com>
- *
- * $Log: pp.h,v $
- * Revision 4.1 92/08/07 18:26:20 lwall
- *
- *
- **********************************************************/
+ */
#define ARGS
-#define ARGSproto
+#define ARGSproto void
#define dARGS
#define PP(s) OP* s(ARGS) dARGS
#define MARK mark
#define TARG targ
+#define PUSHMARK(p) if (++markstack_ptr == markstack_max) \
+ markstack_grow(); \
+ *markstack_ptr = (p) - stack_base
+
+#define TOPMARK (*markstack_ptr)
#define POPMARK (*markstack_ptr--)
+
#define dSP register SV **sp = stack_sp
#define dMARK register SV **mark = stack_base + POPMARK
#define dORIGMARK I32 origmark = mark - stack_base
#define SETORIGMARK origmark = mark - stack_base
-#define ORIGMARK stack_base + origmark
+#define ORIGMARK (stack_base + origmark)
#define SPAGAIN sp = stack_sp
#define MSPAGAIN sp = stack_sp; mark = ORIGMARK
#define dTARG SV *targ
-#define GETavn(a,g,st) \
- a = sv_2av(cGVOP->op_gv ? (SV*)cGVOP->op_gv : POPs, &st, &g, 1)
-#define GEThvn(h,g,st) \
- h = sv_2hv(cGVOP->op_gv ? (SV*)cGVOP->op_gv : POPs, &st, &g, 1)
-#define GETav(a,g,st) \
- a = sv_2av(cGVOP->op_gv ? (SV*)cGVOP->op_gv : POPs, &st, &g, 0)
-#define GEThv(h,g,st) \
- h = sv_2hv(cGVOP->op_gv ? (SV*)cGVOP->op_gv : POPs, &st, &g, 0)
-#define GETcv(r,g,st) \
- r = sv_2cv(POPs, &st, &g, 0)
-
#define NORMAL op->op_next
#define DIE return die
-#define PROP if (dying) return die("%s", dying);
#define PUTBACK stack_sp = sp
#define RETURN return PUTBACK, NORMAL
#define RETURNX(x) return x, PUTBACK, NORMAL
#define POPs (*sp--)
-#define POPp (SvPVnx(POPs))
-#define POPn (SvNVnx(POPs))
-#define POPi ((int)SvIVnx(POPs))
-#define POPl ((long)SvIVnx(POPs))
+#define POPp (SvPVx(POPs, na))
+#define POPn (SvNVx(POPs))
+#define POPi ((IV)SvIVx(POPs))
+#define POPl ((long)SvIVx(POPs))
#define TOPs (*sp)
-#define TOPp (SvPVn(TOPs))
-#define TOPn (SvNVn(TOPs))
-#define TOPi ((int)SvIVn(TOPs))
-#define TOPl ((long)SvIVn(TOPs))
+#define TOPp (SvPV(TOPs, na))
+#define TOPn (SvNV(TOPs))
+#define TOPi ((IV)SvIV(TOPs))
+#define TOPl ((long)SvIV(TOPs))
/* Go to some pains in the rare event that we must extend the stack. */
-#define EXTEND(p,n) do { if (stack_max - p < (n)) { \
- av_fill(stack, (p - stack_base) + (n)); \
- sp = AvARRAY(stack) + (sp - stack_base); \
- stack_base = AvARRAY(stack); \
- stack_max = stack_base + AvMAX(stack); \
- } } while (0)
+#define EXTEND(p,n) STMT_START { if (stack_max - p < (n)) { \
+ sp = stack_grow(sp,p, (int) (n)); \
+ } } STMT_END
+
/* Same thing, but update mark register too. */
-#define MEXTEND(p,n) do {if (stack_max - p < (n)) { \
- av_fill(stack, (p - stack_base) + (n)); \
- sp = AvARRAY(stack) + (sp - stack_base); \
- mark = AvARRAY(stack) + (mark - stack_base); \
- stack_base = AvARRAY(stack); \
- stack_max = stack_base + AvMAX(stack); \
- } } while (0)
+#define MEXTEND(p,n) STMT_START {if (stack_max - p < (n)) { \
+ int markoff = mark - stack_base; \
+ sp = stack_grow(sp,p,(int) (n)); \
+ mark = stack_base + markoff; \
+ } } STMT_END
#define PUSHs(s) (*++sp = (s))
-#define PUSHTARG do { SvSETMAGIC(TARG); PUSHs(TARG); } while (0)
-#define PUSHp(p,l) do { sv_setpvn(TARG, (p), (l)); PUSHTARG; } while (0)
-#define PUSHn(n) do { sv_setnv(TARG, (n)); PUSHTARG; } while (0)
-#define PUSHi(i) do { sv_setiv(TARG, (i)); PUSHTARG; } while (0)
-
-#define XPUSHs(s) do { EXTEND(sp,1); (*++sp = (s)); } while (0)
-#define XPUSHTARG do { SvSETMAGIC(TARG); XPUSHs(TARG); } while (0)
-#define XPUSHp(p,l) do { sv_setpvn(TARG, (p), (l)); XPUSHTARG; } while (0)
-#define XPUSHn(n) do { sv_setnv(TARG, (n)); XPUSHTARG; } while (0)
-#define XPUSHi(i) do { sv_setiv(TARG, (i)); XPUSHTARG; } while (0)
-
-#define MXPUSHs(s) do { MEXTEND(sp,1); (*++sp = (s)); } while (0)
-#define MXPUSHTARG do { SvSETMAGIC(TARG); XPUSHs(TARG); } while (0)
-#define MXPUSHp(p,l) do { sv_setpvn(TARG, (p), (l)); XPUSHTARG; } while (0)
-#define MXPUSHn(n) do { sv_setnv(TARG, (n)); XPUSHTARG; } while (0)
-#define MXPUSHi(i) do { sv_setiv(TARG, (i)); XPUSHTARG; } while (0)
+#define PUSHTARG STMT_START { SvSETMAGIC(TARG); PUSHs(TARG); } STMT_END
+#define PUSHp(p,l) STMT_START { sv_setpvn(TARG, (p), (l)); PUSHTARG; } STMT_END
+#define PUSHn(n) STMT_START { sv_setnv(TARG, (double)(n)); PUSHTARG; } STMT_END
+#define PUSHi(i) STMT_START { sv_setiv(TARG, (IV)(i)); PUSHTARG; } STMT_END
+
+#define XPUSHs(s) STMT_START { EXTEND(sp,1); (*++sp = (s)); } STMT_END
+#define XPUSHTARG STMT_START { SvSETMAGIC(TARG); XPUSHs(TARG); } STMT_END
+#define XPUSHp(p,l) STMT_START { sv_setpvn(TARG, (p), (l)); XPUSHTARG; } STMT_END
+#define XPUSHn(n) STMT_START { sv_setnv(TARG, (double)(n)); XPUSHTARG; } STMT_END
+#define XPUSHi(i) STMT_START { sv_setiv(TARG, (IV)(i)); XPUSHTARG; } STMT_END
#define SETs(s) (*sp = s)
-#define SETTARG do { SvSETMAGIC(TARG); SETs(TARG); } while (0)
-#define SETp(p,l) do { sv_setpvn(TARG, (p), (l)); SETTARG; } while (0)
-#define SETn(n) do { sv_setnv(TARG, (n)); SETTARG; } while (0)
-#define SETi(i) do { sv_setiv(TARG, (i)); SETTARG; } while (0)
+#define SETTARG STMT_START { SvSETMAGIC(TARG); SETs(TARG); } STMT_END
+#define SETp(p,l) STMT_START { sv_setpvn(TARG, (p), (l)); SETTARG; } STMT_END
+#define SETn(n) STMT_START { sv_setnv(TARG, (double)(n)); SETTARG; } STMT_END
+#define SETi(i) STMT_START { sv_setiv(TARG, (IV)(i)); SETTARG; } STMT_END
+
+#ifdef OVERLOAD
+#define SETsv(sv) STMT_START { sv_setsv(TARG, (sv)); SETTARG; } STMT_END
+#endif /* OVERLOAD */
#define dTOPss SV *sv = TOPs
#define dPOPss SV *sv = POPs
#define dTOPnv double value = TOPn
#define dPOPnv double value = POPn
-#define dTOPiv I32 value = TOPi
-#define dPOPiv I32 value = POPi
+#define dTOPiv IV value = TOPi
+#define dPOPiv IV value = POPi
-#define dPOPPOPssrl SV *rstr = POPs; SV *lstr = POPs
+#define dPOPPOPssrl SV *right = POPs; SV *left = POPs
#define dPOPPOPnnrl double right = POPn; double left = POPn
-#define dPOPPOPiirl I32 right = POPi; I32 left = POPi
+#define dPOPPOPiirl IV right = POPi; IV left = POPi
-#define dPOPTOPssrl SV *rstr = POPs; SV *lstr = TOPs
+#define dPOPTOPssrl SV *right = POPs; SV *left = TOPs
#define dPOPTOPnnrl double right = POPn; double left = TOPn
-#define dPOPTOPiirl I32 right = POPi; I32 left = TOPi
+#define dPOPTOPiirl IV right = POPi; IV left = TOPi
#define RETPUSHYES RETURNX(PUSHs(&sv_yes))
#define RETPUSHNO RETURNX(PUSHs(&sv_no))
#define SWITCHSTACK(f,t) AvFILL(f) = sp - stack_base; \
stack_base = AvARRAY(t); \
stack_max = stack_base + AvMAX(t); \
- sp = stack_base + AvFILL(t); \
+ sp = stack_sp = stack_base + AvFILL(t); \
stack = t;
-/* XXX need to diffentiate on marked operators? */
-#define FETCH_GV(s) PUTBACK, s = fetch_gv(op,1), SPAGAIN
-#define FETCH_GV1(s) PUTBACK, s = fetch_gv(op,1), SPAGAIN
-#define FETCH_GV2(s) PUTBACK, s = fetch_gv(op,2), SPAGAIN
-#define FETCH_IO(s) PUTBACK, s = fetch_io(op,1), SPAGAIN
-#define FETCH_IO1(s) PUTBACK, s = fetch_io(op,1), SPAGAIN
-#define FETCH_IO2(s) PUTBACK, s = fetch_io(op,2), SPAGAIN
-
-#define ENTER push_scope()
-#define LEAVE pop_scope()
-
-#define SAVEINT(i) save_int((int*)(&i));
-#define SAVEI32(i) save_int((I32*)(&i));
-#define SAVELONG(l) save_int((long*)(&l));
-#define SAVESPTR(s) save_sptr((SV**)(&s))
-#define SAVETMPS save_int(&tmps_floor), tmps_floor = tmps_ix
+#ifdef OVERLOAD
+
+#define AMGf_noright 1
+#define AMGf_noleft 2
+#define AMGf_assign 4
+#define AMGf_unary 8
+
+#define tryAMAGICbinW(meth,assign,set) STMT_START { \
+ if (amagic_generation) { \
+ SV* tmpsv; \
+ SV* right= *(sp); SV* left= *(sp-1);\
+ if ((SvAMAGIC(left)||SvAMAGIC(right))&&\
+ (tmpsv=amagic_call(left, \
+ right, \
+ CAT2(meth,_amg), \
+ (assign)? AMGf_assign: 0))) {\
+ SPAGAIN; \
+ (void)POPs; set(tmpsv); RETURN; } \
+ } \
+ } STMT_END
+
+#define tryAMAGICbin(meth,assign) tryAMAGICbinW(meth,assign,SETsv)
+#define tryAMAGICbinSET(meth,assign) tryAMAGICbinW(meth,assign,SETs)
+
+#define AMG_CALLun(sv,meth) amagic_call(sv,&sv_undef, \
+ CAT2(meth,_amg),AMGf_noright | AMGf_unary)
+#define AMG_CALLbinL(left,right,meth) \
+ amagic_call(left,right,CAT2(meth,_amg),AMGf_noright)
+
+#define tryAMAGICunW(meth,set) STMT_START { \
+ if (amagic_generation) { \
+ SV* tmpsv; \
+ SV* arg= *(sp); \
+ if ((SvAMAGIC(arg))&&\
+ (tmpsv=AMG_CALLun(arg,meth))) {\
+ SPAGAIN; \
+ set(tmpsv); RETURN; } \
+ } \
+ } STMT_END
+
+#define tryAMAGICun(meth) tryAMAGICunW(meth,SETsv)
+#define tryAMAGICunSET(meth) tryAMAGICunW(meth,SETs)
+
+#define opASSIGN (op->op_flags & OPf_STACKED)
+
+/* newSVsv does not behave as advertised, so we copy missing
+ * information by hand */
+
+
+#define RvDEEPCP(rv) STMT_START { SV* ref=SvRV(rv); \
+ if (SvREFCNT(ref)>1) { \
+ SvREFCNT_dec(ref); \
+ SvRV(rv)=AMG_CALLun(rv,copy); \
+ } } STMT_END
+#else
+
+#define tryAMAGICbin(a,b)
+#define tryAMAGICbinSET(a,b)
+#define tryAMAGICun(a)
+#define tryAMAGICunSET(a)
+
+#endif /* OVERLOAD */