X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=662f24628f41392e39d2b45e97a45d61ae153983;hb=13aba0e6afaf51b4b0de5792ac07eb8e735f9747;hp=3de19a9b6e5c04726e706fd1eda47d405c9a15a3;hpb=51c9cbffce75ccfe84b3ba9627ae0d697b0acf29;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index 3de19a9..662f246 100644 --- a/Upper.xs +++ b/Upper.xs @@ -80,6 +80,13 @@ STATIC SV *su_newSV_type(pTHX_ svtype t) { # define newSV_type(T) su_newSV_type(aTHX_ (T)) #endif +#ifdef newSVpvn_flags +# define su_newmortal_pvn(S, L) newSVpvn_flags((S), (L), SVs_TEMP) +#else +# define su_newmortal_pvn(S, L) sv_2mortal(newSVpvn((S), (L))) +#endif +#define su_newmortal_pvs(S) su_newmortal_pvn((S), sizeof(S)-1) + #ifndef SvPV_const # define SvPV_const(S, L) SvPV(S, L) #endif @@ -125,14 +132,55 @@ STATIC SV *su_newSV_type(pTHX_ svtype t) { # define CxHASARGS(C) ((C)->blk_sub.hasargs) #endif +#ifndef CxGIMME +# ifdef G_WANT +# define CxGIMME(C) ((C)->blk_gimme & G_WANT) +# else +# define CxGIMME(C) ((C)->blk_gimme) +# endif +#endif + +#ifndef CxOLD_OP_TYPE +# define CxOLD_OP_TYPE(C) (C)->blk_eval.old_op_type +#endif + +#ifndef OutCopFILE +# define OutCopFILE(C) CopFILE(C) +#endif + +#ifndef OutCopFILE_len +# define OutCopFILE_len(C) strlen(OutCopFILE(C)) +#endif + +#ifndef CopHINTS_get +# define CopHINTS_get(C) ((I32) (C)->op_private & HINT_PRIVATE_MASK) +#endif + +#ifndef CopHINTHASH_get +# define CopHINTHASH_get(C) (C)->cop_hints_hash +#endif + +#ifndef cophh_2hv +# define COPHH struct refcounted_he +# define cophh_2hv(H, F) Perl_refcounted_he_chain_2hv(aTHX_ (H)) +#endif + #ifndef HvNAME_get # define HvNAME_get(H) HvNAME(H) #endif +#ifndef HvNAMELEN +# define HvNAMELEN(H) strlen(HvNAME(H)) +#endif + #ifndef gv_fetchpvn_flags # define gv_fetchpvn_flags(A, B, C, D) gv_fetchpv((A), (C), (D)) #endif +#ifndef hv_fetchs +# define hv_fetchs(H, K, L) hv_fetch((H), (K), sizeof(K)-1, (L)) +#endif + #ifndef OP_GIMME_REVERSE STATIC U8 su_op_gimme_reverse(U8 gimme) { switch (gimme) { @@ -149,6 +197,14 @@ STATIC U8 su_op_gimme_reverse(U8 gimme) { #define OP_GIMME_REVERSE(G) su_op_gimme_reverse(G) #endif +#ifndef OpSIBLING +# ifdef OP_SIBLING +# define OpSIBLING(O) OP_SIBLING(O) +# else +# define OpSIBLING(O) ((O)->op_sibling) +# endif +#endif + #ifndef PERL_MAGIC_tied # define PERL_MAGIC_tied 'P' #endif @@ -1078,6 +1134,15 @@ STATIC void su_unwind(pTHX_ void *ud_) { PERL_UNUSED_VAR(ud_); PL_stack_sp = MY_CXT.unwind_storage.savesp; +#if SU_HAS_PERL(5, 19, 4) + { + I32 i; + SV **sp = PL_stack_sp; + for (i = -items + 1; i <= 0; ++i) + if (!SvTEMP(sp[i])) + sv_2mortal(SvREFCNT_inc(sp[i])); + } +#endif if (cxstack_ix > cxix) dounwind(cxix); @@ -1253,6 +1318,15 @@ cxt_when: } PL_stack_sp = MY_CXT.yield_storage.savesp; +#if SU_HAS_PERL(5, 19, 4) + { + I32 i; + SV **sp = PL_stack_sp; + for (i = -items + 1; i <= 0; ++i) + if (!SvTEMP(sp[i])) + sv_2mortal(SvREFCNT_inc(sp[i])); + } +#endif if (cxstack_ix > cxix) dounwind(cxix); @@ -1335,7 +1409,7 @@ STATIC void su_uplevel_storage_delete(pTHX_ su_uplevel_ud *sud) { } STATIC int su_uplevel_goto_static(const OP *o) { - for (; o; o = o->op_sibling) { + for (; o; o = OpSIBLING(o)) { /* goto ops are unops with kids. */ if (!(o->op_flags & OPf_KIDS)) continue; @@ -1598,6 +1672,9 @@ STATIC CV *su_cv_clone(pTHX_ CV *proto, GV *gv) { #endif CvGV_set(cv, gv); +#if SU_RELEASE && SU_HAS_PERL_EXACT(5, 21, 4) + CvNAMED_off(cv); +#endif CvSTASH_set(cv, CvSTASH(proto)); /* Commit 4c74a7df, publicized with perl 5.13.3, began to add backrefs to * stashes. CvSTASH_set() started to do it as well with commit c68d95645 @@ -2027,8 +2104,8 @@ STATIC I32 su_context_normalize_up(pTHX_ I32 cxix) { return cxix - 1; break; case CXt_SUBST: - if (cx->blk_oldcop && cx->blk_oldcop->op_sibling - && cx->blk_oldcop->op_sibling->op_type == OP_SUBST) + if (cx->blk_oldcop && OpSIBLING(cx->blk_oldcop) + && OpSIBLING(cx->blk_oldcop)->op_type == OP_SUBST) return cxix - 1; break; } @@ -2063,8 +2140,8 @@ STATIC I32 su_context_normalize_down(pTHX_ I32 cxix) { return cxix + 1; break; case CXt_SUBST: - if (next->blk_oldcop && next->blk_oldcop->op_sibling - && next->blk_oldcop->op_sibling->op_type == OP_SUBST) + if (next->blk_oldcop && OpSIBLING(next->blk_oldcop) + && OpSIBLING(next->blk_oldcop)->op_type == OP_SUBST) return cxix + 1; break; } @@ -2075,6 +2152,48 @@ STATIC I32 su_context_normalize_down(pTHX_ I32 cxix) { #define su_context_here() su_context_normalize_up(su_context_skip_db(cxstack_ix)) +STATIC I32 su_context_gimme(pTHX_ I32 cxix) { +#define su_context_gimme(C) su_context_gimme(aTHX_ (C)) + I32 i; + + for (i = cxix; i >= 0; --i) { + PERL_CONTEXT *cx = cxstack + i; + + switch (CxTYPE(cx)) { + /* gimme is always G_ARRAY for loop contexts. */ +#if SU_HAS_PERL(5, 11, 0) + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_LAZYIV: +#else + case CXt_LOOP: +#endif + case CXt_SUBST: { + const COP *cop = cx->blk_oldcop; + if (cop && OpSIBLING(cop)) { + switch (OpSIBLING(cop)->op_flags & OPf_WANT) { + case OPf_WANT_VOID: + return G_VOID; + case OPf_WANT_SCALAR: + return G_SCALAR; + case OPf_WANT_LIST: + return G_ARRAY; + default: + break; + } + } + break; + } + default: + return CxGIMME(cx); + break; + } + } + + return G_VOID; +} + /* --- Interpreter setup/teardown ------------------------------------------ */ STATIC void su_teardown(pTHX_ void *param) { @@ -2171,6 +2290,12 @@ default_cx: \ } \ } STMT_END +#if SU_HAS_PERL(5, 10, 0) +# define SU_INFO_COUNT 11 +#else +# define SU_INFO_COUNT 10 +#endif + XS(XS_Scope__Upper_unwind); /* prototype to pass -Wmissing-prototypes */ XS(XS_Scope__Upper_unwind) { @@ -2257,7 +2382,6 @@ XS(XS_Scope__Upper_leave) { dXSARGS; #endif dMY_CXT; - I32 cxix; PERL_UNUSED_VAR(cv); /* -W */ PERL_UNUSED_VAR(ax); /* -Wall */ @@ -2463,6 +2587,160 @@ PPCODE: } XSRETURN_UNDEF; +void +context_info(...) +PROTOTYPE: ;$ +PREINIT: + I32 cxix; + const PERL_CONTEXT *cx, *dbcx; + COP *cop; +PPCODE: + SU_GET_CONTEXT(0, 0, su_context_skip_db(cxstack_ix)); + cxix = su_context_normalize_up(cxix); + cx = cxstack + cxix; + dbcx = cx; + if (PL_DBsub && cxix && (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)) { + I32 i = su_context_skip_db(cxix - 1) + 1; + if (i < cxix && CxTYPE(cxstack + i) == CXt_SUB) + cx = cxstack + i; + } + cop = cx->blk_oldcop; + EXTEND(SP, SU_INFO_COUNT); + /* stash (0) */ + { + HV *stash = CopSTASH(cop); + if (stash) + PUSHs(su_newmortal_pvn(HvNAME(stash), HvNAMELEN(stash))); + else + PUSHs(&PL_sv_undef); + } + /* file (1) */ + PUSHs(su_newmortal_pvn(OutCopFILE(cop), OutCopFILE_len(cop))); + /* line (2) */ + mPUSHi(CopLINE(cop)); + /* subroutine (3) and has_args (4) */ + switch (CxTYPE(cx)) { + case CXt_SUB: + case CXt_FORMAT: { + GV *cvgv = CvGV(dbcx->blk_sub.cv); + if (cvgv && isGV(cvgv)) { + SV *sv = sv_newmortal(); + gv_efullname3(sv, cvgv, NULL); + PUSHs(sv); + } else { + PUSHs(su_newmortal_pvs("(unknown)")); + } + if (CxHASARGS(cx)) + PUSHs(&PL_sv_yes); + else + PUSHs(&PL_sv_no); + break; + } + case CXt_EVAL: + PUSHs(su_newmortal_pvs("(eval)")); + mPUSHi(0); + break; + default: + PUSHs(&PL_sv_undef); + PUSHs(&PL_sv_undef); + } + /* gimme (5) */ + switch (su_context_gimme(cxix)) { + case G_ARRAY: + PUSHs(&PL_sv_yes); + break; + case G_SCALAR: + PUSHs(&PL_sv_no); + break; + default: /* G_VOID */ + PUSHs(&PL_sv_undef); + break; + } + /* eval text (6) and is_require (7) */ + switch (CxTYPE(cx)) { + case CXt_EVAL: + if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) { + /* eval STRING */ +#if SU_HAS_PERL(5, 17, 4) + PUSHs(newSVpvn_flags(SvPVX(cx->blk_eval.cur_text), + SvCUR(cx->blk_eval.cur_text)-2, + SvUTF8(cx->blk_eval.cur_text)|SVs_TEMP)); +#else + PUSHs(cx->blk_eval.cur_text); +#endif + PUSHs(&PL_sv_no); + break; + } else if (cx->blk_eval.old_namesv) { + /* require */ + PUSHs(sv_mortalcopy(cx->blk_eval.old_namesv)); + PUSHs(&PL_sv_yes); + break; + } + /* FALLTHROUGH */ + default: + /* Anything else including eval BLOCK */ + PUSHs(&PL_sv_undef); + PUSHs(&PL_sv_undef); + break; + } + /* hints (8) */ + mPUSHi(CopHINTS_get(cop)); + /* warnings (9) */ + { + SV *mask = NULL; +#if SU_HAS_PERL(5, 9, 4) + STRLEN *old_warnings = cop->cop_warnings; +#else + SV *old_warnings = cop->cop_warnings; +#endif + if (old_warnings == pWARN_STD) { + if (PL_dowarn & G_WARN_ON) + goto context_info_warnings_on; + else +#if SU_HAS_PERL(5, 17, 4) + mask = &PL_sv_undef; +#else + goto context_info_warnings_off; +#endif + } else if (old_warnings == pWARN_NONE) { +context_info_warnings_off: + mask = su_newmortal_pvn(WARN_NONEstring, WARNsize); + } else if (old_warnings == pWARN_ALL) { + HV *bits; +context_info_warnings_on: +#if SU_HAS_PERL(5, 8, 7) + bits = get_hv("warnings::Bits", 0); + if (bits) { + SV **bits_all = hv_fetchs(bits, "all", FALSE); + if (bits_all) + mask = sv_mortalcopy(*bits_all); + } +#endif + if (!mask) + mask = su_newmortal_pvn(WARN_ALLstring, WARNsize); + } else { +#if SU_HAS_PERL(5, 9, 4) + mask = su_newmortal_pvn((char *) (old_warnings + 1), old_warnings[0]); +#else + mask = sv_mortalcopy(old_warnings); +#endif + } + PUSHs(mask); + } +#if SU_HAS_PERL(5, 10, 0) + /* hints hash (10) */ + { + COPHH *hints_hash = CopHINTHASH_get(cop); + if (hints_hash) { + SV *rhv = sv_2mortal(newRV_noinc((SV *) cophh_2hv(hints_hash, 0))); + PUSHs(rhv); + } else { + PUSHs(&PL_sv_undef); + } + } +#endif + XSRETURN(SU_INFO_COUNT); + void reap(SV *hook, ...) PROTOTYPE: &;$