This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
combopatch
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index 6f92bb5..b04e24f 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -1,7 +1,7 @@
 /*    mg.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, 2005 by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 
 /*
 =head1 Magical Functions
+
+"Magic" is special data attached to SV structures in order to give them
+"magical" properties.  When any Perl code tries to read from, or assign to,
+an SV marked as magical, it calls the 'get' or 'set' function associated
+with that SV's magic. A get is called prior to reading an SV, in order to
+give it a chance to update its internal value (get on $. writes the line
+number of the last read filehandle into to the SV's IV slot), while
+set is called after an SV has been written to, in order to allow it to make
+use of its changed value (set on $/ copies the SV's new value to the
+PL_rs global variable).
+
+Magic is implemented as a linked list of MAGIC structures attached to the
+SV. Each MAGIC struct holds the type of the magic, a pointer to an array
+of functions that implement the get(), set(), length() etc functions,
+plus space for some flags and pointers. For example, a tied variable has
+a MAGIC structure that contains a pointer to the object associated with the
+tie.
+
 */
 
 #include "EXTERN.h"
 
 Signal_t Perl_csighandler(int sig);
 
-/* if you only have signal() and it resets on each signal, FAKE_PERSISTENT_SIGNAL_HANDLERS fixes */
-#if !defined(HAS_SIGACTION) && defined(VMS)
-#  define  FAKE_PERSISTENT_SIGNAL_HANDLERS
-#endif
-/* if we're doing kill() with sys$sigprc on VMS, FAKE_DEFAULT_SIGNAL_HANDLERS */
-#if defined(KILL_BY_SIGPRC)
-#  define  FAKE_DEFAULT_SIGNAL_HANDLERS
-#endif
+static void restore_magic(pTHX_ const void *p);
+static void unwind_handler_stack(pTHX_ const void *p);
 
-static void restore_magic(pTHX_ void *p);
-static void unwind_handler_stack(pTHX_ void *p);
+#ifdef __Lynx__
+/* Missing protos on LynxOS */
+void setruid(uid_t id);
+void seteuid(uid_t id);
+void setrgid(uid_t id);
+void setegid(uid_t id);
+#endif
 
 /*
  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
@@ -93,9 +110,9 @@ Turns on the magical status of an SV.  See C<sv_magic>.
 void
 Perl_mg_magical(pTHX_ SV *sv)
 {
-    MAGIC* mg;
+    const MAGIC* mg;
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+       const MGVTBL* const vtbl = mg->mg_virtual;
        if (vtbl) {
            if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
                SvGMAGICAL_on(sv);
@@ -118,9 +135,21 @@ Do magic after a value is retrieved from the SV.  See C<sv_magic>.
 int
 Perl_mg_get(pTHX_ SV *sv)
 {
-    int new = 0;
+    const I32 mgs_ix = SSNEW(sizeof(MGS));
+    const bool was_temp = (bool)SvTEMP(sv);
+    int have_new = 0;
     MAGIC *newmg, *head, *cur, *mg;
-    I32 mgs_ix = SSNEW(sizeof(MGS));
+    /* guard against sv having being freed midway by holding a private
+       reference. */
+
+    /* sv_2mortal has this side effect of turning on the TEMP flag, which can
+       cause the SV's buffer to get stolen (and maybe other stuff).
+       So restore it.
+    */
+    sv_2mortal(SvREFCNT_inc(sv));
+    if (!was_temp) {
+       SvTEMP_off(sv);
+    }
 
     save_magic(mgs_ix, sv);
 
@@ -130,15 +159,15 @@ Perl_mg_get(pTHX_ SV *sv)
 
     newmg = cur = head = mg = SvMAGIC(sv);
     while (mg) {
-       MGVTBL *vtbl = mg->mg_virtual;
+       const MGVTBL * const vtbl = mg->mg_virtual;
 
        if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
            CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
 
-           /* guard against sv having been freed */
-           if (SvTYPE(sv) == SVTYPEMASK) {
-               Perl_croak(aTHX_ "Tied variable freed while still in use");
-           }
+           /* guard against magic having been deleted - eg FETCH calling
+            * untie */
+           if (!SvMAGIC(sv))
+               break;
 
            /* Don't restore the flags for this entry if it was deleted. */
            if (mg->mg_flags & MGf_GSKIP)
@@ -147,25 +176,31 @@ Perl_mg_get(pTHX_ SV *sv)
 
        mg = mg->mg_moremagic;
 
-       if (new) {
+       if (have_new) {
            /* Have we finished with the new entries we saw? Start again
               where we left off (unless there are more new entries). */
            if (mg == head) {
-               new  = 0;
+               have_new = 0;
                mg   = cur;
                head = newmg;
            }
        }
 
        /* Were any new entries added? */
-       if (!new && (newmg = SvMAGIC(sv)) != head) {
-           new = 1;
+       if (!have_new && (newmg = SvMAGIC(sv)) != head) {
+           have_new = 1;
            cur = mg;
            mg  = newmg;
        }
     }
 
     restore_magic(aTHX_ INT2PTR(void *, (IV)mgs_ix));
+
+    if (SvREFCNT(sv) == 1) {
+       /* We hold the last reference to this SV, which implies that the
+          SV was deleted as a side effect of the routines we called.  */
+       SvOK_off(sv);
+    }
     return 0;
 }
 
@@ -180,15 +215,14 @@ Do magic after a value is assigned to the SV.  See C<sv_magic>.
 int
 Perl_mg_set(pTHX_ SV *sv)
 {
-    I32 mgs_ix;
+    const I32 mgs_ix = SSNEW(sizeof(MGS));
     MAGIC* mg;
     MAGIC* nextmg;
 
-    mgs_ix = SSNEW(sizeof(MGS));
     save_magic(mgs_ix, sv);
 
     for (mg = SvMAGIC(sv); mg; mg = nextmg) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL* vtbl = mg->mg_virtual;
        nextmg = mg->mg_moremagic;      /* it may delete itself */
        if (mg->mg_flags & MGf_GSKIP) {
            mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
@@ -217,11 +251,9 @@ Perl_mg_length(pTHX_ SV *sv)
     STRLEN len;
 
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL * const vtbl = mg->mg_virtual;
        if (vtbl && vtbl->svt_len) {
-            I32 mgs_ix;
-
-           mgs_ix = SSNEW(sizeof(MGS));
+            const I32 mgs_ix = SSNEW(sizeof(MGS));
            save_magic(mgs_ix, sv);
            /* omit MGf_GSKIP -- not changed here */
            len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
@@ -230,8 +262,7 @@ Perl_mg_length(pTHX_ SV *sv)
        }
     }
 
-    if (DO_UTF8(sv))
-    {
+    if (DO_UTF8(sv)) {
         U8 *s = (U8*)SvPV(sv, len);
         len = Perl_utf8_length(aTHX_ s, s + len);
     }
@@ -244,14 +275,12 @@ I32
 Perl_mg_size(pTHX_ SV *sv)
 {
     MAGIC* mg;
-    I32 len;
 
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL* const vtbl = mg->mg_virtual;
        if (vtbl && vtbl->svt_len) {
-            I32 mgs_ix;
-
-           mgs_ix = SSNEW(sizeof(MGS));
+            const I32 mgs_ix = SSNEW(sizeof(MGS));
+            I32 len;
            save_magic(mgs_ix, sv);
            /* omit MGf_GSKIP -- not changed here */
            len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
@@ -262,8 +291,7 @@ Perl_mg_size(pTHX_ SV *sv)
 
     switch(SvTYPE(sv)) {
        case SVt_PVAV:
-           len = AvFILLp((AV *) sv); /* Fallback to non-tied array */
-           return len;
+           return AvFILLp((AV *) sv); /* Fallback to non-tied array */
        case SVt_PVHV:
            /* FIXME */
        default:
@@ -284,14 +312,13 @@ Clear something magical that the SV represents.  See C<sv_magic>.
 int
 Perl_mg_clear(pTHX_ SV *sv)
 {
-    I32 mgs_ix;
+    const I32 mgs_ix = SSNEW(sizeof(MGS));
     MAGIC* mg;
 
-    mgs_ix = SSNEW(sizeof(MGS));
     save_magic(mgs_ix, sv);
 
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL* const vtbl = mg->mg_virtual;
        /* omit GSKIP -- never set here */
 
        if (vtbl && vtbl->svt_clear)
@@ -311,14 +338,14 @@ Finds the magic pointer for type matching the SV.  See C<sv_magic>.
 */
 
 MAGIC*
-Perl_mg_find(pTHX_ SV *sv, int type)
+Perl_mg_find(pTHX_ const SV *sv, int type)
 {
-    MAGIC* mg;
-    if (!sv)
-        return 0;
-    for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       if (mg->mg_type == type)
-           return mg;
+    if (sv) {
+        MAGIC *mg;
+        for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+            if (mg->mg_type == type)
+                return mg;
+        }
     }
     return 0;
 }
@@ -337,7 +364,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
     int count = 0;
     MAGIC* mg;
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL* const vtbl = mg->mg_virtual;
        if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){
            count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen);
        }
@@ -367,12 +394,12 @@ Perl_mg_free(pTHX_ SV *sv)
     MAGIC* mg;
     MAGIC* moremagic;
     for (mg = SvMAGIC(sv); mg; mg = moremagic) {
-       MGVTBL* vtbl = mg->mg_virtual;
+        const MGVTBL* const vtbl = mg->mg_virtual;
        moremagic = mg->mg_moremagic;
        if (vtbl && vtbl->svt_free)
            CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
        if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
-           if (mg->mg_len > 0)
+           if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8)
                Safefree(mg->mg_ptr);
            else if (mg->mg_len == HEf_SVKEY)
                SvREFCNT_dec((SV*)mg->mg_ptr);
@@ -381,19 +408,17 @@ Perl_mg_free(pTHX_ SV *sv)
            SvREFCNT_dec(mg->mg_obj);
        Safefree(mg);
     }
-    SvMAGIC(sv) = 0;
+    SvMAGIC_set(sv, NULL);
     return 0;
 }
 
-
-#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
 #include <signal.h>
-#endif
 
 U32
 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
 {
-    register REGEXP *rx;
+    register const REGEXP *rx;
+    (void)sv;
 
     if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
        if (mg->mg_obj)         /* @+ */
@@ -408,20 +433,19 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
 {
-    register I32 paren;
-    register I32 s;
-    register I32 i;
     register REGEXP *rx;
-    I32 t;
 
     if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
-       paren = mg->mg_len;
+        register const I32 paren = mg->mg_len;
+        register I32 s;
+        register I32 t;
        if (paren < 0)
            return 0;
        if (paren <= (I32)rx->nparens &&
            (s = rx->startp[paren]) != -1 &&
            (t = rx->endp[paren]) != -1)
            {
+                register I32 i;
                if (mg->mg_obj)         /* @+ */
                    i = t;
                else                    /* @- */
@@ -442,9 +466,14 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)sv; (void)mg;
     Perl_croak(aTHX_ PL_no_modify);
     /* NOT REACHED */
+#ifndef HASATTRIBUTE
+    /* No __attribute__, so the compiler doesn't know that croak never returns
+     */
     return 0;
+#endif
 }
 
 U32
@@ -452,7 +481,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
 {
     register I32 paren;
     register I32 i;
-    register REGEXP *rx;
+    register const REGEXP *rx;
     I32 s1, t1;
 
     switch (*mg->mg_ptr) {
@@ -482,12 +511,12 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
            }
            else {
                if (ckWARN(WARN_UNINITIALIZED))
-                   report_uninit();
+                   report_uninit(sv);
            }
        }
        else {
            if (ckWARN(WARN_UNINITIALIZED))
-               report_uninit();
+               report_uninit(sv);
        }
        return 0;
     case '+':
@@ -542,8 +571,9 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 {
+    dVAR;
     register I32 paren;
-    register char *s;
+    register char *s = NULL;
     register I32 i;
     register REGEXP *rx;
 
@@ -557,9 +587,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 
     case '\004':               /* ^D */
        sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK));
-#if defined(YYDEBUG) && defined(DEBUGGING)
-       PL_yydebug = DEBUG_p_TEST;
-#endif
        break;
     case '\005':  /* ^E */
         if (*(mg->mg_ptr+1) == '\0') {
@@ -611,8 +638,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                  SetLastError(dwErr);
             }
 #else
-            sv_setnv(sv, (NV)errno);
-            sv_setpv(sv, errno ? Strerror(errno) : "");
+            {
+                int saveerrno = errno;
+                sv_setnv(sv, (NV)errno);
+                sv_setpv(sv, errno ? Strerror(errno) : "");
+                errno = saveerrno;
+            }
 #endif
 #endif
 #endif
@@ -635,8 +666,10 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
            sv_setsv(sv, &PL_sv_undef);
        break;
     case '\017':               /* ^O & ^OPEN */
-       if (*(mg->mg_ptr+1) == '\0')
+       if (*(mg->mg_ptr+1) == '\0') {
            sv_setpv(sv, PL_osname);
+           SvTAINTED_off(sv);
+       }
        else if (strEQ(mg->mg_ptr, "\017PEN")) {
            if (!PL_compiling.cop_io)
                sv_setsv(sv, &PL_sv_undef);
@@ -651,7 +684,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '\023':               /* ^S */
         if (*(mg->mg_ptr+1) == '\0') {
            if (PL_lex_state != LEX_NOTPARSING)
-               (void)SvOK_off(sv);
+               SvOK_off(sv);
            else if (PL_in_eval)
                sv_setiv(sv, PL_in_eval & ~(EVAL_INREQUIRE));
            else
@@ -671,9 +704,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                    ? (PL_taint_warn || PL_unsafe ? -1 : 1)
                    : 0);
         break;
-    case '\025':               /* $^UNICODE */
+    case '\025':               /* $^UNICODE, $^UTF8LOCALE */
         if (strEQ(mg->mg_ptr, "\025NICODE"))
            sv_setuv(sv, (UV) PL_unicode);
+        else if (strEQ(mg->mg_ptr, "\025TF8LOCALE"))
+           sv_setuv(sv, (UV) PL_utf8locale);
         break;
     case '\027':               /* ^W  & $^WARNING_BITS */
        if (*(mg->mg_ptr+1) == '\0')
@@ -734,11 +769,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                            MAGIC* mg = SvMAGIC(sv);
                            MAGIC* mgt;
                            PL_tainted = 1;
-                           SvMAGIC(sv) = mg->mg_moremagic;
+                           SvMAGIC_set(sv, mg->mg_moremagic);
                            SvTAINT(sv);
                            if ((mgt = SvMAGIC(sv))) {
                                mg->mg_moremagic = mgt;
-                               SvMAGIC(sv) = mg;
+                               SvMAGIC_set(sv, mg);
                            }
                        } else
                            SvTAINTED_off(sv);
@@ -801,7 +836,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        }
        break;
     case '^':
-       s = IoTOP_NAME(GvIOp(PL_defoutgv));
+       if (GvIOp(PL_defoutgv))
+           s = IoTOP_NAME(GvIOp(PL_defoutgv));
        if (s)
            sv_setpv(sv,s);
        else {
@@ -810,20 +846,24 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        }
        break;
     case '~':
-       s = IoFMT_NAME(GvIOp(PL_defoutgv));
+       if (GvIOp(PL_defoutgv))
+           s = IoFMT_NAME(GvIOp(PL_defoutgv));
        if (!s)
            s = GvENAME(PL_defoutgv);
        sv_setpv(sv,s);
        break;
 #ifndef lint
     case '=':
-       sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
+       if (GvIOp(PL_defoutgv))
+           sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv)));
        break;
     case '-':
-       sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
+       if (GvIOp(PL_defoutgv))
+           sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv)));
        break;
     case '%':
-       sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
+       if (GvIOp(PL_defoutgv))
+           sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv)));
        break;
 #endif
     case ':':
@@ -834,7 +874,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase));
        break;
     case '|':
-       sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
+       if (GvIOp(PL_defoutgv))
+           sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 );
        break;
     case ',':
        break;
@@ -913,6 +954,7 @@ Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
 {
+    dVAR;
     register char *s;
     char *ptr;
     STRLEN len, klen;
@@ -990,6 +1032,7 @@ int
 Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg)
 {
     STRLEN n_a;
+    (void)sv;
     my_setenv(MgPV(mg,n_a),Nullch);
     return 0;
 }
@@ -997,7 +1040,7 @@ Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg)
 {
-#if defined(VMS)
+#if defined(VMS) || defined(EPOC) || defined(SYMBIAN)
     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
 #else
     if (PL_localizing) {
@@ -1018,8 +1061,9 @@ Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 {
+    dVAR;
 #ifndef PERL_MICRO
-#if defined(VMS) || defined(EPOC)
+#if defined(VMS) || defined(EPOC) || defined(SYMBIAN)
     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
 #else
 #  if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
@@ -1032,6 +1076,7 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 #      endif
     {
 #      ifndef PERL_USE_SAFE_PUTENV
+    if (!PL_use_safe_putenv) {
     I32 i;
 
     if (environ == PL_origenviron)
@@ -1039,6 +1084,7 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
     else
        for (i = 0; environ[i]; i++)
            safesysfree(environ[i]);
+    }
 #      endif /* PERL_USE_SAFE_PUTENV */
 
     environ[0] = Nullch;
@@ -1047,19 +1093,11 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 #   endif /* PERL_IMPLICIT_SYS || WIN32 */
 #endif /* VMS || EPOC */
 #endif /* !PERL_MICRO */
+    (void)sv;
+    (void)mg;
     return 0;
 }
 
-#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS)||defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
-static int sig_handlers_initted = 0;
-#endif
-#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-static int sig_ignoring[SIG_SIZE];      /* which signals we are ignoring */
-#endif
-#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-static int sig_defaulting[SIG_SIZE];
-#endif
-
 #ifndef PERL_MICRO
 #ifdef HAS_SIGPROCMASK
 static void
@@ -1083,10 +1121,10 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
            Sighandler_t sigstate;
            sigstate = rsignal_state(i);
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-           if (sig_handlers_initted && sig_ignoring[i]) sigstate = SIG_IGN;
+           if (PL_sig_handlers_initted && PL_sig_ignoring[i]) sigstate = SIG_IGN;
 #endif
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-           if (sig_handlers_initted && sig_defaulting[i]) sigstate = SIG_DFL;
+           if (PL_sig_handlers_initted && PL_sig_defaulting[i]) sigstate = SIG_DFL;
 #endif
            /* cache state so we don't fetch it again */
            if(sigstate == SIG_IGN)
@@ -1105,20 +1143,20 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
     /* XXX Some of this code was copied from Perl_magic_setsig. A little
      * refactoring might be in order.
      */
-    register char *s;
+    dVAR;
     STRLEN n_a;
-    SV* to_dec;
-    s = MgPV(mg,n_a);
+    register const char *s = MgPV(mg,n_a);
+    (void)sv;
     if (*s == '_') {
-       SV** svp;
+       SV** svp = 0;
        if (strEQ(s,"__DIE__"))
            svp = &PL_diehook;
        else if (strEQ(s,"__WARN__"))
            svp = &PL_warnhook;
        else
            Perl_croak(aTHX_ "No such hook: %s", s);
-       if (*svp) {
-           to_dec = *svp;
+       if (svp && *svp) {
+            SV *to_dec = *svp;
            *svp = 0;
            SvREFCNT_dec(to_dec);
        }
@@ -1142,10 +1180,10 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
 #endif
            PERL_ASYNC_CHECK();
 #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
-           if (!sig_handlers_initted) Perl_csighandler_init();
+           if (!PL_sig_handlers_initted) Perl_csighandler_init();
 #endif
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-           sig_defaulting[i] = 1;
+           PL_sig_defaulting[i] = 1;
            (void)rsignal(i, PL_csighandlerp);
 #else
            (void)rsignal(i, SIG_DFL);
@@ -1155,7 +1193,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
                PL_psig_name[i]=0;
            }
            if(PL_psig_ptr[i]) {
-               to_dec=PL_psig_ptr[i];
+                SV *to_dec=PL_psig_ptr[i];
                PL_psig_ptr[i]=0;
                LEAVE;
                SvREFCNT_dec(to_dec);
@@ -1167,8 +1205,8 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
     return 0;
 }
 
-void
-Perl_raise_signal(pTHX_ int sig)
+static void
+S_raise_signal(pTHX_ int sig)
 {
     /* Set a flag to say this signal is pending */
     PL_psig_pend[sig]++;
@@ -1186,10 +1224,10 @@ Perl_csighandler(int sig)
 #endif
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
     (void) rsignal(sig, PL_csighandlerp);
-    if (sig_ignoring[sig]) return;
+    if (PL_sig_ignoring[sig]) return;
 #endif
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-    if (sig_defaulting[sig])
+    if (PL_sig_defaulting[sig])
 #ifdef KILL_BY_SIGPRC
             exit((Perl_sig_to_vmscondition(sig)&STS$M_COND_ID)|STS$K_SEVERE|STS$M_INHIB_MSG);
 #else
@@ -1201,7 +1239,7 @@ Perl_csighandler(int sig)
         * with risk we may be in malloc() etc. */
        (*PL_sighandlerp)(sig);
    else
-       Perl_raise_signal(aTHX_ sig);
+       S_raise_signal(aTHX_ sig);
 }
 
 #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
@@ -1209,19 +1247,19 @@ void
 Perl_csighandler_init(void)
 {
     int sig;
-    if (sig_handlers_initted) return;
+    if (PL_sig_handlers_initted) return;
 
     for (sig = 1; sig < SIG_SIZE; sig++) {
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
         dTHX;
-        sig_defaulting[sig] = 1;
+        PL_sig_defaulting[sig] = 1;
         (void) rsignal(sig, PL_csighandlerp);
 #endif
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-        sig_ignoring[sig] = 0;
+        PL_sig_ignoring[sig] = 0;
 #endif
     }
-    sig_handlers_initted = 1;
+    PL_sig_handlers_initted = 1;
 }
 #endif
 
@@ -1244,7 +1282,7 @@ Perl_despatch_signals(pTHX)
 int
 Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 {
-    register char *s;
+    dVAR;
     I32 i;
     SV** svp = 0;
     /* Need to be careful with SvREFCNT_dec(), because that can have side
@@ -1258,7 +1296,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     SV* save_sv;
 #endif
 
-    s = MgPV(mg,len);
+    register const char *s = MgPV(mg,len);
     if (*s == '_') {
        if (strEQ(s,"__DIE__"))
            svp = &PL_diehook;
@@ -1291,13 +1329,13 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 #endif
        PERL_ASYNC_CHECK();
 #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
-       if (!sig_handlers_initted) Perl_csighandler_init();
+       if (!PL_sig_handlers_initted) Perl_csighandler_init();
 #endif
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-       sig_ignoring[i] = 0;
+       PL_sig_ignoring[i] = 0;
 #endif
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-       sig_defaulting[i] = 0;
+       PL_sig_defaulting[i] = 0;
 #endif
        SvREFCNT_dec(PL_psig_name[i]);
        to_dec = PL_psig_ptr[i];
@@ -1323,7 +1361,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     if (strEQ(s,"IGNORE")) {
        if (i) {
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-           sig_ignoring[i] = 1;
+           PL_sig_ignoring[i] = 1;
            (void)rsignal(i, PL_csighandlerp);
 #else
            (void)rsignal(i, SIG_IGN);
@@ -1334,7 +1372,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
        if (i)
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
          {
-           sig_defaulting[i] = 1;
+           PL_sig_defaulting[i] = 1;
            (void)rsignal(i, PL_csighandlerp);
          }
 #else
@@ -1367,6 +1405,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)sv;
+    (void)mg;
     PL_sub_generation++;
     return 0;
 }
@@ -1374,6 +1414,8 @@ Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)sv;
+    (void)mg;
     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
     PL_amagic_generation++;
 
@@ -1383,8 +1425,9 @@ Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
 {
-    HV *hv = (HV*)LvTARG(sv);
+    HV * const hv = (HV*)LvTARG(sv);
     I32 i = 0;
+    (void)mg;
 
     if (hv) {
          (void) hv_iterinit(hv);
@@ -1403,6 +1446,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     if (LvTARG(sv)) {
        hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
     }
@@ -1411,7 +1455,7 @@ Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
 
 /* caller is responsible for stack switching/cleanup */
 STATIC int
-S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
+S_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, I32 flags, int n, SV *val)
 {
     dSP;
 
@@ -1438,9 +1482,9 @@ S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
 }
 
 STATIC int
-S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth)
+S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth)
 {
-    dSP;
+    dVAR; dSP;
 
     ENTER;
     SAVETMPS;
@@ -1459,16 +1503,16 @@ S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth)
 int
 Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg)
 {
-    magic_methpack(sv,mg,"FETCH");
     if (mg->mg_ptr)
        mg->mg_flags |= MGf_GSKIP;
+    magic_methpack(sv,mg,"FETCH");
     return 0;
 }
 
 int
 Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
 {
-    dSP;
+    dVAR; dSP;
     ENTER;
     PUSHSTACKi(PERLSI_MAGIC);
     magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
@@ -1487,7 +1531,7 @@ Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg)
 U32
 Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
 {
-    dSP;
+    dVAR; dSP;
     U32 retval = 0;
 
     ENTER;
@@ -1506,7 +1550,7 @@ Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg)
 {
-    dSP;
+    dVAR; dSP;
 
     ENTER;
     PUSHSTACKi(PERLSI_MAGIC);
@@ -1516,14 +1560,15 @@ Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg)
     call_method("CLEAR", G_SCALAR|G_DISCARD);
     POPSTACK;
     LEAVE;
+
     return 0;
 }
 
 int
 Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
 {
-    dSP;
-    const char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
+    dVAR; dSP;
+    const char * const meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
 
     ENTER;
     SAVETMPS;
@@ -1550,6 +1595,41 @@ Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg)
     return magic_methpack(sv,mg,"EXISTS");
 }
 
+SV *
+Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg)
+{
+    dVAR; dSP;
+    SV *retval = &PL_sv_undef;
+    SV *tied = SvTIED_obj((SV*)hv, mg);
+    HV *pkg = SvSTASH((SV*)SvRV(tied));
+   
+    if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) {
+        SV *key;
+        if (HvEITER(hv))
+            /* we are in an iteration so the hash cannot be empty */
+            return &PL_sv_yes;
+        /* no xhv_eiter so now use FIRSTKEY */
+        key = sv_newmortal();
+        magic_nextpack((SV*)hv, mg, key);
+        HvEITER(hv) = NULL;     /* need to reset iterator */
+        return SvOK(key) ? &PL_sv_yes : &PL_sv_no;
+    }
+   
+    /* there is a SCALAR method that we can call */
+    ENTER;
+    PUSHSTACKi(PERLSI_MAGIC);
+    PUSHMARK(SP);
+    EXTEND(SP, 1);
+    PUSHs(tied);
+    PUTBACK;
+
+    if (call_method("SCALAR", G_SCALAR))
+        retval = *PL_stack_sp--; 
+    POPSTACK;
+    LEAVE;
+    return retval;
+}
+
 int
 Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -1602,7 +1682,7 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
            return 0;
        }
     }
-    (void)SvOK_off(sv);
+    SvOK_off(sv);
     return 0;
 }
 
@@ -1661,6 +1741,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     if (SvFAKE(sv)) {                  /* FAKE globs can get coerced */
        SvFAKE_off(sv);
        gv_efullname3(sv,((GV*)sv), "*");
@@ -1674,16 +1755,12 @@ Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg)
 {
-    register char *s;
     GV* gv;
-    STRLEN n_a;
-
+    (void)mg;
     if (!SvOK(sv))
        return 0;
-    s = SvPV(sv, n_a);
-    if (*s == '*' && s[1])
-       s++;
-    gv = gv_fetchpv(s,TRUE, SVt_PVGV);
+    gv = gv_fetchsv(sv,TRUE, SVt_PVGV);
     if (sv == (SV*)gv)
        return 0;
     if (GvGP(sv))
@@ -1696,10 +1773,11 @@ int
 Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
 {
     STRLEN len;
-    SV *lsv = LvTARG(sv);
-    char *tmps = SvPV(lsv,len);
+    SV * const lsv = LvTARG(sv);
+    const char * const tmps = SvPV(lsv,len);
     I32 offs = LvTARGOFF(sv);
     I32 rem = LvTARGLEN(sv);
+    (void)mg;
 
     if (SvUTF8(lsv))
        sv_pos_u2b(lsv, &offs, &rem);
@@ -1718,24 +1796,30 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
 {
     STRLEN len;
     char *tmps = SvPV(sv, len);
-    SV *lsv = LvTARG(sv);
+    SV * const lsv = LvTARG(sv);
     I32 lvoff = LvTARGOFF(sv);
     I32 lvlen = LvTARGLEN(sv);
+    (void)mg;
 
     if (DO_UTF8(sv)) {
        sv_utf8_upgrade(lsv);
        sv_pos_u2b(lsv, &lvoff, &lvlen);
        sv_insert(lsv, lvoff, lvlen, tmps, len);
+       LvTARGLEN(sv) = sv_len_utf8(sv);
        SvUTF8_on(lsv);
     }
     else if (lsv && SvUTF8(lsv)) {
        sv_pos_u2b(lsv, &lvoff, &lvlen);
+       LvTARGLEN(sv) = len;
        tmps = (char*)bytes_to_utf8((U8*)tmps, &len);
        sv_insert(lsv, lvoff, lvlen, tmps, len);
        Safefree(tmps);
     }
-    else
-        sv_insert(lsv, lvoff, lvlen, tmps, len);
+    else {
+       sv_insert(lsv, lvoff, lvlen, tmps, len);
+       LvTARGLEN(sv) = len;
+    }
+
 
     return 0;
 }
@@ -1751,6 +1835,7 @@ Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)sv;
     if (PL_localizing) {
        if (PL_localizing == 1)
            mg->mg_len <<= 1;
@@ -1767,10 +1852,11 @@ Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
 {
-    SV *lsv = LvTARG(sv);
+    SV * const lsv = LvTARG(sv);
+    (void)mg;
 
     if (!lsv) {
-       (void)SvOK_off(sv);
+       SvOK_off(sv);
        return 0;
     }
 
@@ -1781,6 +1867,7 @@ Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     do_vecset(sv);     /* XXX slurp this routine */
     return 0;
 }
@@ -1820,6 +1907,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     if (LvTARGLEN(sv))
        vivify_defelem(sv);
     if (LvTARG(sv)) {
@@ -1871,15 +1959,17 @@ Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
     AV *av = (AV*)mg->mg_obj;
     SV **svp = AvARRAY(av);
     I32 i = AvFILLp(av);
+    (void)sv;
+
     while (i >= 0) {
-       if (svp[i] && svp[i] != &PL_sv_undef) {
+       if (svp[i]) {
            if (!SvWEAKREF(svp[i]))
                Perl_croak(aTHX_ "panic: magic_killbackrefs");
            /* XXX Should we check that it hasn't changed? */
-           SvRV(svp[i]) = 0;
-           (void)SvOK_off(svp[i]);
+           SvRV_set(svp[i], 0);
+           SvOK_off(svp[i]);
            SvWEAKREF_off(svp[i]);
-           svp[i] = &PL_sv_undef;
+           svp[i] = Nullsv;
        }
        i--;
     }
@@ -1898,6 +1988,7 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     sv_unmagic(sv, PERL_MAGIC_bm);
     SvVALID_off(sv);
     return 0;
@@ -1906,6 +1997,7 @@ Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     sv_unmagic(sv, PERL_MAGIC_fm);
     SvCOMPILED_off(sv);
     return 0;
@@ -1914,7 +2006,7 @@ Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
 {
-    struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
+    const struct ufuncs * const uf = (struct ufuncs *)mg->mg_ptr;
 
     if (uf && uf->uf_set)
        (*uf->uf_set)(aTHX_ uf->uf_index, sv);
@@ -1924,6 +2016,7 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)mg;
     sv_unmagic(sv, PERL_MAGIC_qr);
     return 0;
 }
@@ -1933,6 +2026,7 @@ Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg)
 {
     regexp *re = (regexp *)mg->mg_obj;
     ReREFCNT_dec(re);
+    (void)sv;
     return 0;
 }
 
@@ -1944,6 +2038,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
      * RenE<eacute> Descartes said "I think not."
      * and vanished with a faint plop.
      */
+    (void)sv;
     if (mg->mg_ptr) {
        Safefree(mg->mg_ptr);
        mg->mg_ptr = NULL;
@@ -1957,6 +2052,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg)
 {
+    (void)sv;
     Safefree(mg->mg_ptr);      /* The mg_ptr holds the pos cache. */
     mg->mg_ptr = 0;
     mg->mg_len = -1;           /* The mg_len holds the len cache. */
@@ -1966,7 +2062,7 @@ Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 {
-    register char *s;
+    register const char *s;
     I32 i;
     STRLEN len;
     switch (*mg->mg_ptr) {
@@ -1980,7 +2076,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
     case '\004':       /* ^D */
 #ifdef DEBUGGING
        s = SvPV_nolen(sv);
-       PL_debug = get_debug_opts(&s) | DEBUG_TOP_FLAG;
+       PL_debug = get_debug_opts(&s, 0) | DEBUG_TOP_FLAG;
        DEBUG_x(dump_all());
 #else
        PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
@@ -2028,18 +2124,20 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        if (PL_inplace)
            Safefree(PL_inplace);
        if (SvOK(sv))
-           PL_inplace = savepv(SvPV(sv,len));
+           PL_inplace = savesvpv(sv);
        else
            PL_inplace = Nullch;
        break;
     case '\017':       /* ^O */
        if (*(mg->mg_ptr+1) == '\0') {
-           if (PL_osname)
+           if (PL_osname) {
                Safefree(PL_osname);
-           if (SvOK(sv))
-               PL_osname = savepv(SvPV(sv,len));
-           else
                PL_osname = Nullch;
+           }
+           if (SvOK(sv)) {
+               TAINT_PROPER("assigning to $^O");
+               PL_osname = savesvpv(sv);
+           }
        }
        else if (strEQ(mg->mg_ptr, "\017PEN")) {
            if (!PL_compiling.cop_io)
@@ -2079,7 +2177,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                    STRLEN len, i;
                    int accumulate = 0 ;
                    int any_fatals = 0 ;
-                   char * ptr = (char*)SvPV(sv, len) ;
+                   const char * const ptr = (char*)SvPV(sv, len) ;
                    for (i = 0 ; i < len ; ++i) {
                        accumulate |= ptr[i] ;
                        any_fatals |= (ptr[i] & 0xAA) ;
@@ -2113,13 +2211,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        break;
     case '^':
        Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
-       IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
-       IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
+       s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
+       IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO);
        break;
     case '~':
        Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
-       IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len));
-       IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
+       s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
+       IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO);
        break;
     case '=':
        IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
@@ -2176,7 +2274,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
     case '#':
        if (PL_ofmt)
            Safefree(PL_ofmt);
-       PL_ofmt = savepv(SvPV(sv,len));
+       PL_ofmt = savesvpv(sv);
        break;
     case '[':
        PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
@@ -2222,9 +2320,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #ifdef HAS_SETRESUID
       (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
 #else
-       if (PL_uid == PL_euid)          /* special case $< = $> */
+       if (PL_uid == PL_euid) {                /* special case $< = $> */
+#ifdef PERL_DARWIN
+           /* workaround for Darwin's setuid peculiarity, cf [perl #24122] */
+           if (PL_uid != 0 && PerlProc_getuid() == 0)
+               (void)PerlProc_setuid(0);
+#endif
            (void)PerlProc_setuid(PL_uid);
-       else {
+       else {
            PL_uid = PerlProc_getuid();
            Perl_croak(aTHX_ "setruid() not implemented");
        }
@@ -2291,7 +2394,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
     case ')':
 #ifdef HAS_SETGROUPS
        {
-           char *p = SvPV(sv, len);
+           const char *p = SvPV(sv, len);
            Groups_t gary[NGROUPS];
 
            while (isSPACE(*p))
@@ -2371,16 +2474,16 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        {
             union pstun un;
             s = SvPV(sv, len);
-            un.pst_command = s;
+            un.pst_command = (char *)s;
             pstat(PSTAT_SETCMD, un, len, 0, 0);
        }
 #endif
        /* PL_origalen is set in perl_parse(). */
        s = SvPV_force(sv,len);
-       if (len >= (STRLEN)PL_origalen) {
-           /* Longer than original, will be truncated. */
-           Copy(s, PL_origargv[0], PL_origalen, char);
-           PL_origargv[0][PL_origalen - 1] = 0;
+       if (len >= (STRLEN)PL_origalen-1) {
+           /* Longer than original, will be truncated. We assume that
+             * PL_origalen bytes are available. */
+           Copy(s, PL_origargv[0], PL_origalen-1, char);
        }
        else {
            /* Shorter than original, will be padded. */
@@ -2393,9 +2496,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                    * --jhi */
                   (int)' ',
                   PL_origalen - len - 1);
-           for (i = 1; i < PL_origargc; i++)
-                PL_origargv[i] = 0;
        }
+       PL_origargv[0][PL_origalen-1] = 0;
+       for (i = 1; i < PL_origargc; i++)
+           PL_origargv[i] = 0;
        UNLOCK_DOLLARZERO_MUTEX;
        break;
 #endif
@@ -2404,13 +2508,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 }
 
 I32
-Perl_whichsig(pTHX_ char *sig)
+Perl_whichsig(pTHX_ const char *sig)
 {
-    register char **sigv;
+    register char* const* sigv;
 
-    for (sigv = PL_sig_name; *sigv; sigv++)
+    for (sigv = (char* const*)PL_sig_name; *sigv; sigv++)
        if (strEQ(sig,*sigv))
-           return PL_sig_num[sigv - PL_sig_name];
+           return PL_sig_num[sigv - (char* const*)PL_sig_name];
 #ifdef SIGCLD
     if (strEQ(sig,"CHLD"))
        return SIGCLD;
@@ -2422,10 +2526,6 @@ Perl_whichsig(pTHX_ char *sig)
     return -1;
 }
 
-#if !defined(PERL_IMPLICIT_CONTEXT)
-static SV* sig_sv;
-#endif
-
 Signal_t
 Perl_sighandler(int sig)
 {
@@ -2447,8 +2547,6 @@ Perl_sighandler(int sig)
        flags |= 1;
     if (PL_markstack_ptr < PL_markstack_max - 2)
        flags |= 4;
-    if (PL_retstack_ix < PL_retstack_max - 2)
-       flags |= 8;
     if (PL_scopestack_ix < PL_scopestack_max - 3)
        flags |= 16;
 
@@ -2466,10 +2564,6 @@ Perl_sighandler(int sig)
     }
     if (flags & 4)
        PL_markstack_ptr++;             /* Protect mark. */
-    if (flags & 8) {
-       PL_retstack_ix++;
-       PL_retstack[PL_retstack_ix] = NULL;
-    }
     if (flags & 16)
        PL_scopestack_ix += 1;
     /* sv_2cv is too complicated, try a simpler variant first: */
@@ -2491,7 +2585,7 @@ Perl_sighandler(int sig)
        sv = SvREFCNT_inc(PL_psig_name[sig]);
        flags |= 64;
 #if !defined(PERL_IMPLICIT_CONTEXT)
-       sig_sv = sv;
+       PL_sig_sv = sv;
 #endif
     } else {
        sv = sv_newmortal();
@@ -2523,15 +2617,13 @@ Perl_sighandler(int sig)
        (void)rsignal(sig, PL_csighandlerp);
 #endif
 #endif /* !PERL_MICRO */
-       Perl_die(aTHX_ Nullformat);
+       DieNull;
     }
 cleanup:
     if (flags & 1)
        PL_savestack_ix -= 8; /* Unprotect save in progress. */
     if (flags & 4)
        PL_markstack_ptr--;
-    if (flags & 8)
-       PL_retstack_ix--;
     if (flags & 16)
        PL_scopestack_ix -= 1;
     if (flags & 64)
@@ -2545,7 +2637,7 @@ cleanup:
 
 
 static void
-restore_magic(pTHX_ void *p)
+restore_magic(pTHX_ const void *p)
 {
     MGS* mgs = SSPTR(PTR2IV(p), MGS*);
     SV* sv = mgs->mgs_sv;
@@ -2555,6 +2647,13 @@ restore_magic(pTHX_ void *p)
 
     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
     {
+#ifdef PERL_COPY_ON_WRITE
+       /* While magic was saved (and off) sv_setsv may well have seen
+          this SV as a prime candidate for COW.  */
+       if (SvIsCOW(sv))
+           sv_force_normal(sv);
+#endif
+
        if (mgs->mgs_flags)
            SvFLAGS(sv) |= mgs->mgs_flags;
        else
@@ -2586,16 +2685,17 @@ restore_magic(pTHX_ void *p)
 }
 
 static void
-unwind_handler_stack(pTHX_ void *p)
+unwind_handler_stack(pTHX_ const void *p)
 {
-    U32 flags = *(U32*)p;
+    dVAR;
+    const U32 flags = *(const U32*)p;
 
     if (flags & 1)
        PL_savestack_ix -= 5; /* Unprotect save in progress. */
     /* cxstack_ix-- Not needed, die already unwound it. */
 #if !defined(PERL_IMPLICIT_CONTEXT)
     if (flags & 64)
-       SvREFCNT_dec(sig_sv);
+       SvREFCNT_dec(PL_sig_sv);
 #endif
 }