Group the debugger changes in one place.
[p5sagit/p5-mst-13.2.git] / perlio.c
index 78d6380..304107b 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -158,7 +158,11 @@ PerlIO_intmode2str(int rawmode, char *mode, int *writing)
 int
 PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
 {
-    if (!names || !*names || strEQ(names, ":crlf") || strEQ(names, ":raw")) {
+    if (!names || !*names
+        || strEQ(names, ":crlf")
+        || strEQ(names, ":raw")
+        || strEQ(names, ":bytes")
+       ) {
        return 0;
     }
     Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl", names);
@@ -805,6 +809,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
                        Perl_warner(aTHX_ packWARN(WARN_LAYER),
                              "perlio: invalid separator character %c%c%c in layer specification list %s",
                              q, *s, q, s);
+                   SETERRNO(EINVAL, LIB$_INVARG);
                    return -1;
                }
                do {
@@ -1098,6 +1103,12 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
        return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE;
     }
     else {
+       if (*f) {
+           /* Turn off UTF-8-ness, to undo UTF-8 locale effects
+              This may be too simplistic!
+            */
+           PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
+       }
        /* FIXME?: Looking down the layer stack seems wrong,
           but is a way of reaching past (say) an encoding layer
           to flip CRLF-ness of the layer(s) below
@@ -1287,8 +1298,13 @@ PerlIO_resolve_layers(pTHX_ const char *layers,
        else {
            av = def;
        }
-       PerlIO_parse_layers(aTHX_ av, layers);
-       return av;
+       if (PerlIO_parse_layers(aTHX_ av, layers) == 0) {
+            return av;
+       }
+       else {
+           PerlIO_list_free(aTHX_ av);
+           return (PerlIO_list_t *) NULL;
+       }
     }
     else {
        if (incdef)
@@ -1330,6 +1346,9 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
        }
        else {
            layera = PerlIO_resolve_layers(aTHX_ layers, mode, narg, args);
+           if (!layera) {
+               return NULL;
+           }
        }
        /*
         * Start at "top" of layer stack
@@ -1677,7 +1696,7 @@ PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
 PerlIO_funcs PerlIO_utf8 = {
     "utf8",
     sizeof(PerlIOl),
-    PERLIO_K_DUMMY | PERLIO_F_UTF8,
+    PERLIO_K_DUMMY | PERLIO_K_UTF8,
     PerlIOUtf8_pushed,
     NULL,
     NULL,
@@ -2350,7 +2369,7 @@ PerlIO_funcs PerlIO_unix = {
     sizeof(PerlIOUnix),
     PERLIO_K_RAW,
     PerlIOUnix_pushed,
-    PerlIOBase_noop_ok,
+    PerlIOBase_popped,
     PerlIOUnix_open,
     NULL,
     PerlIOUnix_fileno,
@@ -2379,6 +2398,14 @@ PerlIO_funcs PerlIO_unix = {
  * stdio as a layer
  */
 
+#if defined(VMS) && !defined(STDIO_BUFFER_WRITABLE)
+/* perl5.8 - This ensures the last minute VMS ungetc fix is not
+   broken by the last second glibc 2.3 fix
+ */
+#define STDIO_BUFFER_WRITABLE
+#endif
+
+
 typedef struct {
     struct _PerlIO base;
     FILE *stdio;                /* The stream */
@@ -2437,21 +2464,25 @@ PerlIO_importFILE(FILE *stdio, int fl)
        /* We need to probe to see how we can open the stream
           so start with read/write and then try write and read
           we dup() so that we can fclose without loosing the fd.
+
+          Note that the errno value set by a failing fdopen
+          varies between stdio implementations.
         */
        int fd = PerlLIO_dup(fileno(stdio));
        char *mode = "r+";
        FILE *f2 = fdopen(fd, mode);
        PerlIOStdio *s;
-       if (!f2 && errno == EINVAL) {
+       if (!f2) {
            mode = "w";
            f2 = fdopen(fd, mode);
        }
-       if (!f2 && errno == EINVAL) {
+       if (!f2) {
            mode = "r";
            f2 = fdopen(fd, mode);
        }
        if (!f2) {
            /* Don't seem to be able to open */
+           PerlLIO_close(fd);
            return f;
        }
        fclose(f2);
@@ -2623,15 +2654,57 @@ PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 SSize_t
 PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
 {
-    FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
-    STDCHAR *buf = ((STDCHAR *) vbuf) + count - 1;
     SSize_t unread = 0;
-    while (count > 0) {
-       int ch = *buf-- & 0xff;
-       if (PerlSIO_ungetc(ch, s) != ch)
-           break;
-       unread++;
-       count--;
+    FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
+
+#ifdef STDIO_BUFFER_WRITABLE
+    if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
+       STDCHAR *buf = ((STDCHAR *) vbuf) + count;
+       STDCHAR *base = PerlIO_get_base(f);
+       SSize_t cnt   = PerlIO_get_cnt(f);
+       STDCHAR *ptr  = PerlIO_get_ptr(f);
+       SSize_t avail = ptr - base;
+       if (avail > 0) {
+           if (avail > count) {
+               avail = count;
+           }
+           ptr -= avail;
+           Move(buf-avail,ptr,avail,STDCHAR);
+           count -= avail;
+           unread += avail;
+           PerlIO_set_ptrcnt(f,ptr,cnt+avail);
+           if (PerlSIO_feof(s) && unread >= 0)
+               PerlSIO_clearerr(s);
+       }
+    }
+    else
+#endif
+    if (PerlIO_has_cntptr(f)) {
+       /* We can get pointer to buffer but not its base
+          Do ungetc() but check chars are ending up in the
+          buffer
+        */
+       STDCHAR *eptr = (STDCHAR*)PerlSIO_get_ptr(s);
+       STDCHAR *buf = ((STDCHAR *) vbuf) + count;
+       while (count > 0) {
+           int ch = *--buf & 0xFF;
+           if (ungetc(ch,s) != ch) {
+               /* ungetc did not work */
+               break;
+           }
+           if ((STDCHAR*)PerlSIO_get_ptr(s) != --eptr || ((*eptr & 0xFF) != ch)) {
+               /* Did not change pointer as expected */
+               fgetc(s);  /* get char back again */
+               break;
+           }
+           /* It worked ! */
+           count--;
+           unread++;
+       }
+    }
+
+    if (count > 0) {
+       unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
     }
     return unread;
 }
@@ -2684,24 +2757,6 @@ PerlIOStdio_flush(pTHX_ PerlIO *f)
 }
 
 IV
-PerlIOStdio_fill(pTHX_ PerlIO *f)
-{
-    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
-    int c;
-    /*
-     * fflush()ing read-only streams can cause trouble on some stdio-s
-     */
-    if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
-       if (PerlSIO_fflush(stdio) != 0)
-           return EOF;
-    }
-    c = PerlSIO_fgetc(stdio);
-    if (c == EOF || PerlSIO_ungetc(c, stdio) != c)
-       return EOF;
-    return 0;
-}
-
-IV
 PerlIOStdio_eof(pTHX_ PerlIO *f)
 {
     return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
@@ -2798,14 +2853,78 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
 #endif                          /* STDIO_CNT_LVALUE */
 }
 
+
 #endif
 
+IV
+PerlIOStdio_fill(pTHX_ PerlIO *f)
+{
+    FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
+    int c;
+    /*
+     * fflush()ing read-only streams can cause trouble on some stdio-s
+     */
+    if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
+       if (PerlSIO_fflush(stdio) != 0)
+           return EOF;
+    }
+    c = PerlSIO_fgetc(stdio);
+    if (c == EOF)
+       return EOF;
+
+#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
+
+#ifdef STDIO_BUFFER_WRITABLE
+    if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
+       /* Fake ungetc() to the real buffer in case system's ungetc
+          goes elsewhere
+        */
+       STDCHAR *base = (STDCHAR*)PerlSIO_get_base(stdio);
+       SSize_t cnt   = PerlSIO_get_cnt(stdio);
+       STDCHAR *ptr  = (STDCHAR*)PerlSIO_get_ptr(stdio);
+       if (ptr == base+1) {
+           *--ptr = (STDCHAR) c;
+           PerlIOStdio_set_ptrcnt(aTHX_ f,ptr,cnt+1);
+           if (PerlSIO_feof(stdio))
+               PerlSIO_clearerr(stdio);
+           return 0;
+       }
+    }
+    else
+#endif
+    if (PerlIO_has_cntptr(f)) {
+       STDCHAR ch = c;
+       if (PerlIOStdio_unread(aTHX_ f,&ch,1) == 1) {
+           return 0;
+       }
+    }
+#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;
+}
+
+
+
 PerlIO_funcs PerlIO_stdio = {
     "stdio",
     sizeof(PerlIOStdio),
     PERLIO_K_BUFFERED,
     PerlIOBase_pushed,
-    PerlIOBase_noop_ok,
+    PerlIOBase_popped,
     PerlIOStdio_open,
     NULL,
     PerlIOStdio_fileno,
@@ -3014,6 +3133,9 @@ PerlIOBuf_flush(pTHX_ PerlIO *f)
                /* Reload n as some layers may pop themselves on seek */
                b->posn = PerlIO_tell(n = PerlIONext(f));
            }
+           else {
+               return code;
+           }
        }
     }
     b->ptr = b->end = b->buf;
@@ -3153,6 +3275,9 @@ PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
            PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
        }
     }
+    if (count > 0) {
+       unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
+    }
     return unread;
 }
 
@@ -3234,6 +3359,20 @@ PerlIOBuf_tell(pTHX_ PerlIO *f)
 }
 
 IV
+PerlIOBuf_popped(pTHX_ PerlIO *f)
+{
+    IV code = PerlIOBase_popped(aTHX_ f);
+    PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
+    if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
+       Safefree(b->buf);
+    }
+    b->buf = NULL;
+    b->ptr = b->end = b->buf;
+    PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
+    return code;
+}
+
+IV
 PerlIOBuf_close(pTHX_ PerlIO *f)
 {
     IV code = PerlIOBase_close(aTHX_ f);
@@ -3322,7 +3461,7 @@ PerlIO_funcs PerlIO_perlio = {
     sizeof(PerlIOBuf),
     PERLIO_K_BUFFERED,
     PerlIOBuf_pushed,
-    PerlIOBase_noop_ok,
+    PerlIOBuf_popped,
     PerlIOBuf_open,
     NULL,
     PerlIOBase_fileno,
@@ -3443,7 +3582,7 @@ PerlIO_funcs PerlIO_pending = {
     sizeof(PerlIOBuf),
     PERLIO_K_BUFFERED,
     PerlIOPending_pushed,
-    PerlIOBase_noop_ok,
+    PerlIOBuf_popped,
     NULL,
     NULL,
     PerlIOBase_fileno,
@@ -3736,7 +3875,7 @@ PerlIO_funcs PerlIO_crlf = {
     sizeof(PerlIOCrlf),
     PERLIO_K_BUFFERED | PERLIO_K_CANCRLF,
     PerlIOCrlf_pushed,
-    PerlIOBase_noop_ok,         /* popped */
+    PerlIOBuf_popped,         /* popped */
     PerlIOBuf_open,
     NULL,
     PerlIOBase_fileno,
@@ -4051,7 +4190,7 @@ PerlIO_funcs PerlIO_mmap = {
     sizeof(PerlIOMmap),
     PERLIO_K_BUFFERED,
     PerlIOBuf_pushed,
-    PerlIOBase_noop_ok,
+    PerlIOBuf_popped,
     PerlIOBuf_open,
     NULL,
     PerlIOBase_fileno,