X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=c8de4302383d714c9e14eb23a57afeb5bf233ff6;hb=b0d725bd65b94259e76048f864c972d9b70aac6b;hp=bf413ff0329b69ed1af14bced53f689fdd31d211;hpb=9313f2dc8e1f534131fee3e6235f4a533396a0ac;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index bf413ff..c8de430 100644 --- a/Magic.xs +++ b/Magic.xs @@ -133,6 +133,12 @@ # define VMG_UVAR 0 #endif +#if VMG_HAS_PERL_MAINT(5, 11, 0, 32969) || VMG_HAS_PERL(5, 12, 0) +# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 1 +#else +# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 0 +#endif + /* Applied to dev-5.9 as 25854, integrated to maint-5.8 as 28160, partially * reverted to dev-5.11 as 9cdcb38b */ #if VMG_HAS_PERL_MAINT(5, 8, 9, 28160) || VMG_HAS_PERL_MAINT(5, 9, 3, 25854) || VMG_HAS_PERL(5, 10, 0) @@ -169,10 +175,10 @@ # define VMG_COMPAT_ARRAY_UNDEF_CLEAR 0 #endif -#if VMG_HAS_PERL_MAINT(5, 11, 0, 32969) || VMG_HAS_PERL(5, 12, 0) -# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 1 +#if VMG_HAS_PERL(5, 11, 0) +# define VMG_COMPAT_HASH_DELETE_NOUVAR_VOID 1 #else -# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 0 +# define VMG_COMPAT_HASH_DELETE_NOUVAR_VOID 0 #endif #if VMG_HAS_PERL(5, 13, 2) @@ -1080,6 +1086,18 @@ STATIC int vmg_svt_set(pTHX_ SV *sv, MAGIC *mg) { return vmg_cb_call1(w->cb_set, w->opinfo, sv, mg->mg_obj); } +STATIC U32 vmg_sv_len(pTHX_ SV *sv) { +#define vmg_sv_len(S) vmg_sv_len(aTHX_ (S)) + STRLEN len; +#if VMG_HAS_PERL(5, 9, 3) + const U8 *s = VOID2(const U8 *, VOID2(const void *, SvPV_const(sv, len))); +#else + U8 *s = SvPV(sv, len); +#endif + + return DO_UTF8(sv) ? utf8_length(s, s + len) : len; +} + STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg); unsigned int opinfo = w->opinfo; @@ -1097,16 +1115,7 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) { PUSHs(sv_2mortal(newRV_inc(sv))); PUSHs(mg->mg_obj ? mg->mg_obj : &PL_sv_undef); if (t < SVt_PVAV) { - STRLEN l; -#if VMG_HAS_PERL(5, 9, 3) - const U8 *s = VOID2(const U8 *, VOID2(const void *, SvPV_const(sv, l))); -#else - U8 *s = SvPV(sv, l); -#endif - if (DO_UTF8(sv)) - len = utf8_length(s, s + l); - else - len = l; + len = vmg_sv_len(sv); mPUSHu(len); } else if (t == SVt_PVAV) { len = av_len((AV *) sv) + 1; @@ -1195,13 +1204,13 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { return ret; } -STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, -# if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) || VMG_HAS_PERL(5, 12, 0) - I32 keylen -# else - int keylen -# endif - ) { +#if VMG_HAS_PERL_MAINT(5, 11, 0, 33256) || VMG_HAS_PERL(5, 12, 0) +# define VMG_SVT_COPY_KEYLEN_TYPE I32 +#else +# define VMG_SVT_COPY_KEYLEN_TYPE int +#endif + +STATIC int vmg_svt_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, const char *key, VMG_SVT_COPY_KEYLEN_TYPE keylen) { const vmg_wizard *w = vmg_wizard_from_mg_nocheck(mg); SV *keysv; int ret; @@ -1257,9 +1266,9 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { if (uf[1].uf_set) uf[1].uf_set(aTHX_ action, sv); - action &= HV_FETCH_ISSTORE | HV_FETCH_ISEXISTS | HV_FETCH_LVALUE | HV_DELETE; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const vmg_wizard *w; + switch (mg->mg_type) { case PERL_MAGIC_ext: break; @@ -1269,8 +1278,11 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { default: continue; } + w = vmg_wizard_from_mg(mg); - if (!w) continue; + if (!w) + continue; + switch (w->uvar) { case 0: continue; @@ -1278,7 +1290,9 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { if (!newkey) newkey = key = umg->mg_obj = sv_mortalcopy(umg->mg_obj); } - switch (action) { + + switch (action + & (HV_FETCH_ISSTORE|HV_FETCH_ISEXISTS|HV_FETCH_LVALUE|HV_DELETE)) { case 0: if (w->cb_fetch) vmg_cb_call2(w->cb_fetch, w->opinfo, sv, mg->mg_obj, key); @@ -1300,21 +1314,21 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *sv) { } } - if (SvRMAGICAL(sv) && !tied) { + if (SvRMAGICAL(sv) && !tied && !(action & (HV_FETCH_ISSTORE|HV_DELETE))) { /* Temporarily hide the RMAGICAL flag of the hash so it isn't wrongly * mistaken for a tied hash by the rest of hv_common. It will be reset by * the op_ppaddr of a new fake op injected between the current and the next * one. */ - OP *o = PL_op; - if (!o->op_next || o->op_next->op_ppaddr != vmg_pp_resetuvar) { + OP *nop = PL_op->op_next; + if (!nop || nop->op_ppaddr != vmg_pp_resetuvar) { SVOP *svop; NewOp(1101, svop, 1, SVOP); svop->op_type = OP_STUB; svop->op_ppaddr = vmg_pp_resetuvar; - svop->op_next = o->op_next; + svop->op_next = nop; svop->op_flags = 0; svop->op_sv = sv; - o->op_next = (OP *) svop; + PL_op->op_next = (OP *) svop; } SvRMAGICAL_off(sv); } @@ -1361,6 +1375,8 @@ 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_SCALAR_LENGTH_NOLEN", + newSVuv(VMG_COMPAT_SCALAR_LENGTH_NOLEN)); newCONSTSUB(stash, "VMG_COMPAT_ARRAY_PUSH_NOLEN", newSVuv(VMG_COMPAT_ARRAY_PUSH_NOLEN)); newCONSTSUB(stash, "VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID", @@ -1369,8 +1385,8 @@ BOOT: newSVuv(VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID)); newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNDEF_CLEAR", newSVuv(VMG_COMPAT_ARRAY_UNDEF_CLEAR)); - newCONSTSUB(stash, "VMG_COMPAT_SCALAR_LENGTH_NOLEN", - newSVuv(VMG_COMPAT_SCALAR_LENGTH_NOLEN)); + newCONSTSUB(stash, "VMG_COMPAT_HASH_DELETE_NOUVAR_VOID", + newSVuv(VMG_COMPAT_HASH_DELETE_NOUVAR_VOID)); newCONSTSUB(stash, "VMG_COMPAT_GLOB_GET", newSVuv(VMG_COMPAT_GLOB_GET)); newCONSTSUB(stash, "VMG_PERL_PATCHLEVEL", newSVuv(VMG_PERL_PATCHLEVEL)); newCONSTSUB(stash, "VMG_THREADSAFE", newSVuv(VMG_THREADSAFE));