X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=b218de98cbc0bee835762d1d6d07b01b37f75971;hb=a8d75011f6169928695d9fda6cf5e8ebc1cc6e92;hp=c81db042afbd9252fe76462b9a1e2906c30c183f;hpb=751094f5d7b43171afc7104e957ca7fe2d21eb34;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index c81db04..b218de9 100644 --- a/Magic.xs +++ b/Magic.xs @@ -12,10 +12,22 @@ #define R(S) fprintf(stderr, "R(" #S ") = %d\n", SvREFCNT(S)) +#define PERL_VERSION_GE(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S)))))) + #define PERL_VERSION_LE(R, V, S) (PERL_REVISION < (R) || (PERL_REVISION == (R) && (PERL_VERSION < (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION <= (S)))))) #define PERL_API_VERSION_GE(R, V, S) (PERL_API_REVISION > (R) || (PERL_API_REVISION == (R) && (PERL_API_VERSION > (V) || (PERL_API_VERSION == (V) && (PERL_API_SUBVERSION >= (S)))))) +#define PERL_API_VERSION_LE(R, V, S) (PERL_API_REVISION < (R) || (PERL_API_REVISION == (R) && (PERL_API_VERSION < (V) || (PERL_API_VERSION == (V) && (PERL_API_SUBVERSION <= (S)))))) + +#ifndef VMG_PERL_PATCHLEVEL +# ifdef PERL_PATCHNUM +# define VMG_PERL_PATCHLEVEL PERL_PATCHNUM +# else +# define VMG_PERL_PATCHLEVEL 0 +# endif +#endif + /* --- Compatibility ------------------------------------------------------- */ #ifndef Newx @@ -41,7 +53,6 @@ # define MGf_COPY 0 #endif -#undef MGf_DUP /* Disable it for now. */ #ifndef MGf_DUP # define MGf_DUP 0 #endif @@ -56,6 +67,19 @@ # define VMG_UVAR 0 #endif +#if (VMG_PERL_PATCHLEVEL >= 25854) || PERL_VERSION_GE(5, 9, 3) +# define VMG_COMPAT_ARRAY_PUSH_NOLEN 1 +#else +# define VMG_COMPAT_ARRAY_PUSH_NOLEN 0 +#endif + +/* since 5.9.5 - see #43357 */ +#if (VMG_PERL_PATCHLEVEL >= 31473) || PERL_VERSION_GE(5, 9, 5) +# define VMG_COMPAT_ARRAY_UNDEF_CLEAR 1 +#else +# define VMG_COMPAT_ARRAY_UNDEF_CLEAR 0 +#endif + #if VMG_UVAR /* Bug-free mg_magical - see http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-01/msg00036.html */ @@ -97,9 +121,9 @@ START_MY_CXT /* --- Signatures ---------------------------------------------------------- */ #define SIG_MIN ((U16) (1u << 8)) -#define SIG_MAX ((U16) (1u << 16 - 1)) +#define SIG_MAX ((U16) ((1u << 16) - 1)) #define SIG_NBR (SIG_MAX - SIG_MIN + 1) -#define SIG_WIZ ((U16) (1u << 8 - 1)) +#define SIG_WIZ ((U16) ((1u << 8) - 1)) /* ... Generate signatures ................................................. */ @@ -183,7 +207,6 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, AV *args) { STATIC SV *vmg_data_get(SV *sv, U16 sig) { MAGIC *mg, *moremagic; - MGWIZ *w; if (SvTYPE(sv) >= SVt_PVMG) { for (mg = SvMAGIC(sv); mg; mg = moremagic) { @@ -198,6 +221,7 @@ STATIC SV *vmg_data_get(SV *sv, U16 sig) { /* ... Magic cast/dispell .................................................. */ +#if VMG_UVAR STATIC I32 vmg_svt_val(pTHX_ IV, SV *); STATIC void vmg_uvar_del(SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) { @@ -210,6 +234,7 @@ STATIC void vmg_uvar_del(SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) Safefree(mg->mg_ptr); Safefree(mg); } +#endif /* VMG_UVAR */ STATIC UV vmg_cast(pTHX_ SV *sv, SV *wiz, AV *args) { #define vmg_cast(S, W, A) vmg_cast(aTHX_ (S), (W), (A)) @@ -352,6 +377,7 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) { /* Revert the original uvar magic. */ uf[0] = uf[1]; Renew(uf, 1, struct ufuncs); + mg->mg_ptr = (char *) uf; mg->mg_len = sizeof(struct ufuncs); } else { /* Remove the uvar magic. */ @@ -368,6 +394,7 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) { STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data) { #define vmg_cb_call(I, S, D) vmg_cb_call(aTHX_ (I), (S), (D)) + SV *svr; int ret; dSP; @@ -386,7 +413,8 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data) { SPAGAIN; if (count != 1) { croak("Callback needs to return 1 scalar\n"); } - ret = POPi; + svr = POPs; + ret = SvOK(svr) ? SvIV(svr) : 0; PUTBACK; @@ -396,9 +424,10 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, SV *sv, SV *data) { return ret; } -#if MGf_COPY || VMG_UVAR +#if VMG_UVAR STATIC int vmg_cb_call2(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2) { #define vmg_cb_call2(I, S, D, S2) vmg_cb_call2(aTHX_ (I), (S), (D), (S2)) + SV *svr; int ret; dSP; @@ -418,7 +447,44 @@ STATIC int vmg_cb_call2(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2) { SPAGAIN; if (count != 1) { croak("Callback needs to return 1 scalar\n"); } - ret = POPi; + svr = POPs; + ret = SvOK(svr) ? SvIV(svr) : 0; + + PUTBACK; + + FREETMPS; + LEAVE; + + return ret; +} +#endif /* VMG_UVAR */ + +#if MGf_COPY +STATIC int vmg_cb_call3(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2, SV *sv3) { +#define vmg_cb_call3(I, S, D, S2, S3) vmg_cb_call3(aTHX_ (I), (S), (D), (S2), (S3)) + SV *svr; + int ret; + + dSP; + int count; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newRV_inc(sv))); + XPUSHs(data ? data : &PL_sv_undef); + XPUSHs(sv2 ? sv2 : &PL_sv_undef); + if (sv3) { XPUSHs(sv3); } + PUTBACK; + + count = call_sv(cb, G_SCALAR); + + SPAGAIN; + + if (count != 1) { croak("Callback needs to return 1 scalar\n"); } + svr = POPs; + ret = SvOK(svr) ? SvIV(svr) : 0; PUTBACK; @@ -427,7 +493,7 @@ STATIC int vmg_cb_call2(pTHX_ SV *cb, SV *sv, SV *data, SV *sv2) { return ret; } -#endif /* MGf_COPY || VMG_UVAR */ +#endif /* MGf_COPY */ STATIC int vmg_svt_get(pTHX_ SV *sv, MAGIC *mg) { return vmg_cb_call(SV2MGWIZ(mg->mg_ptr)->cb_get, sv, mg->mg_obj); @@ -438,6 +504,8 @@ STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) { } STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { + SV *svr; + I32 len; U32 ret; dSP; @@ -450,7 +518,8 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { XPUSHs(sv_2mortal(newRV_inc(sv))); XPUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef); if (SvTYPE(sv) == SVt_PVAV) { - XPUSHs(sv_2mortal(newSViv(av_len((AV *) sv) + 1))); + len = av_len((AV *) sv) + 1; + XPUSHs(sv_2mortal(newSViv(len))); } PUTBACK; @@ -459,7 +528,9 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { SPAGAIN; if (count != 1) { croak("Callback needs to return 1 scalar\n"); } - ret = POPi; + svr = POPs; + ret = SvOK(svr) ? SvUV(svr) + : ((SvTYPE(sv) == SVt_PVAV) ? len : 1); PUTBACK; @@ -482,12 +553,33 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { } #if MGf_COPY -STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *name, int namelen) { - return vmg_cb_call2(SV2MGWIZ(mg->mg_ptr)->cb_copy, sv, mg->mg_obj, nsv); +STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, +# if PERL_API_VERSION_GE(5, 11, 0) + I32 keylen +# else + int keylen +# endif + ) { + SV *keysv; + int ret; + + if (keylen == HEf_SVKEY) { + keysv = (SV *) key; + } else { + keysv = newSVpvn(key, keylen); + } + + ret = vmg_cb_call3(SV2MGWIZ(mg->mg_ptr)->cb_copy, sv, mg->mg_obj, keysv, nsv); + + if (keylen != HEf_SVKEY) { + SvREFCNT_dec(keysv); + } + + return ret; } #endif /* MGf_COPY */ -#if MGf_DUP +#if 0 /* MGf_DUP */ STATIC int vmg_svt_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param) { return 0; } @@ -520,20 +612,21 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { || (mg->mg_private < SIG_MIN) || (mg->mg_private > SIG_MAX)) { continue; } w = SV2MGWIZ(mg->mg_ptr); + if (!w->uvar) { continue; } switch (action) { case 0: - vmg_cb_call2(w->cb_fetch, sv, mg->mg_obj, key); + if (w->cb_fetch) { vmg_cb_call2(w->cb_fetch, sv, mg->mg_obj, key); } break; case HV_FETCH_ISSTORE: case HV_FETCH_LVALUE: case (HV_FETCH_ISSTORE|HV_FETCH_LVALUE): - vmg_cb_call2(w->cb_store, sv, mg->mg_obj, key); + if (w->cb_store) { vmg_cb_call2(w->cb_store, sv, mg->mg_obj, key); } break; case HV_FETCH_ISEXISTS: - vmg_cb_call2(w->cb_exists, sv, mg->mg_obj, key); + if (w->cb_exists) { vmg_cb_call2(w->cb_exists, sv, mg->mg_obj, key); } break; case HV_DELETE: - vmg_cb_call2(w->cb_delete, sv, mg->mg_obj, key); + if (w->cb_delete) { vmg_cb_call2(w->cb_delete, sv, mg->mg_obj, key); } break; } } @@ -570,10 +663,10 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { #endif /* MGf_COPY */ #if MGf_DUP if (w->cb_dup != NULL) { SvREFCNT_dec(SvRV(w->cb_dup)); } -#endif /* MGf_COPY */ +#endif /* MGf_DUP */ #if MGf_LOCAL if (w->cb_local != NULL) { SvREFCNT_dec(SvRV(w->cb_local)); } -#endif /* MGf_COPY */ +#endif /* MGf_LOCAL */ #if VMG_UVAR if (w->cb_fetch != NULL) { SvREFCNT_dec(SvRV(w->cb_fetch)); } if (w->cb_store != NULL) { SvREFCNT_dec(SvRV(w->cb_store)); } @@ -600,7 +693,7 @@ STATIC MGVTBL vmg_wizard_vtbl = { #endif /* MGf_DUP */ #if MGf_LOCAL NULL, /* local */ -#endif /* MGf_DUP */ +#endif /* MGf_LOCAL */ }; STATIC const char vmg_invalid_wiz[] = "Invalid wizard object"; @@ -664,6 +757,10 @@ BOOT: newCONSTSUB(stash, "MGf_DUP", newSVuv(MGf_DUP)); newCONSTSUB(stash, "MGf_LOCAL", newSVuv(MGf_LOCAL)); newCONSTSUB(stash, "VMG_UVAR", newSVuv(VMG_UVAR)); + newCONSTSUB(stash, "VMG_COMPAT_ARRAY_PUSH_NOLEN", + newSVuv(VMG_COMPAT_ARRAY_PUSH_NOLEN)); + newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNDEF_CLEAR", + newSVuv(VMG_COMPAT_ARRAY_UNDEF_CLEAR)); } SV *_wizard(...) @@ -700,7 +797,7 @@ CODE: if (SvOK(svsig)) { SV **old; sig = vmg_sv2sig(svsig); - if (old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0)) { + if ((old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0))) { ST(0) = sv_2mortal(newRV_inc(*old)); XSRETURN(1); } @@ -722,7 +819,10 @@ CODE: VMG_SET_SVT_CB(ST(i++), copy); #endif /* MGf_COPY */ #if MGf_DUP - VMG_SET_SVT_CB(ST(i++), dup); + /* VMG_SET_SVT_CB(ST(i++), dup); */ + i++; + t->svt_dup = NULL; + w->cb_dup = NULL; #endif /* MGf_DUP */ #if MGf_LOCAL VMG_SET_SVT_CB(ST(i++), local); @@ -781,7 +881,7 @@ CODE: char buf[8]; SV **old; U16 sig = vmg_sv2sig(wiz); - if (old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0)) { + if ((old = hv_fetch(MY_CXT.wizz, buf, sprintf(buf, "%u", sig), 0))) { wiz = *old; } else { XSRETURN_UNDEF;