implement C<goto &func> and other fixes (via private mail)
[p5sagit/p5-mst-13.2.git] / scope.c
diff --git a/scope.c b/scope.c
index eb43648..020713f 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -204,6 +204,18 @@ save_svref(SV **sptr)
     return save_scalar_at(sptr);
 }
 
+/* Like save_svref(), but doesn't deal with magic.  Can be used to
+ * restore a global SV to its prior contents, freeing new value. */
+void
+save_generic_svref(SV **sptr)
+{
+    dTHR;
+    SSCHECK(3);
+    SSPUSHPTR(sptr);
+    SSPUSHPTR(SvREFCNT_inc(*sptr));
+    SSPUSHINT(SAVEt_GENERIC_SVREF);
+}
+
 void
 save_gp(GV *gv, I32 empty)
 {
@@ -578,6 +590,16 @@ leave_scope(I32 base)
            ptr = &GvSV(gv);
            SvREFCNT_dec(gv);
            goto restore_sv;
+        case SAVEt_GENERIC_SVREF:              /* generic sv */
+           value = (SV*)SSPOPPTR;
+           ptr = SSPOPPTR;
+           if (ptr) {
+               sv = *(SV**)ptr;
+               *(SV**)ptr = value;
+               SvREFCNT_dec(sv);
+           }
+           SvREFCNT_dec(value);
+           break;
         case SAVEt_SVREF:                      /* scalar reference */
            value = (SV*)SSPOPPTR;
            ptr = SSPOPPTR;
@@ -791,7 +813,7 @@ leave_scope(I32 base)
            if (ptr) {
                sv = *(SV**)ptr;
                if (sv && sv != &PL_sv_undef) {
-                   if (SvRMAGICAL(av) && mg_find((SV*)av, 'P'))
+                   if (SvTIED_mg((SV*)av, 'P'))
                        (void)SvREFCNT_inc(sv);
                    SvREFCNT_dec(av);
                    goto restore_sv;
@@ -809,7 +831,7 @@ leave_scope(I32 base)
                SV *oval = HeVAL((HE*)ptr);
                if (oval && oval != &PL_sv_undef) {
                    ptr = &HeVAL((HE*)ptr);
-                   if (SvRMAGICAL(hv) && mg_find((SV*)hv, 'P'))
+                   if (SvTIED_mg((SV*)hv, 'P'))
                        (void)SvREFCNT_inc(*(SV**)ptr);
                    SvREFCNT_dec(hv);
                    SvREFCNT_dec(sv);