This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perl_sv_chop() can return early if it's being asked to do nothing.
[perl5.git] / perlio.c
index 6e2d9e1..76fe225 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -134,6 +134,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode)
      */
 #ifdef DOSISH
 #  if defined(atarist) || defined(__MINT__)
+    PERL_UNUSED_ARG(iotype);
     if (!fflush(fp)) {
         if (mode & O_BINARY)
             ((FILE *) fp)->_flag |= _IOBIN;
@@ -144,6 +145,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode)
     return 0;
 #  else
     dTHX;
+    PERL_UNUSED_ARG(iotype);
 #ifdef NETWARE
     if (PerlLIO_setmode(fp, mode) != -1) {
 #else
@@ -174,6 +176,9 @@ document
 #else
 #  if defined(USEMYBINMODE)
     dTHX;
+#    if defined(__CYGWIN__)
+    PERL_UNUSED_ARG(iotype);
+#    endif
     if (my_binmode(fp, iotype, mode) != FALSE)
         return 1;
     else
@@ -502,9 +507,8 @@ PerlIO_debug(const char *fmt, ...)
 #else
        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));
+       SV * const sv = Perl_newSVpvf(aTHX_ "%s:%" IVdf " ", s ? s : "(none)",
+                                     (IV) CopLINE(PL_curcop));
        Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
 
        s = SvPV_const(sv, len);
@@ -902,7 +906,7 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
 SV *
 PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
 {
-    HV * const stash = gv_stashpvs("PerlIO::Layer", TRUE);
+    HV * const stash = gv_stashpvs("PerlIO::Layer", GV_ADD);
     SV * const sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
     return sv;
 }
@@ -914,6 +918,7 @@ XS(XS_PerlIO__Layer__NoWarnings)
      */
     dVAR;
     dXSARGS;
+    PERL_UNUSED_ARG(cv);
     if (items)
        PerlIO_debug("warning:%s\n",SvPV_nolen_const(ST(0)));
     XSRETURN(0);
@@ -923,6 +928,7 @@ XS(XS_PerlIO__Layer__find)
 {
     dVAR;
     dXSARGS;
+    PERL_UNUSED_ARG(cv);
     if (items < 2)
        Perl_croak(aTHX_ "Usage class->find(name[,load])");
     else {
@@ -2261,6 +2267,8 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
        if (self->Getarg)
            arg = (*self->Getarg)(aTHX_ o, param, flags);
        f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg);
+       if (PerlIOBase(o)->flags & PERLIO_F_UTF8)
+           PerlIOBase(f)->flags |= PERLIO_F_UTF8;
        if (arg)
            SvREFCNT_dec(arg);
     }
@@ -2405,22 +2413,36 @@ PerlIO_cleanup(pTHX)
     }
 }
 
-void PerlIO_teardown(pTHX) /* Call only from PERL_SYS_TERM(). */
+void PerlIO_teardown() /* Call only from PERL_SYS_TERM(). */
 {
     dVAR;
+#if 0
+/* XXX we can't rely on an interpreter being present at this late stage,
+   XXX so we can't use a function like PerlLIO_write that relies on one
+   being present (at least in win32) :-(.
+   Disable for now.
+*/
 #ifdef DEBUGGING
     {
        /* By now all filehandles should have been closed, so any
         * stray (non-STD-)filehandles indicate *possible* (PerlIO)
         * errors. */
+#define PERLIO_TEARDOWN_MESSAGE_BUF_SIZE 64
+#define PERLIO_TEARDOWN_MESSAGE_FD 2
+       char buf[PERLIO_TEARDOWN_MESSAGE_BUF_SIZE];
        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]);
+           if (PL_perlio_fd_refcnt[i]) {
+               const STRLEN len =
+                   my_snprintf(buf, sizeof(buf),
+                               "PerlIO_teardown: fd %d refcnt=%d\n",
+                               i, PL_perlio_fd_refcnt[i]);
+               PerlLIO_write(PERLIO_TEARDOWN_MESSAGE_FD, buf, len);
+           }
        }
     }
 #endif
+#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. */
@@ -2872,6 +2894,7 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
        if ((f = PerlIO_push(aTHX_(f = PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, NULL))) {
            s = PerlIOSelf(f, PerlIOStdio);
            s->stdio = stdio;
+           PerlIOUnix_refcnt_inc(fileno(stdio));
        }
     }
     return f;
@@ -3419,9 +3442,15 @@ PerlIOStdio_fill(pTHX_ PerlIO *f)
        if (PerlSIO_fflush(stdio) != 0)
            return EOF;
     }
-    c = PerlSIO_fgetc(stdio);
-    if (c == EOF)
-       return EOF;
+    for (;;) {
+       c = PerlSIO_fgetc(stdio);
+       if (c != EOF)
+           break;
+       if (! PerlSIO_ferror(stdio) || errno != EINTR)
+           return EOF;
+       PERL_ASYNC_CHECK();
+       SETERRNO(0,0);
+    }
 
 #if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
 
@@ -3538,6 +3567,7 @@ PerlIO_exportFILE(PerlIO * f, const char *mode)
            if ((f2 = PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_stdio), buf, NULL))) {
                PerlIOStdio *s = PerlIOSelf((f = f2), PerlIOStdio);
                s->stdio = stdio;
+               PerlIOUnix_refcnt_inc(fileno(stdio));
                /* Link previous lower layers under new one */
                *PerlIONext(f) = l;
            }
@@ -3555,6 +3585,7 @@ FILE *
 PerlIO_findFILE(PerlIO *f)
 {
     PerlIOl *l = *f;
+    FILE *stdio;
     while (l) {
        if (l->tab == &PerlIO_stdio) {
            PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
@@ -3563,7 +3594,19 @@ PerlIO_findFILE(PerlIO *f)
        l = *PerlIONext(&l);
     }
     /* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */
-    return PerlIO_exportFILE(f, NULL);
+    /* However, we're not really exporting a FILE * to someone else (who
+       becomes responsible for closing it, or calling PerlIO_releaseFILE())
+       So we need to undo its refernce count increase on the underlying file
+       descriptor. We have to do this, because if the loop above returns you
+       the FILE *, then *it* didn't increase any reference count. So there's
+       only one way to be consistent. */
+    stdio = PerlIO_exportFILE(f, NULL);
+    if (stdio) {
+       const int fd = fileno(stdio);
+       if (fd >= 0)
+           PerlIOUnix_refcnt_dec(fd);
+    }
+    return stdio;
 }
 
 /* Use this to reverse PerlIO_exportFILE calls. */
@@ -3577,6 +3620,9 @@ PerlIO_releaseFILE(PerlIO *p, FILE *f)
            PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
            if (s->stdio == f) {
                dTHX;
+               const int fd = fileno(f);
+               if (fd >= 0)
+                   PerlIOUnix_refcnt_dec(fd);
                PerlIO_pop(aTHX_ p);
                return;
            }
@@ -5016,16 +5062,16 @@ int
 PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
 {
     dTHX;
-    SV * const sv = newSVpvs("");
+    SV * sv;
     const char *s;
     STRLEN len;
     SSize_t wrote;
 #ifdef NEED_VA_COPY
     va_list apc;
     Perl_va_copy(ap, apc);
-    sv_vcatpvf(sv, fmt, &apc);
+    sv = vnewSVpvf(fmt, &apc);
 #else
-    sv_vcatpvf(sv, fmt, &ap);
+    sv = vnewSVpvf(fmt, &ap);
 #endif
     s = SvPV_const(sv, len);
     wrote = PerlIO_write(f, s, len);
@@ -5080,8 +5126,8 @@ PerlIO_tmpfile(void)
          if (f)
               PerlIOBase(f)->flags |= PERLIO_F_TEMP;
          PerlLIO_unlink(SvPVX_const(sv));
-         SvREFCNT_dec(sv);
      }
+     SvREFCNT_dec(sv);
 #    else      /* !HAS_MKSTEMP, fallback to stdio tmpfile(). */
      FILE * const stdio = PerlSIO_tmpfile();
 
@@ -5108,30 +5154,30 @@ const char *
 Perl_PerlIO_context_layers(pTHX_ const char *mode)
 {
     dVAR;
-    const char *type = NULL;
+    const char *direction = NULL;
+    SV *layers;
     /*
      * 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;
-               }
-           }
-       }
+
+    if (!PL_curcop)
+       return NULL;
+
+    if (mode && mode[0] != 'r') {
+       if (PL_curcop->cop_hints & HINT_LEXICAL_IO_OUT)
+           direction = "open>";
+    } else {
+       if (PL_curcop->cop_hints & HINT_LEXICAL_IO_IN)
+           direction = "open<";
     }
-    return type;
+    if (!direction)
+       return NULL;
+
+    layers = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
+                                     0, direction, 5, 0, 0);
+
+    assert(layers);
+    return SvOK(layers) ? SvPV_nolen_const(layers) : NULL;
 }