X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=6a0b35e77bfb733c038838f378c8001b7e7c88eb;hb=7c5f28e56c17629e34fa0b2e6e4626e040f9c21d;hp=231acccc4dbf105c942243cdb2502a5cf28f4ea9;hpb=f0bcaf18260322fd0bc7ebe1bcae0cff45681a4d;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index 231accc..6a0b35e 100644 --- a/Upper.xs +++ b/Upper.xs @@ -569,7 +569,7 @@ STATIC void su_unwind(pTHX_ void *ud_) { if (items > A) { \ SV *lsv = ST(A); \ if (SvOK(lsv)) \ - level = SvUV(lsv); \ + level = SvIV(lsv); \ if (level < 0) \ XSRETURN(0); \ } \ @@ -578,10 +578,17 @@ STATIC void su_unwind(pTHX_ void *ud_) { #define SU_DOPOPTOCX(t) \ STMT_START { \ - I32 i, cxix = cxstack_ix, from = 0; \ - if (items) \ - from = SvIV(ST(0)); \ - for (i = cxix - from; i >= 0; --i) { \ + I32 i, cxix = cxstack_ix, level = 0; \ + if (items) { \ + SV *lsv = ST(0); \ + if (SvOK(lsv)) \ + level = SvIV(lsv); \ + if (level < 0) \ + level = 0; \ + else if (level > cxix) \ + level = cxix; \ + } \ + for (i = cxix - level; i >= 0; --i) { \ if (CxTYPE(&cxstack[i]) == t) { \ ST(0) = sv_2mortal(newSViv(cxix - i)); \ XSRETURN(1); \ @@ -598,19 +605,20 @@ XS(XS_Scope__Upper_unwind) { #else dXSARGS; #endif - I32 from = 0, cxix = cxstack_ix; + I32 level = 0, cxix = cxstack_ix; su_ud_unwind *ud; - SV *level; PERL_UNUSED_VAR(cv); /* -W */ PERL_UNUSED_VAR(ax); /* -Wall */ if (items) { - from = SvIV(ST(items - 1)); - if (from < 0) - from = 0; - else if (from > cxix) - from = cxix; + SV *lsv = ST(items - 1); + if (SvOK(lsv)) + level = SvIV(lsv); + if (level < 0) + level = 0; + else if (level > cxix) + level = cxix; } - cxix -= from; + cxix -= level; do { PERL_CONTEXT *cx = cxstack + cxix; switch (CxTYPE(cx)) { @@ -692,6 +700,69 @@ PROTOTYPE: ;$ PPCODE: SU_DOPOPTOCX(CXt_EVAL); +void +CALLER(...) +PROTOTYPE: ;$ +PREINIT: + I32 cxix = cxstack_ix, caller = 0, level = 0; +PPCODE: + if (items) { + SV *csv = ST(0); + if (SvOK(csv)) + caller = SvIV(csv); + } + cxix = cxstack_ix; + while (cxix > 0) { + PERL_CONTEXT *cx = cxstack + cxix--; + switch (CxTYPE(cx)) { + case CXt_SUB: + case CXt_EVAL: + case CXt_FORMAT: + --caller; + if (caller < 0) + goto done; + break; + } + ++level; + } +done: + ST(0) = sv_2mortal(newSViv(level)); + XSRETURN(1); + +void +want_at(...) +PROTOTYPE: ;$ +PREINIT: + I32 cxix = cxstack_ix, level = 0; +PPCODE: + if (items) { + SV *lsv = ST(0); + if (SvOK(lsv)) + level = SvIV(lsv); + if (level < 0) + level = 0; + else if (level > cxix) + level = cxix; + } + cxix -= level; + while (cxix > 0) { + PERL_CONTEXT *cx = cxstack + cxix--; + switch (CxTYPE(cx)) { + case CXt_SUB: + case CXt_EVAL: + case CXt_FORMAT: { + I32 gimme = cx->blk_gimme; + switch (gimme) { + case G_VOID: XSRETURN_UNDEF; break; + case G_SCALAR: XSRETURN_NO; break; + case G_ARRAY: XSRETURN_YES; break; + } + break; + } + } + } + XSRETURN_UNDEF; + void reap(SV *hook, ...) PROTOTYPE: &;$