X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Upper.xs;h=0e36df1e98a4cbc7f5b65be2d703442e3b61d2be;hb=57746d0b3de44a1205902e433488c8a1afe69469;hp=d34c7ffd7bc220db87bc44fc90373f19c7f9630d;hpb=b12d0710fc9e762dc2791d97f9f660454b9bb1f2;p=perl%2Fmodules%2FScope-Upper.git diff --git a/Upper.xs b/Upper.xs index d34c7ff..0e36df1 100644 --- a/Upper.xs +++ b/Upper.xs @@ -256,6 +256,11 @@ static U8 su_op_gimme_reverse(U8 gimme) { # define MY_CXT_CLONE NOOP #endif +/* --- Error messages ------------------------------------------------------ */ + +static const char su_stack_smash[] = "Cannot target a scope outside of the current stack"; +static const char su_no_such_target[] = "No targetable %s scope in the current stack"; + /* --- Unique context ID global storage ------------------------------------ */ /* ... Sequence ID counter ................................................. */ @@ -758,11 +763,12 @@ typedef struct { typedef struct { su_ud_common ci; - SV *cb; + SV *cb; } su_ud_reap; -static void su_call(pTHX_ void *ud_) { - su_ud_reap *ud = (su_ud_reap *) ud_; +#define SU_UD_REAP_CB(U) (((su_ud_reap *) (U))->cb) + +static void su_call(pTHX_ SV *cb) { #if SU_SAVE_LAST_CX I32 cxix; PERL_CONTEXT saved_cx; @@ -772,8 +778,8 @@ static void su_call(pTHX_ void *ud_) { SU_D({ PerlIO_printf(Perl_debug_log, - "%p: @@@ call\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n", - ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix); + "@@@ call scope_ix=%2d save_ix=%2d\n", + PL_scopestack_ix, PL_savestack_ix); }); ENTER; @@ -789,7 +795,7 @@ static void su_call(pTHX_ void *ud_) { saved_cx = cxstack[cxix]; #endif /* SU_SAVE_LAST_CX */ - call_sv(ud->cb, G_VOID); + call_sv(cb, G_VOID); #if SU_SAVE_LAST_CX cxstack[cxix] = saved_cx; @@ -800,35 +806,29 @@ static void su_call(pTHX_ void *ud_) { FREETMPS; LEAVE; - SvREFCNT_dec(ud->cb); - SU_UD_FREE(ud); -} + SvREFCNT_dec(cb); -static void su_reap(pTHX_ void *ud) { -#define su_reap(U) su_reap(aTHX_ (U)) - SU_D({ - PerlIO_printf(Perl_debug_log, - "%p: === reap\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n", - ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix); - }); - - SAVEDESTRUCTOR_X(su_call, ud); + return; } /* ... Localize & localize array/hash element .............................. */ typedef struct { su_ud_common ci; - SV *sv; - SV *val; - SV *elem; + SV *sv; + SV *val; + SV *elem; } su_ud_localize; +#define SU_UD_LOCALIZE_SV(U) (((su_ud_localize *) (U))->sv) +#define SU_UD_LOCALIZE_VAL(U) (((su_ud_localize *) (U))->val) +#define SU_UD_LOCALIZE_ELEM(U) (((su_ud_localize *) (U))->elem) + #define SU_UD_LOCALIZE_FREE(U) STMT_START { \ - SvREFCNT_dec((U)->elem); \ - SvREFCNT_dec((U)->val); \ - SvREFCNT_dec((U)->sv); \ - SU_UD_FREE(U); \ + SvREFCNT_dec(SU_UD_LOCALIZE_ELEM(U)); \ + SvREFCNT_dec(SU_UD_LOCALIZE_VAL(U)); \ + SvREFCNT_dec(SU_UD_LOCALIZE_SV(U)); \ + SU_UD_FREE(U); \ } STMT_END static I32 su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) { @@ -949,14 +949,14 @@ static void su_localize(pTHX_ void *ud_) { case SVt_PVAV: if (elem) { su_save_aelem(GvAV(gv), elem, val); - goto done; + return; } else save_ary(gv); break; case SVt_PVHV: if (elem) { su_save_helem(GvHV(gv), elem, val); - goto done; + return; } else save_hash(gv); break; @@ -974,8 +974,24 @@ static void su_localize(pTHX_ void *ud_) { if (val) SvSetMagicSV((SV *) gv, val); -done: - SU_UD_LOCALIZE_FREE(ud); + return; +} + +/* ... Unique context ID ................................................... */ + +typedef struct { + su_ud_common ci; + su_uid *uid; +} su_ud_uid; + +#define SU_UD_UID_UID(U) (((su_ud_uid *) (U))->uid) + +static void su_uid_drop(pTHX_ void *ud_) { + su_uid *uid = ud_; + + uid->flags &= ~SU_UID_ACTIVE; + + return; } /* --- Pop a context back -------------------------------------------------- */ @@ -1026,14 +1042,6 @@ static const char *su_block_type[] = { # define SU_CXNAME(C) su_block_type[CxTYPE(C)] #endif -static void su_uid_bump(pTHX_ void *); - -static void (*su_handler[])(pTHX_ void *) = { - su_reap, - su_localize, - su_uid_bump -}; - static void su_pop(pTHX_ void *ud) { #define su_pop(U) su_pop(aTHX_ (U)) I32 depth, base, mark, *origin; @@ -1099,7 +1107,26 @@ static void su_pop(pTHX_ void *ud) { ud, depth, PL_scopestack_ix, PL_savestack_ix)); SAVEDESTRUCTOR_X(su_pop, ud); } else { - su_handler[SU_UD_TYPE(ud)](aTHX_ ud); + switch (SU_UD_TYPE(ud)) { + case SU_UD_TYPE_REAP: { + SU_D({ + PerlIO_printf(Perl_debug_log, + "%p: === reap\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n", + ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix); + }); + SAVEDESTRUCTOR_X(su_call, SU_UD_REAP_CB(ud)); + SU_UD_FREE(ud); + break; + } + case SU_UD_TYPE_LOCALIZE: + su_localize(ud); + SU_UD_LOCALIZE_FREE(ud); + break; + case SU_UD_TYPE_UID: + SAVEDESTRUCTOR_X(su_uid_drop, SU_UD_UID_UID(ud)); + SU_UD_FREE(ud); + break; + } } SU_D(PerlIO_printf(Perl_debug_log, @@ -2004,20 +2031,6 @@ static int su_uid_storage_check(pTHX_ UV depth, UV seq) { return uid && (uid->seq == seq) && (uid->flags & SU_UID_ACTIVE); } -static void su_uid_drop(pTHX_ void *ud_) { - su_uid *uid = ud_; - - uid->flags &= ~SU_UID_ACTIVE; -} - -static void su_uid_bump(pTHX_ void *ud_) { - su_ud_reap *ud = ud_; - - SAVEDESTRUCTOR_X(su_uid_drop, ud->cb); - - SU_UD_FREE(ud); -} - static SV *su_uid_get(pTHX_ I32 cxix) { #define su_uid_get(I) su_uid_get(aTHX_ (I)) su_uid *uid; @@ -2028,15 +2041,14 @@ static SV *su_uid_get(pTHX_ I32 cxix) { uid = su_uid_storage_fetch(depth); if (!(uid->flags & SU_UID_ACTIVE)) { - su_ud_reap *ud; + su_ud_uid *ud; - uid->seq = su_uid_seq_next(depth); + uid->seq = su_uid_seq_next(depth); uid->flags |= SU_UID_ACTIVE; - Newx(ud, 1, su_ud_reap); - SU_UD_ORIGIN(ud) = NULL; - SU_UD_TYPE(ud) = SU_UD_TYPE_UID; - ud->cb = (SV *) uid; + Newx(ud, 1, su_ud_uid); + SU_UD_TYPE(ud) = SU_UD_TYPE_UID; + ud->uid = uid; su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE); } @@ -2579,6 +2591,8 @@ PPCODE: --cxix; cxix = su_context_skip_db(cxix); cxix = su_context_normalize_up(cxix); + } else { + warn(su_stack_smash); } EXTEND(SP, 1); mPUSHi(cxix); @@ -2604,6 +2618,7 @@ PPCODE: XSRETURN(1); } } + warn(su_no_such_target, "subroutine"); XSRETURN_UNDEF; void @@ -2624,6 +2639,7 @@ PPCODE: XSRETURN(1); } } + warn(su_no_such_target, "eval"); XSRETURN_UNDEF; void @@ -2635,8 +2651,10 @@ PPCODE: SU_GET_LEVEL(0, 0); cxix = su_context_here(); while (--level >= 0) { - if (cxix <= 0) + if (cxix <= 0) { + warn(su_stack_smash); break; + } --cxix; cxix = su_context_skip_db(cxix); cxix = su_context_normalize_up(cxix); @@ -2666,6 +2684,8 @@ PPCODE: } } done: + if (level >= 0) + warn(su_stack_smash); EXTEND(SP, 1); mPUSHi(cxix); XSRETURN(1); @@ -2864,9 +2884,10 @@ CODE: SU_GET_CONTEXT(1, 1, su_context_skip_db(cxstack_ix)); cxix = su_context_normalize_down(cxix); Newx(ud, 1, su_ud_reap); - SU_UD_ORIGIN(ud) = NULL; - SU_UD_TYPE(ud) = SU_UD_TYPE_REAP; - ud->cb = newSVsv(hook); + SU_UD_TYPE(ud) = SU_UD_TYPE_REAP; + ud->cb = (SvROK(hook) && SvTYPE(SvRV(hook)) >= SVt_PVCV) + ? SvRV(hook) : hook; + SvREFCNT_inc_simple_void(ud->cb); su_init(ud, cxix, SU_SAVE_DESTRUCTOR_SIZE); void @@ -2880,8 +2901,7 @@ CODE: SU_GET_CONTEXT(2, 2, su_context_skip_db(cxstack_ix)); cxix = su_context_normalize_down(cxix); Newx(ud, 1, su_ud_localize); - SU_UD_ORIGIN(ud) = NULL; - SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; + SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; size = su_ud_localize_init(ud, sv, val, NULL); su_init(ud, cxix, size); @@ -2898,6 +2918,7 @@ CODE: SU_GET_CONTEXT(3, 3, su_context_skip_db(cxstack_ix)); cxix = su_context_normalize_down(cxix); Newx(ud, 1, su_ud_localize); + /* Initialize SU_UD_ORIGIN(ud) in case SU_UD_LOCALIZE_FREE(ud) needs it */ SU_UD_ORIGIN(ud) = NULL; SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; size = su_ud_localize_init(ud, sv, val, elem); @@ -2918,8 +2939,7 @@ CODE: SU_GET_CONTEXT(2, 2, su_context_skip_db(cxstack_ix)); cxix = su_context_normalize_down(cxix); Newx(ud, 1, su_ud_localize); - SU_UD_ORIGIN(ud) = NULL; - SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; + SU_UD_TYPE(ud) = SU_UD_TYPE_LOCALIZE; size = su_ud_localize_init(ud, sv, NULL, elem); su_init(ud, cxix, size);