]> git.vpit.fr Git - perl/modules/Variable-Magic.git/blobdiff - Magic.xs
Compatibility fix for 5.11.1
[perl/modules/Variable-Magic.git] / Magic.xs
index 14a33f4a12a5cb7419ebc847b782dd402958f445..628bf5666c8602338f06db61241facbc58479de9 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
 # define dNOOP
 #endif
 
+/* Safe unless stated otherwise in Makefile.PL */
+#ifndef VMG_FORKSAFE
+# define VMG_FORKSAFE 1
+#endif
+
 #ifndef VMG_MULTIPLICITY
 # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT)
 #  define VMG_MULTIPLICITY 1
@@ -135,20 +140,32 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) {
 # 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
 #endif
 
-/* Applied to dev-5.9 as 25854, integrated to maint-5.8 as 28160 */
-#ifndef VMG_COMPAT_ARRAY_PUSH_NOLEN
-# if VMG_HAS_PERL_MAINT(5, 8, 9, 28160) || VMG_HAS_PERL_MAINT(5, 9, 3, 25854) || VMG_HAS_PERL(5, 10, 0)
+/* 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)
+# ifndef VMG_COMPAT_ARRAY_PUSH_NOLEN
+/* This branch should only apply for perls before the official 5.11.0 release.
+ * Makefile.PL takes care of the higher ones. */
 #  define VMG_COMPAT_ARRAY_PUSH_NOLEN 1
-# else
+# endif
+# ifndef VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID
+#  define VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID 1
+# endif
+#else
+# ifndef VMG_COMPAT_ARRAY_PUSH_NOLEN
 #  define VMG_COMPAT_ARRAY_PUSH_NOLEN 0
 # endif
+# ifndef VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID
+#  define VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID 0
+# endif
 #endif
 
 /* Applied to dev-5.11 as 34908 */
@@ -229,8 +246,10 @@ STATIC const char *const vmg_opclassnames[] = {
 };
 
 STATIC opclass vmg_opclass(const OP *o) {
+#if 0
  if (!o)
   return OPc_NULL;
+#endif
 
  if (o->op_type == 0)
   return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
@@ -335,8 +354,7 @@ STATIC U16 vmg_gensig(pTHX) {
  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;
@@ -513,7 +531,8 @@ STATIC UV vmg_cast(pTHX_ SV *sv, SV *wiz, AV *args) {
   /* 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. */
@@ -545,7 +564,8 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
 #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;
@@ -565,7 +585,8 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
    }
   }
  }
- if (!mg) { return 0; }
+ if (!mg)
+  return 0;
 
  if (prevmagic) {
   prevmagic->mg_moremagic = moremagic;
@@ -574,8 +595,11 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
  }
  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
@@ -596,7 +620,8 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) {
    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;
@@ -804,6 +829,10 @@ STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
 
 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;
 
@@ -841,8 +870,23 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  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;
@@ -852,15 +896,6 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  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);
@@ -928,8 +963,10 @@ STATIC I32 vmg_svt_val(pTHX_ IV action, SV *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) {
@@ -1018,29 +1055,37 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) {
   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);
@@ -1226,6 +1271,8 @@ BOOT:
  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_PUSH_NOLEN_VOID",
+                    newSVuv(VMG_COMPAT_ARRAY_PUSH_NOLEN_VOID));
  newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID",
                     newSVuv(VMG_COMPAT_ARRAY_UNSHIFT_NOLEN_VOID));
  newCONSTSUB(stash, "VMG_COMPAT_ARRAY_UNDEF_CLEAR",
@@ -1234,6 +1281,7 @@ BOOT:
                     newSVuv(VMG_COMPAT_SCALAR_LENGTH_NOLEN));
  newCONSTSUB(stash, "VMG_PERL_PATCHLEVEL", newSVuv(VMG_PERL_PATCHLEVEL));
  newCONSTSUB(stash, "VMG_THREADSAFE",      newSVuv(VMG_THREADSAFE));
+ newCONSTSUB(stash, "VMG_FORKSAFE",        newSVuv(VMG_FORKSAFE));
  newCONSTSUB(stash, "VMG_OP_INFO_NAME",    newSVuv(VMG_OP_INFO_NAME));
  newCONSTSUB(stash, "VMG_OP_INFO_OBJECT",  newSVuv(VMG_OP_INFO_OBJECT));
 }
@@ -1398,9 +1446,11 @@ OUTPUT:
 
 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
 
@@ -1418,7 +1468,7 @@ CODE:
   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));
@@ -1436,7 +1486,8 @@ PREINIT:
 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);