This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove the AIX work around code. Instead it should just set it's LOCALTIME_MAX to...
[perl5.git] / pp_sys.c
index fe20ead..74958ac 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -1,7 +1,7 @@
 /*    pp_sys.c
  *
- *    Copyright (C) 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others
+ *    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ *    2004, 2005, 2006, 2007 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.
@@ -27,6 +27,8 @@
 #include "EXTERN.h"
 #define PERL_IN_PP_SYS_C
 #include "perl.h"
+#include "time64.h"
+#include "time64.c"
 
 #ifdef I_SHADOW
 /* Shadow password support for solaris - pdo@cs.umd.edu
@@ -199,15 +201,6 @@ void endservent(void);
 
 #undef PERL_EFF_ACCESS /* EFFective uid/gid ACCESS */
 
-/* AIX 5.2 and below use mktime for localtime, and defines the edge case
- * for time 0x7fffffff to be valid only in UTC. AIX 5.3 provides localtime64
- * available in the 32bit environment, which could warrant Configure
- * checks in the future.
- */
-#ifdef  _AIX
-#define LOCALTIME_EDGECASE_BROKEN
-#endif
-
 /* F_OK unused: if stat() cannot find it... */
 
 #if !defined(PERL_EFF_ACCESS) && defined(HAS_ACCESS) && defined(EFF_ONLY_OK) && !defined(NO_EFF_ONLY_OK)
@@ -297,27 +290,12 @@ S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
 
     return res;
 }
-#   define PERL_EFF_ACCESS(p,f) (emulate_eaccess((p), (f)))
-#endif
-
-#if !defined(PERL_EFF_ACCESS)
-/* With it or without it: anyway you get a warning: either that
-   it is unused, or it is declared static and never defined.
- */
-STATIC int
-S_emulate_eaccess(pTHX_ const char* path, Mode_t mode)
-{
-    (void)path;
-    (void)mode;
-    Perl_croak(aTHX_ "switching effective uid is not implemented");
-    /*NOTREACHED*/
-    return -1;
-}
+#   define PERL_EFF_ACCESS(p,f) (S_emulate_eaccess(aTHX_ (p), (f)))
 #endif
 
 PP(pp_backtick)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     PerlIO *fp;
     const char * const tmps = POPpconstx;
     const I32 gimme = GIMME_V;
@@ -330,34 +308,34 @@ PP(pp_backtick)
        mode = "rt";
     fp = PerlProc_popen(tmps, mode);
     if (fp) {
-        const char * const type = PL_curcop->cop_io ? SvPV_nolen_const(PL_curcop->cop_io) : NULL;
+        const char * const type = Perl_PerlIO_context_layers(aTHX_ NULL);
        if (type && *type)
            PerlIO_apply_layers(aTHX_ fp,mode,type);
 
        if (gimme == G_VOID) {
            char tmpbuf[256];
            while (PerlIO_read(fp, tmpbuf, sizeof tmpbuf) > 0)
-               ;
+               NOOP;
        }
        else if (gimme == G_SCALAR) {
            ENTER;
            SAVESPTR(PL_rs);
            PL_rs = &PL_sv_undef;
            sv_setpvn(TARG, "", 0);     /* note that this preserves previous buffer */
-           while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch)
-               ;
+           while (sv_gets(TARG, fp, SvCUR(TARG)) != NULL)
+               NOOP;
            LEAVE;
            XPUSHs(TARG);
            SvTAINTED_on(TARG);
        }
        else {
            for (;;) {
-               SV * const sv = NEWSV(56, 79);
-               if (sv_gets(sv, fp, 0) == Nullch) {
+               SV * const sv = newSV(79);
+               if (sv_gets(sv, fp, 0) == NULL) {
                    SvREFCNT_dec(sv);
                    break;
                }
-               XPUSHs(sv_2mortal(sv));
+               mXPUSHs(sv);
                if (SvLEN(sv) - SvCUR(sv) > 20) {
                    SvPV_shrink_to_cur(sv);
                }
@@ -403,7 +381,7 @@ PP(pp_glob)
     PL_last_in_gv = (GV*)*PL_stack_sp--;
 
     SAVESPTR(PL_rs);           /* This is not permanent, either. */
-    PL_rs = sv_2mortal(newSVpvn("\000", 1));
+    PL_rs = newSVpvs_flags("\000", SVs_TEMP);
 #ifndef DOSISH
 #ifndef CSH
     *SvPVX(PL_rs) = '\n';
@@ -417,13 +395,14 @@ PP(pp_glob)
 
 PP(pp_rcatline)
 {
+    dVAR;
     PL_last_in_gv = cGVOP_gv;
     return do_readline();
 }
 
 PP(pp_warn)
 {
-    dSP; dMARK;
+    dVAR; dSP; dMARK;
     SV *tmpsv;
     const char *tmps;
     STRLEN len;
@@ -436,6 +415,7 @@ PP(pp_warn)
     else if (SP == MARK) {
        tmpsv = &PL_sv_no;
        EXTEND(SP, 1);
+       SP = MARK + 1;
     }
     else {
        tmpsv = TOPs;
@@ -445,20 +425,20 @@ PP(pp_warn)
        SV * const error = ERRSV;
        SvUPGRADE(error, SVt_PV);
        if (SvPOK(error) && SvCUR(error))
-           sv_catpv(error, "\t...caught");
+           sv_catpvs(error, "\t...caught");
        tmpsv = error;
        tmps = SvPV_const(tmpsv, len);
     }
     if (!tmps || !len)
-       tmpsv = sv_2mortal(newSVpvn("Warning: something's wrong", 26));
+       tmpsv = newSVpvs_flags("Warning: something's wrong", SVs_TEMP);
 
-    Perl_warn(aTHX_ "%"SVf, tmpsv);
+    Perl_warn(aTHX_ "%"SVf, SVfARG(tmpsv));
     RETSETYES;
 }
 
 PP(pp_die)
 {
-    dSP; dMARK;
+    dVAR; dSP; dMARK;
     const char *tmps;
     SV *tmpsv;
     STRLEN len;
@@ -476,7 +456,7 @@ PP(pp_die)
     }
     else {
        tmpsv = TOPs;
-        tmps = SvROK(tmpsv) ? Nullch : SvPV_const(tmpsv, len);
+        tmps = SvROK(tmpsv) ? (const char *)NULL : SvPV_const(tmpsv, len);
     }
     if (!tmps || !len) {
        SV * const error = ERRSV;
@@ -501,22 +481,22 @@ PP(pp_die)
                    sv_setsv(error,*PL_stack_sp--);
                }
            }
-           DIE(aTHX_ Nullch);
+           DIE(aTHX_ NULL);
        }
        else {
            if (SvPOK(error) && SvCUR(error))
-               sv_catpv(error, "\t...propagated");
+               sv_catpvs(error, "\t...propagated");
            tmpsv = error;
            if (SvOK(tmpsv))
                tmps = SvPV_const(tmpsv, len);
            else
-               tmps = Nullch;
+               tmps = NULL;
        }
     }
     if (!tmps || !len)
-       tmpsv = sv_2mortal(newSVpvn("Died", 4));
+       tmpsv = newSVpvs_flags("Died", SVs_TEMP);
 
-    DIE(aTHX_ "%"SVf, tmpsv);
+    DIE(aTHX_ "%"SVf, SVfARG(tmpsv));
 }
 
 /* I/O. */
@@ -536,11 +516,16 @@ PP(pp_open)
 
     if (!isGV(gv))
        DIE(aTHX_ PL_no_usym, "filehandle");
-    if ((io = GvIOp(gv)))
+
+    if ((io = GvIOp(gv))) {
+       MAGIC *mg;
        IoFLAGS(GvIOp(gv)) &= ~IOf_UNTAINT;
 
-    if (io) {
-       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (IoDIRP(io) && ckWARN2(WARN_IO, WARN_DEPRECATED))
+           Perl_warner(aTHX_ packWARN2(WARN_IO, WARN_DEPRECATED),
+                   "Opening dirhandle %s also as a file", GvENAME(gv));
+
+       mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
        if (mg) {
            /* Method's args are same as ours ... */
            /* ... except handle is replaced by the object */
@@ -563,7 +548,7 @@ PP(pp_open)
     }
 
     tmps = SvPV_const(sv, len);
-    ok = do_openn(gv, tmps, len, FALSE, O_RDONLY, 0, Nullfp, MARK+1, (SP-MARK));
+    ok = do_openn(gv, tmps, len, FALSE, O_RDONLY, 0, NULL, MARK+1, (SP-MARK));
     SP = ORIGMARK;
     if (ok)
        PUSHi( (I32)PL_forkprocess );
@@ -577,21 +562,23 @@ PP(pp_open)
 PP(pp_close)
 {
     dVAR; dSP;
-    IO *io;
-    MAGIC *mg;
     GV * const gv = (MAXARG == 0) ? PL_defoutgv : (GV*)POPs;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       PUTBACK;
-       ENTER;
-       call_method("CLOSE", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       RETURN;
+    if (gv) {
+       IO * const io = GvIO(gv);
+       if (io) {
+           MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+           if (mg) {
+               PUSHMARK(SP);
+               XPUSHs(SvTIED_obj((SV*)io, mg));
+               PUTBACK;
+               ENTER;
+               call_method("CLOSE", G_SCALAR);
+               LEAVE;
+               SPAGAIN;
+               RETURN;
+           }
+       }
     }
     EXTEND(SP, 1);
     PUSHs(boolSV(do_close(gv, TRUE)));
@@ -601,6 +588,7 @@ PP(pp_close)
 PP(pp_pipe_op)
 {
 #ifdef HAS_PIPE
+    dVAR;
     dSP;
     register IO *rstio;
     register IO *wstio;
@@ -612,7 +600,7 @@ PP(pp_pipe_op)
     if (!rgv || !wgv)
        goto badexit;
 
-    if (SvTYPE(rgv) != SVt_PVGV || SvTYPE(wgv) != SVt_PVGV)
+    if (!isGV_with_GP(rgv) || !isGV_with_GP(wgv))
        DIE(aTHX_ PL_no_usym, "filehandle");
     rstio = GvIOn(rgv);
     wstio = GvIOn(wgv);
@@ -633,10 +621,14 @@ PP(pp_pipe_op)
     IoTYPE(wstio) = IoTYPE_WRONLY;
 
     if (!IoIFP(rstio) || !IoOFP(wstio)) {
-       if (IoIFP(rstio)) PerlIO_close(IoIFP(rstio));
-       else PerlLIO_close(fd[0]);
-       if (IoOFP(wstio)) PerlIO_close(IoOFP(wstio));
-       else PerlLIO_close(fd[1]);
+       if (IoIFP(rstio))
+           PerlIO_close(IoIFP(rstio));
+       else
+           PerlLIO_close(fd[0]);
+       if (IoOFP(wstio))
+           PerlIO_close(IoOFP(wstio));
+       else
+           PerlLIO_close(fd[1]);
        goto badexit;
     }
 #if defined(HAS_FCNTL) && defined(F_SETFD)
@@ -692,14 +684,19 @@ PP(pp_fileno)
 
 PP(pp_umask)
 {
+    dVAR;
     dSP;
 #ifdef HAS_UMASK
     dTARGET;
     Mode_t anum;
 
     if (MAXARG < 1) {
-       anum = PerlLIO_umask(0);
-       (void)PerlLIO_umask(anum);
+       anum = PerlLIO_umask(022);
+       /* setting it to 022 between the two calls to umask avoids
+        * to have a window where the umask is set to 0 -- meaning
+        * that another thread could create world-writeable files. */
+       if (anum != 022)
+           (void)PerlLIO_umask(anum);
     }
     else
        anum = PerlLIO_umask(POPi);
@@ -722,8 +719,7 @@ PP(pp_binmode)
     GV *gv;
     IO *io;
     PerlIO *fp;
-    MAGIC *mg;
-    SV *discp = Nullsv;
+    SV *discp = NULL;
 
     if (MAXARG < 1)
        RETPUSHUNDEF;
@@ -733,19 +729,20 @@ PP(pp_binmode)
 
     gv = (GV*)POPs;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       if (discp)
-           XPUSHs(discp);
-       PUTBACK;
-       ENTER;
-       call_method("BINMODE", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       RETURN;
+    if (gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
+           if (discp)
+               XPUSHs(discp);
+           PUTBACK;
+           ENTER;
+           call_method("BINMODE", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           RETURN;
+       }
     }
 
     EXTEND(SP, 1);
@@ -757,22 +754,27 @@ PP(pp_binmode)
     }
 
     PUTBACK;
-    if (PerlIO_binmode(aTHX_ fp,IoTYPE(io),mode_from_discipline(discp),
-                       (discp) ? SvPV_nolen_const(discp) : Nullch)) {
-       if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
-            if (!PerlIO_binmode(aTHX_ IoOFP(io),IoTYPE(io),
-                       mode_from_discipline(discp),
-                       (discp) ? SvPV_nolen_const(discp) : Nullch)) {
-               SPAGAIN;
-               RETPUSHUNDEF;
-            }
+    {
+       STRLEN len = 0;
+       const char *d = NULL;
+       int mode;
+       if (discp)
+           d = SvPV_const(discp, len);
+       mode = mode_from_discipline(d, len);
+       if (PerlIO_binmode(aTHX_ fp, IoTYPE(io), mode, d)) {
+           if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
+               if (!PerlIO_binmode(aTHX_ IoOFP(io), IoTYPE(io), mode, d)) {
+                   SPAGAIN;
+                   RETPUSHUNDEF;
+               }
+           }
+           SPAGAIN;
+           RETPUSHYES;
+       }
+       else {
+           SPAGAIN;
+           RETPUSHUNDEF;
        }
-       SPAGAIN;
-       RETPUSHYES;
-    }
-    else {
-       SPAGAIN;
-       RETPUSHUNDEF;
     }
 }
 
@@ -797,26 +799,29 @@ PP(pp_tie)
            methname = "TIEARRAY";
            break;
        case SVt_PVGV:
+           if (isGV_with_GP(varsv)) {
 #ifdef GV_UNIQUE_CHECK
-           if (GvUNIQUE((GV*)varsv)) {
-                Perl_croak(aTHX_ "Attempt to tie unique GV");
-           }
+               if (GvUNIQUE((GV*)varsv)) {
+                   Perl_croak(aTHX_ "Attempt to tie unique GV");
+               }
 #endif
-           methname = "TIEHANDLE";
-           how = PERL_MAGIC_tiedscalar;
-           /* For tied filehandles, we apply tiedscalar magic to the IO
-              slot of the GP rather than the GV itself. AMS 20010812 */
-           if (!GvIOp(varsv))
-               GvIOp(varsv) = newIO();
-           varsv = (SV *)GvIOp(varsv);
-           break;
+               methname = "TIEHANDLE";
+               how = PERL_MAGIC_tiedscalar;
+               /* For tied filehandles, we apply tiedscalar magic to the IO
+                  slot of the GP rather than the GV itself. AMS 20010812 */
+               if (!GvIOp(varsv))
+                   GvIOp(varsv) = newIO();
+               varsv = (SV *)GvIOp(varsv);
+               break;
+           }
+           /* FALL THROUGH */
        default:
            methname = "TIESCALAR";
            how = PERL_MAGIC_tiedscalar;
            break;
     }
     items = SP - MARK++;
-    if (sv_isobject(*MARK)) {
+    if (sv_isobject(*MARK)) { /* Calls GET magic. */
        ENTER;
        PUSHSTACKi(PERLSI_MAGIC);
        PUSHMARK(SP);
@@ -830,10 +835,12 @@ PP(pp_tie)
        /* Not clear why we don't call call_method here too.
         * perhaps to get different error message ?
         */
-       stash = gv_stashsv(*MARK, FALSE);
+       STRLEN len;
+       const char *name = SvPV_nomg_const(*MARK, len);
+       stash = gv_stashpvn(name, len, 0);
        if (!stash || !(gv = gv_fetchmethod(stash, methname))) {
            DIE(aTHX_ "Can't locate object method \"%s\" via package \"%"SVf"\"",
-                methname, *MARK);
+                methname, SVfARG(SvOK(*MARK) ? *MARK : &PL_sv_no));
        }
        ENTER;
        PUSHSTACKi(PERLSI_MAGIC);
@@ -856,7 +863,7 @@ PP(pp_tie)
             SvTYPE(varsv) == SVt_PVHV))
            Perl_croak(aTHX_
                       "Self-ties of arrays and hashes are not supported");
-       sv_magic(varsv, (SvRV(sv) == varsv ? Nullsv : sv), how, Nullch, 0);
+       sv_magic(varsv, (SvRV(sv) == varsv ? NULL : sv), how, NULL, 0);
     }
     LEAVE;
     SP = PL_stack_base + markoff;
@@ -872,7 +879,7 @@ PP(pp_untie)
     const char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
                ? PERL_MAGIC_tied : PERL_MAGIC_tiedscalar;
 
-    if (SvTYPE(sv) == SVt_PVGV && !(sv = (SV *)GvIOp(sv)))
+    if (isGV_with_GP(sv) && !(sv = (SV *)GvIOp(sv)))
        RETPUSHYES;
 
     if ((mg = SvTIED_mg(sv, how))) {
@@ -883,7 +890,7 @@ PP(pp_untie)
            if (gv && isGV(gv) && (cv = GvCV(gv))) {
               PUSHMARK(SP);
               XPUSHs(SvTIED_obj((SV*)gv, mg));
-              XPUSHs(sv_2mortal(newSViv(SvREFCNT(obj)-1)));
+              mXPUSHi(SvREFCNT(obj) - 1);
               PUTBACK;
               ENTER;
               call_sv((SV *)cv, G_VOID);
@@ -903,13 +910,14 @@ PP(pp_untie)
 
 PP(pp_tied)
 {
+    dVAR;
     dSP;
     const MAGIC *mg;
     SV *sv = POPs;
     const char how = (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
                ? PERL_MAGIC_tied : PERL_MAGIC_tiedscalar;
 
-    if (SvTYPE(sv) == SVt_PVGV && !(sv = (SV *)GvIOp(sv)))
+    if (isGV_with_GP(sv) && !(sv = (SV *)GvIOp(sv)))
        RETPUSHUNDEF;
 
     if ((mg = SvTIED_mg(sv, how))) {
@@ -930,15 +938,13 @@ PP(pp_dbmopen)
     GV *gv;
 
     HV * const hv = (HV*)POPs;
-    SV * const sv = sv_mortalcopy(&PL_sv_no);
-
-    sv_setpv(sv, "AnyDBM_File");
-    stash = gv_stashsv(sv, FALSE);
+    SV * const sv = newSVpvs_flags("AnyDBM_File", SVs_TEMP);
+    stash = gv_stashsv(sv, 0);
     if (!stash || !(gv = gv_fetchmethod(stash, "TIEHASH"))) {
        PUTBACK;
        require_pv("AnyDBM_File.pm");
        SPAGAIN;
-       if (!(gv = gv_fetchmethod(stash, "TIEHASH")))
+       if (!stash || !(gv = gv_fetchmethod(stash, "TIEHASH")))
            DIE(aTHX_ "No dbm on this machine");
     }
 
@@ -949,9 +955,9 @@ PP(pp_dbmopen)
     PUSHs(sv);
     PUSHs(left);
     if (SvIV(right))
-       PUSHs(sv_2mortal(newSVuv(O_RDWR|O_CREAT)));
+       mPUSHu(O_RDWR|O_CREAT);
     else
-       PUSHs(sv_2mortal(newSVuv(O_RDWR)));
+       mPUSHu(O_RDWR);
     PUSHs(right);
     PUTBACK;
     call_sv((SV*)GvCV(gv), G_SCALAR);
@@ -962,7 +968,7 @@ PP(pp_dbmopen)
        PUSHMARK(SP);
        PUSHs(sv);
        PUSHs(left);
-       PUSHs(sv_2mortal(newSVuv(O_RDONLY)));
+       mPUSHu(O_RDONLY);
        PUSHs(right);
        PUTBACK;
        call_sv((SV*)GvCV(gv), G_SCALAR);
@@ -971,7 +977,7 @@ PP(pp_dbmopen)
 
     if (sv_isobject(TOPs)) {
        sv_unmagic((SV *) hv, PERL_MAGIC_tied);
-       sv_magic((SV*)hv, TOPs, PERL_MAGIC_tied, Nullch, 0);
+       sv_magic((SV*)hv, TOPs, PERL_MAGIC_tied, NULL, 0);
     }
     LEAVE;
     RETURN;
@@ -980,7 +986,7 @@ PP(pp_dbmopen)
 PP(pp_sselect)
 {
 #ifdef HAS_SELECT
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     register I32 i;
     register I32 j;
     register char *s;
@@ -1066,7 +1072,7 @@ PP(pp_sselect)
        timebuf.tv_usec = (long)(value * 1000000.0);
     }
     else
-       tbuf = Null(struct timeval*);
+       tbuf = NULL;
 
     for (i = 1; i <= 3; i++) {
        sv = SP[i];
@@ -1133,8 +1139,7 @@ PP(pp_sselect)
     if (GIMME == G_ARRAY && tbuf) {
        value = (NV)(timebuf.tv_sec) +
                (NV)(timebuf.tv_usec) / 1000000.0;
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setnv(sv, value);
+       mPUSHn(value);
     }
     RETURN;
 #else
@@ -1145,8 +1150,8 @@ PP(pp_sselect)
 void
 Perl_setdefout(pTHX_ GV *gv)
 {
-    if (gv)
-       (void)SvREFCNT_inc(gv);
+    dVAR;
+    SvREFCNT_inc_simple_void(gv);
     if (PL_defoutgv)
        SvREFCNT_dec(PL_defoutgv);
     PL_defoutgv = gv;
@@ -1154,9 +1159,9 @@ Perl_setdefout(pTHX_ GV *gv)
 
 PP(pp_select)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     HV *hv;
-    GV * const newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : (GV *) NULL;
+    GV * const newdefout = (PL_op->op_private > 0) ? ((GV *) POPs) : NULL;
     GV * egv = GvEGV(PL_defoutgv);
 
     if (!egv)
@@ -1167,11 +1172,11 @@ PP(pp_select)
     else {
        GV * const * const gvp = (GV**)hv_fetch(hv, GvNAME(egv), GvNAMELEN(egv), FALSE);
        if (gvp && *gvp == egv) {
-           gv_efullname4(TARG, PL_defoutgv, Nullch, TRUE);
+           gv_efullname4(TARG, PL_defoutgv, NULL, TRUE);
            XPUSHTARG;
        }
        else {
-           XPUSHs(sv_2mortal(newRV((SV*)egv)));
+           mXPUSHs(newRV((SV*)egv));
        }
     }
 
@@ -1188,23 +1193,23 @@ PP(pp_getc)
 {
     dVAR; dSP; dTARGET;
     IO *io = NULL;
-    MAGIC *mg;
     GV * const gv = (MAXARG==0) ? PL_stdingv : (GV*)POPs;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       const I32 gimme = GIMME_V;
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       PUTBACK;
-       ENTER;
-       call_method("GETC", gimme);
-       LEAVE;
-       SPAGAIN;
-       if (gimme == G_SCALAR)
-           SvSetMagicSV_nosteal(TARG, TOPs);
-       RETURN;
+    if (gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           const I32 gimme = GIMME_V;
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
+           PUTBACK;
+           ENTER;
+           call_method("GETC", gimme);
+           LEAVE;
+           SPAGAIN;
+           if (gimme == G_SCALAR)
+               SvSetMagicSV_nosteal(TARG, TOPs);
+           RETURN;
+       }
     }
     if (!gv || do_eof(gv)) { /* make sure we have fp with something */
        if ((!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY))
@@ -1237,12 +1242,13 @@ S_doform(pTHX_ CV *cv, GV *gv, OP *retop)
     register PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
 
+    PERL_ARGS_ASSERT_DOFORM;
+
     ENTER;
     SAVETMPS;
 
     PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp);
-    PUSHFORMAT(cx);
-    cx->blk_sub.retop = retop;
+    PUSHFORMAT(cx, retop);
     SAVECOMPPAD();
     PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1);
 
@@ -1252,11 +1258,13 @@ S_doform(pTHX_ CV *cv, GV *gv, OP *retop)
 
 PP(pp_enterwrite)
 {
+    dVAR;
     dSP;
     register GV *gv;
     register IO *io;
     GV *fgv;
     CV *cv;
+    SV * tmpsv = NULL;
 
     if (MAXARG == 0)
        gv = PL_defoutgv;
@@ -1275,16 +1283,19 @@ PP(pp_enterwrite)
     else
        fgv = gv;
 
+    if (!fgv)
+       goto not_a_format_reference;
+
     cv = GvFORM(fgv);
     if (!cv) {
-       if (fgv) {
-           SV * const tmpsv = sv_newmortal();
-           const char *name;
-           gv_efullname4(tmpsv, fgv, Nullch, FALSE);
-           name = SvPV_nolen_const(tmpsv);
-           if (name && *name)
-               DIE(aTHX_ "Undefined format \"%s\" called", name);
-       }
+       const char *name;
+       tmpsv = sv_newmortal();
+       gv_efullname4(tmpsv, fgv, NULL, FALSE);
+       name = SvPV_nolen_const(tmpsv);
+       if (name && *name)
+           DIE(aTHX_ "Undefined format \"%s\" called", name);
+
+       not_a_format_reference:
        DIE(aTHX_ "Not a format reference");
     }
     if (CvCLONE(cv))
@@ -1297,18 +1308,20 @@ PP(pp_enterwrite)
 PP(pp_leavewrite)
 {
     dVAR; dSP;
-    GV * const gv = cxstack[cxstack_ix].blk_sub.gv;
+    GV * const gv = cxstack[cxstack_ix].blk_format.gv;
     register IO * const io = GvIOp(gv);
-    PerlIO * const ofp = IoOFP(io);
+    PerlIO *ofp;
     PerlIO *fp;
     SV **newsp;
     I32 gimme;
     register PERL_CONTEXT *cx;
 
+    if (!io || !(ofp = IoOFP(io)))
+        goto forget_top;
+
     DEBUG_f(PerlIO_printf(Perl_debug_log, "left=%ld, todo=%ld\n",
          (long)IoLINES_LEFT(io), (long)FmLINES(PL_formtarget)));
-    if (!io || !ofp)
-       goto forget_top;
+
     if (IoLINES_LEFT(io) < FmLINES(PL_formtarget) &&
        PL_formtarget != PL_toptarget)
     {
@@ -1322,14 +1335,14 @@ PP(pp_leavewrite)
                if (!IoFMT_NAME(io))
                    IoFMT_NAME(io) = savepv(GvNAME(gv));
                topname = sv_2mortal(Perl_newSVpvf(aTHX_ "%s_TOP", GvNAME(gv)));
-               topgv = gv_fetchsv(topname, FALSE, SVt_PVFM);
+               topgv = gv_fetchsv(topname, 0, SVt_PVFM);
                if ((topgv && GvFORM(topgv)) ||
-                 !gv_fetchpv("top",FALSE,SVt_PVFM))
+                 !gv_fetchpvs("top", GV_NOTQUAL, SVt_PVFM))
                    IoTOP_NAME(io) = savesvpv(topname);
                else
-                   IoTOP_NAME(io) = savepvn("top", 3);
+                   IoTOP_NAME(io) = savepvs("top");
            }
-           topgv = gv_fetchpv(IoTOP_NAME(io),FALSE, SVt_PVFM);
+           topgv = gv_fetchpv(IoTOP_NAME(io), 0, SVt_PVFM);
            if (!topgv || !GvFORM(topgv)) {
                IoLINES_LEFT(io) = IoPAGE_LEN(io);
                goto forget_top;
@@ -1369,18 +1382,16 @@ PP(pp_leavewrite)
        if (!cv) {
            SV * const sv = sv_newmortal();
            const char *name;
-           gv_efullname4(sv, fgv, Nullch, FALSE);
+           gv_efullname4(sv, fgv, NULL, FALSE);
            name = SvPV_nolen_const(sv);
            if (name && *name)
-               DIE(aTHX_ "Undefined top format \"%s\" called",name);
+               DIE(aTHX_ "Undefined top format \"%s\" called", name);
+           else
+               DIE(aTHX_ "Undefined top format called");
        }
-       /* why no:
-       else
-           DIE(aTHX_ "Undefined top format called");
-       ?*/
-       if (CvCLONE(cv))
+       if (cv && CvCLONE(cv))
            cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
-       return doform(cv,gv,PL_op);
+       return doform(cv, gv, PL_op);
     }
 
   forget_top:
@@ -1428,33 +1439,33 @@ PP(pp_prtf)
     IO *io;
     PerlIO *fp;
     SV *sv;
-    MAGIC *mg;
 
     GV * const gv = (PL_op->op_flags & OPf_STACKED) ? (GV*)*++MARK : PL_defoutgv;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       if (MARK == ORIGMARK) {
-           MEXTEND(SP, 1);
-           ++MARK;
-           Move(MARK, MARK + 1, (SP - MARK) + 1, SV*);
-           ++SP;
+    if (gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           if (MARK == ORIGMARK) {
+               MEXTEND(SP, 1);
+               ++MARK;
+               Move(MARK, MARK + 1, (SP - MARK) + 1, SV*);
+               ++SP;
+           }
+           PUSHMARK(MARK - 1);
+           *MARK = SvTIED_obj((SV*)io, mg);
+           PUTBACK;
+           ENTER;
+           call_method("PRINTF", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           MARK = ORIGMARK + 1;
+           *MARK = *SP;
+           SP = MARK;
+           RETURN;
        }
-       PUSHMARK(MARK - 1);
-       *MARK = SvTIED_obj((SV*)io, mg);
-       PUTBACK;
-       ENTER;
-       call_method("PRINTF", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       MARK = ORIGMARK + 1;
-       *MARK = *SP;
-       SP = MARK;
-       RETURN;
     }
 
-    sv = NEWSV(0,0);
+    sv = newSV(0);
     if (!(io = GvIO(gv))) {
        if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
            report_evil_fh(gv, io, PL_op->op_type);
@@ -1472,6 +1483,8 @@ PP(pp_prtf)
        goto just_say_no;
     }
     else {
+       if (SvTAINTED(MARK[1]))
+           TAINT_PROPER("printf");
        do_sprintf(sv, SP - MARK, MARK + 1);
        if (!do_print(sv, fp))
            goto just_say_no;
@@ -1494,6 +1507,7 @@ PP(pp_prtf)
 
 PP(pp_sysopen)
 {
+    dVAR;
     dSP;
     const int perm = (MAXARG > 3) ? POPi : 0666;
     const int mode = POPi;
@@ -1504,7 +1518,7 @@ PP(pp_sysopen)
     /* Need TIEHANDLE method ? */
     const char * const tmps = SvPV_const(sv, len);
     /* FIXME? do_open should do const  */
-    if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) {
+    if (do_open(gv, tmps, len, TRUE, mode, perm, NULL)) {
        IoLINES(GvIOp(gv)) = 0;
        PUSHs(&PL_sv_yes);
     }
@@ -1605,7 +1619,7 @@ PP(pp_sysread)
        buffer = SvGROW(bufsv, (STRLEN)(length+1));
        /* 'offset' means 'flags' here */
        count = PerlSock_recvfrom(PerlIO_fileno(IoIFP(io)), buffer, length, offset,
-                         (struct sockaddr *)namebuf, &bufsize);
+                                 (struct sockaddr *)namebuf, &bufsize);
        if (count < 0)
            RETPUSHUNDEF;
 #ifdef EPOC
@@ -1773,102 +1787,163 @@ PP(pp_send)
     IO *io;
     SV *bufsv;
     const char *buffer;
-    Size_t length = 0;
     SSize_t retval;
     STRLEN blen;
-    MAGIC *mg;
+    STRLEN orig_blen_bytes;
     const int op_type = PL_op->op_type;
+    bool doing_utf8;
+    U8 *tmpbuf = NULL;
     
     GV *const gv = (GV*)*++MARK;
     if (PL_op->op_type == OP_SYSWRITE
-       && gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       SV *sv;
+       && gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           SV *sv;
+
+           if (MARK == SP - 1) {
+               EXTEND(SP, 1000);
+               sv = sv_2mortal(newSViv(sv_len(*SP)));
+               PUSHs(sv);
+               PUTBACK;
+           }
 
-       if (MARK == SP - 1) {
-           EXTEND(SP, 1000);
-           sv = sv_2mortal(newSViv(sv_len(*SP)));
+           PUSHMARK(ORIGMARK);
+           *(ORIGMARK+1) = SvTIED_obj((SV*)io, mg);
+           ENTER;
+           call_method("WRITE", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           sv = POPs;
+           SP = ORIGMARK;
            PUSHs(sv);
-           PUTBACK;
+           RETURN;
        }
-       
-       PUSHMARK(ORIGMARK);
-       *(ORIGMARK+1) = SvTIED_obj((SV*)io, mg);
-       ENTER;
-       call_method("WRITE", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       sv = POPs;
-       SP = ORIGMARK;
-       PUSHs(sv);
-       RETURN;
     }
     if (!gv)
        goto say_undef;
 
     bufsv = *++MARK;
 
-    if (op_type == OP_SYSWRITE) {
-       if (MARK >= SP) {
-           length = (Size_t) sv_len(bufsv);
-       } else {
-#if Size_t_size > IVSIZE
-           length = (Size_t)SvNVx(*++MARK);
-#else
-           length = (Size_t)SvIVx(*++MARK);
-#endif
-           if ((SSize_t)length < 0)
-               DIE(aTHX_ "Negative length");
-       }
-    }
     SETERRNO(0,0);
     io = GvIO(gv);
-    if (!io || !IoIFP(io)) {
+    if (!io || !IoIFP(io) || IoTYPE(io) == IoTYPE_RDONLY) {
        retval = -1;
-       if (ckWARN(WARN_CLOSED))
-           report_evil_fh(gv, io, PL_op->op_type);
+       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) {
+           if (io && IoIFP(io))
+               report_evil_fh(gv, io, OP_phoney_INPUT_ONLY);
+           else
+               report_evil_fh(gv, io, PL_op->op_type);
+       }
        SETERRNO(EBADF,RMS_IFI);
        goto say_undef;
     }
 
+    /* Do this first to trigger any overloading.  */
+    buffer = SvPV_const(bufsv, blen);
+    orig_blen_bytes = blen;
+    doing_utf8 = DO_UTF8(bufsv);
+
     if (PerlIO_isutf8(IoIFP(io))) {
        if (!SvUTF8(bufsv)) {
-           bufsv = sv_2mortal(newSVsv(bufsv));
-           buffer = sv_2pvutf8(bufsv, &blen);
-       } else
-           buffer = SvPV_const(bufsv, blen);
+           /* We don't modify the original scalar.  */
+           tmpbuf = bytes_to_utf8((const U8*) buffer, &blen);
+           buffer = (char *) tmpbuf;
+           doing_utf8 = TRUE;
+       }
     }
-    else {
-        if (DO_UTF8(bufsv)) {
-             /* Not modifying source SV, so making a temporary copy. */
-             bufsv = sv_2mortal(newSVsv(bufsv));
-             sv_utf8_downgrade(bufsv, FALSE);
-        }
-        buffer = SvPV_const(bufsv, blen);
+    else if (doing_utf8) {
+       STRLEN tmplen = blen;
+       U8 * const result = bytes_from_utf8((const U8*) buffer, &tmplen, &doing_utf8);
+       if (!doing_utf8) {
+           tmpbuf = result;
+           buffer = (char *) tmpbuf;
+           blen = tmplen;
+       }
+       else {
+           assert((char *)result == buffer);
+           Perl_croak(aTHX_ "Wide character in %s", OP_DESC(PL_op));
+       }
     }
 
     if (op_type == OP_SYSWRITE) {
+       Size_t length = 0; /* This length is in characters.  */
+       STRLEN blen_chars;
        IV offset;
-       if (DO_UTF8(bufsv)) {
-           /* length and offset are in chars */
-           blen   = sv_len_utf8(bufsv);
+
+       if (doing_utf8) {
+           if (tmpbuf) {
+               /* The SV is bytes, and we've had to upgrade it.  */
+               blen_chars = orig_blen_bytes;
+           } else {
+               /* The SV really is UTF-8.  */
+               if (SvGMAGICAL(bufsv) || SvAMAGIC(bufsv)) {
+                   /* Don't call sv_len_utf8 again because it will call magic
+                      or overloading a second time, and we might get back a
+                      different result.  */
+                   blen_chars = utf8_length((U8*)buffer, (U8*)buffer + blen);
+               } else {
+                   /* It's safe, and it may well be cached.  */
+                   blen_chars = sv_len_utf8(bufsv);
+               }
+           }
+       } else {
+           blen_chars = blen;
        }
+
+       if (MARK >= SP) {
+           length = blen_chars;
+       } else {
+#if Size_t_size > IVSIZE
+           length = (Size_t)SvNVx(*++MARK);
+#else
+           length = (Size_t)SvIVx(*++MARK);
+#endif
+           if ((SSize_t)length < 0) {
+               Safefree(tmpbuf);
+               DIE(aTHX_ "Negative length");
+           }
+       }
+
        if (MARK < SP) {
            offset = SvIVx(*++MARK);
            if (offset < 0) {
-               if (-offset > (IV)blen)
+               if (-offset > (IV)blen_chars) {
+                   Safefree(tmpbuf);
                    DIE(aTHX_ "Offset outside string");
-               offset += blen;
-           } else if (offset >= (IV)blen && blen > 0)
+               }
+               offset += blen_chars;
+           } else if (offset >= (IV)blen_chars && blen_chars > 0) {
+               Safefree(tmpbuf);
                DIE(aTHX_ "Offset outside string");
+           }
        } else
            offset = 0;
-       if (length > blen - offset)
-           length = blen - offset;
-       if (DO_UTF8(bufsv)) {
-           buffer = (const char*)utf8_hop((const U8 *)buffer, offset);
-           length = utf8_hop((U8 *)buffer, length) - (U8 *)buffer;
+       if (length > blen_chars - offset)
+           length = blen_chars - offset;
+       if (doing_utf8) {
+           /* Here we convert length from characters to bytes.  */
+           if (tmpbuf || SvGMAGICAL(bufsv) || SvAMAGIC(bufsv)) {
+               /* Either we had to convert the SV, or the SV is magical, or
+                  the SV has overloading, in which case we can't or mustn't
+                  or mustn't call it again.  */
+
+               buffer = (const char*)utf8_hop((const U8 *)buffer, offset);
+               length = utf8_hop((U8 *)buffer, length) - (U8 *)buffer;
+           } else {
+               /* It's a real UTF-8 SV, and it's not going to change under
+                  us.  Take advantage of any cache.  */
+               I32 start = offset;
+               I32 len_I32 = length;
+
+               /* Convert the start and end character positions to bytes.
+                  Remember that the second argument to sv_pos_u2b is relative
+                  to the first.  */
+               sv_pos_u2b(bufsv, &start, &len_I32);
+
+               buffer += start;
+               length = len_I32;
+           }
        }
        else {
            buffer = buffer+offset;
@@ -1904,11 +1979,14 @@ PP(pp_send)
     else
        DIE(aTHX_ PL_no_sock_func, "send");
 #endif
+
     if (retval < 0)
        goto say_undef;
     SP = ORIGMARK;
-    if (DO_UTF8(bufsv))
+    if (doing_utf8)
         retval = utf8_length((U8*)buffer, (U8*)buffer + retval);
+
+    Safefree(tmpbuf);
 #if Size_t_size > IVSIZE
     PUSHn(retval);
 #else
@@ -1917,6 +1995,7 @@ PP(pp_send)
     RETURN;
 
   say_undef:
+    Safefree(tmpbuf);
     SP = ORIGMARK;
     RETPUSHUNDEF;
 }
@@ -1925,8 +2004,6 @@ PP(pp_eof)
 {
     dVAR; dSP;
     GV *gv;
-    IO *io;
-    MAGIC *mg;
 
     if (MAXARG == 0) {
        if (PL_op->op_flags & OPf_SPECIAL) {    /* eof() */
@@ -1937,8 +2014,13 @@ PP(pp_eof)
                if ((IoFLAGS(io) & IOf_START) && av_len(GvAVn(gv)) < 0) {
                    IoLINES(io) = 0;
                    IoFLAGS(io) &= ~IOf_START;
-                   do_open(gv, "-", 1, FALSE, O_RDONLY, 0, Nullfp);
-                   sv_setpvn(GvSV(gv), "-", 1);
+                   do_open(gv, "-", 1, FALSE, O_RDONLY, 0, NULL);
+                   if ( GvSV(gv) ) {
+                       sv_setpvn(GvSV(gv), "-", 1);
+                   }
+                   else {
+                       GvSV(gv) = newSVpvn("-", 1);
+                   }
                    SvSETMAGIC(GvSV(gv));
                }
                else if (!nextargv(gv))
@@ -1951,17 +2033,19 @@ PP(pp_eof)
     else
        gv = PL_last_in_gv = (GV*)POPs;         /* eof(FH) */
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       PUTBACK;
-       ENTER;
-       call_method("EOF", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       RETURN;
+    if (gv) {
+       IO * const io = GvIO(gv);
+       MAGIC * mg;
+       if (io && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
+           PUTBACK;
+           ENTER;
+           call_method("EOF", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           RETURN;
+       }
     }
 
     PUSHs(boolSV(!gv || do_eof(gv)));
@@ -1973,23 +2057,23 @@ PP(pp_tell)
     dVAR; dSP; dTARGET;
     GV *gv;
     IO *io;
-    MAGIC *mg;
 
     if (MAXARG != 0)
        PL_last_in_gv = (GV*)POPs;
     gv = PL_last_in_gv;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
-       PUTBACK;
-       ENTER;
-       call_method("TELL", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       RETURN;
+    if (gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
+           PUTBACK;
+           ENTER;
+           call_method("TELL", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           RETURN;
+       }
     }
 
 #if LSEEKSIZE > IVSIZE
@@ -2003,34 +2087,34 @@ PP(pp_tell)
 PP(pp_sysseek)
 {
     dVAR; dSP;
-    IO *io;
     const int whence = POPi;
 #if LSEEKSIZE > IVSIZE
     const Off_t offset = (Off_t)SvNVx(POPs);
 #else
     const Off_t offset = (Off_t)SvIVx(POPs);
 #endif
-    MAGIC *mg;
 
     GV * const gv = PL_last_in_gv = (GV*)POPs;
+    IO *io;
 
-    if (gv && (io = GvIO(gv))
-       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar)))
-    {
-       PUSHMARK(SP);
-       XPUSHs(SvTIED_obj((SV*)io, mg));
+    if (gv && (io = GvIO(gv))) {
+       MAGIC * const mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar);
+       if (mg) {
+           PUSHMARK(SP);
+           XPUSHs(SvTIED_obj((SV*)io, mg));
 #if LSEEKSIZE > IVSIZE
-       XPUSHs(sv_2mortal(newSVnv((NV) offset)));
+           mXPUSHn((NV) offset);
 #else
-       XPUSHs(sv_2mortal(newSViv(offset)));
+           mXPUSHi(offset);
 #endif
-       XPUSHs(sv_2mortal(newSViv(whence)));
-       PUTBACK;
-       ENTER;
-       call_method("SEEK", G_SCALAR);
-       LEAVE;
-       SPAGAIN;
-       RETURN;
+           mXPUSHi(whence);
+           PUTBACK;
+           ENTER;
+           call_method("SEEK", G_SCALAR);
+           LEAVE;
+           SPAGAIN;
+           RETURN;
+       }
     }
 
     if (PL_op->op_type == OP_SEEK)
@@ -2047,7 +2131,7 @@ PP(pp_sysseek)
                 newSViv(sought)
 #endif
                 : newSVpvn(zero_but_true, ZBTLEN);
-            PUSHs(sv_2mortal(sv));
+            mPUSHs(sv);
         }
     }
     RETURN;
@@ -2055,6 +2139,7 @@ PP(pp_sysseek)
 
 PP(pp_truncate)
 {
+    dVAR;
     dSP;
     /* There seems to be no consensus on the length type of truncate()
      * and ftruncate(), both off_t and size_t have supporters. In
@@ -2078,7 +2163,7 @@ PP(pp_truncate)
        IO *io;
 
        if (PL_op->op_flags & OPf_SPECIAL) {
-           tmpgv = gv_fetchsv(POPs, FALSE, SVt_PVIO);
+           tmpgv = gv_fetchsv(POPs, 0, SVt_PVIO);
 
        do_ftruncate_gv:
            if (!GvIO(tmpgv))
@@ -2106,11 +2191,11 @@ PP(pp_truncate)
            SV * const sv = POPs;
            const char *name;
 
-           if (SvTYPE(sv) == SVt_PVGV) {
+           if (isGV_with_GP(sv)) {
                tmpgv = (GV*)sv;                /* *main::FRED for example */
                goto do_ftruncate_gv;
            }
-           else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
+           else if (SvROK(sv) && isGV_with_GP(SvRV(sv))) {
                tmpgv = (GV*) SvRV(sv); /* \*main::FRED for example */
                goto do_ftruncate_gv;
            }
@@ -2149,12 +2234,12 @@ PP(pp_truncate)
 
 PP(pp_ioctl)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     SV * const argsv = POPs;
     const unsigned int func = POPu;
     const int optype = PL_op->op_type;
     GV * const gv = (GV*)POPs;
-    IO * const io = gv ? GvIOn(gv) : Null(IO*);
+    IO * const io = gv ? GvIOn(gv) : NULL;
     char *s;
     IV retval;
 
@@ -2182,7 +2267,7 @@ PP(pp_ioctl)
        s = INT2PTR(char*,retval);              /* ouch */
     }
 
-    TAINT_PROPER(optype == OP_IOCTL ? "ioctl" : "fcntl");
+    TAINT_PROPER(PL_op_desc[optype]);
 
     if (optype == OP_IOCTL)
 #ifdef HAS_IOCTL
@@ -2225,7 +2310,7 @@ PP(pp_ioctl)
 PP(pp_flock)
 {
 #ifdef FLOCK
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     I32 value;
     IO *io = NULL;
     PerlIO *fp;
@@ -2235,7 +2320,7 @@ PP(pp_flock)
     if (gv && (io = GvIO(gv)))
        fp = IoIFP(io);
     else {
-       fp = Nullfp;
+       fp = NULL;
        io = NULL;
     }
     /* XXX Looks to me like io is always NULL at this point */
@@ -2261,7 +2346,7 @@ PP(pp_flock)
 PP(pp_socket)
 {
 #ifdef HAS_SOCKET
-    dSP;
+    dVAR; dSP;
     const int protocol = POPi;
     const int type = POPi;
     const int domain = POPi;
@@ -2272,7 +2357,7 @@ PP(pp_socket)
     if (!gv || !io) {
        if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
            report_evil_fh(gv, io, PL_op->op_type);
-       if (IoIFP(io))
+       if (io && IoIFP(io))
            do_close(gv, FALSE);
        SETERRNO(EBADF,LIB_INVARG);
        RETPUSHUNDEF;
@@ -2311,7 +2396,7 @@ PP(pp_socket)
 PP(pp_sockpair)
 {
 #if defined (HAS_SOCKETPAIR) || (defined (HAS_SOCKET) && defined(SOCK_DGRAM) && defined(AF_INET) && defined(PF_INET))
-    dSP;
+    dVAR; dSP;
     const int protocol = POPi;
     const int type = POPi;
     const int domain = POPi;
@@ -2328,9 +2413,9 @@ PP(pp_sockpair)
            if (!gv2 || !io2)
                report_evil_fh(gv1, io2, PL_op->op_type);
        }
-       if (IoIFP(io1))
+       if (io1 && IoIFP(io1))
            do_close(gv1, FALSE);
-       if (IoIFP(io2))
+       if (io2 && IoIFP(io2))
            do_close(gv2, FALSE);
        RETPUSHUNDEF;
     }
@@ -2372,49 +2457,20 @@ PP(pp_sockpair)
 PP(pp_bind)
 {
 #ifdef HAS_SOCKET
-    dSP;
-#ifdef MPE /* Requires PRIV mode to bind() to ports < 1024 */
-    extern void GETPRIVMODE();
-    extern void GETUSERMODE();
-#endif
+    dVAR; dSP;
     SV * const addrsv = POPs;
     /* OK, so on what platform does bind modify addr?  */
     const char *addr;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
     STRLEN len;
-    int bind_ok = 0;
-#ifdef MPE
-    int mpeprivmode = 0;
-#endif
 
     if (!io || !IoIFP(io))
        goto nuts;
 
     addr = SvPV_const(addrsv, len);
     TAINT_PROPER("bind");
-#ifdef MPE /* Deal with MPE bind() peculiarities */
-    if (((struct sockaddr *)addr)->sa_family == AF_INET) {
-        /* The address *MUST* stupidly be zero. */
-        ((struct sockaddr_in *)addr)->sin_addr.s_addr = INADDR_ANY;
-        /* PRIV mode is required to bind() to ports < 1024. */
-        if (((struct sockaddr_in *)addr)->sin_port < 1024 &&
-            ((struct sockaddr_in *)addr)->sin_port > 0) {
-            GETPRIVMODE(); /* If this fails, we are aborted by MPE/iX. */
-           mpeprivmode = 1;
-       }
-    }
-#endif /* MPE */
-    if (PerlSock_bind(PerlIO_fileno(IoIFP(io)),
-                     (struct sockaddr *)addr, len) >= 0)
-       bind_ok = 1;
-
-#ifdef MPE /* Switch back to USER mode */
-    if (mpeprivmode)
-       GETUSERMODE();
-#endif /* MPE */
-
-    if (bind_ok)
+    if (PerlSock_bind(PerlIO_fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
        RETPUSHYES;
     else
        RETPUSHUNDEF;
@@ -2432,7 +2488,7 @@ nuts:
 PP(pp_connect)
 {
 #ifdef HAS_SOCKET
-    dSP;
+    dVAR; dSP;
     SV * const addrsv = POPs;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
@@ -2462,7 +2518,7 @@ nuts:
 PP(pp_listen)
 {
 #ifdef HAS_SOCKET
-    dSP;
+    dVAR; dSP;
     const int backlog = POPi;
     GV * const gv = (GV*)POPs;
     register IO * const io = gv ? GvIOn(gv) : NULL;
@@ -2488,7 +2544,7 @@ nuts:
 PP(pp_accept)
 {
 #ifdef HAS_SOCKET
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     register IO *nstio;
     register IO *gstio;
     char namebuf[MAXPATHLEN];
@@ -2512,6 +2568,17 @@ PP(pp_accept)
 
     nstio = GvIOn(ngv);
     fd = PerlSock_accept(PerlIO_fileno(IoIFP(gstio)), (struct sockaddr *) namebuf, &len);
+#if defined(OEMVS)
+    if (len == 0) {
+       /* Some platforms indicate zero length when an AF_UNIX client is
+        * not bound. Simulate a non-zero-length sockaddr structure in
+        * this case. */
+       namebuf[0] = 0;        /* sun_len */
+       namebuf[1] = AF_UNIX;  /* sun_family */
+       len = 2;
+    }
+#endif
+
     if (fd < 0)
        goto badexit;
     if (IoIFP(nstio))
@@ -2556,7 +2623,7 @@ badexit:
 PP(pp_shutdown)
 {
 #ifdef HAS_SOCKET
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     const int how = POPi;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
@@ -2580,9 +2647,9 @@ nuts:
 PP(pp_ssockopt)
 {
 #ifdef HAS_SOCKET
-    dSP;
+    dVAR; dSP;
     const int optype = PL_op->op_type;
-    SV * const sv = (optype == OP_GSOCKOPT) ? sv_2mortal(NEWSV(22, 257)) : POPs;
+    SV * const sv = (optype == OP_GSOCKOPT) ? sv_2mortal(newSV(257)) : POPs;
     const unsigned int optname = (unsigned int) POPi;
     const unsigned int lvl = (unsigned int) POPi;
     GV * const gv = (GV*)POPs;
@@ -2657,7 +2724,7 @@ nuts2:
 PP(pp_getpeername)
 {
 #ifdef HAS_SOCKET
-    dSP;
+    dVAR; dSP;
     const int optype = PL_op->op_type;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
@@ -2668,7 +2735,7 @@ PP(pp_getpeername)
     if (!io || !IoIFP(io))
        goto nuts;
 
-    sv = sv_2mortal(NEWSV(22, 257));
+    sv = sv_2mortal(newSV(257));
     (void)SvPOK_only(sv);
     len = 256;
     SvCUR_set(sv, len);
@@ -2722,8 +2789,10 @@ nuts2:
 
 PP(pp_stat)
 {
+    dVAR;
     dSP;
-    GV *gv;
+    GV *gv = NULL;
+    IO *io;
     I32 gimme;
     I32 max = 13;
 
@@ -2734,7 +2803,7 @@ PP(pp_stat)
            do_fstat_warning_check:
                if (ckWARN(WARN_IO))
                    Perl_warner(aTHX_ packWARN(WARN_IO),
-                       "lstat() on filehandle %s", GvENAME(gv));
+                       "lstat() on filehandle %s", gv ? GvENAME(gv) : "");
            } else if (PL_laststype != OP_LSTAT)
                Perl_croak(aTHX_ "The stat preceding lstat() wasn't an lstat");
        }
@@ -2744,9 +2813,23 @@ PP(pp_stat)
            PL_laststype = OP_STAT;
            PL_statgv = gv;
            sv_setpvn(PL_statname, "", 0);
-           PL_laststatval = (GvIO(gv) && IoIFP(GvIOp(gv))
-               ? PerlLIO_fstat(PerlIO_fileno(IoIFP(GvIOn(gv))), &PL_statcache) : -1);
-       }
+            if(gv) {
+                io = GvIO(gv);
+                do_fstat_have_io:
+                if (io) {
+                    if (IoIFP(io)) {
+                        PL_laststatval = 
+                            PerlLIO_fstat(PerlIO_fileno(IoIFP(io)), &PL_statcache);   
+                    } else if (IoDIRP(io)) {
+                        PL_laststatval =
+                            PerlLIO_fstat(my_dirfd(IoDIRP(io)), &PL_statcache);
+                    } else {
+                        PL_laststatval = -1;
+                    }
+               }
+            }
+        }
+
        if (PL_laststatval < 0) {
            if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
                report_evil_fh(gv, GvIO(gv), PL_op->op_type);
@@ -2755,18 +2838,23 @@ PP(pp_stat)
     }
     else {
        SV* const sv = POPs;
-       if (SvTYPE(sv) == SVt_PVGV) {
+       if (isGV_with_GP(sv)) {
            gv = (GV*)sv;
            goto do_fstat;
-       }
-       else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
-           gv = (GV*)SvRV(sv);
-           if (PL_op->op_type == OP_LSTAT)
-               goto do_fstat_warning_check;
-           goto do_fstat;
-       }
+       } else if(SvROK(sv) && isGV_with_GP(SvRV(sv))) {
+            gv = (GV*)SvRV(sv);
+            if (PL_op->op_type == OP_LSTAT)
+                goto do_fstat_warning_check;
+            goto do_fstat;
+        } else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVIO) { 
+            io = (IO*)SvRV(sv);
+            if (PL_op->op_type == OP_LSTAT)
+                goto do_fstat_warning_check;
+            goto do_fstat_have_io; 
+        }
+        
        sv_setpv(PL_statname, SvPV_nolen_const(sv));
-       PL_statgv = Nullgv;
+       PL_statgv = NULL;
        PL_laststype = PL_op->op_type;
        if (PL_op->op_type == OP_LSTAT)
            PL_laststatval = PerlLIO_lstat(SvPV_nolen_const(PL_statname), &PL_statcache);
@@ -2788,53 +2876,53 @@ PP(pp_stat)
     if (max) {
        EXTEND(SP, max);
        EXTEND_MORTAL(max);
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_dev)));
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ino)));
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_mode)));
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_nlink)));
+       mPUSHi(PL_statcache.st_dev);
+       mPUSHi(PL_statcache.st_ino);
+       mPUSHu(PL_statcache.st_mode);
+       mPUSHu(PL_statcache.st_nlink);
 #if Uid_t_size > IVSIZE
-       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_uid)));
+       mPUSHn(PL_statcache.st_uid);
 #else
 #   if Uid_t_sign <= 0
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_uid)));
+       mPUSHi(PL_statcache.st_uid);
 #   else
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_uid)));
+       mPUSHu(PL_statcache.st_uid);
 #   endif
 #endif
 #if Gid_t_size > IVSIZE
-       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_gid)));
+       mPUSHn(PL_statcache.st_gid);
 #else
 #   if Gid_t_sign <= 0
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_gid)));
+       mPUSHi(PL_statcache.st_gid);
 #   else
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_gid)));
+       mPUSHu(PL_statcache.st_gid);
 #   endif
 #endif
 #ifdef USE_STAT_RDEV
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_rdev)));
+       mPUSHi(PL_statcache.st_rdev);
 #else
-       PUSHs(sv_2mortal(newSVpvn("", 0)));
+       PUSHs(newSVpvs_flags("", SVs_TEMP));
 #endif
 #if Off_t_size > IVSIZE
-       PUSHs(sv_2mortal(newSVnv((NV)PL_statcache.st_size)));
+       mPUSHn(PL_statcache.st_size);
 #else
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_size)));
+       mPUSHi(PL_statcache.st_size);
 #endif
 #ifdef BIG_TIME
-       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSVnv(PL_statcache.st_ctime)));
+       mPUSHn(PL_statcache.st_atime);
+       mPUSHn(PL_statcache.st_mtime);
+       mPUSHn(PL_statcache.st_ctime);
 #else
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_atime)));
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_mtime)));
-       PUSHs(sv_2mortal(newSViv(PL_statcache.st_ctime)));
+       mPUSHi(PL_statcache.st_atime);
+       mPUSHi(PL_statcache.st_mtime);
+       mPUSHi(PL_statcache.st_ctime);
 #endif
 #ifdef USE_STAT_BLOCKS
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_blksize)));
-       PUSHs(sv_2mortal(newSVuv(PL_statcache.st_blocks)));
+       mPUSHu(PL_statcache.st_blksize);
+       mPUSHu(PL_statcache.st_blocks);
 #else
-       PUSHs(sv_2mortal(newSVpvn("", 0)));
-       PUSHs(sv_2mortal(newSVpvn("", 0)));
+       PUSHs(newSVpvs_flags("", SVs_TEMP));
+       PUSHs(newSVpvs_flags("", SVs_TEMP));
 #endif
     }
     RETURN;
@@ -2851,6 +2939,7 @@ PP(pp_stat)
 
 PP(pp_ftrread)
 {
+    dVAR;
     I32 result;
     /* Not const, because things tweak this below. Not bool, because there's
        no guarantee that OPp_FT_ACCESS is <= CHAR_MAX  */
@@ -2913,10 +3002,9 @@ PP(pp_ftrread)
        effective = TRUE;
        break;
 
-
     case OP_FTEEXEC:
 #ifdef PERL_EFF_ACCESS
-       access_mode = W_OK;
+       access_mode = X_OK;
 #else
        use_access = 0;
 #endif
@@ -2927,7 +3015,7 @@ PP(pp_ftrread)
 
     if (use_access) {
 #if defined(HAS_ACCESS) || defined (PERL_EFF_ACCESS)
-       const char *const name = POPpx;
+       const char *name = POPpx;
        if (effective) {
 #  ifdef PERL_EFF_ACCESS
            result = PERL_EFF_ACCESS(name, access_mode);
@@ -2962,6 +3050,7 @@ PP(pp_ftrread)
 
 PP(pp_ftis)
 {
+    dVAR;
     I32 result;
     const int op_type = PL_op->op_type;
     dSP;
@@ -3000,6 +3089,7 @@ PP(pp_ftis)
 
 PP(pp_ftrowned)
 {
+    dVAR;
     I32 result;
     dSP;
 
@@ -3084,6 +3174,7 @@ PP(pp_ftrowned)
 
 PP(pp_ftlink)
 {
+    dVAR;
     I32 result = my_lstat();
     dSP;
     if (result < 0)
@@ -3095,10 +3186,11 @@ PP(pp_ftlink)
 
 PP(pp_fttty)
 {
+    dVAR;
     dSP;
     int fd;
     GV *gv;
-    SV *tmpsv = Nullsv;
+    SV *tmpsv = NULL;
 
     STACKED_FTEST_CHECK;
 
@@ -3109,7 +3201,7 @@ PP(pp_fttty)
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
        gv = (GV*)SvRV(POPs);
     else
-       gv = gv_fetchsv(tmpsv = POPs, FALSE, SVt_PVIO);
+       gv = gv_fetchsv(tmpsv = POPs, 0, SVt_PVIO);
 
     if (GvIO(gv) && IoIFP(GvIOp(gv)))
        fd = PerlIO_fileno(IoIFP(GvIOp(gv)));
@@ -3137,6 +3229,7 @@ PP(pp_fttty)
 
 PP(pp_fttext)
 {
+    dVAR;
     dSP;
     I32 i;
     I32 len;
@@ -3157,7 +3250,7 @@ PP(pp_fttext)
     else if (SvROK(TOPs) && isGV(SvRV(TOPs)))
        gv = (GV*)SvRV(POPs);
     else
-       gv = Nullgv;
+       gv = NULL;
 
     if (gv) {
        EXTEND(SP, 1);
@@ -3212,7 +3305,7 @@ PP(pp_fttext)
     else {
        sv = POPs;
       really_filename:
-       PL_statgv = Nullgv;
+       PL_statgv = NULL;
        PL_laststype = OP_STAT;
        sv_setpv(PL_statname, SvPV_nolen_const(sv));
        if (!(fp = PerlIO_open(SvPVX_const(PL_statname), "r"))) {
@@ -3226,7 +3319,7 @@ PP(pp_fttext)
            (void)PerlIO_close(fp);
            RETPUSHUNDEF;
        }
-       PerlIO_binmode(aTHX_ fp, '<', O_BINARY, Nullch);
+       PerlIO_binmode(aTHX_ fp, '<', O_BINARY, NULL);
        len = PerlIO_read(fp, tbuf, sizeof(tbuf));
        (void)PerlIO_close(fp);
        if (len <= 0) {
@@ -3242,7 +3335,7 @@ PP(pp_fttext)
 
 #if defined(DOSISH) || defined(USEMYBINMODE)
     /* ignore trailing ^Z on short files */
-    if (len && len < sizeof(tbuf) && tbuf[len-1] == 26)
+    if (len && len < (I32)sizeof(tbuf) && tbuf[len-1] == 26)
        --len;
 #endif
 
@@ -3295,20 +3388,23 @@ PP(pp_fttext)
 
 PP(pp_chdir)
 {
-    dSP; dTARGET;
-    const char *tmps = 0;
+    dVAR; dSP; dTARGET;
+    const char *tmps = NULL;
     GV *gv = NULL;
 
     if( MAXARG == 1 ) {
        SV * const sv = POPs;
-        if (SvTYPE(sv) == SVt_PVGV) {
+       if (PL_op->op_flags & OPf_SPECIAL) {
+           gv = gv_fetchsv(sv, 0, SVt_PVIO);
+       }
+        else if (isGV_with_GP(sv)) {
            gv = (GV*)sv;
         }
-       else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
+       else if (SvROK(sv) && isGV_with_GP(SvRV(sv))) {
             gv = (GV*)SvRV(sv);
         }
         else {
-           tmps = SvPVx_nolen_const(sv);
+           tmps = SvPV_nolen_const(sv);
        }
     }
 
@@ -3316,10 +3412,10 @@ PP(pp_chdir)
        HV * const table = GvHVn(PL_envgv);
        SV **svp;
 
-        if (    (svp = hv_fetch(table, "HOME", 4, FALSE))
-             || (svp = hv_fetch(table, "LOGDIR", 6, FALSE))
+        if (    (svp = hv_fetchs(table, "HOME", FALSE))
+             || (svp = hv_fetchs(table, "LOGDIR", FALSE))
 #ifdef VMS
-             || (svp = hv_fetch(table, "SYS$LOGIN", 9, FALSE))
+             || (svp = hv_fetchs(table, "SYS$LOGIN", FALSE))
 #endif
            )
         {
@@ -3339,21 +3435,22 @@ PP(pp_chdir)
 #ifdef HAS_FCHDIR
        IO* const io = GvIO(gv);
        if (io) {
-           if (IoIFP(io)) {
-               PUSHi(fchdir(PerlIO_fileno(IoIFP(io))) >= 0);
-           }
-           else if (IoDIRP(io)) {
-#ifdef HAS_DIRFD
-               PUSHi(fchdir(dirfd(IoDIRP(io))) >= 0);
-#else
-               DIE(aTHX_ PL_no_func, "dirfd");
-#endif
+           if (IoDIRP(io)) {
+               PUSHi(fchdir(my_dirfd(IoDIRP(io))) >= 0);
+           } else if (IoIFP(io)) {
+                PUSHi(fchdir(PerlIO_fileno(IoIFP(io))) >= 0);
            }
            else {
+               if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+                   report_evil_fh(gv, io, PL_op->op_type);
+               SETERRNO(EBADF, RMS_IFI);
                PUSHi(0);
            }
         }
        else {
+           if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
+               report_evil_fh(gv, io, PL_op->op_type);
+           SETERRNO(EBADF,RMS_IFI);
            PUSHi(0);
        }
 #else
@@ -3372,7 +3469,7 @@ PP(pp_chdir)
 
 PP(pp_chown)
 {
-    dSP; dMARK; dTARGET;
+    dVAR; dSP; dMARK; dTARGET;
     const I32 value = (I32)apply(PL_op->op_type, MARK, SP);
 
     SP = MARK;
@@ -3383,7 +3480,7 @@ PP(pp_chown)
 PP(pp_chroot)
 {
 #ifdef HAS_CHROOT
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     char * const tmps = POPpx;
     TAINT_PROPER("chroot");
     PUSHi( chroot(tmps) >= 0 );
@@ -3395,7 +3492,7 @@ PP(pp_chroot)
 
 PP(pp_rename)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     int anum;
     const char * const tmps2 = POPpconstx;
     const char * const tmps = SvPV_nolen_const(TOPs);
@@ -3421,7 +3518,7 @@ PP(pp_rename)
 #if defined(HAS_LINK) || defined(HAS_SYMLINK)
 PP(pp_link)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     const int op_type = PL_op->op_type;
     int result;
 
@@ -3469,6 +3566,7 @@ PP(pp_link)
 
 PP(pp_readlink)
 {
+    dVAR;
     dSP;
 #ifdef HAS_SYMLINK
     dTARGET;
@@ -3501,15 +3599,19 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename)
     char *s;
     PerlIO *myfp;
     int anum = 1;
+    Size_t size = strlen(cmd) + (strlen(filename) * 2) + 10;
+
+    PERL_ARGS_ASSERT_DOONELINER;
 
-    Newx(cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
-    strcpy(cmdline, cmd);
-    strcat(cmdline, " ");
+    Newx(cmdline, size, char);
+    my_strlcpy(cmdline, cmd, size);
+    my_strlcat(cmdline, " ", size);
     for (s = cmdline + strlen(cmdline); *filename; ) {
        *s++ = '\\';
        *s++ = *filename++;
     }
-    strcpy(s, " 2>&1");
+    if (s - cmdline < size)
+       my_strlcpy(s, " 2>&1", size - (s - cmdline));
     myfp = PerlProc_popen(cmdline, "r");
     Safefree(cmdline);
 
@@ -3518,7 +3620,7 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename)
        /* Need to save/restore 'PL_rs' ?? */
        s = sv_gets(tmpsv, myfp, 0);
        (void)PerlProc_pclose(myfp);
-       if (s != Nullch) {
+       if (s != NULL) {
            int e;
            for (e = 1;
 #ifdef HAS_SYS_ERRLIST
@@ -3527,7 +3629,7 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename)
                 ; e++)
            {
                /* you don't see this */
-               char *errmsg =
+               const char * const errmsg =
 #ifdef HAS_SYS_ERRLIST
                    sys_errlist[e]
 #else
@@ -3601,7 +3703,7 @@ S_dooneliner(pTHX_ const char *cmd, const char *filename)
 
 PP(pp_mkdir)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     STRLEN len;
     const char *tmps;
     bool copy = FALSE;
@@ -3628,7 +3730,7 @@ PP(pp_mkdir)
 
 PP(pp_rmdir)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     STRLEN len;
     const char *tmps;
     bool copy = FALSE;
@@ -3650,7 +3752,7 @@ PP(pp_rmdir)
 PP(pp_open_dir)
 {
 #if defined(Direntry_t) && defined(HAS_READDIR)
-    dSP;
+    dVAR; dSP;
     const char * const dirname = POPpconstx;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
@@ -3658,6 +3760,9 @@ PP(pp_open_dir)
     if (!io)
        goto nope;
 
+    if ((IoIFP(io) || IoOFP(io)) && ckWARN2(WARN_IO, WARN_DEPRECATED))
+       Perl_warner(aTHX_ packWARN2(WARN_IO, WARN_DEPRECATED),
+               "Opening filehandle %s also as a directory", GvENAME(gv));
     if (IoDIRP(io))
        PerlDir_close(IoDIRP(io));
     if (!(IoDIRP(io) = PerlDir_open(dirname)))
@@ -3681,6 +3786,7 @@ PP(pp_readdir)
 #if !defined(I_DIRENT) && !defined(VMS)
     Direntry_t *readdir (DIR *);
 #endif
+    dVAR;
     dSP;
 
     SV *sv;
@@ -3689,8 +3795,13 @@ PP(pp_readdir)
     register const Direntry_t *dp;
     register IO * const io = GvIOn(gv);
 
-    if (!io || !IoDIRP(io))
-       goto nope;
+    if (!io || !IoDIRP(io)) {
+        if(ckWARN(WARN_IO)) {
+            Perl_warner(aTHX_ packWARN(WARN_IO),
+                "readdir() attempted on invalid dirhandle %s", GvENAME(gv));
+        }
+        goto nope;
+    }
 
     do {
         dp = (Direntry_t *)PerlDir_read(IoDIRP(io));
@@ -3705,9 +3816,8 @@ PP(pp_readdir)
         if (!(IoFLAGS(io) & IOf_UNTAINT))
             SvTAINTED_on(sv);
 #endif
-        XPUSHs(sv_2mortal(sv));
-    }
-    while (gimme == G_ARRAY);
+        mXPUSHs(sv);
+    } while (gimme == G_ARRAY);
 
     if (!dp && gimme != G_ARRAY)
         goto nope;
@@ -3738,8 +3848,13 @@ PP(pp_telldir)
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
 
-    if (!io || !IoDIRP(io))
-       goto nope;
+    if (!io || !IoDIRP(io)) {
+        if(ckWARN(WARN_IO)) {
+            Perl_warner(aTHX_ packWARN(WARN_IO),
+               "telldir() attempted on invalid dirhandle %s", GvENAME(gv));
+        }
+        goto nope;
+    }
 
     PUSHi( PerlDir_tell(IoDIRP(io)) );
     RETURN;
@@ -3755,14 +3870,18 @@ nope:
 PP(pp_seekdir)
 {
 #if defined(HAS_SEEKDIR) || defined(seekdir)
-    dSP;
+    dVAR; dSP;
     const long along = POPl;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
 
-    if (!io || !IoDIRP(io))
-       goto nope;
-
+    if (!io || !IoDIRP(io)) {
+       if(ckWARN(WARN_IO)) {
+           Perl_warner(aTHX_ packWARN(WARN_IO),
+                "seekdir() attempted on invalid dirhandle %s", GvENAME(gv));
+        }
+        goto nope;
+    }
     (void)PerlDir_seek(IoDIRP(io), along);
 
     RETPUSHYES;
@@ -3778,13 +3897,17 @@ nope:
 PP(pp_rewinddir)
 {
 #if defined(HAS_REWINDDIR) || defined(rewinddir)
-    dSP;
+    dVAR; dSP;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
 
-    if (!io || !IoDIRP(io))
+    if (!io || !IoDIRP(io)) {
+       if(ckWARN(WARN_IO)) {
+           Perl_warner(aTHX_ packWARN(WARN_IO),
+               "rewinddir() attempted on invalid dirhandle %s", GvENAME(gv));
+       }
        goto nope;
-
+    }
     (void)PerlDir_rewind(IoDIRP(io));
     RETPUSHYES;
 nope:
@@ -3799,13 +3922,17 @@ nope:
 PP(pp_closedir)
 {
 #if defined(Direntry_t) && defined(HAS_READDIR)
-    dSP;
+    dVAR; dSP;
     GV * const gv = (GV*)POPs;
     register IO * const io = GvIOn(gv);
 
-    if (!io || !IoDIRP(io))
-       goto nope;
-
+    if (!io || !IoDIRP(io)) {
+       if(ckWARN(WARN_IO)) {
+           Perl_warner(aTHX_ packWARN(WARN_IO),
+                "closedir() attempted on invalid dirhandle %s", GvENAME(gv));
+        }
+        goto nope;
+    }
 #ifdef VOID_CLOSEDIR
     PerlDir_close(IoDIRP(io));
 #else
@@ -3831,7 +3958,7 @@ nope:
 PP(pp_fork)
 {
 #ifdef HAS_FORK
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     Pid_t childpid;
 
     EXTEND(SP, 1);
@@ -3840,7 +3967,7 @@ PP(pp_fork)
     if (childpid < 0)
        RETSETUNDEF;
     if (!childpid) {
-       GV * const tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
+       GV * const tmpgv = gv_fetchpvs("$", GV_ADD|GV_NOTQUAL, SVt_PV);
        if (tmpgv) {
             SvREADONLY_off(GvSV(tmpgv));
            sv_setiv(GvSV(tmpgv), (IV)PerlProc_getpid());
@@ -3875,8 +4002,8 @@ PP(pp_fork)
 
 PP(pp_wait)
 {
-#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL)
-    dSP; dTARGET;
+#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) && !defined(__LIBCATAMOUNT__)
+    dVAR; dSP; dTARGET;
     Pid_t childpid;
     int argflags;
 
@@ -3903,8 +4030,8 @@ PP(pp_wait)
 
 PP(pp_waitpid)
 {
-#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL)
-    dSP; dTARGET;
+#if (!defined(DOSISH) || defined(OS2) || defined(WIN32)) && !defined(MACOS_TRADITIONAL) && !defined(__LIBCATAMOUNT__)
+    dVAR; dSP; dTARGET;
     const int optype = POPi;
     const Pid_t pid = TOPi;
     Pid_t result;
@@ -3933,7 +4060,12 @@ PP(pp_waitpid)
 
 PP(pp_system)
 {
-    dSP; dMARK; dORIGMARK; dTARGET;
+    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
+#if defined(__LIBCATAMOUNT__)
+    PL_statusvalue = -1;
+    SP = ORIGMARK;
+    XPUSHi(-1);
+#else
     I32 value;
     int result;
 
@@ -3991,7 +4123,8 @@ PP(pp_system)
            SP = ORIGMARK;
            if (did_pipes) {
                int errkid;
-               int n = 0, n1;
+               unsigned n = 0;
+               SSize_t n1;
 
                while (n < sizeof(int)) {
                    n1 = PerlLIO_read(pp[0],
@@ -4023,7 +4156,7 @@ PP(pp_system)
            value = (I32)do_aexec5(really, MARK, SP, pp[1], did_pipes);
        }
        else if (SP - MARK != 1)
-           value = (I32)do_aexec5(Nullsv, MARK, SP, pp[1], did_pipes);
+           value = (I32)do_aexec5(NULL, MARK, SP, pp[1], did_pipes);
        else {
            value = (I32)do_exec3(SvPVx_nolen(sv_mortalcopy(*SP)), pp[1], did_pipes);
        }
@@ -4034,17 +4167,17 @@ PP(pp_system)
     result = 0;
     if (PL_op->op_flags & OPf_STACKED) {
        SV * const really = *++MARK;
-#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__)
+#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__) || defined(__VMS)
        value = (I32)do_aspawn(really, MARK, SP);
 #  else
        value = (I32)do_aspawn(really, (void **)MARK, (void **)SP);
 #  endif
     }
     else if (SP - MARK != 1) {
-#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__)
-       value = (I32)do_aspawn(Nullsv, MARK, SP);
+#  if defined(WIN32) || defined(OS2) || defined(__SYMBIAN32__) || defined(__VMS)
+       value = (I32)do_aspawn(NULL, MARK, SP);
 #  else
-       value = (I32)do_aspawn(Nullsv, (void **)MARK, (void **)SP);
+       value = (I32)do_aspawn(NULL, (void **)MARK, (void **)SP);
 #  endif
     }
     else {
@@ -4056,13 +4189,14 @@ PP(pp_system)
     do_execfree();
     SP = ORIGMARK;
     XPUSHi(result ? value : STATUS_CURRENT);
-#endif /* !FORK or VMS */
+#endif /* !FORK or VMS or OS/2 */
+#endif
     RETURN;
 }
 
 PP(pp_exec)
 {
-    dSP; dMARK; dORIGMARK; dTARGET;
+    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
     I32 value;
 
     if (PL_tainting) {
@@ -4082,15 +4216,15 @@ PP(pp_exec)
     }
     else if (SP - MARK != 1)
 #ifdef VMS
-       value = (I32)vms_do_aexec(Nullsv, MARK, SP);
+       value = (I32)vms_do_aexec(NULL, MARK, SP);
 #else
 #  ifdef __OPEN_VM
        {
-          (void ) do_aspawn(Nullsv, MARK, SP);
+          (void ) do_aspawn(NULL, MARK, SP);
           value = 0;
        }
 #  else
-       value = (I32)do_aexec(Nullsv, MARK, SP);
+       value = (I32)do_aexec(NULL, MARK, SP);
 #  endif
 #endif
     else {
@@ -4114,7 +4248,7 @@ PP(pp_exec)
 PP(pp_getppid)
 {
 #ifdef HAS_GETPPID
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
 #   ifdef THREADS_HAVE_PIDS
     if (PL_ppid != 1 && getppid() == 1)
        /* maybe the parent process has died. Refresh ppid cache */
@@ -4132,7 +4266,7 @@ PP(pp_getppid)
 PP(pp_getpgrp)
 {
 #ifdef HAS_GETPGRP
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     Pid_t pgrp;
     const Pid_t pid = (MAXARG < 1) ? 0 : SvIVx(POPs);
 
@@ -4153,7 +4287,7 @@ PP(pp_getpgrp)
 PP(pp_setpgrp)
 {
 #ifdef HAS_SETPGRP
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     Pid_t pgrp;
     Pid_t pid;
     if (MAXARG < 2) {
@@ -4185,7 +4319,7 @@ PP(pp_setpgrp)
 PP(pp_getpriority)
 {
 #ifdef HAS_GETPRIORITY
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     const int who = POPi;
     const int which = TOPi;
     SETi( getpriority(which, who) );
@@ -4198,7 +4332,7 @@ PP(pp_getpriority)
 PP(pp_setpriority)
 {
 #ifdef HAS_SETPRIORITY
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     const int niceval = POPi;
     const int who = POPi;
     const int which = TOPi;
@@ -4214,11 +4348,11 @@ PP(pp_setpriority)
 
 PP(pp_time)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
 #ifdef BIG_TIME
-    XPUSHn( time(Null(Time_t*)) );
+    XPUSHn( time(NULL) );
 #else
-    XPUSHi( time(Null(Time_t*)) );
+    XPUSHi( time(NULL) );
 #endif
     RETURN;
 }
@@ -4226,6 +4360,7 @@ PP(pp_time)
 PP(pp_tms)
 {
 #ifdef HAS_TIMES
+    dVAR;
     dSP;
     EXTEND(SP, 4);
 #ifndef VMS
@@ -4236,22 +4371,22 @@ PP(pp_tms)
                                                    /* is returned.                   */
 #endif
 
-    PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_utime)/(NV)PL_clocktick)));
+    mPUSHn(((NV)PL_timesbuf.tms_utime)/(NV)PL_clocktick);
     if (GIMME == G_ARRAY) {
-       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_stime)/(NV)PL_clocktick)));
-       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_cutime)/(NV)PL_clocktick)));
-       PUSHs(sv_2mortal(newSVnv(((NV)PL_timesbuf.tms_cstime)/(NV)PL_clocktick)));
+       mPUSHn(((NV)PL_timesbuf.tms_stime)/(NV)PL_clocktick);
+       mPUSHn(((NV)PL_timesbuf.tms_cutime)/(NV)PL_clocktick);
+       mPUSHn(((NV)PL_timesbuf.tms_cstime)/(NV)PL_clocktick);
     }
     RETURN;
 #else
 #   ifdef PERL_MICRO
     dSP;
-    PUSHs(sv_2mortal(newSVnv((NV)0.0)));
+    mPUSHn(0.0);
     EXTEND(SP, 4);
     if (GIMME == G_ARRAY) {
-        PUSHs(sv_2mortal(newSVnv((NV)0.0)));
-        PUSHs(sv_2mortal(newSVnv((NV)0.0)));
-        PUSHs(sv_2mortal(newSVnv((NV)0.0)));
+        mPUSHn(0.0);
+        mPUSHn(0.0);
+        mPUSHn(0.0);
     }
     RETURN;
 #   else
@@ -4260,103 +4395,70 @@ PP(pp_tms)
 #endif /* HAS_TIMES */
 }
 
-#ifdef LOCALTIME_EDGECASE_BROKEN
-static struct tm *S_my_localtime (pTHX_ Time_t *tp)
-{
-    auto time_t     T;
-    auto struct tm *P;
-
-    /* No workarounds in the valid range */
-    if (!tp || *tp < 0x7fff573f || *tp >= 0x80000000)
-       return (localtime (tp));
-
-    /* This edge case is to workaround the undefined behaviour, where the
-     * TIMEZONE makes the time go beyond the defined range.
-     * gmtime (0x7fffffff) => 2038-01-19 03:14:07
-     * If there is a negative offset in TZ, like MET-1METDST, some broken
-     * implementations of localtime () (like AIX 5.2) barf with bogus
-     * return values:
-     * 0x7fffffff gmtime               2038-01-19 03:14:07
-     * 0x7fffffff localtime            1901-12-13 21:45:51
-     * 0x7fffffff mylocaltime          2038-01-19 04:14:07
-     * 0x3c19137f gmtime               2001-12-13 20:45:51
-     * 0x3c19137f localtime            2001-12-13 21:45:51
-     * 0x3c19137f mylocaltime          2001-12-13 21:45:51
-     * Given that legal timezones are typically between GMT-12 and GMT+12
-     * we turn back the clock 23 hours before calling the localtime
-     * function, and add those to the return value. This will never cause
-     * day wrapping problems, since the edge case is Tue Jan *19*
-     */
-    T = *tp - 82800; /* 23 hour. allows up to GMT-23 */
-    P = localtime (&T);
-    P->tm_hour += 23;
-    if (P->tm_hour >= 24) {
-       P->tm_hour -= 24;
-       P->tm_mday++;   /* 18  -> 19  */
-       P->tm_wday++;   /* Mon -> Tue */
-       P->tm_yday++;   /* 18  -> 19  */
-    }
-    return (P);
-} /* S_my_localtime */
-#endif
-
 PP(pp_gmtime)
 {
+    dVAR;
     dSP;
-    Time_t when;
-    const struct tm *tmbuf;
+    Time64_T when;
+    struct TM tmbuf;
+    struct TM *err;
     static const char * const dayname[] =
        {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
     static const char * const monname[] =
        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
-    if (MAXARG < 1)
-       (void)time(&when);
+    if (MAXARG < 1) {
+       time_t now;
+       (void)time(&now);
+       when = (Time64_T)now;
+    }
     else
-#ifdef BIG_TIME
-       when = (Time_t)SvNVx(POPs);
-#else
-       when = (Time_t)SvIVx(POPs);
-#endif
+       when = (Time64_T)SvNVx(POPs);
 
     if (PL_op->op_type == OP_LOCALTIME)
-#ifdef LOCALTIME_EDGECASE_BROKEN
-       tmbuf = S_my_localtime(aTHX_ &when);
-#else
-       tmbuf = localtime(&when);
-#endif
+        err = localtime64_r(&when, &tmbuf);
     else
-       tmbuf = gmtime(&when);
+       err = gmtime64_r(&when, &tmbuf);
 
-    if (GIMME != G_ARRAY) {
+    if( err == NULL ) {
+       char *opname = PL_op->op_type == OP_LOCALTIME ? "localtime" : "gmtime";
+       Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
+                   "%s under/overflowed the year", opname);
+    }
+
+    if (GIMME != G_ARRAY) {    /* scalar context */
        SV *tsv;
         EXTEND(SP, 1);
         EXTEND_MORTAL(1);
-       if (!tmbuf)
+       if (err == NULL)
            RETPUSHUNDEF;
-       tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d",
-                           dayname[tmbuf->tm_wday],
-                           monname[tmbuf->tm_mon],
-                           tmbuf->tm_mday,
-                           tmbuf->tm_hour,
-                           tmbuf->tm_min,
-                           tmbuf->tm_sec,
-                           tmbuf->tm_year + 1900);
-       PUSHs(sv_2mortal(tsv));
-    }
-    else if (tmbuf) {
+
+       tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %lld",
+                           dayname[tmbuf.tm_wday],
+                           monname[tmbuf.tm_mon],
+                           tmbuf.tm_mday,
+                           tmbuf.tm_hour,
+                           tmbuf.tm_min,
+                           tmbuf.tm_sec,
+                           tmbuf.tm_year + 1900);
+       mPUSHs(tsv);
+    }
+    else {                     /* list context */
+       if ( err == NULL )
+           RETURN;
+
         EXTEND(SP, 9);
         EXTEND_MORTAL(9);
-        PUSHs(sv_2mortal(newSViv(tmbuf->tm_sec)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_min)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_hour)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mday)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_mon)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_year)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_wday)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_yday)));
-       PUSHs(sv_2mortal(newSViv(tmbuf->tm_isdst)));
+        mPUSHi(tmbuf.tm_sec);
+       mPUSHi(tmbuf.tm_min);
+       mPUSHi(tmbuf.tm_hour);
+       mPUSHi(tmbuf.tm_mday);
+       mPUSHi(tmbuf.tm_mon);
+       mPUSHi(tmbuf.tm_year);
+       mPUSHi(tmbuf.tm_wday);
+       mPUSHi(tmbuf.tm_yday);
+       mPUSHi(tmbuf.tm_isdst);
     }
     RETURN;
 }
@@ -4364,7 +4466,7 @@ PP(pp_gmtime)
 PP(pp_alarm)
 {
 #ifdef HAS_ALARM
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     int anum;
     anum = POPi;
     anum = alarm((unsigned int)anum);
@@ -4380,7 +4482,7 @@ PP(pp_alarm)
 
 PP(pp_sleep)
 {
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     I32 duration;
     Time_t lasttime;
     Time_t when;
@@ -4403,7 +4505,7 @@ PP(pp_sleep)
 PP(pp_shmwrite)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
-    dSP; dMARK; dTARGET;
+    dVAR; dSP; dMARK; dTARGET;
     const int op_type = PL_op->op_type;
     I32 value;
 
@@ -4435,7 +4537,7 @@ PP(pp_shmwrite)
 PP(pp_semget)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
-    dSP; dMARK; dTARGET;
+    dVAR; dSP; dMARK; dTARGET;
     const int anum = do_ipcget(PL_op->op_type, MARK, SP);
     SP = MARK;
     if (anum == -1)
@@ -4450,7 +4552,7 @@ PP(pp_semget)
 PP(pp_semctl)
 {
 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
-    dSP; dMARK; dTARGET;
+    dVAR; dSP; dMARK; dTARGET;
     const int anum = do_ipcctl(PL_op->op_type, MARK, SP);
     SP = MARK;
     if (anum == -1)
@@ -4467,12 +4569,35 @@ PP(pp_semctl)
 #endif
 }
 
+/* I can't const this further without getting warnings about the types of
+   various arrays passed in from structures.  */
+static SV *
+S_space_join_names_mortal(pTHX_ char *const *array)
+{
+    SV *target;
+
+    PERL_ARGS_ASSERT_SPACE_JOIN_NAMES_MORTAL;
+
+    if (array && *array) {
+       target = newSVpvs_flags("", SVs_TEMP);
+       while (1) {
+           sv_catpv(target, *array);
+           if (!*++array)
+               break;
+           sv_catpvs(target, " ");
+       }
+    } else {
+       target = sv_mortalcopy(&PL_sv_no);
+    }
+    return target;
+}
+
 /* Get system info. */
 
 PP(pp_ghostent)
 {
 #if defined(HAS_GETHOSTBYNAME) || defined(HAS_GETHOSTBYADDR) || defined(HAS_GETHOSTENT)
-    dSP;
+    dVAR; dSP;
     I32 which = PL_op->op_type;
     register char **elem;
     register SV *sv;
@@ -4498,7 +4623,7 @@ PP(pp_ghostent)
        const int addrtype = POPi;
        SV * const addrsv = POPs;
        STRLEN addrlen;
-       Netdb_host_t addr = (Netdb_host_t) SvPVbyte(addrsv, addrlen);
+       const char *addr = (char *)SvPVbyte(addrsv, addrlen);
 
        hent = PerlSock_gethostbyaddr(addr, (Netdb_hlen_t) addrlen, addrtype);
 #else
@@ -4537,28 +4662,20 @@ PP(pp_ghostent)
     }
 
     if (hent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, (char*)hent->h_name);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       for (elem = hent->h_aliases; elem && *elem; elem++) {
-           sv_catpv(sv, *elem);
-           if (elem[1])
-               sv_catpvn(sv, " ", 1);
-       }
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)hent->h_addrtype);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+       mPUSHs(newSVpv((char*)hent->h_name, 0));
+       PUSHs(space_join_names_mortal(hent->h_aliases));
+       mPUSHi(hent->h_addrtype);
        len = hent->h_length;
-       sv_setiv(sv, (IV)len);
+       mPUSHi(len);
 #ifdef h_addr
        for (elem = hent->h_addr_list; elem && *elem; elem++) {
-           XPUSHs(sv = sv_mortalcopy(&PL_sv_no));
-           sv_setpvn(sv, *elem, len);
+           mXPUSHp(*elem, len);
        }
 #else
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        if (hent->h_addr)
-           sv_setpvn(sv, hent->h_addr, len);
+           mPUSHp(hent->h_addr, len);
+       else
+           PUSHs(sv_mortalcopy(&PL_sv_no));
 #endif /* h_addr */
     }
     RETURN;
@@ -4570,9 +4687,8 @@ PP(pp_ghostent)
 PP(pp_gnetent)
 {
 #if defined(HAS_GETNETBYNAME) || defined(HAS_GETNETBYADDR) || defined(HAS_GETNETENT)
-    dSP;
+    dVAR; dSP;
     I32 which = PL_op->op_type;
-    register char **elem;
     register SV *sv;
 #ifndef HAS_GETNET_PROTOS /* XXX Do we need individual probes? */
     struct netent *getnetbyaddr(Netdb_net_t, int);
@@ -4629,18 +4745,10 @@ PP(pp_gnetent)
     }
 
     if (nent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, nent->n_name);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       for (elem = nent->n_aliases; elem && *elem; elem++) {
-           sv_catpv(sv, *elem);
-           if (elem[1])
-               sv_catpvn(sv, " ", 1);
-       }
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)nent->n_addrtype);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)nent->n_net);
+       mPUSHs(newSVpv(nent->n_name, 0));
+       PUSHs(space_join_names_mortal(nent->n_aliases));
+       mPUSHi(nent->n_addrtype);
+       mPUSHi(nent->n_net);
     }
 
     RETURN;
@@ -4652,9 +4760,8 @@ PP(pp_gnetent)
 PP(pp_gprotoent)
 {
 #if defined(HAS_GETPROTOBYNAME) || defined(HAS_GETPROTOBYNUMBER) || defined(HAS_GETPROTOENT)
-    dSP;
+    dVAR; dSP;
     I32 which = PL_op->op_type;
-    register char **elem;
     register SV *sv;
 #ifndef HAS_GETPROTO_PROTOS /* XXX Do we need individual probes? */
     struct protoent *getprotobyname(Netdb_name_t);
@@ -4699,16 +4806,9 @@ PP(pp_gprotoent)
     }
 
     if (pent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, pent->p_name);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       for (elem = pent->p_aliases; elem && *elem; elem++) {
-           sv_catpv(sv, *elem);
-           if (elem[1])
-               sv_catpvn(sv, " ", 1);
-       }
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)pent->p_proto);
+       mPUSHs(newSVpv(pent->p_name, 0));
+       PUSHs(space_join_names_mortal(pent->p_aliases));
+       mPUSHi(pent->p_proto);
     }
 
     RETURN;
@@ -4720,9 +4820,8 @@ PP(pp_gprotoent)
 PP(pp_gservent)
 {
 #if defined(HAS_GETSERVBYNAME) || defined(HAS_GETSERVBYPORT) || defined(HAS_GETSERVENT)
-    dSP;
+    dVAR; dSP;
     I32 which = PL_op->op_type;
-    register char **elem;
     register SV *sv;
 #ifndef HAS_GETSERV_PROTOS /* XXX Do we need individual probes? */
     struct servent *getservbyname(Netdb_name_t, Netdb_name_t);
@@ -4735,7 +4834,7 @@ PP(pp_gservent)
 #ifdef HAS_GETSERVBYNAME
        const char * const proto = POPpbytex;
        const char * const name = POPpbytex;
-       sent = PerlSock_getservbyname(name, (proto && !*proto) ? Nullch : proto);
+       sent = PerlSock_getservbyname(name, (proto && !*proto) ? NULL : proto);
 #else
        DIE(aTHX_ PL_no_sock_func, "getservbyname");
 #endif
@@ -4747,7 +4846,7 @@ PP(pp_gservent)
 #ifdef HAS_HTONS
        port = PerlSock_htons(port);
 #endif
-       sent = PerlSock_getservbyport(port, (proto && !*proto) ? Nullch : proto);
+       sent = PerlSock_getservbyport(port, (proto && !*proto) ? NULL : proto);
 #else
        DIE(aTHX_ PL_no_sock_func, "getservbyport");
 #endif
@@ -4777,22 +4876,14 @@ PP(pp_gservent)
     }
 
     if (sent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, sent->s_name);
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       for (elem = sent->s_aliases; elem && *elem; elem++) {
-           sv_catpv(sv, *elem);
-           if (elem[1])
-               sv_catpvn(sv, " ", 1);
-       }
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
+       mPUSHs(newSVpv(sent->s_name, 0));
+       PUSHs(space_join_names_mortal(sent->s_aliases));
 #ifdef HAS_NTOHS
-       sv_setiv(sv, (IV)PerlSock_ntohs(sent->s_port));
+       mPUSHi(PerlSock_ntohs(sent->s_port));
 #else
-       sv_setiv(sv, (IV)(sent->s_port));
+       mPUSHi(sent->s_port);
 #endif
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, sent->s_proto);
+       mPUSHs(newSVpv(sent->s_proto, 0));
     }
 
     RETURN;
@@ -4804,7 +4895,7 @@ PP(pp_gservent)
 PP(pp_shostent)
 {
 #ifdef HAS_SETHOSTENT
-    dSP;
+    dVAR; dSP;
     PerlSock_sethostent(TOPi);
     RETSETYES;
 #else
@@ -4815,8 +4906,8 @@ PP(pp_shostent)
 PP(pp_snetent)
 {
 #ifdef HAS_SETNETENT
-    dSP;
-    PerlSock_setnetent(TOPi);
+    dVAR; dSP;
+    (void)PerlSock_setnetent(TOPi);
     RETSETYES;
 #else
     DIE(aTHX_ PL_no_sock_func, "setnetent");
@@ -4826,8 +4917,8 @@ PP(pp_snetent)
 PP(pp_sprotoent)
 {
 #ifdef HAS_SETPROTOENT
-    dSP;
-    PerlSock_setprotoent(TOPi);
+    dVAR; dSP;
+    (void)PerlSock_setprotoent(TOPi);
     RETSETYES;
 #else
     DIE(aTHX_ PL_no_sock_func, "setprotoent");
@@ -4837,8 +4928,8 @@ PP(pp_sprotoent)
 PP(pp_sservent)
 {
 #ifdef HAS_SETSERVENT
-    dSP;
-    PerlSock_setservent(TOPi);
+    dVAR; dSP;
+    (void)PerlSock_setservent(TOPi);
     RETSETYES;
 #else
     DIE(aTHX_ PL_no_sock_func, "setservent");
@@ -4848,7 +4939,7 @@ PP(pp_sservent)
 PP(pp_ehostent)
 {
 #ifdef HAS_ENDHOSTENT
-    dSP;
+    dVAR; dSP;
     PerlSock_endhostent();
     EXTEND(SP,1);
     RETPUSHYES;
@@ -4860,7 +4951,7 @@ PP(pp_ehostent)
 PP(pp_enetent)
 {
 #ifdef HAS_ENDNETENT
-    dSP;
+    dVAR; dSP;
     PerlSock_endnetent();
     EXTEND(SP,1);
     RETPUSHYES;
@@ -4872,7 +4963,7 @@ PP(pp_enetent)
 PP(pp_eprotoent)
 {
 #ifdef HAS_ENDPROTOENT
-    dSP;
+    dVAR; dSP;
     PerlSock_endprotoent();
     EXTEND(SP,1);
     RETPUSHYES;
@@ -4884,7 +4975,7 @@ PP(pp_eprotoent)
 PP(pp_eservent)
 {
 #ifdef HAS_ENDSERVENT
-    dSP;
+    dVAR; dSP;
     PerlSock_endservent();
     EXTEND(SP,1);
     RETPUSHYES;
@@ -4896,7 +4987,7 @@ PP(pp_eservent)
 PP(pp_gpwent)
 {
 #ifdef HAS_PASSWD
-    dSP;
+    dVAR; dSP;
     I32 which = PL_op->op_type;
     register SV *sv;
     struct passwd *pwent  = NULL;
@@ -5008,11 +5099,10 @@ PP(pp_gpwent)
     }
 
     if (pwent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, pwent->pw_name);
+       mPUSHs(newSVpv(pwent->pw_name, 0));
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       SvPOK_off(sv);
+       sv = newSViv(0);
+       mPUSHs(sv);
        /* If we have getspnam(), we try to dig up the shadow
         * password.  If we are underprivileged, the shadow
         * interface will set the errno to EACCES or similar,
@@ -5055,70 +5145,70 @@ PP(pp_gpwent)
        SvTAINTED_on(sv);
 #   endif
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   if Uid_t_sign <= 0
-       sv_setiv(sv, (IV)pwent->pw_uid);
+       mPUSHi(pwent->pw_uid);
 #   else
-       sv_setuv(sv, (UV)pwent->pw_uid);
+       mPUSHu(pwent->pw_uid);
 #   endif
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   if Uid_t_sign <= 0
-       sv_setiv(sv, (IV)pwent->pw_gid);
+       mPUSHi(pwent->pw_gid);
 #   else
-       sv_setuv(sv, (UV)pwent->pw_gid);
+       mPUSHu(pwent->pw_gid);
 #   endif
        /* pw_change, pw_quota, and pw_age are mutually exclusive--
         * because of the poor interface of the Perl getpw*(),
         * not because there's some standard/convention saying so.
         * A better interface would have been to return a hash,
         * but we are accursed by our history, alas. --jhi.  */
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   ifdef PWCHANGE
-       sv_setiv(sv, (IV)pwent->pw_change);
+       mPUSHi(pwent->pw_change);
 #   else
 #       ifdef PWQUOTA
-       sv_setiv(sv, (IV)pwent->pw_quota);
+       mPUSHi(pwent->pw_quota);
 #       else
 #           ifdef PWAGE
-       sv_setpv(sv, pwent->pw_age);
+       mPUSHs(newSVpv(pwent->pw_age, 0));
+#          else
+       /* I think that you can never get this compiled, but just in case.  */
+       PUSHs(sv_mortalcopy(&PL_sv_no));
 #           endif
 #       endif
 #   endif
 
        /* pw_class and pw_comment are mutually exclusive--.
         * see the above note for pw_change, pw_quota, and pw_age. */
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   ifdef PWCLASS
-       sv_setpv(sv, pwent->pw_class);
+       mPUSHs(newSVpv(pwent->pw_class, 0));
 #   else
 #       ifdef PWCOMMENT
-       sv_setpv(sv, pwent->pw_comment);
+       mPUSHs(newSVpv(pwent->pw_comment, 0));
+#      else
+       /* I think that you can never get this compiled, but just in case.  */
+       PUSHs(sv_mortalcopy(&PL_sv_no));
 #       endif
 #   endif
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   ifdef PWGECOS
-       sv_setpv(sv, pwent->pw_gecos);
+       PUSHs(sv = sv_2mortal(newSVpv(pwent->pw_gecos, 0)));
+#   else
+       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #   endif
 #   ifndef INCOMPLETE_TAINTS
        /* pw_gecos is tainted because user himself can diddle with it. */
        SvTAINTED_on(sv);
 #   endif
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, pwent->pw_dir);
+       mPUSHs(newSVpv(pwent->pw_dir, 0));
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, pwent->pw_shell);
+       PUSHs(sv = sv_2mortal(newSVpv(pwent->pw_shell, 0)));
 #   ifndef INCOMPLETE_TAINTS
        /* pw_shell is tainted because user himself can diddle with it. */
        SvTAINTED_on(sv);
 #   endif
 
 #   ifdef PWEXPIRE
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)pwent->pw_expire);
+       mPUSHi(pwent->pw_expire);
 #   endif
     }
     RETURN;
@@ -5130,7 +5220,7 @@ PP(pp_gpwent)
 PP(pp_spwent)
 {
 #if defined(HAS_PASSWD) && defined(HAS_SETPWENT)
-    dSP;
+    dVAR; dSP;
     setpwent();
     RETPUSHYES;
 #else
@@ -5141,7 +5231,7 @@ PP(pp_spwent)
 PP(pp_epwent)
 {
 #if defined(HAS_PASSWD) && defined(HAS_ENDPWENT)
-    dSP;
+    dVAR; dSP;
     endpwent();
     RETPUSHYES;
 #else
@@ -5152,19 +5242,17 @@ PP(pp_epwent)
 PP(pp_ggrent)
 {
 #ifdef HAS_GROUP
-    dSP;
-    I32 which = PL_op->op_type;
-    register char **elem;
-    register SV *sv;
-    struct group *grent;
+    dVAR; dSP;
+    const I32 which = PL_op->op_type;
+    const struct group *grent;
 
     if (which == OP_GGRNAM) {
        const char* const name = POPpbytex;
-       grent = (struct group *)getgrnam(name);
+       grent = (const struct group *)getgrnam(name);
     }
     else if (which == OP_GGRGID) {
        const Gid_t gid = POPi;
-       grent = (struct group *)getgrgid(gid);
+       grent = (const struct group *)getgrgid(gid);
     }
     else
 #ifdef HAS_GETGRENT
@@ -5175,7 +5263,9 @@ PP(pp_ggrent)
 
     EXTEND(SP, 4);
     if (GIMME != G_ARRAY) {
-       PUSHs(sv = sv_newmortal());
+       SV * const sv = sv_newmortal();
+
+       PUSHs(sv);
        if (grent) {
            if (which == OP_GGRNAM)
                sv_setiv(sv, (IV)grent->gr_gid);
@@ -5186,19 +5276,17 @@ PP(pp_ggrent)
     }
 
     if (grent) {
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setpv(sv, grent->gr_name);
+       mPUSHs(newSVpv(grent->gr_name, 0));
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
 #ifdef GRPASSWD
-       sv_setpv(sv, grent->gr_passwd);
+       mPUSHs(newSVpv(grent->gr_passwd, 0));
+#else
+       PUSHs(sv_mortalcopy(&PL_sv_no));
 #endif
 
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
-       sv_setiv(sv, (IV)grent->gr_gid);
+       mPUSHi(grent->gr_gid);
 
 #if !(defined(_CRAYMPP) && defined(USE_REENTRANT_API))
-       PUSHs(sv = sv_mortalcopy(&PL_sv_no));
        /* In UNICOS/mk (_CRAYMPP) the multithreading
         * versions (getgrnam_r, getgrgid_r)
         * seem to return an illegal pointer
@@ -5207,11 +5295,7 @@ PP(pp_ggrent)
         * but the gr_mem is poisonous anyway.
         * So yes, you cannot get the list of group
         * members if building multithreaded in UNICOS/mk. */
-       for (elem = grent->gr_mem; elem && *elem; elem++) {
-           sv_catpv(sv, *elem);
-           if (elem[1])
-               sv_catpvn(sv, " ", 1);
-       }
+       PUSHs(space_join_names_mortal(grent->gr_mem));
 #endif
     }
 
@@ -5224,7 +5308,7 @@ PP(pp_ggrent)
 PP(pp_sgrent)
 {
 #if defined(HAS_GROUP) && defined(HAS_SETGRENT)
-    dSP;
+    dVAR; dSP;
     setgrent();
     RETPUSHYES;
 #else
@@ -5235,7 +5319,7 @@ PP(pp_sgrent)
 PP(pp_egrent)
 {
 #if defined(HAS_GROUP) && defined(HAS_ENDGRENT)
-    dSP;
+    dVAR; dSP;
     endgrent();
     RETPUSHYES;
 #else
@@ -5246,7 +5330,7 @@ PP(pp_egrent)
 PP(pp_getlogin)
 {
 #ifdef HAS_GETLOGIN
-    dSP; dTARGET;
+    dVAR; dSP; dTARGET;
     char *tmps;
     EXTEND(SP, 1);
     if (!(tmps = PerlProc_getlogin()))
@@ -5263,7 +5347,7 @@ PP(pp_getlogin)
 PP(pp_syscall)
 {
 #ifdef HAS_SYSCALL
-    dSP; dMARK; dORIGMARK; dTARGET;
+    dVAR; dSP; dMARK; dORIGMARK; dTARGET;
     register I32 items = SP - MARK;
     unsigned long a[20];
     register I32 i = 0;