X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=95a22ed74520b2f521fc871b075b60b7ba4489e5;hb=0a7ed27cbdbb90c176fc6be11c48e70776c8df84;hp=9c510f99ba5f20b6d5811966233d9c291ee4085d;hpb=c4d42ba6866ff8c6a542ba718db27cca5f64ba1e;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index 9c510f9..95a22ed 100644 --- a/Upper.xs +++ b/Upper.xs @@ -137,7 +137,6 @@ STATIC I32 su_av_key2idx(pTHX_ AV *av, I32 key) { if (SvRMAGICAL(av)) { const MAGIC * const tied_magic = mg_find((SV *) av, PERL_MAGIC_tied); if (tied_magic) { - int adjust_index = 1; SV * const * const negative_indices_glob = hv_fetch(SvSTASH(SvRV(SvTIED_obj((SV *) (av), tied_magic))), NEGATIVE_INDICES_VAR, 16, 0); @@ -248,7 +247,7 @@ STATIC void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) { if (val) { /* local $x{$keysv} = $val; */ SvSetMagicSV(*svp, val); } else { /* local $x{$keysv}; delete $x{$keysv}; */ - hv_delete_ent(hv, keysv, G_DISCARD, HeHASH(he)); + (void)hv_delete_ent(hv, keysv, G_DISCARD, HeHASH(he)); } } @@ -279,7 +278,9 @@ typedef struct { STATIC void su_call(pTHX_ void *ud_) { su_ud_reap *ud = (su_ud_reap *) ud_; #if SU_HAS_PERL(5, 10, 0) + PERL_CONTEXT saved_cx; I32 dieing = PL_op->op_type == OP_DIE; + I32 cxix; #endif dSP; @@ -296,21 +297,22 @@ STATIC void su_call(pTHX_ void *ud_) { * when the new sub scope will be created in call_sv. */ #if SU_HAS_PERL(5, 10, 0) - if (dieing) + if (dieing) { if (cxstack_ix < cxstack_max) - ++cxstack_ix; + cxix = cxstack_ix + 1; else - cxstack_ix = Perl_cxinc(aTHX); + cxix = Perl_cxinc(aTHX); + saved_cx = cxstack[cxix]; + } #endif call_sv(ud->cb, G_VOID); #if SU_HAS_PERL(5, 10, 0) - if (dieing && cxstack_ix > 0) - --cxstack_ix; + if (dieing) + cxstack[cxix] = saved_cx; #endif - SPAGAIN; PUTBACK; FREETMPS; @@ -351,11 +353,9 @@ STATIC void su_localize(pTHX_ void *ud_) { if (SvTYPE(sv) >= SVt_PVGV) { gv = (GV *) sv; - if (!val) { /* local *x; */ + if (!val || !SvROK(val)) { /* local *x; or local *x = $val; */ t = SVt_PVGV; - } else if (!SvROK(val)) { /* local *x = $val; */ - goto assign; - } else { /* local *x = \$val; */ + } else { /* local *x = \$val; */ t = SvTYPE(SvRV(val)); deref = 1; } @@ -421,7 +421,6 @@ STATIC void su_localize(pTHX_ void *ud_) { break; default: gv = (GV *) save_scalar(gv); -maybe_deref: if (deref) /* val != NULL */ val = SvRV(val); break; @@ -431,7 +430,6 @@ maybe_deref: ud, PL_savestack_ix, PL_scopestack[PL_scopestack_ix])); -assign: if (val) SvSetMagicSV((SV *) gv, val); @@ -492,7 +490,6 @@ STATIC void su_pop(pTHX_ void *ud) { STATIC I32 su_init(pTHX_ I32 cxix, void *ud, I32 size) { #define su_init(L, U, S) su_init(aTHX_ (L), (U), (S)) I32 i, depth = 0, *origin; - I32 cur, last, step; LEAVE; @@ -581,6 +578,8 @@ STATIC void su_unwind(pTHX_ void *ud_) { SV **savesp = MY_CXT.savesp; I32 mark; + PERL_UNUSED_VAR(ud_); + if (savesp) PL_stack_sp = savesp; @@ -612,31 +611,61 @@ STATIC void su_unwind(pTHX_ void *ud_) { /* --- XS ------------------------------------------------------------------ */ +#if SU_HAS_PERL(5, 8, 9) +# define SU_SKIP_DB_MAX 2 +#else +# define SU_SKIP_DB_MAX 3 +#endif + +/* Skip context sequences of 1 to SU_SKIP_DB_MAX (included) block contexts + * followed by a DB sub */ + +#define SU_SKIP_DB(C) \ + STMT_START { \ + I32 i = 1; \ + PERL_CONTEXT *cx = cxstack + (C); \ + do { \ + if (CxTYPE(cx) == CXt_BLOCK && (C) >= i) { \ + --cx; \ + if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.cv == GvCV(PL_DBsub)) { \ + (C) -= i + 1; \ + break; \ + } \ + } else \ + break; \ + } while (++i <= SU_SKIP_DB_MAX); \ + } STMT_END + #define SU_GET_CONTEXT(A, B) \ STMT_START { \ if (items > A) { \ SV *csv = ST(B); \ - if (SvOK(csv)) \ - cxix = SvIV(csv); \ + if (!SvOK(csv)) \ + goto default_cx; \ + cxix = SvIV(csv); \ if (cxix < 0) \ cxix = 0; \ else if (cxix > cxstack_ix) \ cxix = cxstack_ix; \ - } else \ + } else { \ +default_cx: \ cxix = cxstack_ix; \ + if (PL_DBsub) \ + SU_SKIP_DB(cxix); \ + } \ } STMT_END -#define SU_DOPOPTOCX(t) \ - STMT_START { \ - I32 cxix; \ - SU_GET_CONTEXT(0, 0); \ - for (; cxix >= 0; --cxix) { \ - if (CxTYPE(cxstack + cxix) == t) { \ - ST(0) = sv_2mortal(newSViv(cxix)); \ - XSRETURN(1); \ - } \ - } \ - XSRETURN_UNDEF; \ +#define SU_GET_LEVEL(A, B) \ + STMT_START { \ + level = 0; \ + if (items > 0) { \ + SV *lsv = ST(B); \ + if (SvOK(lsv)) { \ + level = SvIV(lsv); \ + if (level < 0) \ + level = 0; \ + } \ + } \ } STMT_END XS(XS_Scope__Upper_unwind); /* prototype to pass -Wmissing-prototypes */ @@ -658,6 +687,8 @@ XS(XS_Scope__Upper_unwind) { PERL_CONTEXT *cx = cxstack + cxix; switch (CxTYPE(cx)) { case CXt_SUB: + if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) + continue; case CXt_EVAL: case CXt_FORMAT: MY_CXT.cxix = cxix; @@ -689,23 +720,33 @@ BOOT: HV *stash; MY_CXT_INIT; stash = gv_stashpv(__PACKAGE__, 1); - newCONSTSUB(stash, "TOP", newSViv(0)); + newCONSTSUB(stash, "TOP", newSViv(0)); + newCONSTSUB(stash, "SU_THREADSAFE", newSVuv(SU_THREADSAFE)); newXSproto("Scope::Upper::unwind", XS_Scope__Upper_unwind, file, NULL); } +#if SU_THREADSAFE + void CLONE(...) PROTOTYPE: DISABLE CODE: -#if SU_THREADSAFE - MY_CXT_CLONE; + PERL_UNUSED_VAR(items); + { + MY_CXT_CLONE; + } + #endif /* SU_THREADSAFE */ SV * HERE() PROTOTYPE: +PREINIT: + I32 cxix = cxstack_ix; CODE: - RETVAL = newSViv(cxstack_ix); + if (PL_DBsub) + SU_SKIP_DB(cxix); + RETVAL = newSViv(cxix); OUTPUT: RETVAL @@ -718,61 +759,95 @@ CODE: SU_GET_CONTEXT(0, 0); if (--cxix < 0) cxix = 0; + if (PL_DBsub) + SU_SKIP_DB(cxix); RETVAL = newSViv(cxix); OUTPUT: RETVAL -SV * -DOWN(...) +void +SUB(...) PROTOTYPE: ;$ PREINIT: I32 cxix; -CODE: +PPCODE: SU_GET_CONTEXT(0, 0); - if (++cxix > cxstack_ix) - cxix = cxstack_ix; - RETVAL = newSViv(cxix); -OUTPUT: - RETVAL + for (; cxix >= 0; --cxix) { + PERL_CONTEXT *cx = cxstack + cxix; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_SUB: + if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) + continue; + ST(0) = sv_2mortal(newSViv(cxix)); + XSRETURN(1); + } + } + XSRETURN_UNDEF; void -SUB(...) +EVAL(...) PROTOTYPE: ;$ +PREINIT: + I32 cxix; PPCODE: - SU_DOPOPTOCX(CXt_SUB); + SU_GET_CONTEXT(0, 0); + for (; cxix >= 0; --cxix) { + PERL_CONTEXT *cx = cxstack + cxix; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_EVAL: + ST(0) = sv_2mortal(newSViv(cxix)); + XSRETURN(1); + } + } + XSRETURN_UNDEF; void -EVAL(...) +SCOPE(...) PROTOTYPE: ;$ +PREINIT: + I32 cxix, level; PPCODE: - SU_DOPOPTOCX(CXt_EVAL); + SU_GET_LEVEL(0, 0); + cxix = cxstack_ix; + if (PL_DBsub) { + SU_SKIP_DB(cxix); + while (cxix > 0) { + if (--level < 0) + break; + --cxix; + SU_SKIP_DB(cxix); + } + } else { + cxix -= level; + if (cxix < 0) + cxix = 0; + } + ST(0) = sv_2mortal(newSViv(cxix)); + XSRETURN(1); void CALLER(...) PROTOTYPE: ;$ PREINIT: - I32 cxix, caller = 0; + I32 cxix, level; PPCODE: - if (items) { - SV *csv = ST(0); - if (SvOK(csv)) - caller = SvIV(csv); - if (caller < 0) - caller = 0; - } - cxix = cxstack_ix; - while (cxix > 0) { + SU_GET_LEVEL(0, 0); + for (cxix = cxstack_ix; cxix > 0; --cxix) { PERL_CONTEXT *cx = cxstack + cxix; switch (CxTYPE(cx)) { case CXt_SUB: + if (PL_DBsub && cx->blk_sub.cv == GvCV(PL_DBsub)) + continue; case CXt_EVAL: case CXt_FORMAT: - --caller; - if (caller < 0) + if (--level < 0) goto done; break; } - --cxix; } done: ST(0) = sv_2mortal(newSViv(cxix));