X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perlio.c;h=e645f84139867c9dd97e5cbe25ba59e2e24043d2;hb=532eb83898dc393c9f89b475b9f77385c39eff97;hp=0f34462c3636bfa15510d503f19009858f74ebe1;hpb=23b847786cf7d86c6da9c7a772a1aef6918eee65;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perlio.c b/perlio.c index 0f34462..e645f84 100644 --- a/perlio.c +++ b/perlio.c @@ -106,7 +106,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode) } #ifndef O_ACCMODE -#define O_ACCMODE 3 /* Assume traditional implementation */ +#define O_ACCMODE 3 /* Assume traditional implementation */ #endif int @@ -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); @@ -186,7 +190,15 @@ PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names) PerlIO * PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) { -#ifndef PERL_MICRO +#ifdef PERL_MICRO + return NULL; +#else +#ifdef PERL_IMPLICIT_SYS + return PerlSIO_fdupopen(f); +#else +#ifdef WIN32 + return win32_fdupopen(f); +#else if (f) { int fd = PerlLIO_dup(PerlIO_fileno(f)); if (fd >= 0) { @@ -202,10 +214,12 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) return NULL; } else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); } #endif return NULL; +#endif +#endif } @@ -287,7 +301,7 @@ PerlIO_tmpfile(void) return tmpfile(); } -#else /* PERLIO_IS_STDIO */ +#else /* PERLIO_IS_STDIO */ #ifdef USE_SFIO @@ -323,12 +337,15 @@ PerlIO_init(pTHX) sfset(sfstdout, SF_SHARE, 0); } +/* This is not the reverse of PerlIO_exportFILE(), PerlIO_releaseFILE() is. */ PerlIO * -PerlIO_importFILE(FILE *stdio, int fl) +PerlIO_importFILE(FILE *stdio, const char *mode) { int fd = fileno(stdio); - PerlIO *r = PerlIO_fdopen(fd, "r+"); - return r; + if (!mode || !*mode) { + mode = "r+"; + } + return PerlIO_fdopen(fd, mode); } FILE * @@ -345,7 +362,7 @@ PerlIO_findFILE(PerlIO *pio) } -#else /* USE_SFIO */ +#else /* USE_SFIO */ /*======================================================================================*/ /* * Implement all the PerlIO interface ourselves. @@ -393,7 +410,7 @@ PerlIO_debug(const char *fmt, ...) if (!s) s = "(none)"; sprintf(buffer, "%s:%" IVdf " ", s, (IV) CopLINE(PL_curcop)); - len = strlen(buffer); + len = strlen(buffer); vsprintf(buffer+len, fmt, ap); PerlLIO_write(dbg, buffer, strlen(buffer)); #else @@ -460,11 +477,11 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) PerlIO_funcs *tab = PerlIOBase(f)->tab; PerlIO *new; PerlIO_debug("fdupopen f=%p param=%p\n",(void*)f,(void*)param); - new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags); + new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags); return new; } else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return NULL; } } @@ -601,10 +618,6 @@ PerlIO_destruct(pTHX) f++; } } - PerlIO_list_free(aTHX_ PL_known_layers); - PL_known_layers = NULL; - PerlIO_list_free(aTHX_ PL_def_layerlist); - PL_def_layerlist = NULL; } void @@ -622,7 +635,7 @@ PerlIO_pop(pTHX_ PerlIO *f) if ((*l->tab->Popped) (aTHX_ f) != 0) return; } - *f = l->next;; + *f = l->next; Safefree(l); } } @@ -704,7 +717,7 @@ perlio_mg_free(pTHX_ SV *sv, MAGIC *mg) MGVTBL perlio_vtab = { perlio_mg_get, perlio_mg_set, - NULL, /* len */ + NULL, /* len */ perlio_mg_clear, perlio_mg_free }; @@ -739,7 +752,7 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES) XSRETURN(count); } -#endif /* USE_ATTIBUTES_FOR_PERLIO */ +#endif /* USE_ATTIBUTES_FOR_PERLIO */ SV * PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab) @@ -796,9 +809,10 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ char q = ((*s == '\'') ? '"' : '\''); if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), + 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 { @@ -831,8 +845,8 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ case '\0': e--; - if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), + if (ckWARN(WARN_LAYER)) + Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: argument list not closed for layer \"%.*s\"", (int) (e - s), s); return -1; @@ -855,7 +869,7 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) &PL_sv_undef); } else { - if (warn_layer) + if (warn_layer) Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: unknown layer \"%.*s\"", (int) llen, s); return -1; @@ -876,7 +890,7 @@ PerlIO_default_buffer(pTHX_ PerlIO_list_t *av) tab = &PerlIO_crlf; #else if (PerlIO_stdio.Set_ptrcnt) - tab = &PerlIO_stdio; + tab = &PerlIO_stdio; #endif PerlIO_debug("Pushing %s\n", tab->name); PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0), @@ -902,6 +916,46 @@ PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def) return def; } +IV +PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) +{ + if (PerlIOValid(f)) { + PerlIO_flush(f); + PerlIO_pop(aTHX_ f); + return 0; + } + return -1; +} + +PerlIO_funcs PerlIO_remove = { + sizeof(PerlIO_funcs), + "pop", + 0, + PERLIO_K_DUMMY | PERLIO_K_UTF8, + PerlIOPop_pushed, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* flush */ + NULL, /* fill */ + NULL, + NULL, + NULL, + NULL, + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ +}; + PerlIO_list_t * PerlIO_default_layers(pTHX) { @@ -924,6 +978,7 @@ PerlIO_default_layers(pTHX) PerlIO_define_layer(aTHX_ & PerlIO_mmap); #endif PerlIO_define_layer(aTHX_ & PerlIO_utf8); + PerlIO_define_layer(aTHX_ & PerlIO_remove); PerlIO_define_layer(aTHX_ & PerlIO_byte); PerlIO_list_push(aTHX_ PL_def_layerlist, PerlIO_find_layer(aTHX_ osLayer->name, 0, 0), @@ -977,17 +1032,35 @@ PerlIO_stdstreams(pTHX) PerlIO * PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg) { - PerlIOl *l = NULL; - Newc('L',l,tab->size,char,PerlIOl); - if (l && f) { - Zero(l, tab->size, char); - l->next = *f; - l->tab = tab; - *f = l; + if (tab->fsize != sizeof(PerlIO_funcs)) { + mismatch: + Perl_croak(aTHX_ "Layer does not match this perl"); + } + if (tab->size) { + PerlIOl *l = NULL; + if (tab->size < sizeof(PerlIOl)) { + 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 = 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) (aTHX_ f, mode, arg, tab) != 0) { + PerlIO_pop(aTHX_ f); + return NULL; + } + } + } + else if (f) { + /* Pseudo-layer where push does its own stack adjust */ PerlIO_debug("PerlIO_push f=%p %s %s %p\n", (void*)f, tab->name, (mode) ? mode : "(Null)", (void*)arg); - if ((*l->tab->Pushed) (aTHX_ f, mode, arg) != 0) { - PerlIO_pop(aTHX_ f); + if ((*tab->Pushed) (aTHX_ f, mode, arg, tab) != 0) { return NULL; } } @@ -995,54 +1068,65 @@ PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg) } IV -PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOBase_binmode(pTHX_ PerlIO *f) { - PerlIO_pop(aTHX_ f); - if (*f) { - PerlIO_flush(f); - PerlIO_pop(aTHX_ f); + if (PerlIOValid(f)) { + /* Is layer suitable for raw stream ? */ + if (PerlIOBase(f)->tab->kind & PERLIO_K_RAW) { + /* Yes - turn off UTF-8-ness, to undo UTF-8 locale effects */ + PerlIOBase(f)->flags &= ~PERLIO_F_UTF8; + } + else { + /* Not suitable - pop it */ + PerlIO_pop(aTHX_ f); + } return 0; - } - return -1; + } + return -1; } IV -PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { - /* - * Remove the dummy layer - */ - PerlIO_pop(aTHX_ f); - /* - * Pop back to bottom layer - */ + if (PerlIOValid(f)) { + PerlIO *t; + PerlIOl *l; PerlIO_flush(f); - while (!(PerlIOBase(f)->tab->kind & PERLIO_K_RAW)) { - if (*PerlIONext(f)) { - PerlIO_pop(aTHX_ f); + /* + * Strip all layers that are not suitable for a raw stream + */ + t = f; + while (t && (l = *t)) { + if (l->tab->Binmode) { + /* Has a handler - normal case */ + if ((*l->tab->Binmode)(aTHX_ f) == 0) { + if (*t == l) { + /* Layer still there - move down a layer */ + t = PerlIONext(t); + } + } + else { + return -1; + } } else { - /* - * Nothing bellow - push unix on top then remove it - */ - if (PerlIO_push(aTHX_ f, PerlIO_default_btm(), mode, arg)) { - PerlIO_pop(aTHX_ PerlIONext(f)); - } - break; + /* No handler - pop it */ + PerlIO_pop(aTHX_ t); } } - PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name); - return 0; + if (PerlIOValid(f)) { + PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name); + return 0; + } } return -1; } int PerlIO_apply_layera(pTHX_ PerlIO *f, const char *mode, - PerlIO_list_t *layers, IV n) + PerlIO_list_t *layers, IV n, IV max) { - IV max = layers->cur; int code = 0; while (n < max) { PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL); @@ -1065,7 +1149,7 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) PerlIO_list_t *layers = PerlIO_list_alloc(aTHX); code = PerlIO_parse_layers(aTHX_ layers, names); if (code == 0) { - code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0); + code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0, layers->cur); } PerlIO_list_free(aTHX_ layers); } @@ -1093,16 +1177,17 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE; } else { - /* 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 - */ + /* Fake 5.6 legacy of using this call to turn ON O_TEXT */ #ifdef PERLIO_USING_CRLF /* Legacy binmode only has meaning if O_TEXT has a value distinct from O_BINARY so we can look for it in mode. */ if (!(mode & O_BINARY)) { /* Text mode */ + /* 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 + */ while (*f) { /* Perhaps we should turn on bottom-most aware layer e.g. Ilya's idea that UNIX TTY could serve @@ -1125,31 +1210,10 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) return FALSE; } #endif - /* Either asked for BINMODE or that is normal on this platform - see if any CRLF aware layers are present and turn off the flag - and possibly remove layer. + /* Legacy binmode is now _defined_ as being equivalent to pushing :raw + So code that used to be here is now in PerlIORaw_pushed(). */ - while (*f) { - if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) { - if ((PerlIOBase(f)->flags & PERLIO_F_CRLF)) { - /* In text mode - flush any pending stuff and flip it */ - PerlIO_flush(f); - PerlIOBase(f)->flags &= ~PERLIO_F_CRLF; -#ifndef PERLIO_USING_CRLF - /* CRLF is unusual case - if this is just the :crlf layer pop it */ - if (PerlIOBase(f)->tab == &PerlIO_crlf) { - PerlIO_pop(aTHX_ f); - } -#endif - /* Normal case is only one layer doing this, so exit on first - abnormal case can always do multiple binmode calls - */ - return TRUE; - } - } - f = PerlIONext(f); - } - return TRUE; + return PerlIO_push(aTHX_ f, &PerlIO_raw, Nullch, Nullsv) ? TRUE : FALSE; } } @@ -1159,7 +1223,7 @@ PerlIO__close(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Close) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1183,7 +1247,7 @@ Perl_PerlIO_fileno(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Fileno) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1205,7 +1269,7 @@ PerlIO_context_layers(pTHX_ const char *mode) * Skip to write part */ const char *s = strchr(type, 0); - if (s && (s - type) < len) { + if (s && (STRLEN)(s - type) < len) { type = s + 1; } } @@ -1221,7 +1285,7 @@ PerlIO_layer_from_ref(pTHX_ SV *sv) * 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); + return PerlIO_find_layer(aTHX_ "scalar", 6, 1); /* * For other types allow if layer is known but don't try and load it @@ -1261,7 +1325,7 @@ PerlIO_resolve_layers(pTHX_ const char *layers, incdef = 0; } /* - * Don't fail if handler cannot be found :Via(...) etc. may do + * Don't fail if handler cannot be found :via(...) etc. may do * something sensible else we will just stringfy and open * resulting string. */ @@ -1282,8 +1346,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) @@ -1325,6 +1394,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 @@ -1356,8 +1428,9 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, * More layers above the one that we used to open - * apply them now */ - if (PerlIO_apply_layera(aTHX_ f, mode, layera, n + 1) - != 0) { + if (PerlIO_apply_layera(aTHX_ f, mode, layera, n + 1, layera->cur) != 0) { + /* If pushing layers fails close the file */ + PerlIO_close(f); f = NULL; } } @@ -1375,7 +1448,7 @@ Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Read) (aTHX_ f, vbuf, count); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1386,7 +1459,7 @@ Perl_PerlIO_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Unread) (aTHX_ f, vbuf, count); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1397,7 +1470,7 @@ Perl_PerlIO_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Write) (aTHX_ f, vbuf, count); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1408,7 +1481,7 @@ Perl_PerlIO_seek(pTHX_ PerlIO *f, Off_t offset, int whence) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Seek) (aTHX_ f, offset, whence); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1419,7 +1492,7 @@ Perl_PerlIO_tell(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Tell) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1435,13 +1508,13 @@ Perl_PerlIO_flush(pTHX_ PerlIO *f) } else { PerlIO_debug("Cannot flush f=%p :%s\n", (void*)f, tab->name); - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } else { PerlIO_debug("Cannot flush f=%p\n", (void*)f); - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1493,7 +1566,7 @@ Perl_PerlIO_fill(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Fill) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1504,7 +1577,7 @@ PerlIO_isutf8(PerlIO *f) if (PerlIOValid(f)) return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0; else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1515,7 +1588,7 @@ Perl_PerlIO_eof(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Eof) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1526,7 +1599,7 @@ Perl_PerlIO_error(pTHX_ PerlIO *f) if (PerlIOValid(f)) return (*PerlIOBase(f)->tab->Error) (aTHX_ f); else { - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); return -1; } } @@ -1537,7 +1610,7 @@ Perl_PerlIO_clearerr(pTHX_ PerlIO *f) if (PerlIOValid(f)) (*PerlIOBase(f)->tab->Clearerr) (aTHX_ f); else - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); } void @@ -1546,7 +1619,7 @@ Perl_PerlIO_setlinebuf(pTHX_ PerlIO *f) if (PerlIOValid(f)) (*PerlIOBase(f)->tab->Setlinebuf) (aTHX_ f); else - SETERRNO(EBADF, SS$_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); } int @@ -1648,17 +1721,16 @@ Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt) } } + /*--------------------------------------------------------------------------------------*/ /* * utf8 and raw dummy layers */ IV -PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { - if (*PerlIONext(f)) { - PerlIO_funcs *tab = PerlIOBase(f)->tab; - PerlIO_pop(aTHX_ f); + if (PerlIOValid(f)) { if (tab->kind & PERLIO_K_UTF8) PerlIOBase(f)->flags |= PERLIO_F_UTF8; else @@ -1669,9 +1741,10 @@ PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) } PerlIO_funcs PerlIO_utf8 = { + sizeof(PerlIO_funcs), "utf8", - sizeof(PerlIOl), - PERLIO_K_DUMMY | PERLIO_F_UTF8, + 0, + PERLIO_K_DUMMY | PERLIO_K_UTF8, PerlIOUtf8_pushed, NULL, NULL, @@ -1683,22 +1756,23 @@ PerlIO_funcs PerlIO_utf8 = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; PerlIO_funcs PerlIO_byte = { + sizeof(PerlIO_funcs), "bytes", - sizeof(PerlIOl), + 0, PERLIO_K_DUMMY, PerlIOUtf8_pushed, NULL, @@ -1711,17 +1785,17 @@ PerlIO_funcs PerlIO_byte = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; PerlIO * @@ -1735,8 +1809,9 @@ PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, } PerlIO_funcs PerlIO_raw = { + sizeof(PerlIO_funcs), "raw", - sizeof(PerlIOl), + 0, PERLIO_K_DUMMY, PerlIORaw_pushed, PerlIOBase_popped, @@ -1749,17 +1824,17 @@ PerlIO_funcs PerlIO_raw = { NULL, NULL, NULL, - NULL, /* flush */ - NULL, /* fill */ + NULL, /* flush */ + NULL, /* fill */ NULL, NULL, NULL, NULL, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; /*--------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------*/ @@ -1774,44 +1849,46 @@ PerlIOBase_fileno(pTHX_ PerlIO *f) } char * -PerlIO_modestr(PerlIO *f, char *buf) +PerlIO_modestr(PerlIO * f, char *buf) { char *s = buf; - IV flags = PerlIOBase(f)->flags; - if (flags & PERLIO_F_APPEND) { - *s++ = 'a'; - if (flags & PERLIO_F_CANREAD) { - *s++ = '+'; + if (PerlIOValid(f)) { + IV flags = PerlIOBase(f)->flags; + if (flags & PERLIO_F_APPEND) { + *s++ = 'a'; + if (flags & PERLIO_F_CANREAD) { + *s++ = '+'; + } } - } - else if (flags & PERLIO_F_CANREAD) { - *s++ = 'r'; - if (flags & PERLIO_F_CANWRITE) - *s++ = '+'; - } - else if (flags & PERLIO_F_CANWRITE) { - *s++ = 'w'; - if (flags & PERLIO_F_CANREAD) { - *s++ = '+'; + else if (flags & PERLIO_F_CANREAD) { + *s++ = 'r'; + if (flags & PERLIO_F_CANWRITE) + *s++ = '+'; + } + else if (flags & PERLIO_F_CANWRITE) { + *s++ = 'w'; + if (flags & PERLIO_F_CANREAD) { + *s++ = '+'; + } } - } #ifdef PERLIO_USING_CRLF - if (!(flags & PERLIO_F_CRLF)) - *s++ = 'b'; + if (!(flags & PERLIO_F_CRLF)) + *s++ = 'b'; #endif + } *s = '\0'; return buf; } + IV -PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { PerlIOl *l = PerlIOBase(f); #if 0 const char *omode = mode; char temp[8]; #endif - PerlIO_funcs *tab = PerlIOBase(f)->tab; l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_TRUNCATE | PERLIO_F_APPEND); if (tab->Set_ptrcnt != NULL) @@ -1830,7 +1907,7 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) l->flags |= PERLIO_F_TRUNCATE | PERLIO_F_CANWRITE; break; default: - SETERRNO(EINVAL, LIB$_INVARG); + SETERRNO(EINVAL, LIB_INVARG); return -1; } while (*mode) { @@ -1845,7 +1922,7 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) l->flags |= PERLIO_F_CRLF; break; default: - SETERRNO(EINVAL, LIB$_INVARG); + SETERRNO(EINVAL, LIB_INVARG); return -1; } } @@ -1896,7 +1973,7 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) SSize_t avail = PerlIO_get_cnt(f); SSize_t take = 0; if (avail > 0) - take = (count < avail) ? count : avail; + take = ((SSize_t)count < avail) ? count : avail; if (take > 0) { STDCHAR *ptr = PerlIO_get_ptr(f); Copy(ptr, buf, take, STDCHAR); @@ -2071,7 +2148,9 @@ PerlIO_cleanup(pTHX) { int i; #ifdef USE_ITHREADS - PerlIO_debug("Cleanup %p\n",aTHX); + PerlIO_debug("Cleanup layers for %p\n",aTHX); +#else + PerlIO_debug("Cleanup layers\n"); #endif /* Raise STDIN..STDERR refcount so we don't close them */ for (i=0; i < 3; i++) @@ -2080,6 +2159,15 @@ PerlIO_cleanup(pTHX) /* Restore STDIN..STDERR refcount */ for (i=0; i < 3; i++) PerlIOUnix_refcnt_dec(i); + + if (PL_known_layers) { + PerlIO_list_free(aTHX_ PL_known_layers); + PL_known_layers = NULL; + } + if(PL_def_layerlist) { + PerlIO_list_free(aTHX_ PL_def_layerlist); + PL_def_layerlist = NULL; + } } @@ -2090,9 +2178,9 @@ PerlIO_cleanup(pTHX) */ typedef struct { - struct _PerlIO base; /* The generic part */ - int fd; /* UNIX like file descriptor */ - int oflags; /* open/fcntl flags */ + struct _PerlIO base; /* The generic part */ + int fd; /* UNIX like file descriptor */ + int oflags; /* open/fcntl flags */ } PerlIOUnix; int @@ -2145,7 +2233,7 @@ PerlIOUnix_oflags(const char *mode) */ oflags |= O_BINARY; if (*mode || oflags == -1) { - SETERRNO(EINVAL, LIB$_INVARG); + SETERRNO(EINVAL, LIB_INVARG); oflags = -1; } return oflags; @@ -2158,12 +2246,12 @@ PerlIOUnix_fileno(pTHX_ PerlIO *f) } IV -PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { - IV code = PerlIOBase_pushed(aTHX_ f, mode, arg); + IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab); PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); if (*PerlIONext(f)) { - /* We never call down so any pending stuff now */ + /* We never call down so do any pending stuff now */ PerlIO_flush(PerlIONext(f)); s->fd = PerlIO_fileno(PerlIONext(f)); /* @@ -2182,7 +2270,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n, const char *mode, int fd, int imode, int perm, PerlIO *f, int narg, SV **args) { - if (f) { + if (PerlIOValid(f)) { if (PerlIOBase(f)->flags & PERLIO_F_OPEN) (*PerlIOBase(f)->tab->Close)(aTHX_ f); } @@ -2204,15 +2292,17 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, mode++; if (!f) { f = PerlIO_allocate(aTHX); - s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg), - PerlIOUnix); } - else - s = PerlIOSelf(f, PerlIOUnix); + if (!PerlIOValid(f)) { + if (!(f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) { + return NULL; + } + } + s = PerlIOSelf(f, PerlIOUnix); s->fd = fd; s->oflags = imode; PerlIOBase(f)->flags |= PERLIO_F_OPEN; - PerlIOUnix_refcnt_inc(fd); + PerlIOUnix_refcnt_inc(fd); return f; } else { @@ -2251,8 +2341,10 @@ SSize_t PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { int fd = PerlIOSelf(f, PerlIOUnix)->fd; - if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) + if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD) || + PerlIOBase(f)->flags & (PERLIO_F_EOF|PERLIO_F_ERROR)) { return 0; + } while (1) { SSize_t len = PerlLIO_read(fd, vbuf, count); if (len >= 0 || errno != EINTR) { @@ -2306,10 +2398,10 @@ PerlIOUnix_close(pTHX_ PerlIO *f) if (PerlIOUnix_refcnt_dec(fd) > 0) { PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; return 0; - } + } } else { - SETERRNO(EBADF,SS$_IVCHAN); + SETERRNO(EBADF,SS_IVCHAN); return -1; } while (PerlLIO_close(fd) != 0) { @@ -2326,12 +2418,14 @@ PerlIOUnix_close(pTHX_ PerlIO *f) } PerlIO_funcs PerlIO_unix = { + sizeof(PerlIO_funcs), "unix", sizeof(PerlIOUnix), PERLIO_K_RAW, PerlIOUnix_pushed, - PerlIOBase_noop_ok, + PerlIOBase_popped, PerlIOUnix_open, + PerlIOBase_binmode, /* binmode */ NULL, PerlIOUnix_fileno, PerlIOUnix_dup, @@ -2341,17 +2435,17 @@ PerlIO_funcs PerlIO_unix = { PerlIOUnix_seek, PerlIOUnix_tell, PerlIOUnix_close, - PerlIOBase_noop_ok, /* flush */ - PerlIOBase_noop_fail, /* fill */ + PerlIOBase_noop_ok, /* flush */ + PerlIOBase_noop_fail, /* fill */ PerlIOBase_eof, PerlIOBase_error, PerlIOBase_clearerr, PerlIOBase_setlinebuf, - NULL, /* get_base */ - NULL, /* get_bufsiz */ - NULL, /* get_ptr */ - NULL, /* get_cnt */ - NULL, /* set_ptrcnt */ + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ }; /*--------------------------------------------------------------------------------------*/ @@ -2359,15 +2453,28 @@ 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 */ + FILE *stdio; /* The stream */ } PerlIOStdio; IV PerlIOStdio_fileno(pTHX_ PerlIO *f) { - return PerlSIO_fileno(PerlIOSelf(f, PerlIOStdio)->stdio); + FILE *s; + if (PerlIOValid(f) && (s = PerlIOSelf(f, PerlIOStdio)->stdio)) { + return PerlSIO_fileno(s); + } + errno = EBADF; + return -1; } char * @@ -2384,40 +2491,69 @@ PerlIOStdio_mode(const char *mode, char *tmode) return ret; } -/* - * This isn't used yet ... - */ IV -PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { - if (*PerlIONext(f)) { - PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); - char tmode[8]; - FILE *stdio = - PerlSIO_fdopen(PerlIO_fileno(PerlIONext(f)), mode = - PerlIOStdio_mode(mode, tmode)); - if (stdio) { - s->stdio = stdio; - /* We never call down so any pending stuff now */ - PerlIO_flush(PerlIONext(f)); - } - else - return -1; + PerlIO *n; + if (PerlIOValid(f) && PerlIOValid(n = PerlIONext(f))) { + PerlIO_funcs *toptab = PerlIOBase(n)->tab; + if (toptab == tab) { + /* Top is already stdio - pop self (duplicate) and use original */ + PerlIO_pop(aTHX_ f); + return 0; + } else { + int fd = PerlIO_fileno(n); + char tmode[8]; + FILE *stdio; + if (fd >= 0 && (stdio = PerlSIO_fdopen(fd, + mode = PerlIOStdio_mode(mode, tmode)))) { + PerlIOSelf(f, PerlIOStdio)->stdio = stdio; + /* We never call down so do any pending stuff now */ + PerlIO_flush(PerlIONext(f)); + } + else { + return -1; + } + } } - return PerlIOBase_pushed(aTHX_ f, mode, arg); + return PerlIOBase_pushed(aTHX_ f, mode, arg, tab); } + PerlIO * -PerlIO_importFILE(FILE *stdio, int fl) +PerlIO_importFILE(FILE *stdio, const char *mode) { dTHX; PerlIO *f = NULL; if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, - "r+", Nullsv), PerlIOStdio); - s->stdio = stdio; + PerlIOStdio *s; + if (!mode || !*mode) { + /* 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)); + FILE *f2 = PerlSIO_fdopen(fd, (mode = "r+")); + if (!f2) { + f2 = PerlSIO_fdopen(fd, (mode = "w")); + } + if (!f2) { + f2 = PerlSIO_fdopen(fd, (mode = "r")); + } + if (!f2) { + /* Don't seem to be able to open */ + PerlLIO_close(fd); + return f; + } + fclose(f2); + } + if ((f = PerlIO_push(aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, mode, Nullsv))) { + s = PerlIOSelf(f, PerlIOStdio); + s->stdio = stdio; + } } return f; } @@ -2428,7 +2564,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, int perm, PerlIO *f, int narg, SV **args) { char tmode[8]; - if (f) { + if (PerlIOValid(f)) { char *path = SvPV_nolen(*args); PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); FILE *stdio; @@ -2451,16 +2587,22 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, else { FILE *stdio = PerlSIO_fopen(path, mode); if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), self, + PerlIOStdio *s; + if (!f) { + f = PerlIO_allocate(aTHX); + } + if ((f = PerlIO_push(aTHX_ f, self, (mode = PerlIOStdio_mode(mode, tmode)), - PerlIOArg), - PerlIOStdio); - s->stdio = stdio; - PerlIOUnix_refcnt_inc(fileno(s->stdio)); + PerlIOArg))) { + s = PerlIOSelf(f, PerlIOStdio); + s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); + } + return f; + } + else { + return NULL; } - return f; } } if (fd >= 0) { @@ -2488,12 +2630,15 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, PerlIOStdio_mode(mode, tmode)); } if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), self, - mode, PerlIOArg), PerlIOStdio); - s->stdio = stdio; - PerlIOUnix_refcnt_inc(fileno(s->stdio)); + PerlIOStdio *s; + if (!f) { + f = PerlIO_allocate(aTHX); + } + if ((f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) { + s = PerlIOSelf(f, PerlIOStdio); + s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); + } return f; } } @@ -2513,7 +2658,7 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) int fd = PerlLIO_dup(fileno(stdio)); if (fd >= 0) { char mode[8]; - stdio = fdopen(fd, PerlIO_modestr(o,mode)); + stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o,mode)); } else { /* FIXME: To avoid messy error recovery if dup fails @@ -2535,10 +2680,13 @@ PerlIOStdio_close(pTHX_ PerlIO *f) Sock_size_t optlen = sizeof(int); #endif FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; + if (!stdio) { + errno = EBADF; + return -1; + } if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) { /* Do not close it but do flush any buffers */ - PerlIO_flush(f); - return 0; + return PerlIO_flush(f); } return ( #ifdef SOCKS5_VERSION_NAME @@ -2580,15 +2728,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; } @@ -2641,24 +2831,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); @@ -2723,7 +2895,7 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) FILE *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, (void*)ptr); /* LHS STDCHAR* cast non-portable */ #ifdef STDIO_PTR_LVAL_SETS_CNT if (PerlSIO_get_cnt(stdio) != (cnt)) { assert(PerlSIO_get_cnt(stdio) == (cnt)); @@ -2735,35 +2907,101 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) */ return; #endif -#else /* STDIO_PTR_LVALUE */ +#else /* STDIO_PTR_LVALUE */ PerlProc_abort(); -#endif /* STDIO_PTR_LVALUE */ +#endif /* STDIO_PTR_LVALUE */ } /* * Now (or only) set cnt */ #ifdef STDIO_CNT_LVALUE PerlSIO_set_cnt(stdio, cnt); -#else /* STDIO_CNT_LVALUE */ +#else /* STDIO_CNT_LVALUE */ #if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT)) PerlSIO_set_ptr(stdio, PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) - cnt)); -#else /* STDIO_PTR_LVAL_SETS_CNT */ +#else /* STDIO_PTR_LVAL_SETS_CNT */ PerlProc_abort(); -#endif /* STDIO_PTR_LVAL_SETS_CNT */ -#endif /* STDIO_CNT_LVALUE */ +#endif /* STDIO_PTR_LVAL_SETS_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 = { + sizeof(PerlIO_funcs), "stdio", sizeof(PerlIOStdio), - PERLIO_K_BUFFERED, - PerlIOBase_pushed, - PerlIOBase_noop_ok, + PERLIO_K_BUFFERED|PERLIO_K_RAW, + PerlIOStdio_pushed, + PerlIOBase_popped, PerlIOStdio_open, + PerlIOBase_binmode, /* binmode */ NULL, PerlIOStdio_fileno, PerlIOStdio_dup, @@ -2791,32 +3029,50 @@ PerlIO_funcs PerlIO_stdio = { PerlIOStdio_get_cnt, #if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT))) PerlIOStdio_set_ptrcnt -#else /* STDIO_PTR_LVALUE */ +#else /* STDIO_PTR_LVALUE */ NULL -#endif /* STDIO_PTR_LVALUE */ -#else /* USE_STDIO_PTR */ +#endif /* STDIO_PTR_LVALUE */ +#else /* USE_STDIO_PTR */ NULL, NULL, NULL -#endif /* USE_STDIO_PTR */ +#endif /* USE_STDIO_PTR */ }; +/* Note that calls to PerlIO_exportFILE() are reversed using + * PerlIO_releaseFILE(), not importFILE. */ FILE * -PerlIO_exportFILE(PerlIO *f, int fl) +PerlIO_exportFILE(PerlIO * f, const char *mode) { dTHX; - FILE *stdio; - PerlIO_flush(f); - stdio = fdopen(PerlIO_fileno(f), "r+"); - if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, "r+", Nullsv), - PerlIOStdio); - s->stdio = stdio; + FILE *stdio = NULL; + if (PerlIOValid(f)) { + char buf[8]; + PerlIO_flush(f); + if (!mode || !*mode) { + mode = PerlIO_modestr(f, buf); + } + stdio = PerlSIO_fdopen(PerlIO_fileno(f), mode); + if (stdio) { + PerlIOl *l = *f; + /* De-link any lower layers so new :stdio sticks */ + *f = NULL; + if ((f = PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv))) { + PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); + s->stdio = stdio; + /* Link previous lower layers under new one */ + *PerlIONext(f) = l; + } + else { + /* restore layers list */ + *f = l; + } + } } return stdio; } + FILE * PerlIO_findFILE(PerlIO *f) { @@ -2828,12 +3084,27 @@ PerlIO_findFILE(PerlIO *f) } l = *PerlIONext(&l); } - return PerlIO_exportFILE(f, 0); + /* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */ + return PerlIO_exportFILE(f, Nullch); } +/* Use this to reverse PerlIO_exportFILE calls. */ void PerlIO_releaseFILE(PerlIO *p, FILE *f) { + PerlIOl *l; + while ((l = *p)) { + if (l->tab == &PerlIO_stdio) { + PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio); + if (s->stdio == f) { + dTHX; + PerlIO_pop(aTHX_ p); + return; + } + } + p = PerlIONext(p); + } + return; } /*--------------------------------------------------------------------------------------*/ @@ -2842,19 +3113,20 @@ PerlIO_releaseFILE(PerlIO *p, FILE *f) */ IV -PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); int fd = PerlIO_fileno(f); - Off_t posn; if (fd >= 0 && PerlLIO_isatty(fd)) { PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY; } - posn = PerlIO_tell(PerlIONext(f)); - if (posn != (Off_t) - 1) { - b->posn = posn; + if (*PerlIONext(f)) { + Off_t posn = PerlIO_tell(PerlIONext(f)); + if (posn != (Off_t) - 1) { + b->posn = posn; + } } - return PerlIOBase_pushed(aTHX_ f, mode, arg); + return PerlIOBase_pushed(aTHX_ f, mode, arg, tab); } PerlIO * @@ -2867,7 +3139,7 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab); next = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, next, narg, args); - if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg) != 0) { + if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg, self) != 0) { return NULL; } } @@ -2881,9 +3153,9 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, */ } f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, - NULL, narg, args); + f, narg, args); if (f) { - if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { + if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { /* * if push fails during open, open fails. close will pop us. */ @@ -2950,19 +3222,26 @@ PerlIOBuf_flush(pTHX_ PerlIO *f) */ b->posn += (b->ptr - buf); if (b->ptr < b->end) { - /* - * We did not consume all of it + /* We did not consume all of it - try and seek downstream to + our logical position */ - if (PerlIO_seek(n, b->posn, SEEK_SET) == 0) { + if (PerlIOValid(n) && PerlIO_seek(n, b->posn, SEEK_SET) == 0) { /* Reload n as some layers may pop themselves on seek */ b->posn = PerlIO_tell(n = PerlIONext(f)); } + else { + /* Seek failed (e.g. pipe or tty). Do NOT clear buffer or pre-read + data is lost for good - so return saying "ok" having undone + the position adjust + */ + b->posn -= (b->ptr - buf); + return code; + } } } b->ptr = b->end = b->buf; PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF); /* We check for Valid because of dubious decision to make PerlIO_flush(NULL) flush all */ - /* FIXME: Doing downstream flush may be sub-optimal see PerlIOBuf_fill() below */ if (PerlIOValid(n) && PerlIO_flush(n) != 0) code = -1; return code; @@ -2975,10 +3254,8 @@ PerlIOBuf_fill(pTHX_ PerlIO *f) PerlIO *n = PerlIONext(f); SSize_t avail; /* - * FIXME: doing the down-stream flush maybe sub-optimal if it causes - * pre-read data in stdio buffer to be discarded. - * However, skipping the flush also skips _our_ hosekeeping - * and breaks tell tests. So we do the flush. + * 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) return -1; @@ -2986,9 +3263,15 @@ PerlIOBuf_fill(pTHX_ PerlIO *f) PerlIOBase_flush_linebuf(aTHX); if (!b->buf) - PerlIO_get_base(f); /* allocate via vtable */ + PerlIO_get_base(f); /* allocate via vtable */ b->ptr = b->end = b->buf; + + if (!PerlIOValid(n)) { + PerlIOBase(f)->flags |= PERLIO_F_EOF; + return -1; + } + if (PerlIO_fast_gets(n)) { /* * Layer below is also buffered. We do _NOT_ want to call its @@ -3009,7 +3292,7 @@ PerlIOBuf_fill(pTHX_ PerlIO *f) if (avail > 0) { STDCHAR *ptr = PerlIO_get_ptr(n); SSize_t cnt = avail; - if (avail > b->bufsiz) + if (avail > (SSize_t)b->bufsiz) avail = b->bufsiz; Copy(ptr, b->buf, avail, STDCHAR); PerlIO_set_ptrcnt(n, ptr + avail, cnt - avail); @@ -3096,6 +3379,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; } @@ -3177,6 +3463,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); @@ -3261,12 +3561,14 @@ PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) PerlIO_funcs PerlIO_perlio = { + sizeof(PerlIO_funcs), "perlio", sizeof(PerlIOBuf), - PERLIO_K_BUFFERED, + PERLIO_K_BUFFERED|PERLIO_K_RAW, PerlIOBuf_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, PerlIOBuf_open, + PerlIOBase_binmode, /* binmode */ NULL, PerlIOBase_fileno, PerlIOBuf_dup, @@ -3349,9 +3651,9 @@ PerlIOPending_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) } IV -PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { - IV code = PerlIOBase_pushed(aTHX_ f, mode, arg); + IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab); PerlIOl *l = PerlIOBase(f); /* * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets() @@ -3368,11 +3670,11 @@ PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { SSize_t avail = PerlIO_get_cnt(f); SSize_t got = 0; - if (count < avail) + if ((SSize_t)count < avail) avail = count; if (avail > 0) got = PerlIOBuf_read(aTHX_ f, vbuf, avail); - if (got >= 0 && got < count) { + if (got >= 0 && got < (SSize_t)count) { SSize_t more = PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got); if (more >= 0 || got == 0) @@ -3382,12 +3684,14 @@ PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) } PerlIO_funcs PerlIO_pending = { + sizeof(PerlIO_funcs), "pending", sizeof(PerlIOBuf), - PERLIO_K_BUFFERED, + PERLIO_K_BUFFERED|PERLIO_K_RAW, /* not sure about RAW here */ PerlIOPending_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, NULL, + PerlIOBase_binmode, /* binmode */ NULL, PerlIOBase_fileno, PerlIOBuf_dup, @@ -3420,17 +3724,17 @@ PerlIO_funcs PerlIO_pending = { */ typedef struct { - PerlIOBuf base; /* PerlIOBuf stuff */ - STDCHAR *nl; /* Position of crlf we "lied" about in the + PerlIOBuf base; /* PerlIOBuf stuff */ + STDCHAR *nl; /* Position of crlf we "lied" about in the * buffer */ } PerlIOCrlf; IV -PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) +PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) { IV code; PerlIOBase(f)->flags |= PERLIO_F_CRLF; - code = PerlIOBuf_pushed(aTHX_ f, mode, arg); + code = PerlIOBuf_pushed(aTHX_ f, mode, arg, tab); #if 0 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n", f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)", @@ -3532,19 +3836,19 @@ PerlIOCrlf_get_cnt(pTHX_ PerlIO *f) } else { int code; - b->ptr++; /* say we have read it as far as + b->ptr++; /* say we have read it as far as * flush() is concerned */ - b->buf++; /* Leave space in front of buffer */ - b->bufsiz--; /* Buffer is thus smaller */ - code = PerlIO_fill(f); /* Fetch some more */ - b->bufsiz++; /* Restore size for next time */ - b->buf--; /* Point at space */ - b->ptr = nl = b->buf; /* Which is what we hand + b->buf++; /* Leave space in front of buffer */ + b->bufsiz--; /* Buffer is thus smaller */ + code = PerlIO_fill(f); /* Fetch some more */ + b->bufsiz++; /* Restore size for next time */ + b->buf--; /* Point at space */ + b->ptr = nl = b->buf; /* Which is what we hand * off */ - b->posn--; /* Buffer starts here */ - *nl = 0xd; /* Fill in the CR */ + b->posn--; /* Buffer starts here */ + *nl = 0xd; /* Fill in the CR */ if (code == 0) - goto test; /* fill() call worked */ + goto test; /* fill() call worked */ /* * CR at EOF - just fall through */ @@ -3563,32 +3867,32 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf); - IV flags = PerlIOBase(f)->flags; if (!b->buf) PerlIO_get_base(f); if (!ptr) { if (c->nl) { ptr = c->nl + 1; - if (ptr == b->end && *c->nl == 0xd) { + if (ptr == b->end && *c->nl == 0xd) { /* Defered CR at end of buffer case - we lied about count */ - ptr--; - } - } + ptr--; + } + } else { ptr = b->end; } ptr -= cnt; } else { -#if 1 +#if 0 /* * Test code - delete when it works ... */ + IV flags = PerlIOBase(f)->flags; STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end; - if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) { + if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) { /* Defered CR at end of buffer case - we lied about count */ chk--; - } + } chk -= cnt; if (ptr != chk ) { @@ -3638,8 +3942,8 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) break; } else { - *(b->ptr)++ = 0xd; /* CR */ - *(b->ptr)++ = 0xa; /* LF */ + *(b->ptr)++ = 0xd; /* CR */ + *(b->ptr)++ = 0xa; /* LF */ buf++; if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) { PerlIO_flush(f); @@ -3674,20 +3978,38 @@ PerlIOCrlf_flush(pTHX_ PerlIO *f) return PerlIOBuf_flush(aTHX_ f); } +IV +PerlIOCrlf_binmode(pTHX_ PerlIO *f) +{ + if ((PerlIOBase(f)->flags & PERLIO_F_CRLF)) { + /* In text mode - flush any pending stuff and flip it */ + PerlIOBase(f)->flags &= ~PERLIO_F_CRLF; +#ifndef PERLIO_USING_CRLF + /* CRLF is unusual case - if this is just the :crlf layer pop it */ + if (PerlIOBase(f)->tab == &PerlIO_crlf) { + PerlIO_pop(aTHX_ f); + } +#endif + } + return 0; +} + PerlIO_funcs PerlIO_crlf = { + sizeof(PerlIO_funcs), "crlf", sizeof(PerlIOCrlf), - PERLIO_K_BUFFERED | PERLIO_K_CANCRLF, + PERLIO_K_BUFFERED | PERLIO_K_CANCRLF | PERLIO_K_RAW, PerlIOCrlf_pushed, - PerlIOBase_noop_ok, /* popped */ + PerlIOBuf_popped, /* popped */ PerlIOBuf_open, + PerlIOCrlf_binmode, /* binmode */ NULL, PerlIOBase_fileno, PerlIOBuf_dup, - PerlIOBuf_read, /* generic read works with ptr/cnt lies + PerlIOBuf_read, /* generic read works with ptr/cnt lies * ... */ - PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */ - PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */ + PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */ + PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */ PerlIOBuf_seek, PerlIOBuf_tell, PerlIOBuf_close, @@ -3711,10 +4033,10 @@ PerlIO_funcs PerlIO_crlf = { */ typedef struct { - PerlIOBuf base; /* PerlIOBuf stuff */ - Mmap_t mptr; /* Mapped address */ - Size_t len; /* mapped length */ - STDCHAR *bbuf; /* malloced buffer if map fails */ + PerlIOBuf base; /* PerlIOBuf stuff */ + Mmap_t mptr; /* Mapped address */ + Size_t len; /* mapped length */ + STDCHAR *bbuf; /* malloced buffer if map fails */ } PerlIOMmap; static size_t page_size = 0; @@ -3739,7 +4061,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f) if (!page_size) { #if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE)) { - SETERRNO(0, SS$_NORMAL); + SETERRNO(0, SS_NORMAL); # ifdef _SC_PAGESIZE page_size = sysconf(_SC_PAGESIZE); # else @@ -3765,7 +4087,7 @@ PerlIOMmap_map(pTHX_ PerlIO *f) page_size = getpagesize(); # else # if defined(I_SYS_PARAM) && defined(PAGESIZE) - page_size = PAGESIZE; /* compiletime, bad */ + page_size = PAGESIZE; /* compiletime, bad */ # endif # endif #endif @@ -3849,11 +4171,11 @@ PerlIOMmap_get_base(pTHX_ PerlIO *f) /* * We have a write buffer or flushed PerlIOBuf read buffer */ - m->bbuf = b->buf; /* save it in case we need it again */ - b->buf = NULL; /* Clear to trigger below */ + m->bbuf = b->buf; /* save it in case we need it again */ + b->buf = NULL; /* Clear to trigger below */ } if (!b->buf) { - PerlIOMmap_map(aTHX_ f); /* Try and map it */ + PerlIOMmap_map(aTHX_ f); /* Try and map it */ if (!b->buf) { /* * Map did not work - recover PerlIOBuf buffer if we have one @@ -3990,12 +4312,14 @@ PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) PerlIO_funcs PerlIO_mmap = { + sizeof(PerlIO_funcs), "mmap", sizeof(PerlIOMmap), - PERLIO_K_BUFFERED, + PERLIO_K_BUFFERED|PERLIO_K_RAW, PerlIOBuf_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, PerlIOBuf_open, + PerlIOBase_binmode, /* binmode */ NULL, PerlIOBase_fileno, PerlIOMmap_dup, @@ -4018,7 +4342,7 @@ PerlIO_funcs PerlIO_mmap = { PerlIOBuf_set_ptrcnt, }; -#endif /* HAS_MMAP */ +#endif /* HAS_MMAP */ PerlIO * Perl_PerlIO_stdin(pTHX) @@ -4209,11 +4533,10 @@ PerlIO_tmpfile(void) PerlIO *f = NULL; FILE *stdio = PerlSIO_tmpfile(); if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, - "w+", Nullsv), PerlIOStdio); - s->stdio = stdio; + if ((f = PerlIO_push(aTHX_(PerlIO_allocate(aTHX)), &PerlIO_stdio, "w+", Nullsv))) { + PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); + s->stdio = stdio; + } } return f; #else @@ -4236,8 +4559,8 @@ PerlIO_tmpfile(void) #undef HAS_FSETPOS #undef HAS_FGETPOS -#endif /* USE_SFIO */ -#endif /* PERLIO_IS_STDIO */ +#endif /* USE_SFIO */ +#endif /* PERLIO_IS_STDIO */ /*======================================================================================*/ /* @@ -4257,7 +4580,7 @@ PerlIO_setpos(PerlIO *f, SV *pos) if (f && len == sizeof(Off_t)) return PerlIO_seek(f, *posn, SEEK_SET); } - SETERRNO(EINVAL, SS$_IVCHAN); + SETERRNO(EINVAL, SS_IVCHAN); return -1; } #else @@ -4277,7 +4600,7 @@ PerlIO_setpos(PerlIO *f, SV *pos) #endif } } - SETERRNO(EINVAL, SS$_IVCHAN); + SETERRNO(EINVAL, SS_IVCHAN); return -1; } #endif @@ -4316,7 +4639,7 @@ int vprintf(char *pat, char *args) { _doprnt(pat, args, stdout); - return 0; /* wrong, but perl doesn't use the return + return 0; /* wrong, but perl doesn't use the return * value */ } @@ -4324,7 +4647,7 @@ int vfprintf(FILE *fd, char *pat, char *args) { _doprnt(pat, args, fd); - return 0; /* wrong, but perl doesn't use the return + return 0; /* wrong, but perl doesn't use the return * value */ } @@ -4364,3 +4687,6 @@ PerlIO_sprintf(char *s, int n, const char *fmt, ...) + + +