]> git.vpit.fr Git - perl/modules/Variable-Magic.git/blobdiff - Magic.xs
Rename vmg_uvar_del() to vmg_mg_del() to reuse its logic
[perl/modules/Variable-Magic.git] / Magic.xs
index d87c651834fb44073924f65f940f042e31e50414..94d816fe00fef8a826352b47b93fc70415c6ef40 100644 (file)
--- a/Magic.xs
+++ b/Magic.xs
@@ -222,8 +222,8 @@ STATIC void vmg_mg_magical(SV *sv) {
 
 /* ... Safe version of call_sv() ........................................... */
 
-STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, SV *dsv) {
-#define vmg_call_sv(S, F, D) vmg_call_sv(aTHX_ (S), (F), (D))
+STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, int (*cleanup)(pTHX_ void *), void *ud) {
+#define vmg_call_sv(S, F, C, U) vmg_call_sv(aTHX_ (S), (F), (C), (U))
  I32 ret, cxix, in_eval = 0;
  PERL_CONTEXT saved_cx;
  SV *old_err = NULL;
@@ -269,23 +269,10 @@ STATIC I32 vmg_call_sv(pTHX_ SV *sv, I32 flags, SV *dsv) {
 #else
    ++PL_Ierror_count;
 #endif
-   } else if (!in_eval) {
-    if (dsv) {
-     /* We are about to croak() while dsv is being destroyed. Try to clean up
-      * things a bit. */
-     MAGIC *mg = SvMAGIC(dsv);
-     SvREFCNT_dec((SV *) mg->mg_ptr);
-     /* mg->mg_obj may not be refcounted if the data constructor returned the
-      * variable itself. */
-     if (mg->mg_flags & MGf_REFCOUNTED)
-      SvREFCNT_dec(mg->mg_obj);
-     SvMAGIC_set(dsv, mg->mg_moremagic);
-     Safefree(mg);
-     mg_magical(dsv);
-     SvREFCNT_dec(dsv);
-    }
+  } else if (!in_eval) {
+   if (!cleanup || cleanup(aTHX_ ud))
     croak(NULL);
-   }
+  }
  } else {
   if (old_err) {
    SvREFCNT_dec(ERRSV);
@@ -741,7 +728,7 @@ STATIC SV *vmg_data_new(pTHX_ SV *ctor, SV *sv, SV **args, I32 items) {
   PUSHs(args[i]);
  PUTBACK;
 
- vmg_call_sv(ctor, G_SCALAR, NULL);
+ vmg_call_sv(ctor, G_SCALAR, 0, NULL);
 
  SPAGAIN;
  nsv = POPs;
@@ -768,6 +755,7 @@ STATIC SV *vmg_data_get(pTHX_ SV *sv, const vmg_wizard *w) {
 /* ... Magic cast/dispell .................................................. */
 
 #if VMG_UVAR
+
 STATIC I32 vmg_svt_val(pTHX_ IV, SV *);
 
 typedef struct {
@@ -775,17 +763,32 @@ typedef struct {
  struct ufuncs old_uf;
 } vmg_uvar_ud;
 
-STATIC void vmg_uvar_del(SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) {
- if (prevmagic) {
+#endif /* VMG_UVAR */
+
+STATIC void vmg_mg_del(pTHX_ SV *sv, MAGIC *prevmagic, MAGIC *mg, MAGIC *moremagic) {
+#define vmg_mg_del(S, P, M, N) vmg_mg_del(aTHX_ (S), (P), (M), (N))
+ if (prevmagic)
   prevmagic->mg_moremagic = moremagic;
- } else {
+ else
   SvMAGIC_set(sv, moremagic);
- }
  mg->mg_moremagic = NULL;
- Safefree(mg->mg_ptr);
+
+ /* Destroy private data */
+#if VMG_UVAR
+ if (mg->mg_type == PERL_MAGIC_uvar) {
+  Safefree(mg->mg_ptr);
+ } else {
+#endif /* VMG_UVAR */
+  if (mg->mg_obj != sv)
+   SvREFCNT_dec(mg->mg_obj);
+  /* Unreference the wizard */
+  SvREFCNT_dec((SV *) mg->mg_ptr);
+#if VMG_UVAR
+ }
+#endif /* VMG_UVAR */
+
  Safefree(mg);
 }
-#endif /* VMG_UVAR */
 
 STATIC UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args, I32 items) {
 #define vmg_cast(S, W, WIZ, A, I) vmg_cast(aTHX_ (S), (W), (WIZ), (A), (I))
@@ -858,7 +861,7 @@ STATIC UV vmg_cast(pTHX_ SV *sv, const vmg_wizard *w, const SV *wiz, SV **args,
    } else {
     /* It's another uvar magic, backup it and replace it by ours. */
     ud.old_uf = *uf;
-    vmg_uvar_del(sv, prevmagic, mg, moremagic);
+    vmg_mg_del(sv, prevmagic, mg, moremagic);
    }
   }
 
@@ -911,19 +914,7 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
  if (!mg)
   return 0;
 
- if (prevmagic) {
-  prevmagic->mg_moremagic = moremagic;
- } else {
-  SvMAGIC_set(sv, moremagic);
- }
- mg->mg_moremagic = NULL;
-
- /* Destroy private data */
- if (mg->mg_obj != sv)
-  SvREFCNT_dec(mg->mg_obj);
- /* Unreference the wizard */
- SvREFCNT_dec((SV *) mg->mg_ptr);
- Safefree(mg);
+ vmg_mg_del(sv, prevmagic, mg, moremagic);
 
 #if VMG_UVAR
  if (uvars == 1 && SvTYPE(sv) >= SVt_PVHV) {
@@ -958,7 +949,7 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, const vmg_wizard *w) {
     mg->mg_len = sizeof(*uf);
    } else {
     /* Remove the uvar magic. */
-    vmg_uvar_del(sv, prevmagic, mg, moremagic);
+    vmg_mg_del(sv, prevmagic, mg, moremagic);
    }
   }
  }
@@ -1065,7 +1056,7 @@ STATIC int vmg_cb_call(pTHX_ SV *cb, unsigned int flags, SV *sv, ...) {
   XPUSHs(vmg_op_info(opinfo));
  PUTBACK;
 
- vmg_call_sv(cb, G_SCALAR, NULL);
+ vmg_call_sv(cb, G_SCALAR, 0, NULL);
 
  SPAGAIN;
  svr = POPs;
@@ -1157,7 +1148,7 @@ STATIC U32 vmg_svt_len(pTHX_ SV *sv, MAGIC *mg) {
   XPUSHs(vmg_op_info(opinfo));
  PUTBACK;
 
- vmg_call_sv(w->cb_len, G_SCALAR, NULL);
+ vmg_call_sv(w->cb_len, G_SCALAR, 0, NULL);
 
  SPAGAIN;
  svr = POPs;
@@ -1197,6 +1188,23 @@ STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) {
 
 /* ... free magic .......................................................... */
 
+STATIC int vmg_svt_free_cleanup(pTHX_ void *ud) {
+ SV    *sv = VOID2(SV *, ud);
+ MAGIC *mg;
+
+ /* We are about to croak() while sv is being destroyed. Try to clean up
+  * things a bit. */
+ mg = SvMAGIC(sv);
+ if (mg) {
+  vmg_mg_del(sv, NULL, mg, mg->mg_moremagic);
+  mg_magical(sv);
+ }
+ SvREFCNT_dec(sv);
+
+ /* After that, propagate the error upwards. */
+ return 1;
+}
+
 STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
  const vmg_wizard *w;
  int ret = 0;
@@ -1232,7 +1240,7 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
   XPUSHs(vmg_op_info(w->opinfo));
  PUTBACK;
 
- vmg_call_sv(w->cb_free, G_SCALAR, sv);
+ vmg_call_sv(w->cb_free, G_SCALAR, vmg_svt_free_cleanup, sv);
 
  SPAGAIN;
  svr = POPs;
@@ -1456,9 +1464,11 @@ PROTOTYPES: ENABLE
 BOOT:
 {
  HV *stash;
+ int c;
 
  MY_CXT_INIT;
- MY_CXT.b__op_stashes[0] = NULL;
+ for (c = OPc_NULL; c < OPc_MAX; ++c)
+  MY_CXT.b__op_stashes[c] = NULL;
 #if VMG_THREADSAFE
  MUTEX_INIT(&vmg_vtable_refcount_mutex);
  MUTEX_INIT(&vmg_op_name_init_mutex);