X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/411caa507cab4ba311ec4000c486ad2592d51146..d0328fd7d629f8429b08eacaee4fd3cb902fdf5e:/pp.h diff --git a/pp.h b/pp.h index 2226c20..7b5f322 100644 --- a/pp.h +++ b/pp.h @@ -1,23 +1,18 @@ /* pp.h * - * Copyright (c) 1991-2000, Larry Wall + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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_THREADS -#define ARGS thr -#define dARGS struct perl_thread *thr; -#else -#define ARGS -#define dARGS -#endif /* USE_THREADS */ - #define PP(s) OP * Perl_##s(pTHX) /* +=head1 Stack Manipulation Macros + =for apidoc AmU||SP Stack pointer. This is usually handled by C. See C and C. @@ -25,7 +20,7 @@ C. =for apidoc AmU||MARK Stack marker variable for the XSUB. See C. -=for apidoc Ams||PUSHMARK +=for apidoc Am|void|PUSHMARK|SP Opening bracket for arguments on a callback. See C and L. @@ -33,6 +28,13 @@ L. Declares a local copy of perl's stack pointer for the XSUB, available via the C macro. See C. +=for apidoc ms||djSP + +Declare Just C. This is actually identical to C, and declares +a local copy of perl's stack pointer, available via the C macro. +See C. (Available for backward source code compatibility with the +old (Perl 5.005) thread model.) + =for apidoc Ams||dMARK Declare a stack marker variable, C, for the XSUB. See C and C. @@ -46,29 +48,31 @@ The original stack mark for the XSUB. See C. =for apidoc Ams||SPAGAIN Refetch the stack pointer. Used after a callback. See L. -=cut -*/ +=cut */ +#undef SP /* Solaris 2.7 i386 has this in /usr/include/sys/reg.h */ #define SP sp #define MARK mark #define TARG targ -#define PUSHMARK(p) if (++PL_markstack_ptr == PL_markstack_max) \ - markstack_grow(); \ - *PL_markstack_ptr = (p) - PL_stack_base +#define PUSHMARK(p) \ + STMT_START { \ + if (++PL_markstack_ptr == PL_markstack_max) \ + markstack_grow(); \ + *PL_markstack_ptr = (I32)((p) - PL_stack_base);\ + } STMT_END #define TOPMARK (*PL_markstack_ptr) #define POPMARK (*PL_markstack_ptr--) -#define djSP register SV **sp = PL_stack_sp -#define dSP djSP +#define dSP SV **sp = PL_stack_sp +#define djSP dSP #define dMARK register SV **mark = PL_stack_base + POPMARK -#define dORIGMARK I32 origmark = mark - PL_stack_base -#define SETORIGMARK origmark = mark - PL_stack_base +#define dORIGMARK const I32 origmark = (I32)(mark - PL_stack_base) #define ORIGMARK (PL_stack_base + origmark) #define SPAGAIN sp = PL_stack_sp -#define MSPAGAIN sp = PL_stack_sp; mark = ORIGMARK +#define MSPAGAIN STMT_START { sp = PL_stack_sp; mark = ORIGMARK; } STMT_END #define GETTARGETSTACKED targ = (PL_op->op_flags & OPf_STACKED ? POPs : PAD_SV(PL_op->op_targ)) #define dTARGETSTACKED SV * GETTARGETSTACKED @@ -93,8 +97,14 @@ See C and L for other uses. Pops an SV off the stack. =for apidoc Amn|char*|POPp +Pops a string off the stack. Deprecated. New code should use POPpx. + +=for apidoc Amn|char*|POPpx Pops a string off the stack. +=for apidoc Amn|char*|POPpbytex +Pops a string off the stack which must consist of bytes i.e. characters < 256. + =for apidoc Amn|NV|POPn Pops a double off the stack. @@ -108,13 +118,15 @@ Pops a long off the stack. */ #define PUTBACK PL_stack_sp = sp -#define RETURN return PUTBACK, NORMAL -#define RETURNOP(o) return PUTBACK, o -#define RETURNX(x) return x, PUTBACK, NORMAL +#define RETURN return (PUTBACK, NORMAL) +#define RETURNOP(o) return (PUTBACK, o) +#define RETURNX(x) return (x, PUTBACK, NORMAL) #define POPs (*sp--) #define POPp (SvPVx(POPs, PL_na)) /* deprecated */ -#define POPpx (SvPVx(POPs, n_a)) +#define POPpx (SvPVx_nolen(POPs)) +#define POPpconstx (SvPVx_nolen_const(POPs)) +#define POPpbytex (SvPVbytex_nolen(POPs)) #define POPn (SvNVx(POPs)) #define POPi ((IV)SvIVx(POPs)) #define POPu ((UV)SvUVx(POPs)) @@ -126,8 +138,10 @@ Pops a long off the stack. #endif #define TOPs (*sp) +#define TOPm1s (*(sp-1)) +#define TOPp1s (*(sp+1)) #define TOPp (SvPV(TOPs, PL_na)) /* deprecated */ -#define TOPpx (SvPV(TOPs, n_a)) +#define TOPpx (SvPV_nolen(TOPs)) #define TOPn (SvNV(TOPs)) #define TOPi ((IV)SvIV(TOPs)) #define TOPu ((UV)SvUV(TOPs)) @@ -148,56 +162,128 @@ onto the stack. =for apidoc Am|void|PUSHs|SV* sv Push an SV onto the stack. The stack must have room for this element. -Does not handle 'set' magic. See C. +Does not handle 'set' magic. Does not use C. See also C, +C and C. =for apidoc Am|void|PUSHp|char* str|STRLEN len Push a string onto the stack. The stack must have room for this element. -The C indicates the length of the string. Handles 'set' magic. See -C. +The C indicates the length of the string. Handles 'set' magic. Uses +C, so C or C should be called to declare it. Do not +call multiple C-oriented macros to return lists from XSUB's - see +C instead. See also C and C. =for apidoc Am|void|PUSHn|NV nv Push a double onto the stack. The stack must have room for this element. -Handles 'set' magic. See C. +Handles 'set' magic. Uses C, so C or C should be +called to declare it. Do not call multiple C-oriented macros to +return lists from XSUB's - see C instead. See also C and +C. =for apidoc Am|void|PUSHi|IV iv Push an integer onto the stack. The stack must have room for this element. -Handles 'set' magic. See C. +Handles 'set' magic. Uses C, so C or C should be +called to declare it. Do not call multiple C-oriented macros to +return lists from XSUB's - see C instead. See also C and +C. =for apidoc Am|void|PUSHu|UV uv Push an unsigned integer onto the stack. The stack must have room for this -element. See C. +element. Handles 'set' magic. Uses C, so C or C +should be called to declare it. Do not call multiple C-oriented +macros to return lists from XSUB's - see C instead. See also +C and C. =for apidoc Am|void|XPUSHs|SV* sv Push an SV onto the stack, extending the stack if necessary. Does not -handle 'set' magic. See C. +handle 'set' magic. Does not use C. See also C, +C and C. =for apidoc Am|void|XPUSHp|char* str|STRLEN len Push a string onto the stack, extending the stack if necessary. The C -indicates the length of the string. Handles 'set' magic. See -C. +indicates the length of the string. Handles 'set' magic. Uses C, so +C or C should be called to declare it. Do not call +multiple C-oriented macros to return lists from XSUB's - see +C instead. See also C and C. =for apidoc Am|void|XPUSHn|NV nv Push a double onto the stack, extending the stack if necessary. Handles -'set' magic. See C. +'set' magic. Uses C, so C or C should be called to +declare it. Do not call multiple C-oriented macros to return lists +from XSUB's - see C instead. See also C and C. =for apidoc Am|void|XPUSHi|IV iv Push an integer onto the stack, extending the stack if necessary. Handles -'set' magic. See C. +'set' magic. Uses C, so C or C should be called to +declare it. Do not call multiple C-oriented macros to return lists +from XSUB's - see C instead. See also C and C. =for apidoc Am|void|XPUSHu|UV uv Push an unsigned integer onto the stack, extending the stack if necessary. -See C. +Handles 'set' magic. Uses C, so C or C should be +called to declare it. Do not call multiple C-oriented macros to +return lists from XSUB's - see C instead. See also C and +C. + +=for apidoc Am|void|mPUSHs|SV* sv +Push an SV onto the stack and mortalizes the SV. The stack must have room +for this element. Does not use C. See also C and C. + +=for apidoc Am|void|PUSHmortal +Push a new mortal SV onto the stack. The stack must have room for this +element. Does not use C. See also C, C and C. + +=for apidoc Am|void|mPUSHp|char* str|STRLEN len +Push a string onto the stack. The stack must have room for this element. +The C indicates the length of the string. Does not use C. +See also C, C and C. + +=for apidoc Am|void|mPUSHn|NV nv +Push a double onto the stack. The stack must have room for this element. +Does not use C. See also C, C and C. + +=for apidoc Am|void|mPUSHi|IV iv +Push an integer onto the stack. The stack must have room for this element. +Does not use C. See also C, C and C. + +=for apidoc Am|void|mPUSHu|UV uv +Push an unsigned integer onto the stack. The stack must have room for this +element. Does not use C. See also C, C and C. + +=for apidoc Am|void|mXPUSHs|SV* sv +Push an SV onto the stack, extending the stack if necessary and mortalizes +the SV. Does not use C. See also C and C. + +=for apidoc Am|void|XPUSHmortal +Push a new mortal SV onto the stack, extending the stack if necessary. +Does not use C. See also C, C and C. + +=for apidoc Am|void|mXPUSHp|char* str|STRLEN len +Push a string onto the stack, extending the stack if necessary. The C +indicates the length of the string. Does not use C. See also C, +C and C. + +=for apidoc Am|void|mXPUSHn|NV nv +Push a double onto the stack, extending the stack if necessary. +Does not use C. See also C, C and C. + +=for apidoc Am|void|mXPUSHi|IV iv +Push an integer onto the stack, extending the stack if necessary. +Does not use C. See also C, C and C. + +=for apidoc Am|void|mXPUSHu|UV uv +Push an unsigned integer onto the stack, extending the stack if necessary. +Does not use C. See also C, C and C. =cut */ -#define EXTEND(p,n) STMT_START { if (PL_stack_max - p < (n)) { \ +#define EXTEND(p,n) STMT_START { if (PL_stack_max - p < (int)(n)) { \ sp = stack_grow(sp,p, (int) (n)); \ } } STMT_END /* Same thing, but update mark register too. */ -#define MEXTEND(p,n) STMT_START {if (PL_stack_max - p < (n)) { \ - int markoff = mark - PL_stack_base; \ +#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 @@ -217,6 +303,20 @@ See C. #define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END #define XPUSHundef STMT_START { SvOK_off(TARG); XPUSHs(TARG); } STMT_END +#define mPUSHs(s) PUSHs(sv_2mortal(s)) +#define PUSHmortal PUSHs(sv_newmortal()) +#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); 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 SETs(s) (*sp = s) #define SETTARG STMT_START { SvSETMAGIC(TARG); SETs(TARG); } STMT_END #define SETp(p,l) STMT_START { sv_setpvn(TARG, (p), (l)); SETTARG; } STMT_END @@ -299,58 +399,77 @@ See C. #define AMGf_assign 4 #define AMGf_unary 8 -#define tryAMAGICbinW(meth,assign,set) STMT_START { \ - if (PL_amagic_generation) { \ - SV* tmpsv; \ - SV* right= *(sp); SV* left= *(sp-1);\ - if ((SvAMAGIC(left)||SvAMAGIC(right))&&\ - (tmpsv=amagic_call(left, \ +#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, \ - CAT2(meth,_amg), \ - (assign)? AMGf_assign: 0))) {\ - SPAGAIN; \ - (void)POPs; set(tmpsv); RETURN; } \ - } \ + (meth_enum), \ + (assign)? AMGf_assign: 0); \ + if (tmpsv) { \ + SPAGAIN; \ + (void)POPs; set(tmpsv); RETURN; } \ + } \ } STMT_END -#define tryAMAGICbin(meth,assign) tryAMAGICbinW(meth,assign,SETsv) +#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) + #define tryAMAGICbinSET(meth,assign) tryAMAGICbinW(meth,assign,SETs) -#define AMG_CALLun(sv,meth) amagic_call(sv,&PL_sv_undef, \ - CAT2(meth,_amg),AMGf_noright | AMGf_unary) +#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 AMG_CALLbinL(left,right,meth) \ amagic_call(left,right,CAT2(meth,_amg),AMGf_noright) -#define tryAMAGICunW(meth,set,shift,ret) STMT_START { \ - if (PL_amagic_generation) { \ +#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(arg,meth))) {\ + (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(meth) tryAMAGICunW(meth,SETsvUN,0,RETURN) +#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) \ - { dSP; sp--; /* get TARGET from below PL_stack_sp */ \ + STMT_START { dSP; sp--; /* get TARGET from below PL_stack_sp */ \ { dTARGETSTACKED; \ - { dSP; tryAMAGICunW(meth,FORCE_SETs,shift,RETURN);}}} - -#define setAGAIN(ref) 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; \ - } + { 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; \ + } \ + } 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 { \ @@ -370,6 +489,23 @@ See C. 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); \ - SvRV(rv)=AMG_CALLun(rv,copy); \ } } 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()) + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * ex: set ts=8 sts=4 sw=4 noet: + */