This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perlunicode: Update nonchars discussion for Unicode 7.0
[perl5.git] / perlio.c
index 29c4bf7..92fa2be 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -199,10 +199,12 @@ PerlIO_intmode2str(int rawmode, char *mode, int *writing)
            mode[ix++] = '+';
        }
     }
-#ifdef PERLIO_BINARY_AND_TEXT_DIFFERENT_AND_EFFECTIVE
+#if O_BINARY != 0
+    /* Unless O_BINARY is different from zero, bit-and:ing
+     * with it won't do much good. */
     if (rawmode & O_BINARY)
        mode[ix++] = 'b';
-#endif
+# endif
     mode[ix] = '\0';
     return ptype;
 }
@@ -389,14 +391,13 @@ PerlIO_debug(const char *fmt, ...)
        }
     }
     if (PL_perlio_debug_fd > 0) {
-        int rc = 0;
 #ifdef USE_ITHREADS
        const char * const s = CopFILE(PL_curcop);
        /* Use fixed buffer as sv_catpvf etc. needs SVs */
        char buffer[1024];
        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);
-       rc = PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2);
+       PERL_UNUSED_RESULT(PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2));
 #else
        const char *s = CopFILE(PL_curcop);
        STRLEN len;
@@ -405,11 +406,9 @@ PerlIO_debug(const char *fmt, ...)
        Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
 
        s = SvPV_const(sv, len);
-       rc = PerlLIO_write(PL_perlio_debug_fd, s, len);
+       PERL_UNUSED_RESULT(PerlLIO_write(PL_perlio_debug_fd, s, len));
        SvREFCNT_dec(sv);
 #endif
-        /* silently ignore failures */
-        PERL_UNUSED_VAR(rc);
     }
     va_end(ap);
 }
@@ -429,6 +428,9 @@ PerlIO_verify_head(pTHX_ PerlIO *f)
 {
     PerlIOl *head, *p;
     int seen = 0;
+#ifndef PERL_IMPLICIT_SYS
+    PERL_UNUSED_CONTEXT;
+#endif
     if (!PerlIOValid(f))
        return;
     p = head = PerlIOBase(f)->head;
@@ -464,7 +466,6 @@ PerlIO_init_table(pTHX)
 PerlIO *
 PerlIO_allocate(pTHX)
 {
-    dVAR;
     /*
      * Find a free slot in the table, allocating new table as necessary
      */
@@ -476,10 +477,7 @@ PerlIO_allocate(pTHX)
        last = (PerlIOl **) (f);
        for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
            if (!((++f)->next)) {
-               f->flags = 0; /* lockcnt */
-               f->tab = NULL;
-               f->head = f;
-               return (PerlIO *)f;
+               goto good_exit;
            }
        }
     }
@@ -488,6 +486,8 @@ PerlIO_allocate(pTHX)
        return NULL;
     }
     *last = (PerlIOl*) f++;
+
+    good_exit:
     f->flags = 0; /* lockcnt */
     f->tab = NULL;
     f->head = f;
@@ -561,7 +561,6 @@ 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;
 
@@ -631,7 +630,6 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
 void
 PerlIO_destruct(pTHX)
 {
-    dVAR;
     PerlIOl **table = &PL_perlio;
     PerlIOl *f;
 #ifdef USE_ITHREADS
@@ -697,7 +695,6 @@ PerlIO_pop(pTHX_ PerlIO *f)
 AV *
 PerlIO_get_layers(pTHX_ PerlIO *f)
 {
-    dVAR;
     AV * const av = newAV();
 
     if (PerlIOValid(f)) {
@@ -731,7 +728,7 @@ PerlIO_get_layers(pTHX_ PerlIO *f)
 PerlIO_funcs *
 PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
 {
-    dVAR;
+
     IV i;
     if ((SSize_t) len <= 0)
        len = strlen(name);
@@ -852,7 +849,7 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
     XSRETURN(count);
 }
 
-#endif                          /* USE_ATTIBUTES_FOR_PERLIO */
+#endif                          /* USE_ATTRIBUTES_FOR_PERLIO */
 
 SV *
 PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
@@ -868,7 +865,6 @@ XS(XS_PerlIO__Layer__NoWarnings)
     /* This is used as a %SIG{__WARN__} handler to suppress warnings
        during loading of layers.
      */
-    dVAR;
     dXSARGS;
     PERL_UNUSED_ARG(cv);
     if (items)
@@ -879,7 +875,6 @@ XS(XS_PerlIO__Layer__NoWarnings)
 XS(XS_PerlIO__Layer__find); /* prototype to pass -Wmissing-prototypes */
 XS(XS_PerlIO__Layer__find)
 {
-    dVAR;
     dXSARGS;
     PERL_UNUSED_ARG(cv);
     if (items < 2)
@@ -887,7 +882,7 @@ XS(XS_PerlIO__Layer__find)
     else {
        STRLEN len;
        const char * const name = SvPV_const(ST(1), len);
-       const bool load = (items > 2) ? SvTRUE(ST(2)) : 0;
+       const bool load = (items > 2) ? SvTRUE_NN(ST(2)) : 0;
        PerlIO_funcs * const layer = PerlIO_find_layer(aTHX_ name, len, load);
        ST(0) =
            (layer) ? sv_2mortal(PerlIO_tab_sv(aTHX_ layer)) :
@@ -899,7 +894,6 @@ 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, NULL);
@@ -909,7 +903,6 @@ PerlIO_define_layer(pTHX_ PerlIO_funcs *tab)
 int
 PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
 {
-    dVAR;
     if (names) {
        const char *s = names;
        while (*s) {
@@ -1002,7 +995,6 @@ 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;
@@ -1011,8 +1003,7 @@ PerlIO_default_buffer(pTHX_ PerlIO_list_t *av)
        tab = &PerlIO_stdio;
 #endif
     PerlIO_debug("Pushing %s\n", tab->name);
-    PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0),
-                    &PL_sv_undef);
+    PerlIO_list_push(aTHX_ av, (PerlIO_funcs *)tab, &PL_sv_undef);
 }
 
 SV *
@@ -1082,7 +1073,6 @@ PERLIO_FUNCS_DECL(PerlIO_remove) = {
 PerlIO_list_t *
 PerlIO_default_layers(pTHX)
 {
-    dVAR;
     if (!PL_def_layerlist) {
        const char * const s = TAINTING_get ? NULL : PerlEnv_getenv("PERLIO");
        PERLIO_FUNCS_DECL(*osLayer) = &PerlIO_unix;
@@ -1101,9 +1091,8 @@ PerlIO_default_layers(pTHX)
        PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_utf8));
        PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_remove));
        PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_byte));
-       PerlIO_list_push(aTHX_ PL_def_layerlist,
-                        PerlIO_find_layer(aTHX_ osLayer->name, 0, 0),
-                        &PL_sv_undef);
+       PerlIO_list_push(aTHX_ PL_def_layerlist, (PerlIO_funcs *)osLayer,
+                         &PL_sv_undef);
        if (s) {
            PerlIO_parse_layers(aTHX_ PL_def_layerlist, s);
        }
@@ -1131,7 +1120,6 @@ Perl_boot_core_PerlIO(pTHX)
 PerlIO_funcs *
 PerlIO_default_layer(pTHX_ I32 n)
 {
-    dVAR;
     PerlIO_list_t * const av = PerlIO_default_layers(aTHX);
     if (n < 0)
        n += av->cur;
@@ -1144,7 +1132,6 @@ PerlIO_default_layer(pTHX_ I32 n)
 void
 PerlIO_stdstreams(pTHX)
 {
-    dVAR;
     if (!PL_perlio) {
        PerlIO_init_table(aTHX);
        PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT);
@@ -1418,15 +1405,13 @@ Perl_PerlIO_close(pTHX_ PerlIO *f)
 int
 Perl_PerlIO_fileno(pTHX_ PerlIO *f)
 {
-    dVAR;
-     Perl_PerlIO_or_Base(f, Fileno, fileno, -1, (aTHX_ f));
+    Perl_PerlIO_or_Base(f, Fileno, fileno, -1, (aTHX_ f));
 }
 
 
 static PerlIO_funcs *
 PerlIO_layer_from_ref(pTHX_ SV *sv)
 {
-    dVAR;
     /*
      * For any scalar type load the handler which is bundled with perl
      */
@@ -1461,7 +1446,6 @@ 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)
@@ -1472,7 +1456,7 @@ PerlIO_resolve_layers(pTHX_ const char *layers,
         * If it is a reference but not an object see if we have a handler
         * for it
         */
-       if (SvROK(arg) && !sv_isobject(arg)) {
+       if (SvROK(arg) && !SvOBJECT(SvRV(arg))) {
            PerlIO_funcs * const handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
            if (handler) {
                def = PerlIO_list_alloc(aTHX);
@@ -1515,7 +1499,6 @@ 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)
@@ -1639,7 +1622,6 @@ 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;
@@ -1682,7 +1664,6 @@ Perl_PerlIO_flush(pTHX_ PerlIO *f)
 void
 PerlIOBase_flush_linebuf(pTHX)
 {
-    dVAR;
     PerlIOl **table = &PL_perlio;
     PerlIOl *f;
     while ((f = *table)) {
@@ -2078,6 +2059,7 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
         if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) {
            PerlIOBase(f)->flags |= PERLIO_F_ERROR;
            SETERRNO(EBADF, SS_IVCHAN);
+           PerlIO_save_errno(f);
            return 0;
        }
        while (count > 0) {
@@ -2251,6 +2233,10 @@ S_more_refcounted_fds(pTHX_ const int new_fd) {
     const int new_max = 16 + (new_fd & ~15);
     int *new_array;
 
+#ifndef PERL_IMPLICIT_SYS
+    PERL_UNUSED_CONTEXT;
+#endif
+
     PerlIO_debug("More fds - old=%d, need %d, new=%d\n",
                 old_max, new_fd, new_max);
 
@@ -2385,7 +2371,6 @@ PerlIOUnix_refcnt(int fd)
 void
 PerlIO_cleanup(pTHX)
 {
-    dVAR;
     int i;
 #ifdef USE_ITHREADS
     PerlIO_debug("Cleanup layers for %p\n",(void*)aTHX);
@@ -2465,6 +2450,9 @@ typedef struct {
 static void
 S_lockcnt_dec(pTHX_ const void* f)
 {
+#ifndef PERL_IMPLICIT_SYS
+    PERL_UNUSED_CONTEXT;
+#endif
     PerlIO_lockcnt((PerlIO*)f)--;
 }
 
@@ -2532,25 +2520,42 @@ PerlIOUnix_oflags(const char *mode)
            oflags |= O_WRONLY;
        break;
     }
-#ifdef PERLIO_BINARY_AND_TEXT_DIFFERENT_AND_EFFECTIVE
-    if (*mode == 'b') {
-       oflags |= O_BINARY;
+
+    /* XXX TODO: PerlIO_open() test that exercises 'rb' and 'rt'. */
+
+    /* Unless O_BINARY is different from O_TEXT, first bit-or:ing one
+     * of them in, and then bit-and-masking the other them away, won't
+     * have much of an effect. */
+    switch (*mode) {
+    case 'b':
+#if O_TEXT != O_BINARY
+        oflags |= O_BINARY;
        oflags &= ~O_TEXT;
-       mode++;
-    }
-    else if (*mode == 't') {
+#endif
+        mode++;
+        break;
+    case 't':
+#if O_TEXT != O_BINARY
        oflags |= O_TEXT;
        oflags &= ~O_BINARY;
-       mode++;
-    }
-    else {
+#endif
+        mode++;
+        break;
+    default:
+#  if O_BINARY != 0
+        /* bit-or:ing with zero O_BINARY would be useless. */
        /*
         * If neither "t" nor "b" was specified, open the file
         * in O_BINARY mode.
+         *
+         * Note that if something else than the zero byte was seen
+         * here (e.g. bogus mode "rx"), just few lines later we will
+         * set the errno and invalidate the flags.
         */
        oflags |= O_BINARY;
+#  endif
+        break;
     }
-#endif
     if (*mode || oflags == -1) {
        SETERRNO(EINVAL, LIB_INVARG);
        oflags = -1;
@@ -2709,7 +2714,6 @@ 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;
     int fd;
     if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */
        return -1;
@@ -2728,6 +2732,7 @@ PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
            if (len < 0) {
                if (errno != EAGAIN) {
                    PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+                   PerlIO_save_errno(f);
                }
            }
            else if (len == 0 && count != 0) {
@@ -2740,13 +2745,12 @@ PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
        if (PL_sig_pending && S_perlio_async_run(aTHX_ f))
            return -1;
     }
-    /*NOTREACHED*/
+    NOT_REACHED; /*NOTREACHED*/
 }
 
 SSize_t
 PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
-    dVAR;
     int fd;
     if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */
        return -1;
@@ -2761,6 +2765,7 @@ PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
            if (len < 0) {
                if (errno != EAGAIN) {
                    PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+                   PerlIO_save_errno(f);
                }
            }
            return len;
@@ -2769,7 +2774,7 @@ PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
        if (PL_sig_pending && S_perlio_async_run(aTHX_ f))
            return -1;
     }
-    /*NOTREACHED*/
+    NOT_REACHED; /*NOTREACHED*/
 }
 
 Off_t
@@ -2784,7 +2789,6 @@ 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) {
@@ -2926,11 +2930,27 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
 {
     dTHX;
     PerlIO *f = NULL;
+#ifdef EBCDIC
+        int rc;
+        char filename[FILENAME_MAX];
+        fldata_t fileinfo;
+#endif
     if (stdio) {
        PerlIOStdio *s;
         int fd0 = fileno(stdio);
         if (fd0 < 0) {
+#ifdef EBCDIC
+                         rc = fldata(stdio,filename,&fileinfo);
+                         if(rc != 0){
+                                 return NULL;
+                         }
+                         if(fileinfo.__dsorgHFS){
+            return NULL;
+        }
+                         /*This MVS dataset , OK!*/
+#else
             return NULL;
+#endif
         }
        if (!mode || !*mode) {
            /* We need to probe to see how we can open the stream
@@ -2962,7 +2982,24 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
        if ((f = PerlIO_push(aTHX_(PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, NULL))) {
            s = PerlIOSelf(f, PerlIOStdio);
            s->stdio = stdio;
+#ifdef EBCDIC
+               fd0 = fileno(stdio);
+               if(fd0 != -1){
+                       PerlIOUnix_refcnt_inc(fd0);
+               }
+               else{
+                       rc = fldata(stdio,filename,&fileinfo);
+                       if(rc != 0){
+                               PerlIOUnix_refcnt_inc(fd0);
+                       }
+                       if(fileinfo.__dsorgHFS){
+                               PerlIOUnix_refcnt_inc(fd0);
+                       }
+                         /*This MVS dataset , OK!*/
+               }
+#else
            PerlIOUnix_refcnt_inc(fileno(stdio));
+#endif
        }
     }
     return f;
@@ -3290,7 +3327,6 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
 SSize_t
 PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
-    dVAR;
     FILE * s;
     SSize_t got = 0;
     if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */
@@ -3383,7 +3419,6 @@ 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;
     if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */
        return -1;
@@ -3519,7 +3554,20 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
     FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
     if (ptr != NULL) {
 #ifdef STDIO_PTR_LVALUE
+        /* This is a long-standing infamous mess.  The root of the
+         * problem is that one cannot know the signedness of char, and
+         * more precisely the signedness of FILE._ptr.  The following
+         * things have been tried, and they have all failed (across
+         * different compilers (remember that core needs to to build
+         * also with c++) and compiler options:
+         *
+         * - casting the RHS to (void*) -- works in *some* places
+         * - casting the LHS to (void*) -- totally unportable
+         *
+         * So let's try silencing the warning at least for gcc. */
+        GCC_DIAG_IGNORE(-Wpointer-sign);
        PerlSIO_set_ptr(stdio, ptr); /* LHS STDCHAR* cast non-portable */
+        GCC_DIAG_RESTORE;
 #ifdef STDIO_PTR_LVAL_SETS_CNT
        assert(PerlSIO_get_cnt(stdio) == (cnt));
 #endif
@@ -3608,20 +3656,12 @@ PerlIOStdio_fill(pTHX_ PerlIO *f)
     }
 #endif
 
-#if defined(VMS)
-    /* An ungetc()d char is handled separately from the regular
-     * buffer, so we stuff it in the buffer ourselves.
-     * Should never get called as should hit code above
-     */
-    *(--((*stdio)->_ptr)) = (unsigned char) c;
-    (*stdio)->_cnt++;
-#else
     /* If buffer snoop scheme above fails fall back to
        using ungetc().
      */
     if (PerlSIO_ungetc(c, stdio) != c)
        return EOF;
-#endif
+
     return 0;
 }
 
@@ -3745,7 +3785,6 @@ PerlIO_findFILE(PerlIO *f)
 void
 PerlIO_releaseFILE(PerlIO *p, FILE *f)
 {
-    dVAR;
     PerlIOl *l;
     while ((l = *p)) {
        if (l->tab == &PerlIO_stdio) {
@@ -3893,6 +3932,7 @@ PerlIOBuf_flush(pTHX_ PerlIO *f)
            }
            else if (count < 0 || PerlIO_error(n)) {
                PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+               PerlIO_save_errno(f);
                code = -1;
                break;
            }
@@ -3995,7 +4035,10 @@ PerlIOBuf_fill(pTHX_ PerlIO *f)
        if (avail == 0)
            PerlIOBase(f)->flags |= PERLIO_F_EOF;
        else
+       {
            PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+           PerlIO_save_errno(f);
+       }
        return -1;
     }
     b->end = b->buf + avail;
@@ -4777,7 +4820,6 @@ PERLIO_FUNCS_DECL(PerlIO_crlf) = {
 PerlIO *
 Perl_PerlIO_stdin(pTHX)
 {
-    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -4787,7 +4829,6 @@ Perl_PerlIO_stdin(pTHX)
 PerlIO *
 Perl_PerlIO_stdout(pTHX)
 {
-    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -4797,7 +4838,6 @@ Perl_PerlIO_stdout(pTHX)
 PerlIO *
 Perl_PerlIO_stderr(pTHX)
 {
-    dVAR;
     if (!PL_perlio) {
        PerlIO_stdstreams(aTHX);
     }
@@ -5022,6 +5062,34 @@ PerlIO_tmpfile(void)
      return f;
 }
 
+void
+Perl_PerlIO_save_errno(pTHX_ PerlIO *f)
+{
+    if (!PerlIOValid(f))
+       return;
+    PerlIOBase(f)->err = errno;
+#ifdef VMS
+    PerlIOBase(f)->os_err = vaxc$errno;
+#elif defined(OS2)
+    PerlIOBase(f)->os_err = Perl_rc;
+#elif defined(WIN32)
+    PerlIOBase(f)->os_err = GetLastError();
+#endif
+}
+
+void
+Perl_PerlIO_restore_errno(pTHX_ PerlIO *f)
+{
+    if (!PerlIOValid(f))
+       return;
+    SETERRNO(PerlIOBase(f)->err, PerlIOBase(f)->os_err);
+#ifdef OS2
+    Perl_rc = PerlIOBase(f)->os_err);
+#elif defined(WIN32)
+    SetLastError(PerlIOBase(f)->os_err);
+#endif
+}
+
 #undef HAS_FSETPOS
 #undef HAS_FGETPOS
 
@@ -5035,7 +5103,6 @@ PerlIO_tmpfile(void)
 const char *
 Perl_PerlIO_context_layers(pTHX_ const char *mode)
 {
-    dVAR;
     const char *direction = NULL;
     SV *layers;
     /*
@@ -5068,11 +5135,13 @@ int
 PerlIO_setpos(PerlIO *f, SV *pos)
 {
     if (SvOK(pos)) {
-       STRLEN len;
-       dTHX;
-       const Off_t * const posn = (Off_t *) SvPV(pos, len);
-       if (f && len == sizeof(Off_t))
-           return PerlIO_seek(f, *posn, SEEK_SET);
+       if (f) {
+           dTHX;
+           STRLEN len;
+           const Off_t * const posn = (Off_t *) SvPV(pos, len);
+           if(len == sizeof(Off_t))
+               return PerlIO_seek(f, *posn, SEEK_SET);
+       }
     }
     SETERRNO(EINVAL, SS_IVCHAN);
     return -1;
@@ -5082,15 +5151,16 @@ PerlIO_setpos(PerlIO *f, SV *pos)
 int
 PerlIO_setpos(PerlIO *f, SV *pos)
 {
-    dTHX;
     if (SvOK(pos)) {
-       STRLEN len;
-       Fpos_t * const fpos = (Fpos_t *) SvPV(pos, len);
-       if (f && len == sizeof(Fpos_t)) {
+       if (f) {
+           dTHX;
+           STRLEN len;
+           Fpos_t * const fpos = (Fpos_t *) SvPV(pos, len);
+           if(len == sizeof(Fpos_t))
 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
-           return fsetpos64(f, fpos);
+               return fsetpos64(f, fpos);
 #else
-           return fsetpos(f, fpos);
+               return fsetpos(f, fpos);
 #endif
        }
     }
@@ -5147,12 +5217,22 @@ vfprintf(FILE *fd, char *pat, char *args)
 
 #endif
 
+/* print a failure format string message to stderr and fail exit the process
+   using only libc without depending on any perl data structures being
+   initialized.
+*/
+
+void
+Perl_noperl_die(const char* pat, ...)
+{
+    va_list(arglist);
+    PERL_ARGS_ASSERT_NOPERL_DIE;
+    va_start(arglist, pat);
+    vfprintf(stderr, pat, arglist);
+    va_end(arglist);
+    exit(1);
+}
+
 /*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
  * ex: set ts=8 sts=4 sw=4 et:
  */