# endif
#endif
-/* uvar magic and Hash::Util::FieldHash were commited with 28419 */
-#if VMG_HAS_PERL_MAINT(5, 9, 4, 28419) || VMG_HAS_PERL(5, 10, 0)
+/* uvar magic and Hash::Util::FieldHash were commited with 28419, but only
+ * enable it on 5.10 */
+#if VMG_HAS_PERL(5, 10, 0)
# define VMG_UVAR 1
#else
# define VMG_UVAR 0
char buf[8];
dMY_CXT;
- if (HvKEYS(MY_CXT.wizards) >= SIG_NBR)
- croak(vmg_toomanysigs);
+ if (HvKEYS(MY_CXT.wizards) >= SIG_NBR) croak(vmg_toomanysigs);
do {
sig = SIG_NBR * Drand01() + SIG_MIN;
/* One uvar magic in the chain is enough. */
for (prevmagic = NULL, mg = SvMAGIC(sv); mg; prevmagic = mg, mg = moremagic) {
moremagic = mg->mg_moremagic;
- if (mg->mg_type == PERL_MAGIC_uvar) { break; }
+ if (mg->mg_type == PERL_MAGIC_uvar)
+ break;
}
if (mg) { /* Found another uvar magic. */
#endif /* VMG_UVAR */
MAGIC *mg, *prevmagic, *moremagic = NULL;
- if (SvTYPE(sv) < SVt_PVMG) { return 0; }
+ if (SvTYPE(sv) < SVt_PVMG)
+ return 0;
for (prevmagic = NULL, mg = SvMAGIC(sv); mg; prevmagic = mg, mg = moremagic) {
moremagic = mg->mg_moremagic;
}
}
}
- if (!mg) { return 0; }
+ if (!mg)
+ return 0;
if (prevmagic) {
prevmagic->mg_moremagic = moremagic;
}
mg->mg_moremagic = NULL;
- if (mg->mg_obj != sv) { SvREFCNT_dec(mg->mg_obj); } /* Destroy private data */
- SvREFCNT_dec((SV *) mg->mg_ptr); /* Unreference the wizard */
+ /* Destroy private data */
+ if (mg->mg_obj != sv)
+ SvREFCNT_dec(mg->mg_obj);
+ /* Unreference the wizard */
+ SvREFCNT_dec((SV *) mg->mg_ptr);
Safefree(mg);
#if VMG_UVAR
struct ufuncs *uf;
for (prevmagic = NULL, mg = SvMAGIC(sv); mg; prevmagic = mg, mg = moremagic){
moremagic = mg->mg_moremagic;
- if (mg->mg_type == PERL_MAGIC_uvar) { break; }
+ if (mg->mg_type == PERL_MAGIC_uvar)
+ break;
}
/* assert(mg); */
uf = (struct ufuncs *) mg->mg_ptr;
STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
const MGWIZ *w;
+#if VMG_HAS_PERL(5, 9, 5)
+ PERL_CONTEXT saved_cx;
+ I32 cxix;
+#endif
unsigned int had_err, has_err, flags = G_SCALAR | G_EVAL;
int ret = 0;
if (had_err)
flags |= G_KEEPERR;
+#if VMG_HAS_PERL(5, 9, 5)
+ /* This context should not be used anymore, but since we croak in places the
+ * core doesn't even dare to, some pointers to it may remain in the upper call
+ * stack. Make sure call_sv() doesn't clobber it. */
+ if (cxstack_ix < cxstack_max)
+ cxix = cxstack_ix + 1;
+ else
+ cxix = Perl_cxinc(aTHX);
+ saved_cx = cxstack[cxix];
+#endif
+
call_sv(w->cb_free, flags);
+#if VMG_HAS_PERL(5, 9, 5)
+ cxstack[cxix] = saved_cx;
+#endif
+
has_err = SvTRUE(ERRSV);
if (IN_PERL_COMPILETIME && !had_err && has_err)
++PL_error_count;
FREETMPS;
LEAVE;
- if (has_err) {
- /* Get the eval context that was pushed by call_sv, and fake an entry for the
- * namesv, as die_where will need it to be non NULL later */
- PERL_CONTEXT *cx = cxstack + cxstack_ix + 1;
- if (!cx->blk_eval.old_namesv)
- cx->blk_eval.old_namesv
- = sv_2mortal(newSVpvn_share("Variable/Magic/DUMMY.pm", 23, 0));
- }
-
/* Calling SvREFCNT_dec() will trigger destructors in an infinite loop, so
* we have to rely on SvREFCNT() being a lvalue. Heck, even the core does it */
--SvREFCNT(sv);
key = umg->mg_obj;
uf = (struct ufuncs *) umg->mg_ptr;
- if (uf[1].uf_val != NULL) { uf[1].uf_val(aTHX_ action, sv); }
- if (uf[1].uf_set != NULL) { uf[1].uf_set(aTHX_ action, sv); }
+ if (uf[1].uf_val)
+ uf[1].uf_val(aTHX_ action, 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) {
if (hv_delete(MY_CXT.wizards, buf, sprintf(buf, "%u", w->sig), 0) != wiz)
return 0;
}
- SvFLAGS(wiz) |= SVf_BREAK;
- FREETMPS;
- if (w->cb_data != NULL) { SvREFCNT_dec(SvRV(w->cb_data)); }
- if (w->cb_get != NULL) { SvREFCNT_dec(SvRV(w->cb_get)); }
- if (w->cb_set != NULL) { SvREFCNT_dec(SvRV(w->cb_set)); }
- if (w->cb_len != NULL) { SvREFCNT_dec(SvRV(w->cb_len)); }
- if (w->cb_clear != NULL) { SvREFCNT_dec(SvRV(w->cb_clear)); }
- if (w->cb_free != NULL) { SvREFCNT_dec(SvRV(w->cb_free)); }
+ /* Unmortalize the wizard to avoid it being freed in weird places. */
+ if (SvTEMP(wiz) && !SvREFCNT(wiz)) {
+ const I32 myfloor = PL_tmps_floor;
+ I32 i;
+ for (i = PL_tmps_ix; i > myfloor; --i) {
+ if (PL_tmps_stack[i] == wiz)
+ PL_tmps_stack[i] = NULL;
+ }
+ }
+
+ if (w->cb_data) SvREFCNT_dec(SvRV(w->cb_data));
+ if (w->cb_get) SvREFCNT_dec(SvRV(w->cb_get));
+ if (w->cb_set) SvREFCNT_dec(SvRV(w->cb_set));
+ if (w->cb_len) SvREFCNT_dec(SvRV(w->cb_len));
+ if (w->cb_clear) SvREFCNT_dec(SvRV(w->cb_clear));
+ if (w->cb_free) SvREFCNT_dec(SvRV(w->cb_free));
#if MGf_COPY
- if (w->cb_copy != NULL) { SvREFCNT_dec(SvRV(w->cb_copy)); }
+ if (w->cb_copy) SvREFCNT_dec(SvRV(w->cb_copy));
#endif /* MGf_COPY */
#if 0 /* MGf_DUP */
- if (w->cb_dup != NULL) { SvREFCNT_dec(SvRV(w->cb_dup)); }
+ if (w->cb_dup) SvREFCNT_dec(SvRV(w->cb_dup));
#endif /* MGf_DUP */
#if MGf_LOCAL
- if (w->cb_local != NULL) { SvREFCNT_dec(SvRV(w->cb_local)); }
+ if (w->cb_local) SvREFCNT_dec(SvRV(w->cb_local));
#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)); }
- if (w->cb_exists != NULL) { SvREFCNT_dec(SvRV(w->cb_exists)); }
- if (w->cb_delete != NULL) { SvREFCNT_dec(SvRV(w->cb_delete)); }
+ if (w->cb_fetch) SvREFCNT_dec(SvRV(w->cb_fetch));
+ if (w->cb_store) SvREFCNT_dec(SvRV(w->cb_store));
+ if (w->cb_exists) SvREFCNT_dec(SvRV(w->cb_exists));
+ if (w->cb_delete) SvREFCNT_dec(SvRV(w->cb_delete));
#endif /* VMG_UVAR */
Safefree(w->vtbl);
SV *getsig(SV *wiz)
PROTOTYPE: $
+PREINIT:
+ U16 sig;
CODE:
- if (!SvROK(wiz)) { croak(vmg_invalid_wiz); }
- RETVAL = newSVuv(SV2MGWIZ(SvRV(wiz))->sig);
+ sig = vmg_wizard_sig(wiz);
+ RETVAL = newSVuv(sig);
OUTPUT:
RETVAL
for (i = 2; i < items; ++i) {
SV *arg = ST(i);
SvREFCNT_inc(arg);
- if (av_store(args, i - 2, arg) == NULL) { croak(vmg_argstorefailed); }
+ if (av_store(args, i - 2, arg) == NULL) croak(vmg_argstorefailed);
}
}
ret = newSVuv(vmg_cast(SvRV(sv), wiz, args));
PPCODE:
sig = vmg_wizard_sig(wiz);
data = vmg_data_get(SvRV(sv), sig);
- if (!data) { XSRETURN_UNDEF; }
+ if (!data)
+ XSRETURN_EMPTY;
ST(0) = data;
XSRETURN(1);