This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
resolve problems with tools_other() and htmlifypods
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index 0ac0742..4369e4a 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -1,6 +1,6 @@
 /*    mg.c
  *
- *    Copyright (c) 1991-2000, Larry Wall
+ *    Copyright (c) 1991-2001, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 #  ifndef NGROUPS
 #    define NGROUPS 32
 #  endif
+#  ifdef I_GRP
+#    include <grp.h>
+#  endif
 #endif
 
-static void restore_magic(pTHXo_ void *p);
-static void unwind_handler_stack(pTHXo_ void *p);
+/* 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_ void *p);
+static void unwind_handler_stack(pTHX_ void *p);
 
 /*
  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
@@ -42,7 +54,7 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
     MGS* mgs;
     assert(SvMAGICAL(sv));
 
-    SAVEDESTRUCTOR_X(restore_magic, (void*)mgs_ix);
+    SAVEDESTRUCTOR_X(restore_magic, INT2PTR(void*, (IV)mgs_ix));
 
     mgs = SSPTR(mgs_ix, MGS*);
     mgs->mgs_sv = sv;
@@ -51,7 +63,7 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
 
     SvMAGICAL_off(sv);
     SvREADONLY_off(sv);
-    SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+    SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_NOK|SVp_POK)) >> PRIVSHIFT;
 }
 
 /*
@@ -90,34 +102,48 @@ Do magic after a value is retrieved from the SV.  See C<sv_magic>.
 int
 Perl_mg_get(pTHX_ SV *sv)
 {
-    I32 mgs_ix;
-    MAGIC* mg;
-    MAGIC** mgp;
-    int mgp_valid = 0;
+    int new = 0;
+    MAGIC *newmg, *head, *cur, *mg;
+    I32 mgs_ix = SSNEW(sizeof(MGS));
 
-    mgs_ix = SSNEW(sizeof(MGS));
     save_magic(mgs_ix, sv);
 
-    mgp = &SvMAGIC(sv);
-    while ((mg = *mgp) != 0) {
-       MGVTBL* vtbl = mg->mg_virtual;
+    /* We must call svt_get(sv, mg) for each valid entry in the linked
+       list of magic. svt_get() may delete the current entry, add new
+       magic to the head of the list, or upgrade the SV. AMS 20010810 */
+
+    newmg = cur = head = mg = SvMAGIC(sv);
+    while (mg) {
+       MGVTBL *vtbl = mg->mg_virtual;
+
        if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
            CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
-           /* Ignore this magic if it's been deleted */
-           if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
-                 (mg->mg_flags & MGf_GSKIP))
-               (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
+           /* Don't restore the flags for this entry if it was deleted. */
+           if (mg->mg_flags & MGf_GSKIP)
+               (SSPTR(mgs_ix, MGS *))->mgs_flags = 0;
+       }
+
+       mg = mg->mg_moremagic;
+
+       if (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;
+               mg   = cur;
+               head = newmg;
+           }
        }
-       /* Advance to next magic (complicated by possible deletion) */
-       if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
-           mgp = &mg->mg_moremagic;
-           mgp_valid = 1;
+
+       /* Were any new entries added? */
+       if (!new && (newmg = SvMAGIC(sv)) != head) {
+           new = 1;
+           cur = mg;
+           mg  = newmg;
        }
-       else
-           mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
     }
 
-    restore_magic(aTHXo_ (void*)mgs_ix);
+    restore_magic(aTHX_ INT2PTR(void *, (IV)mgs_ix));
     return 0;
 }
 
@@ -150,7 +176,7 @@ Perl_mg_set(pTHX_ SV *sv)
            CALL_FPTR(vtbl->svt_set)(aTHX_ sv, mg);
     }
 
-    restore_magic(aTHXo_ (void*)mgs_ix);
+    restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
     return 0;
 }
 
@@ -166,7 +192,6 @@ U32
 Perl_mg_length(pTHX_ SV *sv)
 {
     MAGIC* mg;
-    char *junk;
     STRLEN len;
 
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
@@ -178,12 +203,18 @@ Perl_mg_length(pTHX_ SV *sv)
            save_magic(mgs_ix, sv);
            /* omit MGf_GSKIP -- not changed here */
            len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
-           restore_magic(aTHXo_ (void*)mgs_ix);
+           restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
            return len;
        }
     }
 
-    junk = SvPV(sv, len);
+    if (DO_UTF8(sv)) 
+    {
+        U8 *s = (U8*)SvPV(sv, len);
+        len = Perl_utf8_length(aTHX_ s, s + len);
+    }
+    else
+        (void)SvPV(sv, len);
     return len;
 }
 
@@ -202,7 +233,7 @@ Perl_mg_size(pTHX_ SV *sv)
            save_magic(mgs_ix, sv);
            /* omit MGf_GSKIP -- not changed here */
            len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
-           restore_magic(aTHXo_ (void*)mgs_ix);
+           restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
            return len;
        }
     }
@@ -245,7 +276,7 @@ Perl_mg_clear(pTHX_ SV *sv)
            CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg);
     }
 
-    restore_magic(aTHXo_ (void*)mgs_ix);
+    restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix));
     return 0;
 }
 
@@ -261,6 +292,8 @@ MAGIC*
 Perl_mg_find(pTHX_ 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;
@@ -284,8 +317,9 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
        if (isUPPER(mg->mg_type)) {
            sv_magic(nsv,
-                    mg->mg_type == 'P' ? SvTIED_obj(sv, mg) :
-                    (mg->mg_type == 'D' && mg->mg_obj) ? sv : mg->mg_obj,
+                    mg->mg_type == PERL_MAGIC_tied ? SvTIED_obj(sv, mg) :
+                    (mg->mg_type == PERL_MAGIC_regdata && mg->mg_obj)
+                                                       ? sv : mg->mg_obj,
                     toLOWER(mg->mg_type), key, klen);
            count++;
        }
@@ -311,11 +345,12 @@ Perl_mg_free(pTHX_ SV *sv)
        moremagic = mg->mg_moremagic;
        if (vtbl && vtbl->svt_free)
            CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
-       if (mg->mg_ptr && mg->mg_type != 'g')
+       if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
            if (mg->mg_len >= 0)
                Safefree(mg->mg_ptr);
            else if (mg->mg_len == HEf_SVKEY)
                SvREFCNT_dec((SV*)mg->mg_ptr);
+       }
        if (mg->mg_flags & MGf_REFCOUNTED)
            SvREFCNT_dec(mg->mg_obj);
        Safefree(mg);
@@ -324,6 +359,7 @@ Perl_mg_free(pTHX_ SV *sv)
     return 0;
 }
 
+
 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
 #include <signal.h>
 #endif
@@ -333,7 +369,7 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg)
 {
     register REGEXP *rx;
 
-    if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+    if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
        if (mg->mg_obj)         /* @+ */
            return rx->nparens;
        else                    /* @- */
@@ -352,7 +388,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
     register REGEXP *rx;
     I32 t;
 
-    if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+    if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
        paren = mg->mg_len;
        if (paren < 0)
            return 0;
@@ -364,7 +400,14 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg)
                    i = t;
                else                    /* @- */
                    i = s;
-               sv_setiv(sv,i);
+               
+               if (i > 0 && PL_reg_match_utf8) {
+                   char *b = rx->subbeg;
+                   if (b)
+                       i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i));
+               }
+
+               sv_setiv(sv, i);
            }
     }
     return 0;
@@ -389,7 +432,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
     switch (*mg->mg_ptr) {
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
 
            paren = atoi(mg->mg_ptr); /* $& is in [0] */
          getparen:
@@ -399,27 +442,36 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
            {
                i = t1 - s1;
              getlen:
-               if (i > 0 && DO_UTF8(PL_reg_sv)) {
+               if (i > 0 && PL_reg_match_utf8) {
                    char *s    = rx->subbeg + s1;
                    char *send = rx->subbeg + t1;
 
-                   i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
+                   i = t1 - s1;
+                   if (is_utf8_string((U8*)s, i))
+                       i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send);
                }
                if (i < 0)
-                   Perl_croak(aTHX_ "panic: magic_len: %d", i);
+                   Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i);
                return i;
            }
        }
        return 0;
     case '+':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            paren = rx->lastparen;
            if (paren)
                goto getparen;
        }
        return 0;
+    case '\016': /* ^N */
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+           paren = rx->lastcloseparen;
+           if (paren)
+               goto getparen;
+       }
+       return 0;
     case '`':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            if (rx->startp[0] != -1) {
                i = rx->startp[0];
                if (i > 0) {
@@ -431,7 +483,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg)
        }
        return 0;
     case '\'':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            if (rx->endp[0] != -1) {
                i = rx->sublen - rx->endp[0];
                if (i > 0) {
@@ -470,68 +522,72 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\004':               /* ^D */
-       sv_setiv(sv, (IV)(PL_debug & 32767));
+       sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK));
 #if defined(YYDEBUG) && defined(DEBUGGING)
-       PL_yydebug = (PL_debug & 1);
+       PL_yydebug = DEBUG_p_TEST;
 #endif
        break;
     case '\005':  /* ^E */
+        if (*(mg->mg_ptr+1) == '\0') {
 #ifdef MACOS_TRADITIONAL
-       {
-           char msg[256];
+            {
+                 char msg[256];
        
-           sv_setnv(sv,(double)gMacPerl_OSErr);
-           sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : "");     
-       }
+                 sv_setnv(sv,(double)gMacPerl_OSErr);
+                 sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : "");       
+            }
 #else  
 #ifdef VMS
-       {
-#          include <descrip.h>
-#          include <starlet.h>
-           char msg[255];
-           $DESCRIPTOR(msgdsc,msg);
-           sv_setnv(sv,(NV) vaxc$errno);
-           if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
-               sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
-           else
-               sv_setpv(sv,"");
-       }
+            {
+#                include <descrip.h>
+#                include <starlet.h>
+                 char msg[255];
+                 $DESCRIPTOR(msgdsc,msg);
+                 sv_setnv(sv,(NV) vaxc$errno);
+                 if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
+                      sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
+                 else
+                      sv_setpv(sv,"");
+            }
 #else
 #ifdef OS2
-       if (!(_emx_env & 0x200)) {      /* Under DOS */
-           sv_setnv(sv, (NV)errno);
-           sv_setpv(sv, errno ? Strerror(errno) : "");
-       } else {
-           if (errno != errno_isOS2) {
-               int tmp = _syserrno();
-               if (tmp)        /* 2nd call to _syserrno() makes it 0 */
-                   Perl_rc = tmp;
-           }
-           sv_setnv(sv, (NV)Perl_rc);
-           sv_setpv(sv, os2error(Perl_rc));
-       }
+            if (!(_emx_env & 0x200)) { /* Under DOS */
+                 sv_setnv(sv, (NV)errno);
+                 sv_setpv(sv, errno ? Strerror(errno) : "");
+            } else {
+                 if (errno != errno_isOS2) {
+                      int tmp = _syserrno();
+                      if (tmp) /* 2nd call to _syserrno() makes it 0 */
+                           Perl_rc = tmp;
+                 }
+                 sv_setnv(sv, (NV)Perl_rc);
+                 sv_setpv(sv, os2error(Perl_rc));
+            }
 #else
 #ifdef WIN32
-       {
-           DWORD dwErr = GetLastError();
-           sv_setnv(sv, (NV)dwErr);
-           if (dwErr)
-           {
-               PerlProc_GetOSError(sv, dwErr);
-           }
-           else
-               sv_setpv(sv, "");
-           SetLastError(dwErr);
-       }
+            {
+                 DWORD dwErr = GetLastError();
+                 sv_setnv(sv, (NV)dwErr);
+                 if (dwErr)
+                 {
+                      PerlProc_GetOSError(sv, dwErr);
+                 }
+                 else
+                      sv_setpv(sv, "");
+                 SetLastError(dwErr);
+            }
 #else
-       sv_setnv(sv, (NV)errno);
-       sv_setpv(sv, errno ? Strerror(errno) : "");
+            sv_setnv(sv, (NV)errno);
+            sv_setpv(sv, errno ? Strerror(errno) : "");
 #endif
 #endif
 #endif
 #endif
-       SvNOK_on(sv);   /* what a wonderful hack! */
-       break;
+            SvNOK_on(sv);      /* what a wonderful hack! */
+        }
+        else if (strEQ(mg->mg_ptr+1, "NCODING"))
+             sv_setsv(sv, PL_encoding);
+        break;
     case '\006':               /* ^F */
        sv_setiv(sv, (IV)PL_maxsysfd);
        break;
@@ -564,19 +620,25 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
                (void)SvOK_off(sv);
            else if (PL_in_eval)
                sv_setiv(sv, PL_in_eval & ~(EVAL_INREQUIRE));
+           else
+               sv_setiv(sv, 0);
        }
        break;
     case '\024':               /* ^T */
+        if (*(mg->mg_ptr+1) == '\0') {
 #ifdef BIG_TIME
-       sv_setnv(sv, PL_basetime);
+            sv_setnv(sv, PL_basetime);
 #else
-       sv_setiv(sv, (IV)PL_basetime);
+            sv_setiv(sv, (IV)PL_basetime);
 #endif
-       break;
+        }
+        else if (strEQ(mg->mg_ptr, "\024AINT"))
+            sv_setiv(sv, PL_tainting);
+        break;
     case '\027':               /* ^W  & $^WARNING_BITS & ^WIDE_SYSTEM_CALLS */
        if (*(mg->mg_ptr+1) == '\0')
            sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) ? TRUE : FALSE));
-       else if (strEQ(mg->mg_ptr, "\027ARNING_BITS")) {
+       else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
            if (PL_compiling.cop_warnings == pWARN_NONE ||
                PL_compiling.cop_warnings == pWARN_STD)
            {
@@ -590,12 +652,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
            }
            SvPOK_only(sv);
        }
-       else if (strEQ(mg->mg_ptr, "\027IDE_SYSTEM_CALLS"))
+       else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS"))
            sv_setiv(sv, (IV)PL_widesyscalls);
        break;
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            I32 s1, t1;
 
            /*
@@ -615,13 +677,13 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 
              getrx:
                if (i >= 0) {
-                   bool was_tainted;
+                   bool was_tainted = FALSE;
                    if (PL_tainting) {
                        was_tainted = PL_tainted;
                        PL_tainted = FALSE;
                    }
                    sv_setpvn(sv, s, i);
-                   if (DO_UTF8(PL_reg_sv))
+                   if (PL_reg_match_utf8 && is_utf8_string((U8*)s, i))
                        SvUTF8_on(sv);
                    else
                        SvUTF8_off(sv);
@@ -634,15 +696,23 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        sv_setsv(sv,&PL_sv_undef);
        break;
     case '+':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            paren = rx->lastparen;
            if (paren)
                goto getparen;
        }
        sv_setsv(sv,&PL_sv_undef);
        break;
+    case '\016':               /* ^N */
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
+           paren = rx->lastcloseparen;
+           if (paren)
+               goto getparen;
+       }
+       sv_setsv(sv,&PL_sv_undef);
+       break;
     case '`':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            if ((s = rx->subbeg) && rx->startp[0] != -1) {
                i = rx->startp[0];
                goto getrx;
@@ -651,7 +721,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        sv_setsv(sv,&PL_sv_undef);
        break;
     case '\'':
-       if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+       if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
            if (rx->subbeg && rx->endp[0] != -1) {
                s = rx->subbeg + rx->endp[0];
                i = rx->sublen - rx->endp[0];
@@ -663,7 +733,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '.':
 #ifndef lint
        if (GvIO(PL_last_in_gv)) {
-           sv_setiv(sv, (IV)IoLINES(GvIO(PL_last_in_gv)));
+           sv_setiv(sv, (IV)IoLINES(GvIOp(PL_last_in_gv)));
        }
 #endif
        break;
@@ -715,6 +785,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case ',':
        break;
     case '\\':
+       if (PL_ors_sv)
+           sv_setpv(sv,SvPVX(PL_ors_sv));
        break;
     case '#':
        sv_setpv(sv,PL_ofmt);
@@ -772,11 +844,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
     case '0':
        break;
 #endif
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
     case '@':
        sv_setsv(sv, thr->errsv);
        break;
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
     }
     return 0;
 }
@@ -787,7 +859,7 @@ Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg)
     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
 
     if (uf && uf->uf_val)
-       (*uf->uf_val)(uf->uf_index, sv);
+       (*uf->uf_val)(aTHX_ uf->uf_index, sv);
     return 0;
 }
 
@@ -797,7 +869,6 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
     register char *s;
     char *ptr;
     STRLEN len, klen;
-    I32 i;
 
     s = SvPV(sv,len);
     ptr = MgPV(mg,klen);
@@ -850,6 +921,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
            while (s < strend) {
                char tmpbuf[256];
                struct stat st;
+               I32 i;
                s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
                             s, strend, ':', &i);
                s++;
@@ -902,26 +974,10 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 #if defined(VMS) || defined(EPOC)
     Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system");
 #else
-#   ifdef PERL_IMPLICIT_SYS
+#   if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
     PerlEnv_clearenv();
 #   else
-#      ifdef WIN32
-    char *envv = GetEnvironmentStrings();
-    char *cur = envv;
-    STRLEN len;
-    while (*cur) {
-       char *end = strchr(cur,'=');
-       if (end && end != cur) {
-           *end = '\0';
-           my_setenv(cur,Nullch);
-           *end = '=';
-           cur = end + strlen(end+1)+2;
-       }
-       else if ((len = strlen(cur)))
-           cur += len+1;
-    }
-    FreeEnvironmentStrings(envv);
-#      else
+#       ifdef USE_ENVIRON_ARRAY
 #          ifndef PERL_USE_SAFE_PUTENV
     I32 i;
 
@@ -934,12 +990,22 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg)
 
     environ[0] = Nullch;
 
-#      endif /* WIN32 */
-#   endif /* PERL_IMPLICIT_SYS */
-#endif /* VMS */
+#       endif /* USE_ENVIRON_ARRAY */
+#   endif /* PERL_IMPLICIT_SYS || WIN32 */
+#endif /* VMS || EPC */
     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
 int
 Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
@@ -952,8 +1018,14 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
        if(PL_psig_ptr[i])
            sv_setsv(sv,PL_psig_ptr[i]);
        else {
-           Sighandler_t sigstate = rsignal_state(i);
-
+           Sighandler_t sigstate;
+           sigstate = rsignal_state(i);
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+           if (sig_handlers_initted && sig_ignoring[i]) sigstate = SIG_IGN;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+           if (sig_handlers_initted && sig_defaulting[i]) sigstate = SIG_DFL;
+#endif
            /* cache state so we don't fetch it again */
            if(sigstate == SIG_IGN)
                sv_setpv(sv,"IGNORE");
@@ -985,12 +1057,82 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
     return 0;
 }
 
+void
+Perl_raise_signal(pTHX_ int sig)
+{
+    /* Set a flag to say this signal is pending */
+    PL_psig_pend[sig]++;
+    /* And one to say _a_ signal is pending */
+    PL_sig_pending = 1;
+}
+
+Signal_t
+Perl_csighandler(int sig)
+{
+#ifndef PERL_OLD_SIGNALS
+    dTHX;
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+    (void) rsignal(sig, &Perl_csighandler);
+    if (sig_ignoring[sig]) return;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+    if (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
+            exit(1);
+#endif
+#endif
+
+#ifdef PERL_OLD_SIGNALS
+    /* Call the perl level handler now with risk we may be in malloc() etc. */
+    (*PL_sighandlerp)(sig);
+#else
+    Perl_raise_signal(aTHX_ sig);
+#endif
+}
+
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+void
+Perl_csighandler_init(void)
+{
+    int sig;
+    if (sig_handlers_initted) return;
+
+    for (sig = 1; sig < SIG_SIZE; sig++) {
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+        dTHX;
+        sig_defaulting[sig] = 1;
+        (void) rsignal(sig, &Perl_csighandler);
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+        sig_ignoring[sig] = 0;
+#endif
+    }
+    sig_handlers_initted = 1;
+}
+#endif
+
+void
+Perl_despatch_signals(pTHX)
+{
+    int sig;
+    PL_sig_pending = 0;
+    for (sig = 1; sig < SIG_SIZE; sig++) {
+       if (PL_psig_pend[sig]) {
+           PL_psig_pend[sig] = 0;
+           (*PL_sighandlerp)(sig);
+       }
+    }
+}
+
 int
 Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 {
     register char *s;
     I32 i;
-    SV** svp;
+    SV** svp = 0;
     STRLEN len;
 
     s = MgPV(mg,len);
@@ -1014,6 +1156,15 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
                Perl_warner(aTHX_ WARN_SIGNAL, "No such signal: SIG%s", s);
            return 0;
        }
+#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS)
+       if (!sig_handlers_initted) Perl_csighandler_init();
+#endif
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+       sig_ignoring[i] = 0;
+#endif
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+         sig_defaulting[i] = 0;
+#endif
        SvREFCNT_dec(PL_psig_name[i]);
        SvREFCNT_dec(PL_psig_ptr[i]);
        PL_psig_ptr[i] = SvREFCNT_inc(sv);
@@ -1023,21 +1174,33 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     }
     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
        if (i)
-           (void)rsignal(i, PL_sighandlerp);
+           (void)rsignal(i, &Perl_csighandler);
        else
            *svp = SvREFCNT_inc(sv);
        return 0;
     }
     s = SvPV_force(sv,len);
     if (strEQ(s,"IGNORE")) {
-       if (i)
+       if (i) {
+#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
+           sig_ignoring[i] = 1;
+           (void)rsignal(i, &Perl_csighandler);
+#else
            (void)rsignal(i, SIG_IGN);
-       else
+#endif
+       } else
            *svp = 0;
     }
     else if (strEQ(s,"DEFAULT") || !*s) {
        if (i)
+#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
+         {
+           sig_defaulting[i] = 1;
+           (void)rsignal(i, &Perl_csighandler);
+         }
+#else
            (void)rsignal(i, SIG_DFL);
+#endif
        else
            *svp = 0;
     }
@@ -1050,7 +1213,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
        if (!strchr(s,':') && !strchr(s,'\''))
            sv_insert(sv, 0, 0, "main::", 6);
        if (i)
-           (void)rsignal(i, PL_sighandlerp);
+           (void)rsignal(i, &Perl_csighandler);
        else
            *svp = SvREFCNT_inc(sv);
     }
@@ -1078,19 +1241,16 @@ int
 Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
 {
     HV *hv = (HV*)LvTARG(sv);
-    HE *entry;
     I32 i = 0;
-
+     
     if (hv) {
-       (void) hv_iterinit(hv);
-       if (! SvTIED_mg((SV*)hv, 'P'))
-           i = HvKEYS(hv);
-       else {
-           /*SUPPRESS 560*/
-           while ((entry = hv_iternext(hv))) {
-               i++;
-           }
-       }
+         (void) hv_iterinit(hv);
+         if (! SvTIED_mg((SV*)hv, PERL_MAGIC_tied))
+            i = HvKEYS(hv);
+         else {
+            while (hv_iternext(hv))
+                i++;
+         }
     }
 
     sv_setiv(sv, (IV)i);
@@ -1122,7 +1282,7 @@ S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
            else if (mg->mg_len == HEf_SVKEY)
                PUSHs((SV*)mg->mg_ptr);
        }
-       else if (mg->mg_type == 'p') {
+       else if (mg->mg_type == PERL_MAGIC_tiedelem) {
            PUSHs(sv_2mortal(newSViv(mg->mg_len)));
        }
     }
@@ -1285,7 +1445,7 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
     SV* lsv = LvTARG(sv);
 
     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
-       mg = mg_find(lsv, 'g');
+       mg = mg_find(lsv, PERL_MAGIC_regex_global);
        if (mg && mg->mg_len >= 0) {
            I32 i = mg->mg_len;
            if (DO_UTF8(lsv))
@@ -1309,12 +1469,12 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
     mg = 0;
 
     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
-       mg = mg_find(lsv, 'g');
+       mg = mg_find(lsv, PERL_MAGIC_regex_global);
     if (!mg) {
        if (!SvOK(sv))
            return 0;
-       sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
-       mg = mg_find(lsv, 'g');
+       sv_magic(lsv, (SV*)0, PERL_MAGIC_regex_global, Nullch, 0);
+       mg = mg_find(lsv, PERL_MAGIC_regex_global);
     }
     else if (!SvOK(sv)) {
        mg->mg_len = -1;
@@ -1393,12 +1553,14 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg)
     I32 offs = LvTARGOFF(sv);
     I32 rem = LvTARGLEN(sv);
 
+    if (SvUTF8(lsv))
+       sv_pos_u2b(lsv, &offs, &rem);
     if (offs > len)
        offs = len;
     if (rem + offs > len)
        rem = len - offs;
     sv_setpvn(sv, tmps + offs, (STRLEN)rem);
-    if (DO_UTF8(lsv))
+    if (SvUTF8(lsv))
         SvUTF8_on(sv);
     return 0;
 }
@@ -1407,8 +1569,26 @@ int
 Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
 {
     STRLEN len;
-    char *tmps = SvPV(sv,len);
-    sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
+    char *tmps = SvPV(sv, len);
+    SV *lsv = LvTARG(sv);
+    I32 lvoff = LvTARGOFF(sv);
+    I32 lvlen = LvTARGLEN(sv);
+
+    if (DO_UTF8(sv)) {
+       sv_utf8_upgrade(lsv);
+       sv_pos_u2b(lsv, &lvoff, &lvlen);
+       sv_insert(lsv, lvoff, lvlen, tmps, len);
+       SvUTF8_on(lsv);
+    }
+    else if (lsv && SvUTF8(lsv)) {
+       sv_pos_u2b(lsv, &lvoff, &lvlen);
+       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);
+
     return 0;
 }
 
@@ -1514,7 +1694,7 @@ Perl_vivify_defelem(pTHX_ SV *sv)
     MAGIC *mg;
     SV *value = Nullsv;
 
-    if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
+    if (!LvTARGLEN(sv) || !(mg = mg_find(sv, PERL_MAGIC_defelem)))
        return;
     if (mg->mg_obj) {
        SV *ahv = LvTARG(sv);
@@ -1583,7 +1763,7 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
 {
-    sv_unmagic(sv, 'B');
+    sv_unmagic(sv, PERL_MAGIC_bm);
     SvVALID_off(sv);
     return 0;
 }
@@ -1591,7 +1771,7 @@ Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg)
 int
 Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg)
 {
-    sv_unmagic(sv, 'f');
+    sv_unmagic(sv, PERL_MAGIC_fm);
     SvCOMPILED_off(sv);
     return 0;
 }
@@ -1602,7 +1782,7 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg)
     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
 
     if (uf && uf->uf_set)
-       (*uf->uf_set)(uf->uf_index, sv);
+       (*uf->uf_set)(aTHX_ uf->uf_index, sv);
     return 0;
 }
 
@@ -1646,27 +1826,36 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\004':       /* ^D */
-       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
+       PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG;
        DEBUG_x(dump_all());
        break;
     case '\005':  /* ^E */
+        if (*(mg->mg_ptr+1) == '\0') {
 #ifdef MACOS_TRADITIONAL
-       gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+             gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
 #else
 #  ifdef VMS
-       set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+             set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
 #  else
 #    ifdef WIN32
-       SetLastError( SvIV(sv) );
+             SetLastError( SvIV(sv) );
 #    else
-#      ifndef OS2
-       /* will anyone ever use this? */
-       SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
+#      ifdef OS2
+             os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+#      else
+             /* will anyone ever use this? */
+             SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
 #      endif
 #    endif
 #  endif
 #endif
-       break;
+        }
+        else if (strEQ(mg->mg_ptr+1, "NCODING")) {
+            if (PL_encoding)
+                sv_setsv(PL_encoding, sv);
+            else
+                PL_encoding = newSVsv(sv);
+        }
     case '\006':       /* ^F */
        PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
        break;
@@ -1717,7 +1906,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                                | (i ? G_WARN_ON : G_WARN_OFF) ;
            }
        }
-       else if (strEQ(mg->mg_ptr, "\027ARNING_BITS")) {
+       else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
            if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
                if (!SvPOK(sv) && PL_localizing) {
                    sv_setpvn(sv, WARN_NONEstring, WARNsize);
@@ -1751,7 +1940,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                }
            }
        }
-       else if (strEQ(mg->mg_ptr, "\027IDE_SYSTEM_CALLS"))
+       else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS"))
            PL_widesyscalls = SvTRUE(sv);
        break;
     case '.':
@@ -1760,7 +1949,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                SAVESPTR(PL_last_in_gv);
        }
        else if (SvOK(sv) && GvIO(PL_last_in_gv))
-           IoLINES(GvIOp(PL_last_in_gv)) = (long)SvIV(sv);
+           IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv);
        break;
     case '^':
        Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
@@ -1773,19 +1962,21 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
        break;
     case '=':
-       IoPAGE_LEN(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '-':
-       IoLINES_LEFT(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
            IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
        break;
     case '%':
-       IoPAGE(GvIOp(PL_defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+       IoPAGE(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
        break;
     case '|':
        {
            IO *io = GvIOp(PL_defoutgv);
+           if(!io)
+             break;
            if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
                IoFLAGS(io) &= ~IOf_FLUSH;
            else {
@@ -1803,10 +1994,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        PL_multiline = (i != 0);
        break;
     case '/':
-       SvREFCNT_dec(PL_nrs);
-       PL_nrs = newSVsv(sv);
        SvREFCNT_dec(PL_rs);
-       PL_rs = SvREFCNT_inc(PL_nrs);
+       PL_rs = newSVsv(sv);
        break;
     case '\\':
        if (PL_ors_sv)
@@ -1996,12 +2185,12 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
         * the setproctitle() routine to manipulate that. */
        {
            s = SvPV(sv, len);
-#   if __FreeBSD_version >= 410001
+#   if __FreeBSD_version > 410001
            /* The leading "-" removes the "perl: " prefix,
             * but not the "(perl) suffix from the ps(1)
             * output, because that's what ps(1) shows if the
             * argv[] is modified. */
-           setproctitle("-%s", s, len + 1);
+           setproctitle("-%s", s);
 #   else       /* old FreeBSDs, NetBSD, OpenBSD, anyBSD */
            /* This doesn't really work if you assume that
             * $0 = 'foobar'; will wipe out 'perl' from the $0
@@ -2032,11 +2221,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                    break;
            }
            /* can grab env area too? */
-           if (PL_origenviron && (PL_origenviron[0] == s + 1
-#ifdef OS2
-                               || (PL_origenviron[0] == s + 9 && (s += 8))
-#endif
-              )) {
+           if (PL_origenviron && (PL_origenviron[0] == s + 1)) {
                my_setenv("NoNe  SuCh", Nullch);
                                            /* force copy of environment */
                for (i = 0; PL_origenviron[i]; i++)
@@ -2071,29 +2256,29 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        }
        break;
 #endif
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
     case '@':
        sv_setsv(thr->errsv, sv);
        break;
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
     }
     return 0;
 }
 
-#ifdef USE_THREADS
+#ifdef USE_5005THREADS
 int
 Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg)
 {
     DEBUG_S(PerlIO_printf(Perl_debug_log,
                          "0x%"UVxf": magic_mutexfree 0x%"UVxf"\n",
-                         PTR2UV(thr), PTR2UV(sv));)
+                         PTR2UV(thr), PTR2UV(sv)));
     if (MgOWNER(mg))
        Perl_croak(aTHX_ "panic: magic_mutexfree");
     MUTEX_DESTROY(MgMUTEXP(mg));
     COND_DESTROY(MgCONDP(mg));
     return 0;
 }
-#endif /* USE_THREADS */
+#endif /* USE_5005THREADS */
 
 I32
 Perl_whichsig(pTHX_ char *sig)
@@ -2114,28 +2299,29 @@ Perl_whichsig(pTHX_ char *sig)
     return 0;
 }
 
+#if !defined(PERL_IMPLICIT_CONTEXT)
 static SV* sig_sv;
+#endif
 
 Signal_t
 Perl_sighandler(int sig)
 {
 #if defined(WIN32) && defined(PERL_IMPLICIT_CONTEXT)
-    dTHXoa(PL_curinterp);      /* fake TLS, because signals don't do TLS */
+    dTHXa(PL_curinterp);       /* fake TLS, because signals don't do TLS */
 #else
     dTHX;
 #endif
     dSP;
     GV *gv = Nullgv;
     HV *st;
-    SV *sv, *tSv = PL_Sv;
+    SV *sv = Nullsv, *tSv = PL_Sv;
     CV *cv = Nullcv;
     OP *myop = PL_op;
     U32 flags = 0;
-    I32 o_save_i = PL_savestack_ix;
     XPV *tXpv = PL_Xpv;
 
 #if defined(WIN32) && defined(PERL_IMPLICIT_CONTEXT)
-    PERL_SET_THX(aTHXo);       /* fake TLS, see above */
+    PERL_SET_THX(aTHX);        /* fake TLS, see above */
 #endif
 
     if (PL_savestack_ix + 15 <= PL_savestack_max)
@@ -2155,7 +2341,6 @@ Perl_sighandler(int sig)
        infinity, so we fix 4 (in fact 5): */
     if (flags & 1) {
        PL_savestack_ix += 5;           /* Protect save in progress. */
-       o_save_i = PL_savestack_ix;
        SAVEDESTRUCTOR_X(unwind_handler_stack, (void*)&flags);
     }
     if (flags & 4)
@@ -2184,7 +2369,9 @@ Perl_sighandler(int sig)
     if(PL_psig_name[sig]) {
        sv = SvREFCNT_inc(PL_psig_name[sig]);
        flags |= 64;
+#if !defined(PERL_IMPLICIT_CONTEXT)
        sig_sv = sv;
+#endif
     } else {
        sv = sv_newmortal();
        sv_setpv(sv,PL_sig_name[sig]);
@@ -2195,9 +2382,28 @@ Perl_sighandler(int sig)
     PUSHs(sv);
     PUTBACK;
 
-    call_sv((SV*)cv, G_DISCARD);
+    call_sv((SV*)cv, G_DISCARD|G_EVAL);
 
     POPSTACK;
+    if (SvTRUE(ERRSV)) {
+#ifndef PERL_MICRO
+#ifdef HAS_SIGPROCMASK
+       /* Handler "died", for example to get out of a restart-able read().
+        * Before we re-do that on its behalf re-enable the signal which was
+        * blocked by the system when we entered.
+        */
+       sigset_t set;
+       sigemptyset(&set);
+       sigaddset(&set,sig);
+       sigprocmask(SIG_UNBLOCK, &set, NULL);
+#else
+       /* Not clear if this will work */
+       (void)rsignal(sig, SIG_IGN);
+       (void)rsignal(sig, &Perl_csighandler);
+#endif
+#endif /* !PERL_MICRO */
+       Perl_die(aTHX_ Nullformat);
+    }
 cleanup:
     if (flags & 1)
        PL_savestack_ix -= 8; /* Unprotect save in progress. */
@@ -2217,12 +2423,8 @@ cleanup:
 }
 
 
-#ifdef PERL_OBJECT
-#include "XSUB.h"
-#endif
-
 static void
-restore_magic(pTHXo_ void *p)
+restore_magic(pTHX_ void *p)
 {
     MGS* mgs = SSPTR(PTR2IV(p), MGS*);
     SV* sv = mgs->mgs_sv;
@@ -2263,13 +2465,15 @@ restore_magic(pTHXo_ void *p)
 }
 
 static void
-unwind_handler_stack(pTHXo_ void *p)
+unwind_handler_stack(pTHX_ void *p)
 {
     U32 flags = *(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);
+#endif
 }