This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
lib/perl5db.pl: Remove code now moved to OS2::Process
[perl5.git] / perlio.c
index 55148e8..0d4231c 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -1,5 +1,5 @@
 /*
- * perlio.c Copyright (c) 1996-2005, Nick Ing-Simmons You may distribute
+ * perlio.c Copyright (c) 1996-2006, Nick Ing-Simmons You may distribute
  * under the terms of either the GNU General Public License or the
  * Artistic License, as specified in the README file.
  */
 #ifdef PERL_MICRO
 #   include "uconfig.h"
 #else
-#   include "config.h"
+#   ifndef USE_CROSS_COMPILE
+#       include "config.h"
+#   else
+#       include "xconfig.h"
+#   endif
 #endif
 
 #define PERLIO_NOT_STDIO 0
@@ -56,8 +60,6 @@
 
 #include "XSUB.h"
 
-#define PERLIO_MAX_REFCOUNTABLE_FD 2048
-
 #ifdef __Lynx__
 /* Missing proto on LynxOS */
 int mkstemp(char*);
@@ -66,7 +68,7 @@ int mkstemp(char*);
 /* Call the callback or PerlIOBase, and return failure. */
 #define Perl_PerlIO_or_Base(f, callback, base, failure, args)  \
        if (PerlIOValid(f)) {                                   \
-               const PerlIO_funcs *tab = PerlIOBase(f)->tab;   \
+               const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
                if (tab && tab->callback)                       \
                        return (*tab->callback) args;           \
                else                                            \
@@ -79,7 +81,7 @@ int mkstemp(char*);
 /* Call the callback or fail, and return failure. */
 #define Perl_PerlIO_or_fail(f, callback, failure, args)        \
        if (PerlIOValid(f)) {                                   \
-               const PerlIO_funcs *tab = PerlIOBase(f)->tab;   \
+               const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
                if (tab && tab->callback)                       \
                        return (*tab->callback) args;           \
                SETERRNO(EINVAL, LIB_INVARG);                   \
@@ -91,7 +93,7 @@ int mkstemp(char*);
 /* Call the callback or PerlIOBase, and be void. */
 #define Perl_PerlIO_or_Base_void(f, callback, base, args)      \
        if (PerlIOValid(f)) {                                   \
-               const PerlIO_funcs *tab = PerlIOBase(f)->tab;   \
+               const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
                if (tab && tab->callback)                       \
                        (*tab->callback) args;                  \
                else                                            \
@@ -103,7 +105,7 @@ int mkstemp(char*);
 /* Call the callback or fail, and be void. */
 #define Perl_PerlIO_or_fail_void(f, callback, args)            \
        if (PerlIOValid(f)) {                                   \
-               const PerlIO_funcs *tab = PerlIOBase(f)->tab;   \
+               const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
                if (tab && tab->callback)                       \
                        (*tab->callback) args;                  \
                else                                            \
@@ -112,7 +114,15 @@ int mkstemp(char*);
        else                                                    \
                SETERRNO(EBADF, SS_IVCHAN)
 
+#if defined(__osf__) && _XOPEN_SOURCE < 500
+extern int   fseeko(FILE *, off_t, int);
+extern off_t ftello(FILE *);
+#endif
+
 #ifndef USE_SFIO
+
+EXTERN_C int perlsio_binmode(FILE *fp, int iotype, int mode);
+
 int
 perlsio_binmode(FILE *fp, int iotype, int mode)
 {
@@ -122,11 +132,11 @@ perlsio_binmode(FILE *fp, int iotype, int mode)
 #ifdef DOSISH
 #  if defined(atarist) || defined(__MINT__)
     if (!fflush(fp)) {
-       if (mode & O_BINARY)
-           ((FILE *) fp)->_flag |= _IOBIN;
-       else
-           ((FILE *) fp)->_flag &= ~_IOBIN;
-       return 1;
+        if (mode & O_BINARY)
+            ((FILE *) fp)->_flag |= _IOBIN;
+        else
+            ((FILE *) fp)->_flag &= ~_IOBIN;
+        return 1;
     }
     return 0;
 #  else
@@ -137,35 +147,38 @@ perlsio_binmode(FILE *fp, int iotype, int mode)
     if (PerlLIO_setmode(fileno(fp), mode) != -1) {
 #endif
 #    if defined(WIN32) && defined(__BORLANDC__)
-       /*
-        * The translation mode of the stream is maintained independent of
-        * the translation mode of the fd in the Borland RTL (heavy
-        * digging through their runtime sources reveal).  User has to set
-        * the mode explicitly for the stream (though they don't document
-        * this anywhere). GSAR 97-5-24
-        */
-       fseek(fp, 0L, 0);
-       if (mode & O_BINARY)
-           fp->flags |= _F_BIN;
-       else
-           fp->flags &= ~_F_BIN;
+        /*
+         * The translation mode of the stream is maintained independent 
+of
+         * the translation mode of the fd in the Borland RTL (heavy
+         * digging through their runtime sources reveal).  User has to 
+set
+         * the mode explicitly for the stream (though they don't 
+document
+         * this anywhere). GSAR 97-5-24
+         */
+        fseek(fp, 0L, 0);
+        if (mode & O_BINARY)
+            fp->flags |= _F_BIN;
+        else
+            fp->flags &= ~_F_BIN;
 #    endif
-       return 1;
+        return 1;
     }
     else
-       return 0;
+        return 0;
 #  endif
 #else
 #  if defined(USEMYBINMODE)
     dTHX;
     if (my_binmode(fp, iotype, mode) != FALSE)
-       return 1;
+        return 1;
     else
-       return 0;
+        return 0;
 #  else
-    (void)fp;
-    (void)iotype;
-    (void)mode;
+    PERL_UNUSED_ARG(fp);
+    PERL_UNUSED_ARG(iotype);
+    PERL_UNUSED_ARG(mode);
     return 1;
 #  endif
 #endif
@@ -248,9 +261,9 @@ int
 PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
 {
 #ifdef USE_SFIO
-    (void)iotype;
-    (void)mode;
-    (void)names;
+    PERL_UNUSED_ARG(iotype);
+    PERL_UNUSED_ARG(mode);
+    PERL_UNUSED_ARG(names);
     return 1;
 #else
     return perlsio_binmode(fp, iotype, mode);
@@ -260,7 +273,7 @@ PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
 PerlIO *
 PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
 {
-#if defined(PERL_MICRO) || defined(SYMBIAN)
+#if defined(PERL_MICRO) || defined(__SYMBIAN32__)
     return NULL;
 #else
 #ifdef PERL_IMPLICIT_SYS
@@ -273,9 +286,10 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
        const int fd = PerlLIO_dup(PerlIO_fileno(f));
        if (fd >= 0) {
            char mode[8];
-           int omode = fcntl(fd, F_GETFL);
 #ifdef DJGPP
-           omode = djgpp_get_stream_mode(f);
+           const int omode = djgpp_get_stream_mode(f);
+#else
+           const int omode = fcntl(fd, F_GETFL);
 #endif
            PerlIO_intmode2str(omode,mode,NULL);
            /* the r+ is a hack */
@@ -334,7 +348,7 @@ XS(XS_PerlIO__Layer__find)
     if (items < 2)
        Perl_croak(aTHX_ "Usage class->find(name[,load])");
     else {
-       const char *name = SvPV_nolen_const(ST(1));
+       const char * const name = SvPV_nolen_const(ST(1));
        ST(0) = (strEQ(name, "crlf")
                 || strEQ(name, "raw")) ? &PL_sv_yes : &PL_sv_undef;
        XSRETURN(1);
@@ -356,6 +370,7 @@ Perl_boot_core_PerlIO(pTHX)
 void
 PerlIO_init(pTHX)
 {
+    PERL_UNUSED_CONTEXT;
     /*
      * Does nothing (yet) except force this file to be included in perl
      * binary. That allows this file to force inclusion of other functions
@@ -393,6 +408,7 @@ PerlIO_tmpfile(void)
 void
 PerlIO_init(pTHX)
 {
+    PERL_UNUSED_CONTEXT;
     /*
      * Force this file to be included in perl binary. Which allows this
      * file to force inclusion of other functions that may be required by
@@ -457,34 +473,38 @@ PerlIO_debug(const char *fmt, ...)
     va_list ap;
     dSYS;
     va_start(ap, fmt);
-    if (!PL_perlio_debug_fd && !PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) {
-        const char *s = PerlEnv_getenv("PERLIO_DEBUG");
-       if (s && *s)
-           PL_perlio_debug_fd = PerlLIO_open3(s, O_WRONLY | O_CREAT | O_APPEND, 0666);
-       else
+    if (!PL_perlio_debug_fd) {
+       if (!PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) {
+           const char * const s = PerlEnv_getenv("PERLIO_DEBUG");
+           if (s && *s)
+               PL_perlio_debug_fd
+                   = PerlLIO_open3(s, O_WRONLY | O_CREAT | O_APPEND, 0666);
+           else
+               PL_perlio_debug_fd = -1;
+       } else {
+           /* tainting or set*id, so ignore the environment, and ensure we
+              skip these tests next time through.  */
            PL_perlio_debug_fd = -1;
+       }
     }
     if (PL_perlio_debug_fd > 0) {
        dTHX;
-       const char *s = CopFILE(PL_curcop);
-       STRLEN len;
 #ifdef USE_ITHREADS
+       const char * const s = CopFILE(PL_curcop);
        /* Use fixed buffer as sv_catpvf etc. needs SVs */
        char buffer[1024];
-       if (!s)
-           s = "(none)";
-       len = sprintf(buffer, "%.40s:%" IVdf " ", s, (IV) CopLINE(PL_curcop));
-       vsprintf(buffer+len, fmt, ap);
-       PerlLIO_write(PL_perlio_debug_fd, buffer, strlen(buffer));
+       const STRLEN len1 = my_snprintf(buffer, sizeof(buffer), "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop));
+       const STRLEN len2 = my_vsnprintf(buffer + len1, sizeof(buffer) - len1, fmt, ap);
+       PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2);
 #else
-       SV *sv = newSVpvn("", 0);
-       if (!s)
-           s = "(none)";
-       Perl_sv_catpvf(aTHX_ sv, "%s:%" IVdf " ", s,
+       const char *s = CopFILE(PL_curcop);
+       STRLEN len;
+       SV * const sv = newSVpvs("");
+       Perl_sv_catpvf(aTHX_ sv, "%s:%" IVdf " ", s ? s : "(none)",
                       (IV) CopLINE(PL_curcop));
        Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
 
-       s = SvPV(sv, len);
+       s = SvPV_const(sv, len);
        PerlLIO_write(PL_perlio_debug_fd, s, len);
        SvREFCNT_dec(sv);
 #endif
@@ -506,6 +526,7 @@ PerlIO_debug(const char *fmt, ...)
 PerlIO *
 PerlIO_allocate(pTHX)
 {
+    dVAR;
     /*
      * Find a free slot in the table, allocating new table as necessary
      */
@@ -521,7 +542,7 @@ PerlIO_allocate(pTHX)
            }
        }
     }
-    Newz('I',f,PERLIO_TABLE_SIZE,PerlIO);
+    Newxz(f,PERLIO_TABLE_SIZE,PerlIO);
     if (!f) {
        return NULL;
     }
@@ -551,12 +572,12 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
 void
 PerlIO_cleantable(pTHX_ PerlIO **tablep)
 {
-    PerlIO *table = *tablep;
+    PerlIO * const table = *tablep;
     if (table) {
        int i;
        PerlIO_cleantable(aTHX_(PerlIO **) & (table[0]));
        for (i = PERLIO_TABLE_SIZE - 1; i > 0; i--) {
-           PerlIO *f = table + i;
+           PerlIO * const f = table + i;
            if (*f) {
                PerlIO_close(f);
            }
@@ -571,7 +592,8 @@ PerlIO_list_t *
 PerlIO_list_alloc(pTHX)
 {
     PerlIO_list_t *list;
-    Newz('L', list, 1, PerlIO_list_t);
+    PERL_UNUSED_CONTEXT;
+    Newxz(list, 1, PerlIO_list_t);
     list->refcnt = 1;
     return list;
 }
@@ -597,30 +619,33 @@ PerlIO_list_free(pTHX_ PerlIO_list_t *list)
 void
 PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg)
 {
+    dVAR;
     PerlIO_pair_t *p;
+    PERL_UNUSED_CONTEXT;
+
     if (list->cur >= list->len) {
        list->len += 8;
        if (list->array)
            Renew(list->array, list->len, PerlIO_pair_t);
        else
-           New('l', list->array, list->len, PerlIO_pair_t);
+           Newx(list->array, list->len, PerlIO_pair_t);
     }
     p = &(list->array[list->cur++]);
     p->funcs = funcs;
     if ((p->arg = arg)) {
-       (void)SvREFCNT_inc(arg);
+       SvREFCNT_inc_simple_void_NN(arg);
     }
 }
 
 PerlIO_list_t *
 PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param)
 {
-    PerlIO_list_t *list = (PerlIO_list_t *) NULL;
+    PerlIO_list_t *list = NULL;
     if (proto) {
        int i;
        list = PerlIO_list_alloc(aTHX);
        for (i=0; i < proto->cur; i++) {
-           SV *arg = Nullsv;
+           SV *arg = NULL;
            if (proto->array[i].arg)
                arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param);
            PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg);
@@ -639,7 +664,7 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
     PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param);
     PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param);
     PerlIO_allocate(aTHX); /* root slot is never used */
-    PerlIO_debug("Clone %p from %p\n",aTHX,proto);
+    PerlIO_debug("Clone %p from %p\n",(void*)aTHX,(void*)proto);
     while ((f = *table)) {
            int i;
            table = (PerlIO **) (f++);
@@ -650,23 +675,28 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
                f++;
            }
        }
+#else
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(proto);
+    PERL_UNUSED_ARG(param);
 #endif
 }
 
 void
 PerlIO_destruct(pTHX)
 {
+    dVAR;
     PerlIO **table = &PL_perlio;
     PerlIO *f;
 #ifdef USE_ITHREADS
-    PerlIO_debug("Destruct %p\n",aTHX);
+    PerlIO_debug("Destruct %p\n",(void*)aTHX);
 #endif
     while ((f = *table)) {
        int i;
        table = (PerlIO **) (f++);
        for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
            PerlIO *x = f;
-           PerlIOl *l;
+           const PerlIOl *l;
            while ((l = *x)) {
                if (l->tab->kind & PERLIO_K_DESTRUCT) {
                    PerlIO_debug("Destruct popping %s\n", l->tab->name);
@@ -685,7 +715,7 @@ PerlIO_destruct(pTHX)
 void
 PerlIO_pop(pTHX_ PerlIO *f)
 {
-    PerlIOl *l = *f;
+    const PerlIOl *l = *f;
     if (l) {
        PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, l->tab->name);
        if (l->tab->Popped) {
@@ -711,24 +741,25 @@ PerlIO_pop(pTHX_ PerlIO *f)
 AV *
 PerlIO_get_layers(pTHX_ PerlIO *f)
 {
-     AV *av = newAV();
+    dVAR;
+    AV * const av = newAV();
 
-     if (PerlIOValid(f)) {
-         PerlIOl *l = PerlIOBase(f);
-
-         while (l) {
-              SV *name = l->tab && l->tab->name ?
-                   newSVpv(l->tab->name, 0) : &PL_sv_undef;
-              SV *arg = l->tab && l->tab->Getarg ?
-                   (*l->tab->Getarg)(aTHX_ &l, 0, 0) : &PL_sv_undef;
-              av_push(av, name);
-              av_push(av, arg);
-              av_push(av, newSViv((IV)l->flags));
-              l = l->next;
-         }
-     }
+    if (PerlIOValid(f)) {
+       PerlIOl *l = PerlIOBase(f);
+
+       while (l) {
+           SV * const name = l->tab && l->tab->name ?
+           newSVpv(l->tab->name, 0) : &PL_sv_undef;
+           SV * const arg = l->tab && l->tab->Getarg ?
+           (*l->tab->Getarg)(aTHX_ &l, 0, 0) : &PL_sv_undef;
+           av_push(av, name);
+           av_push(av, arg);
+           av_push(av, newSViv((IV)l->flags));
+           l = l->next;
+       }
+    }
 
-     return av;
+    return av;
 }
 
 /*--------------------------------------------------------------------------------------*/
@@ -744,7 +775,7 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
     if ((SSize_t) len <= 0)
        len = strlen(name);
     for (i = 0; i < PL_known_layers->cur; i++) {
-       PerlIO_funcs *f = PL_known_layers->array[i].funcs;
+       PerlIO_funcs * const f = PL_known_layers->array[i].funcs;
        if (memEQ(f->name, name, len) && f->name[len] == 0) {
            PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f);
            return f;
@@ -756,21 +787,20 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
            Perl_croak(aTHX_ "Recursive call to Perl_load_module in PerlIO_find_layer");
            return NULL;
        } else {
-           SV *pkgsv = newSVpvn("PerlIO", 6);
-           SV *layer = newSVpvn(name, len);
-           CV *cv  = get_cv("PerlIO::Layer::NoWarnings", FALSE);
-           ENTER;
+           SV * const pkgsv = newSVpvs("PerlIO");
+           SV * const layer = newSVpvn(name, len);
+           CV * const cv    = get_cv("PerlIO::Layer::NoWarnings", FALSE);
+           ENTER;
            SAVEINT(PL_in_load_module);
            if (cv) {
                SAVEGENERICSV(PL_warnhook);
-               (void)SvREFCNT_inc(cv);
-               PL_warnhook = (SV *) cv;
+               PL_warnhook = (SV *) (SvREFCNT_inc_simple_NN(cv));
            }
            PL_in_load_module++;
            /*
             * The two SVs are magically freed by load_module
             */
-           Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv);
+           Perl_load_module(aTHX_ 0, pkgsv, NULL, layer, NULL);
            PL_in_load_module--;
            LEAVE;
            return PerlIO_find_layer(aTHX_ name, len, 0);
@@ -786,9 +816,9 @@ static int
 perlio_mg_set(pTHX_ SV *sv, MAGIC *mg)
 {
     if (SvROK(sv)) {
-       IO *io = GvIOn((GV *) SvRV(sv));
-       PerlIO *ifp = IoIFP(io);
-       PerlIO *ofp = IoOFP(io);
+       IO * const io = GvIOn((GV *) SvRV(sv));
+       PerlIO * const ifp = IoIFP(io);
+       PerlIO * const ofp = IoOFP(io);
        Perl_warn(aTHX_ "set %" SVf " %p %p %p", sv, io, ifp, ofp);
     }
     return 0;
@@ -798,9 +828,9 @@ static int
 perlio_mg_get(pTHX_ SV *sv, MAGIC *mg)
 {
     if (SvROK(sv)) {
-       IO *io = GvIOn((GV *) SvRV(sv));
-       PerlIO *ifp = IoIFP(io);
-       PerlIO *ofp = IoOFP(io);
+       IO * const io = GvIOn((GV *) SvRV(sv));
+       PerlIO * const ifp = IoIFP(io);
+       PerlIO * const ofp = IoOFP(io);
        Perl_warn(aTHX_ "get %" SVf " %p %p %p", sv, io, ifp, ofp);
     }
     return 0;
@@ -831,8 +861,8 @@ MGVTBL perlio_vtab = {
 XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
 {
     dXSARGS;
-    SV *sv = SvRV(ST(1));
-    AV *av = newAV();
+    SV * const sv = SvRV(ST(1));
+    AV * const av = newAV();
     MAGIC *mg;
     int count = 0;
     int i;
@@ -844,10 +874,10 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
     Perl_warn(aTHX_ "attrib %" SVf, sv);
     for (i = 2; i < items; i++) {
        STRLEN len;
-       const char *name = SvPV_const(ST(i), len);
-       SV *layer = PerlIO_find_layer(aTHX_ name, len, 1);
+       const char * const name = SvPV_const(ST(i), len);
+       SV * const layer = PerlIO_find_layer(aTHX_ name, len, 1);
        if (layer) {
-           av_push(av, SvREFCNT_inc(layer));
+           av_push(av, SvREFCNT_inc_simple_NN(layer));
        }
        else {
            ST(count) = ST(i);
@@ -863,8 +893,8 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
 SV *
 PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
 {
-    HV *stash = gv_stashpv("PerlIO::Layer", TRUE);
-    SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
+    HV * const stash = gv_stashpvs("PerlIO::Layer", TRUE);
+    SV * const sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
     return sv;
 }
 
@@ -873,6 +903,7 @@ XS(XS_PerlIO__Layer__NoWarnings)
     /* This is used as a %SIG{__WARN__} handler to supress warnings
        during loading of layers.
      */
+    dVAR;
     dXSARGS;
     if (items)
        PerlIO_debug("warning:%s\n",SvPV_nolen_const(ST(0)));
@@ -881,14 +912,15 @@ XS(XS_PerlIO__Layer__NoWarnings)
 
 XS(XS_PerlIO__Layer__find)
 {
+    dVAR;
     dXSARGS;
     if (items < 2)
        Perl_croak(aTHX_ "Usage class->find(name[,load])");
     else {
        STRLEN len;
-       const char *name = SvPV_const(ST(1), len);
+       const char * const name = SvPV_const(ST(1), len);
        const bool load = (items > 2) ? SvTRUE(ST(2)) : 0;
-       PerlIO_funcs *layer = PerlIO_find_layer(aTHX_ name, len, load);
+       PerlIO_funcs * const layer = PerlIO_find_layer(aTHX_ name, len, load);
        ST(0) =
            (layer) ? sv_2mortal(PerlIO_tab_sv(aTHX_ layer)) :
            &PL_sv_undef;
@@ -899,15 +931,17 @@ XS(XS_PerlIO__Layer__find)
 void
 PerlIO_define_layer(pTHX_ PerlIO_funcs *tab)
 {
+    dVAR;
     if (!PL_known_layers)
        PL_known_layers = PerlIO_list_alloc(aTHX);
-    PerlIO_list_push(aTHX_ PL_known_layers, tab, Nullsv);
+    PerlIO_list_push(aTHX_ PL_known_layers, tab, NULL);
     PerlIO_debug("define %s %p\n", tab->name, (void*)tab);
 }
 
 int
 PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
 {
+    dVAR;
     if (names) {
        const char *s = names;
        while (*s) {
@@ -916,7 +950,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
            if (*s) {
                STRLEN llen = 0;
                const char *e = s;
-               const char *as = Nullch;
+               const char *as = NULL;
                STRLEN alen = 0;
                if (!isIDFIRST(*s)) {
                    /*
@@ -976,8 +1010,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
                    }
                }
                if (e > s) {
-                   const bool warn_layer = ckWARN(WARN_LAYER);
-                   PerlIO_funcs *layer =
+                   PerlIO_funcs * const layer =
                        PerlIO_find_layer(aTHX_ s, llen, 1);
                    if (layer) {
                        PerlIO_list_push(aTHX_ av, layer,
@@ -986,7 +1019,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
                                         &PL_sv_undef);
                    }
                    else {
-                       if (warn_layer)
+                       if (ckWARN(WARN_LAYER))
                            Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"%.*s\"",
                                  (int) llen, s);
                        return -1;
@@ -1002,6 +1035,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
 void
 PerlIO_default_buffer(pTHX_ PerlIO_list_t *av)
 {
+    dVAR;
     PERLIO_FUNCS_DECL(*tab) = &PerlIO_perlio;
 #ifdef PERLIO_USING_CRLF
     tab = &PerlIO_crlf;
@@ -1036,9 +1070,9 @@ PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def)
 IV
 PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
-    (void)mode;
-    (void)arg;
-    (void)tab;
+    PERL_UNUSED_ARG(mode);
+    PERL_UNUSED_ARG(arg);
+    PERL_UNUSED_ARG(tab);
     if (PerlIOValid(f)) {
        PerlIO_flush(f);
        PerlIO_pop(aTHX_ f);
@@ -1081,8 +1115,9 @@ PERLIO_FUNCS_DECL(PerlIO_remove) = {
 PerlIO_list_t *
 PerlIO_default_layers(pTHX)
 {
+    dVAR;
     if (!PL_def_layerlist) {
-       const char *s = (PL_tainting) ? Nullch : PerlEnv_getenv("PERLIO");
+       const char * const s = (PL_tainting) ? NULL : PerlEnv_getenv("PERLIO");
        PERLIO_FUNCS_DECL(*osLayer) = &PerlIO_unix;
        PL_def_layerlist = PerlIO_list_alloc(aTHX);
        PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_unix));
@@ -1132,7 +1167,8 @@ Perl_boot_core_PerlIO(pTHX)
 PerlIO_funcs *
 PerlIO_default_layer(pTHX_ I32 n)
 {
-    PerlIO_list_t *av = PerlIO_default_layers(aTHX);
+    dVAR;
+    PerlIO_list_t * const av = PerlIO_default_layers(aTHX);
     if (n < 0)
        n += av->cur;
     return PerlIO_layer_fetch(aTHX_ av, n, PERLIO_FUNCS_CAST(&PerlIO_stdio));
@@ -1144,6 +1180,7 @@ PerlIO_default_layer(pTHX_ I32 n)
 void
 PerlIO_stdstreams(pTHX)
 {
+    dVAR;
     if (!PL_perlio) {
        PerlIO_allocate(aTHX);
        PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT);
@@ -1165,19 +1202,26 @@ PerlIO_push(pTHX_ PerlIO *f, PERLIO_FUNCS_DECL(*tab), const char *mode, SV *arg)
            goto mismatch;
        }
        /* Real layer with a data area */
-       Newc('L',l,tab->size,char,PerlIOl);
-       if (l && f) {
-           Zero(l, tab->size, char);
-           l->next = *f;
-           l->tab = (PerlIO_funcs*) tab;
-           *f = l;
-           PerlIO_debug("PerlIO_push f=%p %s %s %p\n", (void*)f, tab->name,
-                       (mode) ? mode : "(Null)", (void*)arg);
-           if (*l->tab->Pushed &&
-               (*l->tab->Pushed) (aTHX_ f, mode, arg, (PerlIO_funcs*) tab) != 0) {
-               PerlIO_pop(aTHX_ f);
-               return NULL;
+       if (f) {
+           char *temp;
+           Newxz(temp, tab->size, char);
+           l = (PerlIOl*)temp;
+           if (l) {
+               l->next = *f;
+               l->tab = (PerlIO_funcs*) tab;
+               *f = l;
+               PerlIO_debug("PerlIO_push f=%p %s %s %p\n",
+                            (void*)f, tab->name,
+                            (mode) ? mode : "(Null)", (void*)arg);
+               if (*l->tab->Pushed &&
+                   (*l->tab->Pushed)
+                     (aTHX_ f, mode, arg, (PerlIO_funcs*) tab) != 0) {
+                   PerlIO_pop(aTHX_ f);
+                   return NULL;
+               }
            }
+           else
+               return NULL;
        }
     }
     else if (f) {
@@ -1213,9 +1257,9 @@ PerlIOBase_binmode(pTHX_ PerlIO *f)
 IV
 PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
-    (void)mode;
-    (void)arg;
-    (void)tab;
+    PERL_UNUSED_ARG(mode);
+    PERL_UNUSED_ARG(arg);
+    PERL_UNUSED_ARG(tab);
 
     if (PerlIOValid(f)) {
        PerlIO *t;
@@ -1257,7 +1301,7 @@ PerlIO_apply_layera(pTHX_ PerlIO *f, const char *mode,
 {
     int code = 0;
     while (n < max) {
-       PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL);
+       PerlIO_funcs * const tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL);
        if (tab) {
            if (!PerlIO_push(aTHX_ f, tab, mode, PerlIOArg)) {
                code = -1;
@@ -1274,7 +1318,7 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
 {
     int code = 0;
     if (f && names) {
-       PerlIO_list_t *layers = PerlIO_list_alloc(aTHX);
+       PerlIO_list_t * const layers = PerlIO_list_alloc(aTHX);
        code = PerlIO_parse_layers(aTHX_ layers, names);
        if (code == 0) {
            code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0, layers->cur);
@@ -1293,9 +1337,10 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
 int
 PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
 {
-    PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n",
-                (void*)f, PerlIOBase(f)->tab->name, iotype, mode,
-                (names) ? names : "(Null)");
+    PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n", (void*)f,
+                 (PerlIOBase(f)) ? PerlIOBase(f)->tab->name : "(Null)",
+                 iotype, mode, (names) ? names : "(Null)");
+
     if (names) {
        /* Do not flush etc. if (e.g.) switching encodings.
           if a pushed layer knows it needs to flush lower layers
@@ -1341,7 +1386,7 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
        /* Legacy binmode is now _defined_ as being equivalent to pushing :raw
           So code that used to be here is now in PerlIORaw_pushed().
         */
-       return PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_raw), Nullch, Nullsv) ? TRUE : FALSE;
+       return PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_raw), NULL, NULL) ? TRUE : FALSE;
     }
 }
 
@@ -1349,7 +1394,7 @@ int
 PerlIO__close(pTHX_ PerlIO *f)
 {
     if (PerlIOValid(f)) {
-       PerlIO_funcs *tab = PerlIOBase(f)->tab;
+       PerlIO_funcs * const tab = PerlIOBase(f)->tab;
        if (tab && tab->Close)
            return (*tab->Close)(aTHX_ f);
        else
@@ -1374,76 +1419,61 @@ Perl_PerlIO_close(pTHX_ PerlIO *f)
 int
 Perl_PerlIO_fileno(pTHX_ PerlIO *f)
 {
+    dVAR;
      Perl_PerlIO_or_Base(f, Fileno, fileno, -1, (aTHX_ f));
 }
 
-static const char *
-PerlIO_context_layers(pTHX_ const char *mode)
-{
-    const char *type = NULL;
-    /*
-     * Need to supply default layer info from open.pm
-     */
-    if (PL_curcop) {
-       SV *layers = PL_curcop->cop_io;
-       if (layers) {
-           STRLEN len;
-           type = SvPV(layers, len);
-           if (type && mode[0] != 'r') {
-               /*
-                * Skip to write part
-                */
-               const char *s = strchr(type, 0);
-               if (s && (STRLEN)(s - type) < len) {
-                   type = s + 1;
-               }
-           }
-       }
-    }
-    return type;
-}
 
 static PerlIO_funcs *
 PerlIO_layer_from_ref(pTHX_ SV *sv)
 {
+    dVAR;
     /*
      * For any scalar type load the handler which is bundled with perl
      */
-    if (SvTYPE(sv) < SVt_PVAV)
-       return PerlIO_find_layer(aTHX_ "scalar", 6, 1);
+    if (SvTYPE(sv) < SVt_PVAV) {
+       PerlIO_funcs *f = PerlIO_find_layer(aTHX_ STR_WITH_LEN("scalar"), 1);
+       /* This isn't supposed to happen, since PerlIO::scalar is core,
+        * but could happen anyway in smaller installs or with PAR */
+       if (!f && ckWARN(WARN_LAYER))
+           Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"scalar\"");
+       return f;
+    }
 
     /*
      * For other types allow if layer is known but don't try and load it
      */
     switch (SvTYPE(sv)) {
     case SVt_PVAV:
-       return PerlIO_find_layer(aTHX_ "Array", 5, 0);
+       return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Array"), 0);
     case SVt_PVHV:
-       return PerlIO_find_layer(aTHX_ "Hash", 4, 0);
+       return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Hash"), 0);
     case SVt_PVCV:
-       return PerlIO_find_layer(aTHX_ "Code", 4, 0);
+       return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Code"), 0);
     case SVt_PVGV:
-       return PerlIO_find_layer(aTHX_ "Glob", 4, 0);
+       return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Glob"), 0);
+    default:
+       return NULL;
     }
-    return NULL;
 }
 
 PerlIO_list_t *
 PerlIO_resolve_layers(pTHX_ const char *layers,
                      const char *mode, int narg, SV **args)
 {
+    dVAR;
     PerlIO_list_t *def = PerlIO_default_layers(aTHX);
     int incdef = 1;
     if (!PL_perlio)
        PerlIO_stdstreams(aTHX);
     if (narg) {
-       SV *arg = *args;
+       SV * const arg = *args;
        /*
         * If it is a reference but not an object see if we have a handler
         * for it
         */
        if (SvROK(arg) && !sv_isobject(arg)) {
-           PerlIO_funcs *handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
+           PerlIO_funcs * const handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
            if (handler) {
                def = PerlIO_list_alloc(aTHX);
                PerlIO_list_push(aTHX_ def, handler, &PL_sv_undef);
@@ -1456,8 +1486,8 @@ PerlIO_resolve_layers(pTHX_ const char *layers,
             */
        }
     }
-    if (!layers)
-       layers = PerlIO_context_layers(aTHX_ mode);
+    if (!layers || !*layers)
+       layers = Perl_PerlIO_context_layers(aTHX_ mode);
     if (layers && *layers) {
        PerlIO_list_t *av;
        if (incdef) {
@@ -1476,7 +1506,7 @@ PerlIO_resolve_layers(pTHX_ const char *layers,
        }
        else {
            PerlIO_list_free(aTHX_ av);
-           return (PerlIO_list_t *) NULL;
+           return NULL;
        }
     }
     else {
@@ -1490,10 +1520,11 @@ PerlIO *
 PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
             int imode, int perm, PerlIO *f, int narg, SV **args)
 {
+    dVAR;
     if (!f && narg == 1 && *args == &PL_sv_undef) {
        if ((f = PerlIO_tmpfile())) {
-           if (!layers)
-               layers = PerlIO_context_layers(aTHX_ mode);
+           if (!layers || !*layers)
+               layers = Perl_PerlIO_context_layers(aTHX_ mode);
            if (layers && *layers)
                PerlIO_apply_layers(aTHX_ f, mode, layers);
        }
@@ -1510,7 +1541,7 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
            PerlIOl *l = *f;
            layera = PerlIO_list_alloc(aTHX);
            while (l) {
-               SV *arg = (l->tab->Getarg)
+               SV * const arg = (l->tab->Getarg)
                        ? (*l->tab->Getarg) (aTHX_ &l, NULL, 0)
                        : &PL_sv_undef;
                PerlIO_list_push(aTHX_ layera, l->tab, arg);
@@ -1528,7 +1559,7 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
         */
        n = layera->cur - 1;
        while (n >= 0) {
-           PerlIO_funcs *t = PerlIO_layer_fetch(aTHX_ layera, n, NULL);
+           PerlIO_funcs * const t = PerlIO_layer_fetch(aTHX_ layera, n, NULL);
            if (t && t->Open) {
                tab = t;
                break;
@@ -1543,8 +1574,8 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
                Perl_croak(aTHX_ "More than one argument to open(,':%s')",tab->name);
            }
            PerlIO_debug("openn(%s,'%s','%s',%d,%x,%o,%p,%d,%p)\n",
-                        tab->name, layers, mode, fd, imode, perm,
-                        (void*)f, narg, (void*)args);
+                        tab->name, layers ? layers : "(Null)", mode, fd,
+                        imode, perm, (void*)f, narg, (void*)args);
            if (tab->Open)
                 f = (*tab->Open) (aTHX_ tab, layera, n, mode, fd, imode, perm,
                                   f, narg, args);
@@ -1605,6 +1636,7 @@ Perl_PerlIO_tell(pTHX_ PerlIO *f)
 int
 Perl_PerlIO_flush(pTHX_ PerlIO *f)
 {
+    dVAR;
     if (f) {
        if (*f) {
            const PerlIO_funcs *tab = PerlIOBase(f)->tab;
@@ -1646,6 +1678,7 @@ Perl_PerlIO_flush(pTHX_ PerlIO *f)
 void
 PerlIOBase_flush_linebuf(pTHX)
 {
+    dVAR;
     PerlIO **table = &PL_perlio;
     PerlIO *f;
     while ((f = *table)) {
@@ -1707,7 +1740,7 @@ int
 PerlIO_has_base(PerlIO *f)
 {
      if (PerlIOValid(f)) {
-          const PerlIO_funcs *tab = PerlIOBase(f)->tab;
+         const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
 
          if (tab)
               return (tab->Get_base != NULL);
@@ -1723,7 +1756,7 @@ int
 PerlIO_fast_gets(PerlIO *f)
 {
     if (PerlIOValid(f) && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) {
-        const PerlIO_funcs *tab = PerlIOBase(f)->tab;
+        const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
 
         if (tab)
              return (tab->Set_ptrcnt != NULL);
@@ -1739,7 +1772,7 @@ int
 PerlIO_has_cntptr(PerlIO *f)
 {
     if (PerlIOValid(f)) {
-       const PerlIO_funcs *tab = PerlIOBase(f)->tab;
+       const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
 
        if (tab)
             return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
@@ -1755,7 +1788,7 @@ int
 PerlIO_canset_cnt(PerlIO *f)
 {
     if (PerlIOValid(f)) {
-         const PerlIO_funcs *tab = PerlIOBase(f)->tab;
+         const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
 
          if (tab)
               return (tab->Set_ptrcnt != NULL);
@@ -1812,8 +1845,9 @@ Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt)
 IV
 PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
-    (void)mode;
-    (void)arg;
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(mode);
+    PERL_UNUSED_ARG(arg);
     if (PerlIOValid(f)) {
        if (tab->kind & PERLIO_K_UTF8)
            PerlIOBase(f)->flags |= PERLIO_F_UTF8;
@@ -1891,8 +1925,8 @@ PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
               IV n, const char *mode, int fd, int imode, int perm,
               PerlIO *old, int narg, SV **args)
 {
-    PerlIO_funcs *tab = PerlIO_default_btm();
-    (void)self;
+    PerlIO_funcs * const tab = PerlIO_default_btm();
+    PERL_UNUSED_ARG(self);
     if (tab && tab->Open)
         return (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
                              old, narg, args);
@@ -1979,7 +2013,8 @@ IV
 PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
     PerlIOl * const l = PerlIOBase(f);
-    (void)arg;
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(arg);
 
     l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE |
                  PERLIO_F_TRUNCATE | PERLIO_F_APPEND);
@@ -2037,7 +2072,8 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 IV
 PerlIOBase_popped(pTHX_ PerlIO *f)
 {
-    (void)f;
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(f);
     return 0;
 }
 
@@ -2048,7 +2084,7 @@ PerlIOBase_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
      * Save the position as current head considers it
      */
     const Off_t old = PerlIO_tell(f);
-    PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_pending), "r", Nullsv);
+    PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_pending), "r", NULL);
     PerlIOSelf(f, PerlIOBuf)->posn = old;
     return PerlIOBuf_unread(aTHX_ f, vbuf, count);
 }
@@ -2064,21 +2100,26 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
            return 0;
        }
        while (count > 0) {
+        get_cnt:
+         {
            SSize_t avail = PerlIO_get_cnt(f);
            SSize_t take = 0;
            if (avail > 0)
-               take = ((SSize_t)count < avail) ? count : avail;
+               take = ((SSize_t)count < avail) ? (SSize_t)count : avail;
            if (take > 0) {
                STDCHAR *ptr = PerlIO_get_ptr(f);
                Copy(ptr, buf, take, STDCHAR);
                PerlIO_set_ptrcnt(f, ptr + take, (avail -= take));
                count -= take;
                buf += take;
+               if (avail == 0)         /* set_ptrcnt could have reset avail */
+                   goto get_cnt;
            }
            if (count > 0 && avail <= 0) {
                if (PerlIO_fill(f) != 0)
                    break;
            }
+         }
        }
        return (buf - (STDCHAR *) vbuf);
     }
@@ -2088,14 +2129,16 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 IV
 PerlIOBase_noop_ok(pTHX_ PerlIO *f)
 {
-    (void)f;
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(f);
     return 0;
 }
 
 IV
 PerlIOBase_noop_fail(pTHX_ PerlIO *f)
 {
-    (void)f;
+    PERL_UNUSED_CONTEXT;
+    PERL_UNUSED_ARG(f);
     return -1;
 }
 
@@ -2131,6 +2174,7 @@ PerlIOBase_close(pTHX_ PerlIO *f)
 IV
 PerlIOBase_eof(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
     if (PerlIOValid(f)) {
        return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
     }
@@ -2140,6 +2184,7 @@ PerlIOBase_eof(pTHX_ PerlIO *f)
 IV
 PerlIOBase_error(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
     if (PerlIOValid(f)) {
        return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
     }
@@ -2150,7 +2195,7 @@ void
 PerlIOBase_clearerr(pTHX_ PerlIO *f)
 {
     if (PerlIOValid(f)) {
-       PerlIO *n = PerlIONext(f);
+       PerlIO * const n = PerlIONext(f);
        PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR | PERLIO_F_EOF);
        if (PerlIOValid(n))
            PerlIO_clearerr(n);
@@ -2160,6 +2205,7 @@ PerlIOBase_clearerr(pTHX_ PerlIO *f)
 void
 PerlIOBase_setlinebuf(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
     if (PerlIOValid(f)) {
        PerlIOBase(f)->flags |= PERLIO_F_LINEBUF;
     }
@@ -2169,7 +2215,7 @@ SV *
 PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
 {
     if (!arg)
-       return Nullsv;
+       return NULL;
 #ifdef sv_dup
     if (param) {
        return sv_dup(arg, param);
@@ -2178,6 +2224,7 @@ PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
        return newSVsv(arg);
     }
 #else
+    PERL_UNUSED_ARG(param);
     return newSVsv(arg);
 #endif
 }
@@ -2185,7 +2232,7 @@ PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
 PerlIO *
 PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
 {
-    PerlIO *nexto = PerlIONext(o);
+    PerlIO * const nexto = PerlIONext(o);
     if (PerlIOValid(nexto)) {
        const PerlIO_funcs * const tab = PerlIOBase(nexto)->tab;
        if (tab && tab->Dup)
@@ -2194,7 +2241,7 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
            f = PerlIOBase_dup(aTHX_ f, nexto, param, flags);
     }
     if (f) {
-       PerlIO_funcs *self = PerlIOBase(o)->tab;
+       PerlIO_funcs * const self = PerlIOBase(o)->tab;
        SV *arg;
        char buf[8];
        PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n",
@@ -2202,7 +2249,7 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
        if (self->Getarg)
            arg = (*self->Getarg)(aTHX_ o, param, flags);
        else {
-           arg = Nullsv;
+           arg = NULL;
        }
        f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg);
        if (arg) {
@@ -2212,34 +2259,83 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
     return f;
 }
 
-#ifdef USE_THREADS
-perl_mutex PerlIO_mutex;
+/* PL_perlio_fd_refcnt[] is in intrpvar.h */
+
+/* Must be called with PL_perlio_mutex locked. */
+static void
+S_more_refcounted_fds(pTHX_ const int new_fd) {
+    dVAR;
+    const int old_max = PL_perlio_fd_refcnt_size;
+    const int new_max = 16 + (new_fd & ~15);
+    int *new_array;
+
+    PerlIO_debug("More fds - old=%d, need %d, new=%d\n",
+                old_max, new_fd, new_max);
+
+    if (new_fd < old_max) {
+       return;
+    }
+
+    assert (new_max > new_fd);
+
+    /* Use plain realloc() since we need this memory to be really
+     * global and visible to all the interpreters and/or threads. */
+    new_array = (int*) realloc(PL_perlio_fd_refcnt, new_max * sizeof(int));
+
+    if (!new_array) {
+#ifdef USE_ITHREADS
+       MUTEX_UNLOCK(&PL_perlio_mutex);
 #endif
+       /* Can't use PerlIO to write as it allocates memory */
+       PerlLIO_write(PerlIO_fileno(Perl_error_log),
+                     PL_no_mem, strlen(PL_no_mem));
+       my_exit(1);
+    }
+
+    PL_perlio_fd_refcnt_size = new_max;
+    PL_perlio_fd_refcnt = new_array;
+
+    PerlIO_debug("Zeroing %p, %d\n",
+                (void*)(new_array + old_max),
+                new_max - old_max);
+
+    Zero(new_array + old_max, new_max - old_max, int);
+}
 
-/* PL_perlio_fd_refcnt[] is in intrpvar.h */
 
 void
 PerlIO_init(pTHX)
 {
- /* Place holder for stdstreams call ??? */
-#ifdef USE_THREADS
-    MUTEX_INIT(&PerlIO_mutex);
-#endif
+    /* MUTEX_INIT(&PL_perlio_mutex) is done in PERL_SYS_INIT3(). */
+    PERL_UNUSED_CONTEXT;
 }
 
 void
 PerlIOUnix_refcnt_inc(int fd)
 {
     dTHX;
-    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
-#ifdef USE_THREADS
-       MUTEX_LOCK(&PerlIO_mutex);
+    if (fd >= 0) {
+       dVAR;
+
+#ifdef USE_ITHREADS
+       MUTEX_LOCK(&PL_perlio_mutex);
 #endif
+       if (fd >= PL_perlio_fd_refcnt_size)
+           S_more_refcounted_fds(aTHX_ fd);
+
        PL_perlio_fd_refcnt[fd]++;
-       PerlIO_debug("fd %d refcnt=%d\n",fd,PL_perlio_fd_refcnt[fd]);
-#ifdef USE_THREADS
-       MUTEX_UNLOCK(&PerlIO_mutex);
+       if (PL_perlio_fd_refcnt[fd] <= 0) {
+           Perl_croak(aTHX_ "refcnt_inc: fd %d: %d <= 0\n",
+                      fd, PL_perlio_fd_refcnt[fd]);
+       }
+       PerlIO_debug("refcnt_inc: fd %d refcnt=%d\n",
+                    fd, PL_perlio_fd_refcnt[fd]);
+
+#ifdef USE_ITHREADS
+       MUTEX_UNLOCK(&PL_perlio_mutex);
 #endif
+    } else {
+       Perl_croak(aTHX_ "refcnt_inc: fd %d < 0\n", fd);
     }
 }
 
@@ -2248,15 +2344,26 @@ PerlIOUnix_refcnt_dec(int fd)
 {
     dTHX;
     int cnt = 0;
-    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
-#ifdef USE_THREADS
-       MUTEX_LOCK(&PerlIO_mutex);
+    if (fd >= 0) {
+       dVAR;
+#ifdef USE_ITHREADS
+       MUTEX_LOCK(&PL_perlio_mutex);
 #endif
+       if (fd >= PL_perlio_fd_refcnt_size) {
+           Perl_croak(aTHX_ "refcnt_dec: fd %d >= refcnt_size %d\n",
+                      fd, PL_perlio_fd_refcnt_size);
+       }
+       if (PL_perlio_fd_refcnt[fd] <= 0) {
+           Perl_croak(aTHX_ "refcnt_dec: fd %d: %d <= 0\n",
+                      fd, PL_perlio_fd_refcnt[fd]);
+       }
        cnt = --PL_perlio_fd_refcnt[fd];
-       PerlIO_debug("fd %d refcnt=%d\n",fd,cnt);
-#ifdef USE_THREADS
-       MUTEX_UNLOCK(&PerlIO_mutex);
+       PerlIO_debug("refcnt_dec: fd %d refcnt=%d\n", fd, cnt);
+#ifdef USE_ITHREADS
+       MUTEX_UNLOCK(&PL_perlio_mutex);
 #endif
+    } else {
+       Perl_croak(aTHX_ "refcnt_dec: fd %d < 0\n", fd);
     }
     return cnt;
 }
@@ -2264,12 +2371,14 @@ PerlIOUnix_refcnt_dec(int fd)
 void
 PerlIO_cleanup(pTHX)
 {
+    dVAR;
     int i;
 #ifdef USE_ITHREADS
-    PerlIO_debug("Cleanup layers for %p\n",aTHX);
+    PerlIO_debug("Cleanup layers for %p\n",(void*)aTHX);
 #else
     PerlIO_debug("Cleanup layers\n");
 #endif
+
     /* Raise STDIN..STDERR refcount so we don't close them */
     for (i=0; i < 3; i++)
        PerlIOUnix_refcnt_inc(i);
@@ -2288,6 +2397,32 @@ PerlIO_cleanup(pTHX)
     }
 }
 
+void PerlIO_teardown(pTHX) /* Call only from PERL_SYS_TERM(). */
+{
+    
+#ifdef DEBUGGING
+    {
+       /* By now all filehandles should have been closed, so any
+        * stray (non-STD-)filehandles indicate *possible* (PerlIO)
+        * errors. */
+       int i;
+       for (i = 3; i < PL_perlio_fd_refcnt_size; i++) {
+           if (PL_perlio_fd_refcnt[i])
+               PerlIO_debug("PerlIO_cleanup: fd %d refcnt=%d\n",
+                            i, PL_perlio_fd_refcnt[i]);
+       }
+    }
+#endif
+    /* Not bothering with PL_perlio_mutex since by now
+     * all the interpreters are gone. */
+    if (PL_perlio_fd_refcnt_size /* Assuming initial size of zero. */
+        && PL_perlio_fd_refcnt) {
+       free(PL_perlio_fd_refcnt); /* To match realloc() in S_more_refcounted_fds(). */
+       PL_perlio_fd_refcnt = NULL;
+       PL_perlio_fd_refcnt_size = 0;
+    }
+}
+
 
 
 /*--------------------------------------------------------------------------------------*/
@@ -2360,6 +2495,7 @@ PerlIOUnix_oflags(const char *mode)
 IV
 PerlIOUnix_fileno(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
     return PerlIOSelf(f, PerlIOUnix)->fd;
 }
 
@@ -2382,6 +2518,7 @@ PerlIOUnix_setfd(pTHX_ PerlIO *f, int fd, int imode)
     s->fd = fd;
     s->oflags = imode;
     PerlIOUnix_refcnt_inc(fd);
+    PERL_UNUSED_CONTEXT;
 }
 
 IV
@@ -2409,6 +2546,7 @@ PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
 {
     const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
     Off_t new_loc;
+    PERL_UNUSED_CONTEXT;
     if (PerlIOBase(f)->flags & PERLIO_F_NOTREG) {
 #ifdef  ESPIPE
        SETERRNO(ESPIPE, LIB_INVARG);
@@ -2419,9 +2557,7 @@ PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
     }
     new_loc = PerlLIO_lseek(fd, offset, whence);
     if (new_loc == (Off_t) - 1)
-     {
-      return -1;
-     }
+       return -1;
     PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
     return  0;
 }
@@ -2466,6 +2602,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
     }
     else {
        if (f) {
+           NOOP;
            /*
             * FIXME: pop layers ???
             */
@@ -2477,12 +2614,12 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 PerlIO *
 PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
 {
-    PerlIOUnix *os = PerlIOSelf(o, PerlIOUnix);
+    const PerlIOUnix * const os = PerlIOSelf(o, PerlIOUnix);
     int fd = os->fd;
     if (flags & PERLIO_DUP_FD) {
        fd = PerlLIO_dup(fd);
     }
-    if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
+    if (fd >= 0) {
        f = PerlIOBase_dup(aTHX_ f, o, param, flags);
        if (f) {
            /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */
@@ -2497,6 +2634,7 @@ PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
 SSize_t
 PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
+    dVAR;
     const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
 #ifdef PERLIO_STD_SPECIAL
     if (fd == 0)
@@ -2528,6 +2666,7 @@ PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 SSize_t
 PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
+    dVAR;
     const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
 #ifdef PERLIO_STD_SPECIAL
     if (fd == 1 || fd == 2)
@@ -2545,11 +2684,14 @@ PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
        }
        PERL_ASYNC_CHECK();
     }
+    /*NOTREACHED*/
 }
 
 Off_t
 PerlIOUnix_tell(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
+
     return PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, 0, SEEK_CUR);
 }
 
@@ -2557,6 +2699,7 @@ PerlIOUnix_tell(pTHX_ PerlIO *f)
 IV
 PerlIOUnix_close(pTHX_ PerlIO *f)
 {
+    dVAR;
     const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
     int code = 0;
     if (PerlIOBase(f)->flags & PERLIO_F_OPEN) {
@@ -2634,9 +2777,12 @@ typedef struct {
 IV
 PerlIOStdio_fileno(pTHX_ PerlIO *f)
 {
-    FILE *s;
-    if (PerlIOValid(f) && (s = PerlIOSelf(f, PerlIOStdio)->stdio)) {
-       return PerlSIO_fileno(s);
+    PERL_UNUSED_CONTEXT;
+
+    if (PerlIOValid(f)) {
+       FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
+       if (s)
+           return PerlSIO_fileno(s);
     }
     errno = EBADF;
     return -1;
@@ -2663,7 +2809,7 @@ PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab
 {
     PerlIO *n;
     if (PerlIOValid(f) && PerlIOValid(n = PerlIONext(f))) {
-        PerlIO_funcs *toptab = PerlIOBase(n)->tab;
+       PerlIO_funcs * const toptab = PerlIOBase(n)->tab;
         if (toptab == tab) {
            /* Top is already stdio - pop self (duplicate) and use original */
            PerlIO_pop(aTHX_ f);
@@ -2717,7 +2863,7 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
            }
            fclose(f2);
        }
-       if ((f = PerlIO_push(aTHX_(f = PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, Nullsv))) {
+       if ((f = PerlIO_push(aTHX_(f = PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, NULL))) {
            s = PerlIOSelf(f, PerlIOStdio);
            s->stdio = stdio;
        }
@@ -2732,8 +2878,8 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 {
     char tmode[8];
     if (PerlIOValid(f)) {
-       const char *path = SvPV_nolen_const(*args);
-       PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
+       const char * const path = SvPV_nolen_const(*args);
+       PerlIOStdio * const s = PerlIOSelf(f, PerlIOStdio);
        FILE *stdio;
        PerlIOUnix_refcnt_dec(fileno(s->stdio));
        stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
@@ -2746,7 +2892,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
     }
     else {
        if (narg > 0) {
-           const char *path = SvPV_nolen_const(*args);
+           const char * const path = SvPV_nolen_const(*args);
            if (*mode == IoTYPE_NUMERIC) {
                mode++;
                fd = PerlLIO_open3(path, imode, perm);
@@ -2761,7 +2907,6 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 #endif
                stdio = PerlSIO_fopen(path, mode);
                if (stdio) {
-                   PerlIOStdio *s;
                    if (!f) {
                        f = PerlIO_allocate(aTHX);
                    }
@@ -2769,9 +2914,10 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                        mode = PerlIOStdio_mode(mode, tmode);
                    f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
                    if (f) {
-                       s = PerlIOSelf(f, PerlIOStdio);
-                       s->stdio = stdio;
-                       PerlIOUnix_refcnt_inc(fileno(s->stdio));
+                       PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
+                       PerlIOUnix_refcnt_inc(fileno(stdio));
+                   } else {
+                       PerlSIO_fclose(stdio);
                    }
                    return f;
                }
@@ -2809,9 +2955,8 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                    f = PerlIO_allocate(aTHX);
                }
                if ((f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) {
-                   PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
-                   s->stdio = stdio;
-                   PerlIOUnix_refcnt_inc(fileno(s->stdio));
+                   PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
+                   PerlIOUnix_refcnt_inc(fileno(stdio));
                }
                return f;
            }
@@ -2837,6 +2982,7 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
                goto set_this;
            }
            else {
+               NOOP;
                /* FIXME: To avoid messy error recovery if dup fails
                   re-use the existing stdio as though flag was not set
                 */
@@ -2853,6 +2999,8 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
 static int
 PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
 {
+    PERL_UNUSED_CONTEXT;
+
     /* XXX this could use PerlIO_canset_fileno() and
      * PerlIO_set_fileno() support from Configure
      */
@@ -2867,31 +3015,8 @@ PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
     f->_fileno = -1;
     return 1;
 #  elif defined(__sun__)
-#    if defined(_LP64)
-    /* On solaris, if _LP64 is defined, the FILE structure is this:
-     *
-     *  struct FILE {
-     *      long __pad[16];
-     *  };
-     *
-     * It turns out that the fd is stored in the top 32 bits of
-     * file->__pad[4]. The lower 32 bits contain flags. file->pad[5] appears
-     * to contain a pointer or offset into another structure. All the
-     * remaining fields are zero.
-     *
-     * We set the top bits to -1 (0xFFFFFFFF).
-     */
-    f->__pad[4] |= 0xffffffff00000000L;
-    assert(fileno(f) == 0xffffffff);
-#    else /* !defined(_LP64) */
-    /* _file is just a unsigned char :-(
-       Not clear why we dup() rather than using -1
-       even if that would be treated as 0xFF - so will
-       a dup fail ...
-     */
-    f->_file = PerlLIO_dup(fileno(f));
-#    endif /* defined(_LP64) */
-    return 1;
+    PERL_UNUSED_ARG(f);
+    return 0;
 #  elif defined(__hpux)
     f->__fileH = 0xff;
     f->__fileL = 0xff;
@@ -2947,7 +3072,7 @@ PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
      */
 #    error "Don't know how to set FILE.fileno on your platform"
 #endif
-    (void)f;
+    PERL_UNUSED_ARG(f);
     return 0;
 #  endif
 }
@@ -2955,14 +3080,13 @@ PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
 IV
 PerlIOStdio_close(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     if (!stdio) {
        errno = EBADF;
        return -1;
     }
     else {
         const int fd = fileno(stdio);
-       int socksfd = 0;
        int invalidate = 0;
        IV result = 0;
        int saveerr = 0;
@@ -2974,36 +3098,26 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
         */
        int optval;
        Sock_size_t optlen = sizeof(int);
-       if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *) &optval, &optlen) == 0) {
-            socksfd = 1;
+       if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *) &optval, &optlen) == 0)
            invalidate = 1;
-       }
 #endif
-       if (PerlIOUnix_refcnt_dec(fd) > 0) {
-           /* File descriptor still in use */
+       if (PerlIOUnix_refcnt_dec(fd) > 0) /* File descriptor still in use */
            invalidate = 1;
-           socksfd = 0;
-       }
        if (invalidate) {
-           /* For STD* handles don't close the stdio at all
-              this is because we have shared the FILE * too
-            */
-           if (stdio == stdin) {
-               /* Some stdios are buggy fflush-ing inputs */
-               return 0;
-           }
-           else if (stdio == stdout || stdio == stderr) {
-               return PerlIO_flush(f);
-           }
+           /* For STD* handles, don't close stdio, since we shared the FILE *, too. */
+           if (stdio == stdin) /* Some stdios are buggy fflush-ing inputs */
+               return 0;
+           if (stdio == stdout || stdio == stderr)
+               return PerlIO_flush(f);
             /* Tricky - must fclose(stdio) to free memory but not close(fd)
               Use Sarathy's trick from maint-5.6 to invalidate the
               fileno slot of the FILE *
            */
            result = PerlIO_flush(f);
            saveerr = errno;
-           if (!(invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio))) {
-               dupfd = PerlLIO_dup(fd);
-           }
+           invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio);
+           if (!invalidate)
+               dupfd = PerlLIO_dup(fd);
        }
         result = PerlSIO_fclose(stdio);
        /* We treat error from stdio as success if we invalidated
@@ -3013,10 +3127,10 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
            errno = saveerr;
            result = 0;
        }
-       if (socksfd) {
-           /* in SOCKS case let close() determine return value */
-           result = close(fd);
-       }
+#ifdef SOCKS5_VERSION_NAME
+       /* in SOCKS' case, let close() determine return value */
+       result = close(fd);
+#endif
        if (dupfd) {
            PerlLIO_dup2(dupfd,fd);
            PerlLIO_close(dupfd);
@@ -3028,7 +3142,8 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
 SSize_t
 PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
-    FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
+    dVAR;
+    FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
     SSize_t got = 0;
     for (;;) {
        if (count == 1) {
@@ -3059,7 +3174,7 @@ SSize_t
 PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
     SSize_t unread = 0;
-    FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
 
 #ifdef STDIO_BUFFER_WRITABLE
     if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
@@ -3116,6 +3231,7 @@ PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 SSize_t
 PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
+    dVAR;
     SSize_t got;
     for (;;) {
        got = PerlSIO_fwrite(vbuf, 1, count,
@@ -3131,25 +3247,32 @@ PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 IV
 PerlIOStdio_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    PERL_UNUSED_CONTEXT;
+
     return PerlSIO_fseek(stdio, offset, whence);
 }
 
 Off_t
 PerlIOStdio_tell(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    PERL_UNUSED_CONTEXT;
+
     return PerlSIO_ftell(stdio);
 }
 
 IV
 PerlIOStdio_flush(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    PERL_UNUSED_CONTEXT;
+
     if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
        return PerlSIO_fflush(stdio);
     }
     else {
+       NOOP;
 #if 0
        /*
         * FIXME: This discards ungetc() and pre-read stuff which is not
@@ -3160,7 +3283,7 @@ PerlIOStdio_flush(pTHX_ PerlIO *f)
        /*
         * Not writeable - sync by attempting a seek
         */
-       int err = errno;
+       const int err = errno;
        if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0)
            errno = err;
 #endif
@@ -3171,28 +3294,36 @@ PerlIOStdio_flush(pTHX_ PerlIO *f)
 IV
 PerlIOStdio_eof(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
+
     return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
 }
 
 IV
 PerlIOStdio_error(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
+
     return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio);
 }
 
 void
 PerlIOStdio_clearerr(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
+
     PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio);
 }
 
 void
 PerlIOStdio_setlinebuf(pTHX_ PerlIO *f)
 {
+    PERL_UNUSED_CONTEXT;
+
 #ifdef HAS_SETLINEBUF
     PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio);
 #else
-    PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
+    PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, NULL, _IOLBF, 0);
 #endif
 }
 
@@ -3200,14 +3331,14 @@ PerlIOStdio_setlinebuf(pTHX_ PerlIO *f)
 STDCHAR *
 PerlIOStdio_get_base(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     return (STDCHAR*)PerlSIO_get_base(stdio);
 }
 
 Size_t
 PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     return PerlSIO_get_bufsiz(stdio);
 }
 #endif
@@ -3216,24 +3347,24 @@ PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f)
 STDCHAR *
 PerlIOStdio_get_ptr(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     return (STDCHAR*)PerlSIO_get_ptr(stdio);
 }
 
 SSize_t
 PerlIOStdio_get_cnt(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     return PerlSIO_get_cnt(stdio);
 }
 
 void
 PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     if (ptr != NULL) {
 #ifdef STDIO_PTR_LVALUE
-       PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */
+       PerlSIO_set_ptr(stdio, ptr); /* LHS STDCHAR* cast non-portable */
 #ifdef STDIO_PTR_LVAL_SETS_CNT
        if (PerlSIO_get_cnt(stdio) != (cnt)) {
            assert(PerlSIO_get_cnt(stdio) == (cnt));
@@ -3271,8 +3402,10 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 IV
 PerlIOStdio_fill(pTHX_ PerlIO *f)
 {
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     int c;
+    PERL_UNUSED_CONTEXT;
+
     /*
      * fflush()ing read-only streams can cause trouble on some stdio-s
      */
@@ -3396,7 +3529,7 @@ PerlIO_exportFILE(PerlIO * f, const char *mode)
            PerlIO *f2;
            /* De-link any lower layers so new :stdio sticks */
            *f = NULL;
-           if ((f2 = PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_stdio), buf, Nullsv))) {
+           if ((f2 = PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_stdio), buf, NULL))) {
                PerlIOStdio *s = PerlIOSelf((f = f2), PerlIOStdio);
                s->stdio = stdio;
                /* Link previous lower layers under new one */
@@ -3424,7 +3557,7 @@ PerlIO_findFILE(PerlIO *f)
        l = *PerlIONext(&l);
     }
     /* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */
-    return PerlIO_exportFILE(f, Nullch);
+    return PerlIO_exportFILE(f, NULL);
 }
 
 /* Use this to reverse PerlIO_exportFILE calls. */
@@ -3518,7 +3651,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 #ifdef PERLIO_USING_CRLF
 #  ifdef PERLIO_IS_BINMODE_FD
                if (PERLIO_IS_BINMODE_FD(fd))
-                   PerlIO_binmode(aTHX_ f,  '<'/*not used*/, O_BINARY, Nullch);
+                   PerlIO_binmode(aTHX_ f,  '<'/*not used*/, O_BINARY, NULL);
                else
 #  endif
                /*
@@ -3534,12 +3667,16 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
 
 /*
  * This "flush" is akin to sfio's sync in that it handles files in either
- * read or write state
+ * read or write state.  For write state, we put the postponed data through
+ * the next layers.  For read state, we seek() the next layers to the
+ * offset given by current position in the buffer, and discard the buffer
+ * state (XXXX supposed to be for seek()able buffers only, but now it is done
+ * in any case?).  Then the pass the stick further in chain.
  */
 IV
 PerlIOBuf_flush(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     int code = 0;
     PerlIO *n = PerlIONext(f);
     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
@@ -3593,17 +3730,21 @@ PerlIOBuf_flush(pTHX_ PerlIO *f)
     return code;
 }
 
+/* This discards the content of the buffer after b->ptr, and rereads
+ * the buffer from the position off in the layer downstream; here off
+ * is at offset corresponding to b->ptr - b->buf.
+ */
 IV
 PerlIOBuf_fill(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     PerlIO *n = PerlIONext(f);
     SSize_t avail;
     /*
      * Down-stream flush is defined not to loose read data so is harmless.
      * we would not normally be fill'ing if there was data left in anycase.
      */
-    if (PerlIO_flush(f) != 0)
+    if (PerlIO_flush(f) != 0)  /* XXXX Check that its seek() succeeded?! */
        return -1;
     if (PerlIOBase(f)->flags & PERLIO_F_TTY)
        PerlIOBase_flush_linebuf(aTHX);
@@ -3611,6 +3752,8 @@ PerlIOBuf_fill(pTHX_ PerlIO *f)
     if (!b->buf)
        PerlIO_get_base(f);     /* allocate via vtable */
 
+    assert(b->buf); /* The b->buf does get allocated via the vtable system. */
+
     b->ptr = b->end = b->buf;
 
     if (!PerlIOValid(n)) {
@@ -3637,7 +3780,7 @@ PerlIOBuf_fill(pTHX_ PerlIO *f)
        }
        if (avail > 0) {
            STDCHAR *ptr = PerlIO_get_ptr(n);
-           SSize_t cnt = avail;
+           const SSize_t cnt = avail;
            if (avail > (SSize_t)b->bufsiz)
                avail = b->bufsiz;
            Copy(ptr, b->buf, avail, STDCHAR);
@@ -3663,7 +3806,7 @@ SSize_t
 PerlIOBuf_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
     if (PerlIOValid(f)) {
-        const PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+        const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
        if (!b->ptr)
            PerlIO_get_base(f);
        return PerlIOBase_read(aTHX_ f, vbuf, count);
@@ -3675,7 +3818,7 @@ SSize_t
 PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
     const STDCHAR *buf = (const STDCHAR *) vbuf + count;
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     SSize_t unread = 0;
     SSize_t avail;
     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
@@ -3794,7 +3937,7 @@ PerlIOBuf_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
 Off_t
 PerlIOBuf_tell(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     /*
      * b->posn is file position where b->buf was read, or will be written
      */
@@ -3829,8 +3972,7 @@ PerlIOBuf_popped(pTHX_ PerlIO *f)
     if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
        Safefree(b->buf);
     }
-    b->buf = NULL;
-    b->ptr = b->end = b->buf;
+    b->ptr = b->end = b->buf = NULL;
     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
     return code;
 }
@@ -3843,8 +3985,7 @@ PerlIOBuf_close(pTHX_ PerlIO *f)
     if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
        Safefree(b->buf);
     }
-    b->buf = NULL;
-    b->ptr = b->end = b->buf;
+    b->ptr = b->end = b->buf = NULL;
     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
     return code;
 }
@@ -3852,7 +3993,7 @@ PerlIOBuf_close(pTHX_ PerlIO *f)
 STDCHAR *
 PerlIOBuf_get_ptr(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (!b->buf)
        PerlIO_get_base(f);
     return b->ptr;
@@ -3861,7 +4002,7 @@ PerlIOBuf_get_ptr(pTHX_ PerlIO *f)
 SSize_t
 PerlIOBuf_get_cnt(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (!b->buf)
        PerlIO_get_base(f);
     if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
@@ -3872,17 +4013,18 @@ PerlIOBuf_get_cnt(pTHX_ PerlIO *f)
 STDCHAR *
 PerlIOBuf_get_base(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
+    PERL_UNUSED_CONTEXT;
+
     if (!b->buf) {
        if (!b->bufsiz)
            b->bufsiz = 4096;
-       b->buf = Newz('B',b->buf,b->bufsiz, STDCHAR);
+       b->buf = Newxz(b->buf,b->bufsiz, STDCHAR);
        if (!b->buf) {
            b->buf = (STDCHAR *) & b->oneword;
            b->bufsiz = sizeof(b->oneword);
        }
-       b->ptr = b->buf;
-       b->end = b->ptr;
+       b->end = b->ptr = b->buf;
     }
     return b->buf;
 }
@@ -3890,7 +4032,7 @@ PerlIOBuf_get_base(pTHX_ PerlIO *f)
 Size_t
 PerlIOBuf_bufsiz(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (!b->buf)
        PerlIO_get_base(f);
     return (b->end - b->buf);
@@ -3899,7 +4041,7 @@ PerlIOBuf_bufsiz(pTHX_ PerlIO *f)
 void
 PerlIOBuf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (!b->buf)
        PerlIO_get_base(f);
     b->ptr = ptr;
@@ -3988,7 +4130,7 @@ PerlIOPending_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
 IV
 PerlIOPending_flush(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
        Safefree(b->buf);
        b->buf = NULL;
@@ -4012,7 +4154,7 @@ IV
 PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
     const IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
-    PerlIOl *l = PerlIOBase(f);
+    PerlIOl * const l = PerlIOBase(f);
     /*
      * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets()
      * etc. get muddled when it changes mid-string when we auto-pop.
@@ -4079,6 +4221,14 @@ PERLIO_FUNCS_DECL(PerlIO_pending) = {
  * crlf - translation On read translate CR,LF to "\n" we do this by
  * overriding ptr/cnt entries to hand back a line at a time and keeping a
  * record of which nl we "lied" about. On write translate "\n" to CR,LF
+ *
+ * c->nl points on the first byte of CR LF pair when it is temporarily
+ * replaced by LF, or to the last CR of the buffer.  In the former case
+ * the caller thinks that the buffer ends at c->nl + 1, in the latter
+ * that it ends at c->nl; these two cases can be distinguished by
+ * *c->nl.  c->nl is set during _getcnt() call, and unset during
+ * _unread() and _flush() calls.
+ * It only matters for read operations.
  */
 
 typedef struct {
@@ -4087,6 +4237,21 @@ typedef struct {
                                 * buffer */
 } PerlIOCrlf;
 
+/* Inherit the PERLIO_F_UTF8 flag from previous layer.
+ * Otherwise the :crlf layer would always revert back to
+ * raw mode.
+ */
+static void
+S_inherit_utf8_flag(PerlIO *f)
+{
+    PerlIO *g = PerlIONext(f);
+    if (PerlIOValid(g)) {
+       if (PerlIOBase(g)->flags & PERLIO_F_UTF8) {
+           PerlIOBase(f)->flags |= PERLIO_F_UTF8;
+       }
+    }
+}
+
 IV
 PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 {
@@ -4104,17 +4269,19 @@ PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
        * any given moment at most one CRLF-capable layer being enabled
        * in the whole layer stack. */
         PerlIO *g = PerlIONext(f);
-        while (g && *g) {
+        while (PerlIOValid(g)) {
              PerlIOl *b = PerlIOBase(g);
              if (b && b->tab == &PerlIO_crlf) {
                   if (!(b->flags & PERLIO_F_CRLF))
                        b->flags |= PERLIO_F_CRLF;
+                  S_inherit_utf8_flag(g);
                   PerlIO_pop(aTHX_ f);
                   return code;
              }           
              g = PerlIONext(g);
         }
     }
+    S_inherit_utf8_flag(f);
     return code;
 }
 
@@ -4122,8 +4289,8 @@ PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
 SSize_t
 PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
-    PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
-    if (c->nl) {
+    PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
+    if (c->nl) {       /* XXXX Shouldn't it be done only if b->ptr > c->nl? */
        *(c->nl) = 0xd;
        c->nl = NULL;
     }
@@ -4144,7 +4311,7 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
                b->posn -= b->bufsiz;
            }
            while (count > 0 && b->ptr > b->buf) {
-               int ch = *--buf;
+               const int ch = *--buf;
                if (ch == '\n') {
                    if (b->ptr - 2 >= b->buf) {
                        *--(b->ptr) = 0xa;
@@ -4153,8 +4320,10 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
                        count--;
                    }
                    else {
-                       buf++;
-                       break;
+                   /* If b->ptr - 1 == b->buf, we are undoing reading 0xa */
+                       *--(b->ptr) = 0xa;      /* Works even if 0xa == '\r' */
+                       unread++;
+                       count--;
                    }
                }
                else {
@@ -4168,14 +4337,15 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
     }
 }
 
+/* XXXX This code assumes that buffer size >=2, but does not check it... */
 SSize_t
 PerlIOCrlf_get_cnt(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     if (!b->buf)
        PerlIO_get_base(f);
     if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
-       PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
+       PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
        if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) {
            STDCHAR *nl = (c->nl) ? c->nl : b->ptr;
          scan:
@@ -4243,8 +4413,8 @@ PerlIOCrlf_get_cnt(pTHX_ PerlIO *f)
 void
 PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
-    PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
     if (!b->buf)
        PerlIO_get_base(f);
     if (!ptr) {
@@ -4261,6 +4431,7 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
        ptr -= cnt;
     }
     else {
+       NOOP;
 #if 0
        /*
         * Test code - delete when it works ...
@@ -4300,15 +4471,15 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
     if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
        return PerlIOBuf_write(aTHX_ f, vbuf, count);
     else {
-       PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+       PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
        const STDCHAR *buf = (const STDCHAR *) vbuf;
-       const STDCHAR *ebuf = buf + count;
+       const STDCHAR * const ebuf = buf + count;
        if (!b->buf)
            PerlIO_get_base(f);
        if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
            return 0;
        while (buf < ebuf) {
-           STDCHAR *eptr = b->buf + b->bufsiz;
+           const STDCHAR * const eptr = b->buf + b->bufsiz;
            PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
            while (buf < ebuf && b->ptr < eptr) {
                if (*buf == '\n') {
@@ -4330,8 +4501,7 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
                    }
                }
                else {
-                   int ch = *buf++;
-                   *(b->ptr)++ = ch;
+                   *(b->ptr)++ = *buf++;
                }
                if (b->ptr >= eptr) {
                    PerlIO_flush(f);
@@ -4348,7 +4518,7 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 IV
 PerlIOCrlf_flush(pTHX_ PerlIO *f)
 {
-    PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
+    PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
     if (c->nl) {
        *(c->nl) = 0xd;
        c->nl = NULL;
@@ -4426,7 +4596,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f)
     if (m->len)
        abort();
     if (flags & PERLIO_F_CANREAD) {
-       PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+       PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
        const int fd = PerlIO_fileno(f);
        Stat_t st;
        code = Fstat(fd, &st);
@@ -4446,7 +4616,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f)
                }
                posn = (b->posn / PL_mmap_page_size) * PL_mmap_page_size;
                len = st.st_size - posn;
-               m->mptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
+               m->mptr = (Mmap_t)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
                if (m->mptr && m->mptr != (Mmap_t) - 1) {
 #if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
                    madvise(m->mptr, len, MADV_SEQUENTIAL);
@@ -4480,12 +4650,19 @@ PerlIOMmap_map(pTHX_ PerlIO *f)
 IV
 PerlIOMmap_unmap(pTHX_ PerlIO *f)
 {
-    PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
-    PerlIOBuf *b = &m->base;
+    PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
     IV code = 0;
     if (m->len) {
+       PerlIOBuf * const b = &m->base;
        if (b->buf) {
-           code = munmap(m->mptr, m->len);
+           /* The munmap address argument is tricky: depending on the
+            * standard it is either "void *" or "caddr_t" (which is
+            * usually "char *" (signed or unsigned).  If we cast it
+            * to "void *", those that have it caddr_t and an uptight
+            * C++ compiler, will freak out.  But casting it as char*
+            * should work.  Maybe.  (Using Mmap_t figured out by
+            * Configure doesn't always work, apparently.) */
+           code = munmap((char*)m->mptr, m->len);
            b->buf = NULL;
            m->len = 0;
            m->mptr = NULL;
@@ -4501,8 +4678,8 @@ PerlIOMmap_unmap(pTHX_ PerlIO *f)
 STDCHAR *
 PerlIOMmap_get_base(pTHX_ PerlIO *f)
 {
-    PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
-    PerlIOBuf *b = &m->base;
+    PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
+    PerlIOBuf * const b = &m->base;
     if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
        /*
         * Already have a readbuffer in progress
@@ -4534,8 +4711,8 @@ PerlIOMmap_get_base(pTHX_ PerlIO *f)
 SSize_t
 PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
-    PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
-    PerlIOBuf *b = &m->base;
+    PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
+    PerlIOBuf * const b = &m->base;
     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
        PerlIO_flush(f);
     if (b->ptr && (b->ptr - count) >= b->buf
@@ -4592,8 +4769,8 @@ PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 IV
 PerlIOMmap_flush(pTHX_ PerlIO *f)
 {
-    PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
-    PerlIOBuf *b = &m->base;
+    PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
+    PerlIOBuf * const b = &m->base;
     IV code = PerlIOBuf_flush(aTHX_ f);
     /*
      * Now we are "synced" at PerlIOBuf level
@@ -4620,7 +4797,7 @@ PerlIOMmap_flush(pTHX_ PerlIO *f)
 IV
 PerlIOMmap_fill(pTHX_ PerlIO *f)
 {
-    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
     IV code = PerlIO_flush(f);
     if (code == 0 && !b->buf) {
        code = PerlIOMmap_map(aTHX_ f);
@@ -4634,8 +4811,8 @@ PerlIOMmap_fill(pTHX_ PerlIO *f)
 IV
 PerlIOMmap_close(pTHX_ PerlIO *f)
 {
-    PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
-    PerlIOBuf *b = &m->base;
+    PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
+    PerlIOBuf * const b = &m->base;
     IV code = PerlIO_flush(f);
     if (m->bbuf) {
        b->buf = m->bbuf;
@@ -4690,6 +4867,7 @@ PERLIO_FUNCS_DECL(PerlIO_mmap) = {
 PerlIO *
 Perl_PerlIO_stdin(pTHX)
 {
+    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -4699,6 +4877,7 @@ Perl_PerlIO_stdin(pTHX)
 PerlIO *
 Perl_PerlIO_stdout(pTHX)
 {
+    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -4708,6 +4887,7 @@ Perl_PerlIO_stdout(pTHX)
 PerlIO *
 Perl_PerlIO_stderr(pTHX)
 {
+    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -4734,10 +4914,10 @@ PerlIO_getname(PerlIO *f, char *buf)
     }
     return name;
 #else
-    (void)f;
-    (void)buf;
+    PERL_UNUSED_ARG(f);
+    PERL_UNUSED_ARG(buf);
     Perl_croak(aTHX_ "Don't know how to get file name");
-    return Nullch;
+    return NULL;
 #endif
 }
 
@@ -4753,7 +4933,7 @@ PerlIO *
 PerlIO_fdopen(int fd, const char *mode)
 {
     dTHX;
-    return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL);
+    return PerlIO_openn(aTHX_ NULL, mode, fd, 0, 0, NULL, 0, NULL);
 }
 
 #undef PerlIO_open
@@ -4761,8 +4941,8 @@ PerlIO *
 PerlIO_open(const char *path, const char *mode)
 {
     dTHX;
-    SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
-    return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name);
+    SV *name = sv_2mortal(newSVpv(path, 0));
+    return PerlIO_openn(aTHX_ NULL, mode, -1, 0, 0, NULL, 1, &name);
 }
 
 #undef Perlio_reopen
@@ -4770,8 +4950,8 @@ PerlIO *
 PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
 {
     dTHX;
-    SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
-    return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name);
+    SV *name = sv_2mortal(newSVpv(path,0));
+    return PerlIO_openn(aTHX_ NULL, mode, -1, 0, 0, f, 1, &name);
 }
 
 #undef PerlIO_getc
@@ -4813,8 +4993,7 @@ int
 PerlIO_puts(PerlIO *f, const char *s)
 {
     dTHX;
-    STRLEN len = strlen(s);
-    return PerlIO_write(f, s, len);
+    return PerlIO_write(f, s, strlen(s));
 }
 
 #undef PerlIO_rewind
@@ -4831,8 +5010,8 @@ int
 PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
 {
     dTHX;
-    SV *sv = newSVpvn("", 0);
-    char *s;
+    SV * const sv = newSVpvs("");
+    const char *s;
     STRLEN len;
     SSize_t wrote;
 #ifdef NEED_VA_COPY
@@ -4842,7 +5021,7 @@ PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
 #else
     sv_vcatpvf(sv, fmt, &ap);
 #endif
-    s = SvPV(sv, len);
+    s = SvPV_const(sv, len);
     wrote = PerlIO_write(f, s, len);
     SvREFCNT_dec(sv);
     return wrote;
@@ -4885,7 +5064,7 @@ PerlIO_tmpfile(void)
          f = PerlIO_fdopen(fd, "w+b");
 #else /* WIN32 */
 #    if defined(HAS_MKSTEMP) && ! defined(VMS) && ! defined(OS2)
-     SV *sv = newSVpv("/tmp/PerlIO_XXXXXX", 0);
+     SV * const sv = newSVpvs("/tmp/PerlIO_XXXXXX");
      /*
       * I have no idea how portable mkstemp() is ... NI-S
       */
@@ -4898,18 +5077,11 @@ PerlIO_tmpfile(void)
          SvREFCNT_dec(sv);
      }
 #    else      /* !HAS_MKSTEMP, fallback to stdio tmpfile(). */
-     FILE *stdio = PerlSIO_tmpfile();
+     FILE * const stdio = PerlSIO_tmpfile();
 
-     if (stdio) {
-         if ((f = PerlIO_push(aTHX_(PerlIO_allocate(aTHX)),
-                               PERLIO_FUNCS_CAST(&PerlIO_stdio),
-                              "w+", Nullsv))) {
-               PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
+     if (stdio)
+         f = PerlIO_fdopen(fileno(stdio), "w+");
 
-               if (s)
-                    s->stdio = stdio;
-          }
-     }
 #    endif /* else HAS_MKSTEMP */
 #endif /* else WIN32 */
      return f;
@@ -4926,6 +5098,36 @@ PerlIO_tmpfile(void)
  * Now some functions in terms of above which may be needed even if we are
  * not in true PerlIO mode
  */
+const char *
+Perl_PerlIO_context_layers(pTHX_ const char *mode)
+{
+    dVAR;
+    const char *type = NULL;
+    /*
+     * Need to supply default layer info from open.pm
+     */
+    if (PL_curcop && PL_curcop->cop_hints & HINT_LEXICAL_IO) {
+       SV * const layers
+           = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, 0,
+                                      "open", 4, 0, 0);
+       assert(layers);
+       if (SvOK(layers)) {
+           STRLEN len;
+           type = SvPV_const(layers, len);
+           if (type && mode && mode[0] != 'r') {
+               /*
+                * Skip to write part, which is separated by a '\0'
+                */
+               STRLEN read_len = strlen(type);
+               if (read_len < len) {
+                   type += read_len + 1;
+               }
+           }
+       }
+    }
+    return type;
+}
+
 
 #ifndef HAS_FSETPOS
 #undef PerlIO_setpos
@@ -4935,7 +5137,7 @@ PerlIO_setpos(PerlIO *f, SV *pos)
     dTHX;
     if (SvOK(pos)) {
        STRLEN len;
-       Off_t *posn = (Off_t *) SvPV(pos, len);
+       const Off_t * const posn = (Off_t *) SvPV(pos, len);
        if (f && len == sizeof(Off_t))
            return PerlIO_seek(f, *posn, SEEK_SET);
     }
@@ -4950,7 +5152,7 @@ PerlIO_setpos(PerlIO *f, SV *pos)
     dTHX;
     if (SvOK(pos)) {
        STRLEN len;
-       Fpos_t *fpos = (Fpos_t *) SvPV(pos, len);
+       Fpos_t * const fpos = (Fpos_t *) SvPV(pos, len);
        if (f && len == sizeof(Fpos_t)) {
 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
            return fsetpos64(f, fpos);
@@ -5016,16 +5218,15 @@ vfprintf(FILE *fd, char *pat, char *args)
 int
 PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
 {
-    dVAR;
-    const int val = vsprintf(s, fmt, ap);
-    if (n >= 0) {
-       if (strlen(s) >= (STRLEN) n) {
-           dTHX;
-           (void) PerlIO_puts(Perl_error_log,
-                              "panic: sprintf overflow - memory corrupted!\n");
-           my_exit(1);
-       }
+    dTHX; 
+    const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap);
+    PERL_UNUSED_CONTEXT;
+
+#ifndef PERL_MY_VSNPRINTF_GUARDED
+    if (val < 0 || (n > 0 ? val >= n : 0)) {
+       Perl_croak(aTHX_ "panic: my_vsnprintf overflow in PerlIO_vsprintf\n");
     }
+#endif
     return val;
 }
 #endif