/* pp.h
*
- * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
- * 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+ * 2002, 2003, 2004, 2005, 2006, 2007, 2008 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.
#define dSP SV **sp = PL_stack_sp
#define djSP dSP
-#define dMARK register SV **mark = PL_stack_base + POPMARK
+#define dMARK SV **mark = PL_stack_base + POPMARK
#define dORIGMARK const I32 origmark = (I32)(mark - PL_stack_base)
#define ORIGMARK (PL_stack_base + origmark)
Pops an SV off the stack.
=for apidoc Amn|char*|POPp
-Pops a string off the stack. Deprecated. New code should use POPpx.
+Pops a string off the stack.
=for apidoc Amn|char*|POPpx
-Pops a string off the stack.
+Pops a string off the stack. Identical to POPp. There are two names for
+historical reasons.
=for apidoc Amn|char*|POPpbytex
Pops a string off the stack which must consist of bytes i.e. characters < 256.
#define RETURNX(x) return (x, PUTBACK, NORMAL)
#define POPs (*sp--)
-#define POPp (SvPVx(POPs, PL_na)) /* deprecated */
+#define POPp POPpx
#define POPpx (SvPVx_nolen(POPs))
#define POPpconstx (SvPVx_nolen_const(POPs))
#define POPpbytex (SvPVbytex_nolen(POPs))
#define TOPs (*sp)
#define TOPm1s (*(sp-1))
#define TOPp1s (*(sp+1))
-#define TOPp (SvPV(TOPs, PL_na)) /* deprecated */
+#define TOPp TOPpx
#define TOPpx (SvPV_nolen(TOPs))
#define TOPn (SvNV(TOPs))
#define TOPi ((IV)SvIV(TOPs))
=cut
*/
-#define EXTEND(p,n) STMT_START { if (PL_stack_max - p < (int)(n)) { \
- sp = stack_grow(sp,p, (int) (n)); \
- } } STMT_END
+#define EXTEND(p,n) (void)(UNLIKELY(PL_stack_max - p < (int)(n)) && \
+ (sp = stack_grow(sp,p, (int) (n))))
/* Same thing, but update mark register too. */
-#define MEXTEND(p,n) STMT_START {if (PL_stack_max - p < (int)(n)) { \
- const int markoff = mark - PL_stack_base; \
- sp = stack_grow(sp,p,(int) (n)); \
- mark = PL_stack_base + markoff; \
- } } STMT_END
+#define MEXTEND(p,n) STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
+ const int markoff = mark - PL_stack_base; \
+ sp = stack_grow(sp,p,(int) (n)); \
+ mark = PL_stack_base + markoff; \
+ } } STMT_END
#define PUSHs(s) (*++sp = (s))
#define PUSHTARG STMT_START { SvSETMAGIC(TARG); PUSHs(TARG); } STMT_END
#define PUSHi(i) STMT_START { sv_setiv(TARG, (IV)(i)); PUSHTARG; } STMT_END
#define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END
-#define XPUSHs(s) STMT_START { EXTEND(sp,1); (*++sp = (s)); } STMT_END
+#define XPUSHs(s) (EXTEND(sp,1), *++sp = (s))
#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, (NV)(n)); XPUSHTARG; } STMT_END
#define mPUSHs(s) PUSHs(sv_2mortal(s))
#define PUSHmortal PUSHs(sv_newmortal())
-#define mPUSHp(p,l) sv_setpvn(PUSHmortal, (p), (l))
+#define mPUSHp(p,l) PUSHs(newSVpvn_flags((p), (l), SVs_TEMP))
#define mPUSHn(n) sv_setnv(PUSHmortal, (NV)(n))
#define mPUSHi(i) sv_setiv(PUSHmortal, (IV)(i))
#define mPUSHu(u) sv_setuv(PUSHmortal, (UV)(u))
#define mXPUSHs(s) XPUSHs(sv_2mortal(s))
#define XPUSHmortal XPUSHs(sv_newmortal())
-#define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END
+#define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); mPUSHp((p), (l)); } STMT_END
#define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END
#define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END
#define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END
#define dPOPss SV *sv = POPs
#define dTOPnv NV value = TOPn
#define dPOPnv NV value = POPn
+#define dPOPnv_nomg NV value = (sp--, SvNV_nomg(TOPp1s))
#define dTOPiv IV value = TOPi
#define dPOPiv IV value = POPi
#define dTOPuv UV value = TOPu
#define dPOPXiirl(X) IV right = POPi; IV left = CAT2(X,i)
#define USE_LEFT(sv) \
- (SvOK(sv) || SvGMAGICAL(sv) || !(PL_op->op_flags & OPf_STACKED))
-#define dPOPXnnrl_ul(X) \
- NV right = POPn; \
- SV *leftsv = CAT2(X,s); \
- NV left = USE_LEFT(leftsv) ? SvNV(leftsv) : 0.0
-#define dPOPXiirl_ul(X) \
- IV right = POPi; \
+ (SvOK(sv) || !(PL_op->op_flags & OPf_STACKED))
+#define dPOPXiirl_ul_nomg(X) \
+ IV right = (sp--, SvIV_nomg(TOPp1s)); \
SV *leftsv = CAT2(X,s); \
- IV left = USE_LEFT(leftsv) ? SvIV(leftsv) : 0
+ IV left = USE_LEFT(leftsv) ? SvIV_nomg(leftsv) : 0
#define dPOPPOPssrl dPOPXssrl(POP)
#define dPOPPOPnnrl dPOPXnnrl(POP)
-#define dPOPPOPnnrl_ul dPOPXnnrl_ul(POP)
#define dPOPPOPiirl dPOPXiirl(POP)
-#define dPOPPOPiirl_ul dPOPXiirl_ul(POP)
#define dPOPTOPssrl dPOPXssrl(TOP)
#define dPOPTOPnnrl dPOPXnnrl(TOP)
-#define dPOPTOPnnrl_ul dPOPXnnrl_ul(TOP)
+#define dPOPTOPnnrl_nomg \
+ NV right = SvNV_nomg(TOPs); NV left = (sp--, SvNV_nomg(TOPs))
#define dPOPTOPiirl dPOPXiirl(TOP)
-#define dPOPTOPiirl_ul dPOPXiirl_ul(TOP)
+#define dPOPTOPiirl_ul_nomg dPOPXiirl_ul_nomg(TOP)
+#define dPOPTOPiirl_nomg \
+ IV right = SvIV_nomg(TOPs); IV left = (sp--, SvIV_nomg(TOPs))
#define RETPUSHYES RETURNX(PUSHs(&PL_sv_yes))
#define RETPUSHNO RETURNX(PUSHs(&PL_sv_no))
#define EXTEND_MORTAL(n) \
STMT_START { \
- if (PL_tmps_ix + (n) >= PL_tmps_max) \
+ if (UNLIKELY(PL_tmps_ix + (n) >= PL_tmps_max)) \
tmps_grow(n); \
} STMT_END
#define AMGf_noleft 2
#define AMGf_assign 4
#define AMGf_unary 8
+#define AMGf_numeric 0x10 /* for Perl_try_amagic_bin */
+#define AMGf_set 0x20 /* for Perl_try_amagic_bin */
+#define AMGf_want_list 0x40
-#define tryAMAGICbinW_var(meth_enum,assign,set) STMT_START { \
- SV* const left = *(sp-1); \
- SV* const right = *(sp); \
- if ((SvAMAGIC(left)||SvAMAGIC(right))) {\
- SV * const tmpsv = amagic_call(left, \
- right, \
- (meth_enum), \
- (assign)? AMGf_assign: 0); \
- if (tmpsv) { \
- SPAGAIN; \
- (void)POPs; set(tmpsv); RETURN; } \
- } \
- } STMT_END
-
-#define tryAMAGICbinW(meth,assign,set) \
- tryAMAGICbinW_var(CAT2(meth,_amg),assign,set)
-#define tryAMAGICbin_var(meth_enum,assign) \
- tryAMAGICbinW_var(meth_enum,assign,SETsv)
-#define tryAMAGICbin(meth,assign) \
- tryAMAGICbin_var(CAT2(meth,_amg),assign)
+/* do SvGETMAGIC on the stack args before checking for overload */
-#define tryAMAGICbinSET(meth,assign) tryAMAGICbinW(meth,assign,SETs)
-
-#define tryAMAGICbinSET_var(meth_enum,assign) \
- tryAMAGICbinW_var(meth_enum,assign,SETs)
-
-#define AMG_CALLun_var(sv,meth_enum) amagic_call(sv,&PL_sv_undef, \
- meth_enum,AMGf_noright | AMGf_unary)
-#define AMG_CALLun(sv,meth) AMG_CALLun_var(sv,CAT2(meth,_amg))
+#define tryAMAGICun_MG(method, flags) STMT_START { \
+ if ( (SvFLAGS(TOPs) & (SVf_ROK|SVs_GMG)) \
+ && Perl_try_amagic_un(aTHX_ method, flags)) \
+ return NORMAL; \
+ } STMT_END
+#define tryAMAGICbin_MG(method, flags) STMT_START { \
+ if ( ((SvFLAGS(TOPm1s)|SvFLAGS(TOPs)) & (SVf_ROK|SVs_GMG)) \
+ && Perl_try_amagic_bin(aTHX_ method, flags)) \
+ return NORMAL; \
+ } STMT_END
-#define AMG_CALLbinL(left,right,meth) \
- amagic_call(left,right,CAT2(meth,_amg),AMGf_noright)
+#define AMG_CALLunary(sv,meth) \
+ amagic_call(sv,&PL_sv_undef, meth, AMGf_noright | AMGf_unary)
+
+/* No longer used in core. Use AMG_CALLunary instead */
+#define AMG_CALLun(sv,meth) AMG_CALLunary(sv, CAT2(meth,_amg))
+
+#define tryAMAGICunTARGETlist(meth, jump) \
+ STMT_START { \
+ dSP; \
+ SV *tmpsv; \
+ SV *arg= *sp; \
+ int gimme = GIMME_V; \
+ if (SvAMAGIC(arg) && \
+ (tmpsv = amagic_call(arg, &PL_sv_undef, meth, \
+ AMGf_want_list | AMGf_noright \
+ |AMGf_unary))) { \
+ SPAGAIN; \
+ if (gimme == G_VOID) { \
+ (void)POPs; /* XXX ??? */ \
+ } \
+ else if (gimme == G_ARRAY) { \
+ int i; \
+ I32 len; \
+ assert(SvTYPE(tmpsv) == SVt_PVAV); \
+ len = av_len((AV *)tmpsv) + 1; \
+ (void)POPs; /* get rid of the arg */ \
+ EXTEND(sp, len); \
+ for (i = 0; i < len; ++i) \
+ PUSHs(av_shift((AV *)tmpsv)); \
+ } \
+ else { /* AMGf_want_scalar */ \
+ dATARGET; /* just use the arg's location */ \
+ sv_setsv(TARG, tmpsv); \
+ if (opASSIGN) \
+ sp--; \
+ SETTARG; \
+ } \
+ PUTBACK; \
+ if (jump) { \
+ OP *jump_o = NORMAL->op_next; \
+ while (jump_o->op_type == OP_NULL) \
+ jump_o = jump_o->op_next; \
+ assert(jump_o->op_type == OP_ENTERSUB); \
+ PL_markstack_ptr--; \
+ return jump_o->op_next; \
+ } \
+ return NORMAL; \
+ } \
+ } STMT_END
-#define tryAMAGICunW_var(meth_enum,set,shift,ret) STMT_START { \
- SV* tmpsv; \
- SV* arg= sp[shift]; \
- if(0) goto am_again; /* shut up unused warning */ \
- am_again: \
- if ((SvAMAGIC(arg))&&\
- (tmpsv=AMG_CALLun_var(arg,(meth_enum)))) {\
- SPAGAIN; if (shift) sp += shift; \
- set(tmpsv); ret; } \
- } STMT_END
-#define tryAMAGICunW(meth,set,shift,ret) \
- tryAMAGICunW_var(CAT2(meth,_amg),set,shift,ret)
-
-#define FORCE_SETs(sv) STMT_START { sv_setsv(TARG, (sv)); SETTARG; } STMT_END
-
-#define tryAMAGICun_var(meth_enum) tryAMAGICunW_var(meth_enum,SETsvUN,0,RETURN)
-#define tryAMAGICun(meth) tryAMAGICun_var(CAT2(meth,_amg))
-#define tryAMAGICunSET(meth) tryAMAGICunW(meth,SETs,0,RETURN)
-#define tryAMAGICunTARGET(meth, shift) \
- STMT_START { dSP; sp--; /* get TARGET from below PL_stack_sp */ \
- { dTARGETSTACKED; \
- { dSP; tryAMAGICunW(meth,FORCE_SETs,shift,RETURN);}}} STMT_END
-
-#define setAGAIN(ref) \
- STMT_START { \
- sv = ref; \
- if (!SvROK(ref)) \
- Perl_croak(aTHX_ "Overloaded dereference did not return a reference"); \
- if (ref != arg && SvRV(ref) != SvRV(arg)) { \
- arg = ref; \
- goto am_again; \
- } \
+/* This is no longer used anywhere in the core. You might wish to consider
+ calling amagic_deref_call() directly, as it has a cleaner interface. */
+#define tryAMAGICunDEREF(meth) \
+ STMT_START { \
+ sv = amagic_deref_call(*sp, CAT2(meth,_amg)); \
+ SPAGAIN; \
} STMT_END
-#define tryAMAGICunDEREF(meth) tryAMAGICunW(meth,setAGAIN,0,(void)0)
-#define tryAMAGICunDEREF_var(meth_enum) \
- tryAMAGICunW_var(meth_enum,setAGAIN,0,(void)0)
#define opASSIGN (PL_op->op_flags & OPf_STACKED)
#define SETsv(sv) STMT_START { \
{ sv_setsv(TARG, (sv)); SETTARG; } \
else SETs(sv); } STMT_END
-/* newSVsv does not behave as advertised, so we copy missing
- * information by hand */
-
-/* SV* ref causes confusion with the member variable
- changed SV* ref to SV* tmpRef */
-#define RvDEEPCP(rv) STMT_START { SV* tmpRef=SvRV(rv); \
- if (SvREFCNT(tmpRef)>1) { \
- SvRV_set(rv, AMG_CALLun(rv,copy)); \
- SvREFCNT_dec(tmpRef); \
- } } STMT_END
-
/*
=for apidoc mU||LVRET
True if this op will be the return value of an lvalue subroutine
=cut */
#define LVRET ((PL_op->op_private & OPpMAYBE_LVSUB) && is_lvalue_sub())
+#define SvCANEXISTDELETE(sv) \
+ (!SvRMAGICAL(sv) \
+ || !(mg = mg_find((const SV *) sv, PERL_MAGIC_tied)) \
+ || ( (stash = SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(sv), mg)))) \
+ && gv_fetchmethod_autoload(stash, "EXISTS", TRUE) \
+ && gv_fetchmethod_autoload(stash, "DELETE", TRUE) \
+ ) \
+ )
+
+#ifdef PERL_CORE
+
+/* These are just for Perl_tied_method(), which is not part of the public API.
+ Use 0x04 rather than the next available bit, to help the compiler if the
+ architecture can generate more efficient instructions. */
+# define TIED_METHOD_MORTALIZE_NOT_NEEDED 0x04
+# define TIED_METHOD_ARGUMENTS_ON_STACK 0x08
+# define TIED_METHOD_SAY 0x10
+
+/* Used in various places that need to dereference a glob or globref */
+# define MAYBE_DEREF_GV_flags(sv,phlags) \
+ ( \
+ (void)(phlags & SV_GMAGIC && (SvGETMAGIC(sv),0)), \
+ isGV_with_GP(sv) \
+ ? (GV *)(sv) \
+ : SvROK(sv) && SvTYPE(SvRV(sv)) <= SVt_PVLV && \
+ (SvGETMAGIC(SvRV(sv)), isGV_with_GP(SvRV(sv))) \
+ ? (GV *)SvRV(sv) \
+ : NULL \
+ )
+# define MAYBE_DEREF_GV(sv) MAYBE_DEREF_GV_flags(sv,SV_GMAGIC)
+# define MAYBE_DEREF_GV_nomg(sv) MAYBE_DEREF_GV_flags(sv,0)
+
+# define FIND_RUNCV_padid_eq 1
+# define FIND_RUNCV_level_eq 2
+
+#endif
+
/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
* End:
*
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
*/