X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perlio.c;h=304107bcd3f728291020d39b13ec90366a8161dd;hb=1fb76a4637fd4800180784d4acf2abcdd008365e;hp=eb32a045e9977f6283a57986879bfb5d817ef83c;hpb=89aec743e18bc6ebc8fe067d7c780485893d0a8c;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perlio.c b/perlio.c index eb32a04..304107b 100644 --- a/perlio.c +++ b/perlio.c @@ -1,13 +1,18 @@ /* - * perlio.c Copyright (c) 1996-2001, Nick Ing-Simmons You may distribute + * perlio.c Copyright (c) 1996-2002, Nick Ing-Simmons You may distribute * under the terms of either the GNU General Public License or the - * Artistic License, as specified in the README file. + * Artistic License, as specified in the README file. */ /* - * If we have ActivePerl-like PERL_IMPLICIT_SYS then we need a dTHX to get + * Hour after hour for nearly three weary days he had jogged up and down, + * over passes, and through long dales, and across many streams. + */ + +/* + * If we have ActivePerl-like PERL_IMPLICIT_SYS then we need a dTHX to get * at the dispatch tables, even when we do not need it for other reasons. - * Invent a dSYS macro to abstract this out + * Invent a dSYS macro to abstract this out */ #ifdef PERL_IMPLICIT_SYS #define dSYS dTHX @@ -25,7 +30,7 @@ #define PERLIO_NOT_STDIO 0 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO) /* - * #define PerlIO FILE + * #define PerlIO FILE */ #endif /* @@ -38,18 +43,18 @@ #define PERL_IN_PERLIO_C #include "perl.h" -#include "XSUB.h" +#ifdef PERL_IMPLICIT_CONTEXT +#undef dSYS +#define dSYS dTHX +#endif -#undef PerlMemShared_calloc -#define PerlMemShared_calloc(x,y) calloc(x,y) -#undef PerlMemShared_free -#define PerlMemShared_free(x) free(x) +#include "XSUB.h" int perlsio_binmode(FILE *fp, int iotype, int mode) { /* - * This used to be contents of do_binmode in doio.c + * This used to be contents of do_binmode in doio.c */ #ifdef DOSISH # if defined(atarist) || defined(__MINT__) @@ -70,11 +75,11 @@ perlsio_binmode(FILE *fp, int iotype, int mode) #endif # if defined(WIN32) && defined(__BORLANDC__) /* - * The translation mode of the stream is maintained independent of + * The translation mode of the stream is maintained independent of * the translation mode of the fd in the Borland RTL (heavy - * digging through their runtime sources reveal). User has to set + * digging through their runtime sources reveal). User has to set * the mode explicitly for the stream (though they don't document - * this anywhere). GSAR 97-5-24 + * this anywhere). GSAR 97-5-24 */ fseek(fp, 0L, 0); if (mode & O_BINARY) @@ -89,6 +94,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode) # endif #else # if defined(USEMYBINMODE) + dTHX; if (my_binmode(fp, iotype, mode) != FALSE) return 1; else @@ -99,16 +105,69 @@ perlsio_binmode(FILE *fp, int iotype, int mode) #endif } +#ifndef O_ACCMODE +#define O_ACCMODE 3 /* Assume traditional implementation */ +#endif + +int +PerlIO_intmode2str(int rawmode, char *mode, int *writing) +{ + int result = rawmode & O_ACCMODE; + int ix = 0; + int ptype; + switch (result) { + case O_RDONLY: + ptype = IoTYPE_RDONLY; + break; + case O_WRONLY: + ptype = IoTYPE_WRONLY; + break; + case O_RDWR: + default: + ptype = IoTYPE_RDWR; + break; + } + if (writing) + *writing = (result != O_RDONLY); + + if (result == O_RDONLY) { + mode[ix++] = 'r'; + } +#ifdef O_APPEND + else if (rawmode & O_APPEND) { + mode[ix++] = 'a'; + if (result != O_WRONLY) + mode[ix++] = '+'; + } +#endif + else { + if (result == O_WRONLY) + mode[ix++] = 'w'; + else { + mode[ix++] = 'r'; + mode[ix++] = '+'; + } + } + if (rawmode & O_BINARY) + mode[ix++] = 'b'; + mode[ix] = '\0'; + return ptype; +} + #ifndef PERLIO_LAYERS 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); /* - * NOTREACHED + * NOTREACHED */ return -1; } @@ -128,15 +187,54 @@ PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names) #endif } +PerlIO * +PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) +{ +#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) { + char mode[8]; + int omode = fcntl(fd, F_GETFL); +#ifdef DJGPP + omode = djgpp_get_stream_mode(f); +#endif + PerlIO_intmode2str(omode,mode,NULL); + /* the r+ is a hack */ + return PerlIO_fdopen(fd, mode); + } + return NULL; + } + else { + SETERRNO(EBADF, SS$_IVCHAN); + } +#endif + return NULL; +#endif +#endif +} + + /* - * De-mux PerlIO_openn() into fdopen, freopen and fopen type entries + * De-mux PerlIO_openn() into fdopen, freopen and fopen type entries */ PerlIO * PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, int imode, int perm, PerlIO *old, int narg, SV **args) { - if (narg == 1) { + if (narg) { + if (narg > 1) { + Perl_croak(aTHX_ "More than one argument to open"); + } if (*args == &PL_sv_undef) return PerlIO_tmpfile(); else { @@ -186,13 +284,13 @@ Perl_boot_core_PerlIO(pTHX) #ifdef PERLIO_IS_STDIO void -PerlIO_init(void) +PerlIO_init(pTHX) { /* * Does nothing (yet) except force this file to be included in perl - * binary. That allows this file to force inclusion of other functions + * binary. That allows this file to force inclusion of other functions * that may be required by loadable extensions e.g. for - * FileHandle::tmpfile + * FileHandle::tmpfile */ } @@ -203,7 +301,7 @@ PerlIO_tmpfile(void) return tmpfile(); } -#else /* PERLIO_IS_STDIO */ +#else /* PERLIO_IS_STDIO */ #ifdef USE_SFIO @@ -212,7 +310,7 @@ PerlIO_tmpfile(void) /* * This section is just to make sure these functions get pulled in from - * libsfio.a + * libsfio.a */ #undef PerlIO_tmpfile @@ -223,18 +321,18 @@ PerlIO_tmpfile(void) } void -PerlIO_init(void) +PerlIO_init(pTHX) { /* * Force this file to be included in perl binary. Which allows this * file to force inclusion of other functions that may be required by - * loadable extensions e.g. for FileHandle::tmpfile + * loadable extensions e.g. for FileHandle::tmpfile */ /* - * Hack sfio does its own 'autoflush' on stdout in common cases. Flush + * Hack sfio does its own 'autoflush' on stdout in common cases. Flush * results in a lot of lseek()s to regular files and lot of small - * writes to pipes. + * writes to pipes. */ sfset(sfstdout, SF_SHARE, 0); } @@ -261,17 +359,17 @@ PerlIO_findFILE(PerlIO *pio) } -#else /* USE_SFIO */ +#else /* USE_SFIO */ /*======================================================================================*/ /* - * Implement all the PerlIO interface ourselves. + * Implement all the PerlIO interface ourselves. */ #include "perliol.h" /* * We _MUST_ have if we are using lseek() and may have large - * files + * files */ #ifdef I_UNISTD #include @@ -300,6 +398,19 @@ PerlIO_debug(const char *fmt, ...) } if (dbg > 0) { dTHX; +#ifdef USE_ITHREADS + /* Use fixed buffer as sv_catpvf etc. needs SVs */ + char buffer[1024]; + char *s; + STRLEN len; + s = CopFILE(PL_curcop); + if (!s) + s = "(none)"; + sprintf(buffer, "%s:%" IVdf " ", s, (IV) CopLINE(PL_curcop)); + len = strlen(buffer); + vsprintf(buffer+len, fmt, ap); + PerlLIO_write(dbg, buffer, strlen(buffer)); +#else SV *sv = newSVpvn("", 0); char *s; STRLEN len; @@ -313,6 +424,7 @@ PerlIO_debug(const char *fmt, ...) s = SvPV(sv, len); PerlLIO_write(dbg, s, len); SvREFCNT_dec(sv); +#endif } va_end(ap); } @@ -320,26 +432,23 @@ PerlIO_debug(const char *fmt, ...) /*--------------------------------------------------------------------------------------*/ /* - * Inner level routines + * Inner level routines */ /* - * Table of pointers to the PerlIO structs (malloc'ed) + * Table of pointers to the PerlIO structs (malloc'ed) */ -PerlIO *_perlio = NULL; #define PERLIO_TABLE_SIZE 64 - - PerlIO * PerlIO_allocate(pTHX) { /* - * Find a free slot in the table, allocating new table as necessary + * Find a free slot in the table, allocating new table as necessary */ PerlIO **last; PerlIO *f; - last = &_perlio; + last = &PL_perlio; while ((f = *last)) { int i; last = (PerlIO **) (f); @@ -349,7 +458,7 @@ PerlIO_allocate(pTHX) } } } - f = PerlMemShared_calloc(PERLIO_TABLE_SIZE, sizeof(PerlIO)); + Newz('I',f,PERLIO_TABLE_SIZE,PerlIO); if (!f) { return NULL; } @@ -357,6 +466,23 @@ PerlIO_allocate(pTHX) return f + 1; } +#undef PerlIO_fdupopen +PerlIO * +PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) +{ + if (PerlIOValid(f)) { + 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); + return new; + } + else { + SETERRNO(EBADF, SS$_IVCHAN); + return NULL; + } +} + void PerlIO_cleantable(pTHX_ PerlIO **tablep) { @@ -370,16 +496,14 @@ PerlIO_cleantable(pTHX_ PerlIO **tablep) PerlIO_close(f); } } - PerlMemShared_free(table); + Safefree(table); *tablep = NULL; } } -PerlIO_list_t *PerlIO_known_layers; -PerlIO_list_t *PerlIO_def_layerlist; PerlIO_list_t * -PerlIO_list_alloc(void) +PerlIO_list_alloc(pTHX) { PerlIO_list_t *list; Newz('L', list, 1, PerlIO_list_t); @@ -388,12 +512,11 @@ PerlIO_list_alloc(void) } void -PerlIO_list_free(PerlIO_list_t *list) +PerlIO_list_free(pTHX_ PerlIO_list_t *list) { if (list) { if (--list->refcnt == 0) { if (list->array) { - dTHX; IV i; for (i = 0; i < list->cur; i++) { if (list->array[i].arg) @@ -407,9 +530,8 @@ PerlIO_list_free(PerlIO_list_t *list) } void -PerlIO_list_push(PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg) +PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg) { - dTHX; PerlIO_pair_t *p; if (list->cur >= list->len) { list->len += 8; @@ -425,28 +547,55 @@ PerlIO_list_push(PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg) } } - -void -PerlIO_cleanup_layers(pTHX_ void *data) +PerlIO_list_t * +PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param) { -#if 0 - PerlIO_known_layers = Nullhv; - PerlIO_def_layerlist = Nullav; -#endif + PerlIO_list_t *list = (PerlIO_list_t *) NULL; + if (proto) { + int i; + list = PerlIO_list_alloc(aTHX); + for (i=0; i < proto->cur; i++) { + SV *arg = Nullsv; + if (proto->array[i].arg) + arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param); + PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg); + } + } + return list; } void -PerlIO_cleanup() +PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param) { - dTHX; - PerlIO_cleantable(aTHX_ & _perlio); +#ifdef USE_ITHREADS + PerlIO **table = &proto->Iperlio; + PerlIO *f; + PL_perlio = NULL; + PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param); + PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param); + PerlIO_allocate(aTHX); /* root slot is never used */ + PerlIO_debug("Clone %p from %p\n",aTHX,proto); + while ((f = *table)) { + int i; + table = (PerlIO **) (f++); + for (i = 1; i < PERLIO_TABLE_SIZE; i++) { + if (*f) { + (void) fp_dup(f, 0, param); + } + f++; + } + } +#endif } void PerlIO_destruct(pTHX) { - PerlIO **table = &_perlio; + PerlIO **table = &PL_perlio; PerlIO *f; +#ifdef USE_ITHREADS + PerlIO_debug("Destruct %p\n",aTHX); +#endif while ((f = *table)) { int i; table = (PerlIO **) (f++); @@ -473,24 +622,24 @@ PerlIO_pop(pTHX_ PerlIO *f) { PerlIOl *l = *f; if (l) { - PerlIO_debug("PerlIO_pop f=%p %s\n", f, l->tab->name); + PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, l->tab->name); if (l->tab->Popped) { /* * If popped returns non-zero do not free its layer structure * it has either done so itself, or it is shared and still in - * use + * use */ - if ((*l->tab->Popped) (f) != 0) + if ((*l->tab->Popped) (aTHX_ f) != 0) return; } *f = l->next;; - PerlMemShared_free(l); + Safefree(l); } } /*--------------------------------------------------------------------------------------*/ /* - * XS Interface for perl code + * XS Interface for perl code */ PerlIO_funcs * @@ -499,20 +648,20 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load) IV i; if ((SSize_t) len <= 0) len = strlen(name); - for (i = 0; i < PerlIO_known_layers->cur; i++) { - PerlIO_funcs *f = PerlIO_known_layers->array[i].funcs; + for (i = 0; i < PL_known_layers->cur; i++) { + PerlIO_funcs *f = PL_known_layers->array[i].funcs; if (memEQ(f->name, name, len)) { - PerlIO_debug("%.*s => %p\n", (int) len, name, f); + PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f); return f; } } - if (load && PL_subname && PerlIO_def_layerlist - && PerlIO_def_layerlist->cur >= 2) { + if (load && PL_subname && PL_def_layerlist + && PL_def_layerlist->cur >= 2) { SV *pkgsv = newSVpvn("PerlIO", 6); SV *layer = newSVpvn(name, len); ENTER; /* - * The two SVs are magically freed by load_module + * The two SVs are magically freed by load_module */ Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv); LEAVE; @@ -565,7 +714,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 }; @@ -600,7 +749,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) @@ -630,10 +779,10 @@ XS(XS_PerlIO__Layer__find) void PerlIO_define_layer(pTHX_ PerlIO_funcs *tab) { - if (!PerlIO_known_layers) - PerlIO_known_layers = PerlIO_list_alloc(); - PerlIO_list_push(PerlIO_known_layers, tab, Nullsv); - PerlIO_debug("define %s %p\n", tab->name, tab); + if (!PL_known_layers) + PL_known_layers = PerlIO_list_alloc(aTHX); + PerlIO_list_push(aTHX_ PL_known_layers, tab, Nullsv); + PerlIO_debug("define %s %p\n", tab->name, (void*)tab); } int @@ -653,12 +802,14 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) /* * Message is consistent with how attribute lists are * passed. Even though this means "foo : : bar" is - * seen as an invalid separator character. + * seen as an invalid separator character. */ char q = ((*s == '\'') ? '"' : '\''); - Perl_warn(aTHX_ - "perlio: invalid separator character %c%c%c in layer specification list", - q, *s, q); + if (ckWARN(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 { @@ -681,39 +832,42 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) /* * It's a nul terminated string, not allowed * to \ the terminating null. Anything other - * character is passed over. + * character is passed over. */ if (*e++) { break; } /* - * Drop through + * Drop through */ case '\0': e--; - Perl_warn(aTHX_ + if (ckWARN(WARN_LAYER)) + Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: argument list not closed for layer \"%.*s\"", (int) (e - s), s); return -1; default: /* - * boring. + * boring. */ break; } } } if (e > s) { + bool warn_layer = ckWARN(WARN_LAYER); PerlIO_funcs *layer = PerlIO_find_layer(aTHX_ s, llen, 1); if (layer) { - PerlIO_list_push(av, layer, + PerlIO_list_push(aTHX_ av, layer, (as) ? newSVpvn(as, alen) : &PL_sv_undef); } else { - Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"", + if (warn_layer) + Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: unknown layer \"%.*s\"", (int) llen, s); return -1; } @@ -729,16 +883,14 @@ void PerlIO_default_buffer(pTHX_ PerlIO_list_t *av) { PerlIO_funcs *tab = &PerlIO_perlio; - if (O_BINARY != O_TEXT) { - tab = &PerlIO_crlf; - } - else { - if (PerlIO_stdio.Set_ptrcnt) { - tab = &PerlIO_stdio; - } - } +#ifdef PERLIO_USING_CRLF + tab = &PerlIO_crlf; +#else + if (PerlIO_stdio.Set_ptrcnt) + tab = &PerlIO_stdio; +#endif PerlIO_debug("Pushing %s\n", tab->name); - PerlIO_list_push(av, PerlIO_find_layer(aTHX_ tab->name, 0, 0), + PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0), &PL_sv_undef); } @@ -764,10 +916,10 @@ PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def) PerlIO_list_t * PerlIO_default_layers(pTHX) { - if (!PerlIO_def_layerlist) { + if (!PL_def_layerlist) { const char *s = (PL_tainting) ? Nullch : PerlEnv_getenv("PERLIO"); PerlIO_funcs *osLayer = &PerlIO_unix; - PerlIO_def_layerlist = PerlIO_list_alloc(); + PL_def_layerlist = PerlIO_list_alloc(aTHX); PerlIO_define_layer(aTHX_ & PerlIO_unix); #if defined(WIN32) && !defined(UNDER_CE) PerlIO_define_layer(aTHX_ & PerlIO_win32); @@ -784,20 +936,20 @@ PerlIO_default_layers(pTHX) #endif PerlIO_define_layer(aTHX_ & PerlIO_utf8); PerlIO_define_layer(aTHX_ & PerlIO_byte); - PerlIO_list_push(PerlIO_def_layerlist, + PerlIO_list_push(aTHX_ PL_def_layerlist, PerlIO_find_layer(aTHX_ osLayer->name, 0, 0), &PL_sv_undef); if (s) { - PerlIO_parse_layers(aTHX_ PerlIO_def_layerlist, s); + PerlIO_parse_layers(aTHX_ PL_def_layerlist, s); } else { - PerlIO_default_buffer(aTHX_ PerlIO_def_layerlist); + PerlIO_default_buffer(aTHX_ PL_def_layerlist); } } - if (PerlIO_def_layerlist->cur < 2) { - PerlIO_default_buffer(aTHX_ PerlIO_def_layerlist); + if (PL_def_layerlist->cur < 2) { + PerlIO_default_buffer(aTHX_ PL_def_layerlist); } - return PerlIO_def_layerlist; + return PL_def_layerlist; } void @@ -825,7 +977,7 @@ PerlIO_default_layer(pTHX_ I32 n) void PerlIO_stdstreams(pTHX) { - if (!_perlio) { + if (!PL_perlio) { PerlIO_allocate(aTHX); PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT); PerlIO_fdopen(1, "Iw" PERLIO_STDTEXT); @@ -837,15 +989,15 @@ PerlIO * PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg) { PerlIOl *l = NULL; - l = PerlMemShared_calloc(tab->size, sizeof(char)); - if (l) { + 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", f, tab->name, - (mode) ? mode : "(Null)", arg); - if ((*l->tab->Pushed) (f, mode, arg) != 0) { + 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); return NULL; } @@ -854,9 +1006,8 @@ PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg) } IV -PerlIOPop_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { - dTHX; PerlIO_pop(aTHX_ f); if (*f) { PerlIO_flush(f); @@ -867,17 +1018,16 @@ PerlIOPop_pushed(PerlIO *f, const char *mode, SV *arg) } IV -PerlIORaw_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { /* - * Remove the dummy layer + * Remove the dummy layer */ - dTHX; PerlIO_pop(aTHX_ f); /* - * Pop back to bottom layer + * Pop back to bottom layer */ - if (f && *f) { + if (PerlIOValid(f)) { PerlIO_flush(f); while (!(PerlIOBase(f)->tab->kind & PERLIO_K_RAW)) { if (*PerlIONext(f)) { @@ -885,7 +1035,7 @@ PerlIORaw_pushed(PerlIO *f, const char *mode, SV *arg) } else { /* - * Nothing bellow - push unix on top then remove it + * Nothing bellow - push unix on top then remove it */ if (PerlIO_push(aTHX_ f, PerlIO_default_btm(), mode, arg)) { PerlIO_pop(aTHX_ PerlIONext(f)); @@ -893,7 +1043,7 @@ PerlIORaw_pushed(PerlIO *f, const char *mode, SV *arg) break; } } - PerlIO_debug(":raw f=%p :%s\n", f, PerlIOBase(f)->tab->name); + PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name); return 0; } return -1; @@ -901,9 +1051,8 @@ PerlIORaw_pushed(PerlIO *f, const char *mode, SV *arg) 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); @@ -922,13 +1071,13 @@ int PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) { int code = 0; - if (names) { - PerlIO_list_t *layers = PerlIO_list_alloc(); + if (f && 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(layers); + PerlIO_list_free(aTHX_ layers); } return code; } @@ -936,70 +1085,107 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) /*--------------------------------------------------------------------------------------*/ /* - * Given the abstraction above the public API functions + * Given the abstraction above the public API functions */ int PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) { PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n", - f, PerlIOBase(f)->tab->name, iotype, mode, + (void*)f, PerlIOBase(f)->tab->name, iotype, mode, (names) ? names : "(Null)"); - PerlIO_flush(f); - if (!names && (O_TEXT != O_BINARY && (mode & O_BINARY))) { - PerlIO *top = f; - while (*top) { - if (PerlIOBase(top)->tab == &PerlIO_crlf) { - PerlIOBase(top)->flags &= ~PERLIO_F_CRLF; - break; + if (names) { + /* Do not flush etc. if (e.g.) switching encodings. + if a pushed layer knows it needs to flush lower layers + (for example :unix which is never going to call them) + it can do the flush when it is pushed. + */ + 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 + */ +#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 */ + while (*f) { + /* Perhaps we should turn on bottom-most aware layer + e.g. Ilya's idea that UNIX TTY could serve + */ + if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) { + if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) { + /* Not in text mode - flush any pending stuff and flip it */ + PerlIO_flush(f); + PerlIOBase(f)->flags |= PERLIO_F_CRLF; + } + /* Only need to turn it on in one layer so we are done */ + return TRUE; + } + f = PerlIONext(f); + } + /* Not finding a CRLF aware layer presumably means we are binary + which is not what was requested - so we failed + We _could_ push :crlf layer but so could caller + */ + 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. + */ + 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; + } } - top = PerlIONext(top); - PerlIO_flush(top); + f = PerlIONext(f); } + return TRUE; } - return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE; } -#undef PerlIO__close int -PerlIO__close(PerlIO *f) +PerlIO__close(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Close) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Close) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_fdupopen -PerlIO * -PerlIO_fdupopen(pTHX_ PerlIO *f) -{ - if (f && *f) { - char buf[8]; - int fd = PerlLIO_dup(PerlIO_fileno(f)); - PerlIO *new = PerlIO_fdopen(fd, PerlIO_modestr(f, buf)); - if (new) { - Off_t posn = PerlIO_tell(f); - PerlIO_seek(new, posn, SEEK_SET); - } - return new; - } - else { - SETERRNO(EBADF, SS$_IVCHAN); - return NULL; - } -} - -#undef PerlIO_close int -PerlIO_close(PerlIO *f) +Perl_PerlIO_close(pTHX_ PerlIO *f) { - dTHX; int code = -1; - if (f && *f) { - code = (*PerlIOBase(f)->tab->Close) (f); + if (PerlIOValid(f)) { + code = (*PerlIOBase(f)->tab->Close) (aTHX_ f); while (*f) { PerlIO_pop(aTHX_ f); } @@ -1007,12 +1193,11 @@ PerlIO_close(PerlIO *f) return code; } -#undef PerlIO_fileno int -PerlIO_fileno(PerlIO *f) +Perl_PerlIO_fileno(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Fileno) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Fileno) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; @@ -1024,7 +1209,7 @@ PerlIO_context_layers(pTHX_ const char *mode) { const char *type = NULL; /* - * Need to supply default layer info from open.pm + * Need to supply default layer info from open.pm */ if (PL_curcop) { SV *layers = PL_curcop->cop_io; @@ -1033,10 +1218,10 @@ PerlIO_context_layers(pTHX_ const char *mode) type = SvPV(layers, len); if (type && mode[0] != 'r') { /* - * Skip to write part + * Skip to write part */ const char *s = strchr(type, 0); - if (s && (s - type) < len) { + if (s && (STRLEN)(s - type) < len) { type = s + 1; } } @@ -1049,13 +1234,13 @@ static PerlIO_funcs * PerlIO_layer_from_ref(pTHX_ SV *sv) { /* - * For any scalar type load the handler which is bundled with perl + * 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); /* - * For other types allow if layer is known but don't try and load it + * For other types allow if layer is known but don't try and load it */ switch (SvTYPE(sv)) { case SVt_PVAV: @@ -1076,25 +1261,25 @@ PerlIO_resolve_layers(pTHX_ const char *layers, { PerlIO_list_t *def = PerlIO_default_layers(aTHX); int incdef = 1; - if (!_perlio) + if (!PL_perlio) PerlIO_stdstreams(aTHX); if (narg) { SV *arg = *args; /* - * If it is a reference but not an object see if we have a handler - * for it + * If it is a reference but not an object see if we have a handler + * for it */ if (SvROK(arg) && !sv_isobject(arg)) { PerlIO_funcs *handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg)); if (handler) { - def = PerlIO_list_alloc(); - PerlIO_list_push(def, handler, &PL_sv_undef); + def = PerlIO_list_alloc(aTHX); + PerlIO_list_push(aTHX_ def, handler, &PL_sv_undef); 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. + * resulting string. */ } } @@ -1104,17 +1289,22 @@ PerlIO_resolve_layers(pTHX_ const char *layers, PerlIO_list_t *av; if (incdef) { IV i = def->cur; - av = PerlIO_list_alloc(); + av = PerlIO_list_alloc(aTHX); for (i = 0; i < def->cur; i++) { - PerlIO_list_push(av, def->array[i].funcs, + PerlIO_list_push(aTHX_ av, def->array[i].funcs, def->array[i].arg); } } 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) @@ -1139,26 +1329,29 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, PerlIO_list_t *layera = NULL; IV n; PerlIO_funcs *tab = NULL; - if (f && *f) { + if (PerlIOValid(f)) { /* - * This is "reopen" - it is not tested as perl does not use it - * yet + * This is "reopen" - it is not tested as perl does not use it + * yet */ PerlIOl *l = *f; - layera = PerlIO_list_alloc(); + layera = PerlIO_list_alloc(aTHX); while (l) { - SV *arg = - (l->tab->Getarg) ? (*l->tab-> - Getarg) (&l) : &PL_sv_undef; - PerlIO_list_push(layera, l->tab, arg); + SV *arg = (l->tab->Getarg) + ? (*l->tab->Getarg) (aTHX_ &l, NULL, 0) + : &PL_sv_undef; + PerlIO_list_push(aTHX_ layera, l->tab, arg); l = *PerlIONext(&l); } } else { layera = PerlIO_resolve_layers(aTHX_ layers, mode, narg, args); + if (!layera) { + return NULL; + } } /* - * Start at "top" of layer stack + * Start at "top" of layer stack */ n = layera->cur - 1; while (n >= 0) { @@ -1171,136 +1364,108 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, } if (tab) { /* - * Found that layer 'n' can do opens - call it + * Found that layer 'n' can do opens - call it */ + if (narg > 1 && !(tab->kind & PERLIO_K_MULTIARG)) { + Perl_croak(aTHX_ "More than one argument to open(,':%s')",tab->name); + } PerlIO_debug("openn(%s,'%s','%s',%d,%x,%o,%p,%d,%p)\n", - tab->name, layers, mode, fd, imode, perm, f, narg, - args); + tab->name, layers, mode, fd, imode, perm, + (void*)f, narg, (void*)args); f = (*tab->Open) (aTHX_ tab, layera, n, mode, fd, imode, perm, f, narg, args); if (f) { if (n + 1 < layera->cur) { /* * More layers above the one that we used to open - - * apply them now + * 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; } } } } - PerlIO_list_free(layera); + PerlIO_list_free(aTHX_ layera); } return f; } -#undef PerlIO_fdopen -PerlIO * -PerlIO_fdopen(int fd, const char *mode) -{ - dTHX; - return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL); -} - -#undef PerlIO_open -PerlIO * -PerlIO_open(const char *path, const char *mode) -{ - dTHX; - SV *name = sv_2mortal(newSVpvn(path, strlen(path))); - return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name); -} - -#undef PerlIO_reopen -PerlIO * -PerlIO_reopen(const char *path, const char *mode, PerlIO *f) -{ - dTHX; - SV *name = sv_2mortal(newSVpvn(path, strlen(path))); - return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name); -} - -#undef PerlIO_read SSize_t -PerlIO_read(PerlIO *f, void *vbuf, Size_t count) +Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { - if (f && *f) - return (*PerlIOBase(f)->tab->Read) (f, vbuf, count); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Read) (aTHX_ f, vbuf, count); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_unread SSize_t -PerlIO_unread(PerlIO *f, const void *vbuf, Size_t count) +Perl_PerlIO_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - if (f && *f) - return (*PerlIOBase(f)->tab->Unread) (f, vbuf, count); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Unread) (aTHX_ f, vbuf, count); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_write SSize_t -PerlIO_write(PerlIO *f, const void *vbuf, Size_t count) +Perl_PerlIO_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - if (f && *f) - return (*PerlIOBase(f)->tab->Write) (f, vbuf, count); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Write) (aTHX_ f, vbuf, count); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_seek int -PerlIO_seek(PerlIO *f, Off_t offset, int whence) +Perl_PerlIO_seek(pTHX_ PerlIO *f, Off_t offset, int whence) { - if (f && *f) - return (*PerlIOBase(f)->tab->Seek) (f, offset, whence); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Seek) (aTHX_ f, offset, whence); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_tell Off_t -PerlIO_tell(PerlIO *f) +Perl_PerlIO_tell(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Tell) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Tell) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_flush int -PerlIO_flush(PerlIO *f) +Perl_PerlIO_flush(pTHX_ PerlIO *f) { if (f) { if (*f) { PerlIO_funcs *tab = PerlIOBase(f)->tab; if (tab && tab->Flush) { - return (*tab->Flush) (f); + return (*tab->Flush) (aTHX_ f); } else { - PerlIO_debug("Cannot flush f=%p :%s\n", f, tab->name); + PerlIO_debug("Cannot flush f=%p :%s\n", (void*)f, tab->name); SETERRNO(EBADF, SS$_IVCHAN); return -1; } } else { - PerlIO_debug("Cannot flush f=%p\n", f); + PerlIO_debug("Cannot flush f=%p\n", (void*)f); SETERRNO(EBADF, SS$_IVCHAN); return -1; } @@ -1311,9 +1476,9 @@ PerlIO_flush(PerlIO *f) * errorneous input? Maybe some magical value (PerlIO* * PERLIO_FLUSH_ALL = (PerlIO*)-1;)? Yes, stdio does similar * things on fflush(NULL), but should we be bound by their design - * decisions? --jhi + * decisions? --jhi */ - PerlIO **table = &_perlio; + PerlIO **table = &PL_perlio; int code = 0; while ((f = *table)) { int i; @@ -1329,9 +1494,9 @@ PerlIO_flush(PerlIO *f) } void -PerlIOBase_flush_linebuf() +PerlIOBase_flush_linebuf(pTHX) { - PerlIO **table = &_perlio; + PerlIO **table = &PL_perlio; PerlIO *f; while ((f = *table)) { int i; @@ -1347,23 +1512,21 @@ PerlIOBase_flush_linebuf() } } -#undef PerlIO_fill int -PerlIO_fill(PerlIO *f) +Perl_PerlIO_fill(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Fill) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Fill) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_isutf8 int PerlIO_isutf8(PerlIO *f) { - if (f && *f) + if (PerlIOValid(f)) return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0; else { SETERRNO(EBADF, SS$_IVCHAN); @@ -1371,160 +1534,154 @@ PerlIO_isutf8(PerlIO *f) } } -#undef PerlIO_eof int -PerlIO_eof(PerlIO *f) +Perl_PerlIO_eof(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Eof) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Eof) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_error int -PerlIO_error(PerlIO *f) +Perl_PerlIO_error(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Error) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Error) (aTHX_ f); else { SETERRNO(EBADF, SS$_IVCHAN); return -1; } } -#undef PerlIO_clearerr void -PerlIO_clearerr(PerlIO *f) +Perl_PerlIO_clearerr(pTHX_ PerlIO *f) { - if (f && *f) - (*PerlIOBase(f)->tab->Clearerr) (f); + if (PerlIOValid(f)) + (*PerlIOBase(f)->tab->Clearerr) (aTHX_ f); else SETERRNO(EBADF, SS$_IVCHAN); } -#undef PerlIO_setlinebuf void -PerlIO_setlinebuf(PerlIO *f) +Perl_PerlIO_setlinebuf(pTHX_ PerlIO *f) { - if (f && *f) - (*PerlIOBase(f)->tab->Setlinebuf) (f); + if (PerlIOValid(f)) + (*PerlIOBase(f)->tab->Setlinebuf) (aTHX_ f); else SETERRNO(EBADF, SS$_IVCHAN); } -#undef PerlIO_has_base int PerlIO_has_base(PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { return (PerlIOBase(f)->tab->Get_base != NULL); } return 0; } -#undef PerlIO_fast_gets int PerlIO_fast_gets(PerlIO *f) { - if (f && *f && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) { + if (PerlIOValid(f) && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) { PerlIO_funcs *tab = PerlIOBase(f)->tab; return (tab->Set_ptrcnt != NULL); } return 0; } -#undef PerlIO_has_cntptr int PerlIO_has_cntptr(PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { PerlIO_funcs *tab = PerlIOBase(f)->tab; return (tab->Get_ptr != NULL && tab->Get_cnt != NULL); } return 0; } -#undef PerlIO_canset_cnt int PerlIO_canset_cnt(PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { PerlIOl *l = PerlIOBase(f); return (l->tab->Set_ptrcnt != NULL); } return 0; } -#undef PerlIO_get_base STDCHAR * -PerlIO_get_base(PerlIO *f) +Perl_PerlIO_get_base(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Get_base) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Get_base) (aTHX_ f); return NULL; } -#undef PerlIO_get_bufsiz int -PerlIO_get_bufsiz(PerlIO *f) +Perl_PerlIO_get_bufsiz(pTHX_ PerlIO *f) { - if (f && *f) - return (*PerlIOBase(f)->tab->Get_bufsiz) (f); + if (PerlIOValid(f)) + return (*PerlIOBase(f)->tab->Get_bufsiz) (aTHX_ f); return 0; } -#undef PerlIO_get_ptr STDCHAR * -PerlIO_get_ptr(PerlIO *f) +Perl_PerlIO_get_ptr(pTHX_ PerlIO *f) { - PerlIO_funcs *tab = PerlIOBase(f)->tab; - if (tab->Get_ptr == NULL) - return NULL; - return (*tab->Get_ptr) (f); + if (PerlIOValid(f)) { + PerlIO_funcs *tab = PerlIOBase(f)->tab; + if (tab->Get_ptr == NULL) + return NULL; + return (*tab->Get_ptr) (aTHX_ f); + } + return NULL; } -#undef PerlIO_get_cnt int -PerlIO_get_cnt(PerlIO *f) +Perl_PerlIO_get_cnt(pTHX_ PerlIO *f) { - PerlIO_funcs *tab = PerlIOBase(f)->tab; - if (tab->Get_cnt == NULL) - return 0; - return (*tab->Get_cnt) (f); + if (PerlIOValid(f)) { + PerlIO_funcs *tab = PerlIOBase(f)->tab; + if (tab->Get_cnt == NULL) + return 0; + return (*tab->Get_cnt) (aTHX_ f); + } + return 0; } -#undef PerlIO_set_cnt void -PerlIO_set_cnt(PerlIO *f, int cnt) +Perl_PerlIO_set_cnt(pTHX_ PerlIO *f, int cnt) { - (*PerlIOBase(f)->tab->Set_ptrcnt) (f, NULL, cnt); + if (PerlIOValid(f)) { + (*PerlIOBase(f)->tab->Set_ptrcnt) (aTHX_ f, NULL, cnt); + } } -#undef PerlIO_set_ptrcnt void -PerlIO_set_ptrcnt(PerlIO *f, STDCHAR * ptr, int cnt) +Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt) { - PerlIO_funcs *tab = PerlIOBase(f)->tab; - if (tab->Set_ptrcnt == NULL) { - dTHX; - Perl_croak(aTHX_ "PerlIO buffer snooping abuse"); + if (PerlIOValid(f)) { + PerlIO_funcs *tab = PerlIOBase(f)->tab; + if (tab->Set_ptrcnt == NULL) { + Perl_croak(aTHX_ "PerlIO buffer snooping abuse"); + } + (*PerlIOBase(f)->tab->Set_ptrcnt) (aTHX_ f, ptr, cnt); } - (*PerlIOBase(f)->tab->Set_ptrcnt) (f, ptr, cnt); } /*--------------------------------------------------------------------------------------*/ /* - * utf8 and raw dummy layers + * utf8 and raw dummy layers */ IV -PerlIOUtf8_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { - if (PerlIONext(f)) { - dTHX; + if (*PerlIONext(f)) { PerlIO_funcs *tab = PerlIOBase(f)->tab; PerlIO_pop(aTHX_ f); if (tab->kind & PERLIO_K_UTF8) @@ -1539,7 +1696,7 @@ PerlIOUtf8_pushed(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, @@ -1551,17 +1708,17 @@ 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 = { @@ -1579,17 +1736,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 * @@ -1617,28 +1774,28 @@ 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 */ }; /*--------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------*/ /* - * "Methods" of the "base class" + * "Methods" of the "base class" */ IV -PerlIOBase_fileno(PerlIO *f) +PerlIOBase_fileno(pTHX_ PerlIO *f) { - return PerlIO_fileno(PerlIONext(f)); + return PerlIOValid(f) ? PerlIO_fileno(PerlIONext(f)) : -1; } char * @@ -1663,7 +1820,7 @@ PerlIO_modestr(PerlIO *f, char *buf) *s++ = '+'; } } -#if O_TEXT != O_BINARY +#ifdef PERLIO_USING_CRLF if (!(flags & PERLIO_F_CRLF)) *s++ = 'b'; #endif @@ -1672,7 +1829,7 @@ PerlIO_modestr(PerlIO *f, char *buf) } IV -PerlIOBase_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { PerlIOl *l = PerlIOBase(f); #if 0 @@ -1734,28 +1891,27 @@ PerlIOBase_pushed(PerlIO *f, const char *mode, SV *arg) } IV -PerlIOBase_popped(PerlIO *f) +PerlIOBase_popped(pTHX_ PerlIO *f) { return 0; } SSize_t -PerlIOBase_unread(PerlIO *f, const void *vbuf, Size_t count) +PerlIOBase_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - dTHX; /* - * Save the position as current head considers it + * Save the position as current head considers it */ Off_t old = PerlIO_tell(f); SSize_t done; PerlIO_push(aTHX_ f, &PerlIO_pending, "r", Nullsv); PerlIOSelf(f, PerlIOBuf)->posn = old; - done = PerlIOBuf_unread(f, vbuf, count); + done = PerlIOBuf_unread(aTHX_ f, vbuf, count); return done; } SSize_t -PerlIOBase_read(PerlIO *f, void *vbuf, Size_t count) +PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { STDCHAR *buf = (STDCHAR *) vbuf; if (f) { @@ -1765,7 +1921,7 @@ PerlIOBase_read(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); @@ -1784,25 +1940,25 @@ PerlIOBase_read(PerlIO *f, void *vbuf, Size_t count) } IV -PerlIOBase_noop_ok(PerlIO *f) +PerlIOBase_noop_ok(pTHX_ PerlIO *f) { return 0; } IV -PerlIOBase_noop_fail(PerlIO *f) +PerlIOBase_noop_fail(pTHX_ PerlIO *f) { return -1; } IV -PerlIOBase_close(PerlIO *f) +PerlIOBase_close(pTHX_ PerlIO *f) { IV code = 0; PerlIO *n = PerlIONext(f); if (PerlIO_flush(f) != 0) code = -1; - if (n && *n && (*PerlIOBase(n)->tab->Close) (n) != 0) + if (PerlIOValid(n) && (*PerlIOBase(n)->tab->Close)(aTHX_ n) != 0) code = -1; PerlIOBase(f)->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_OPEN); @@ -1810,51 +1966,169 @@ PerlIOBase_close(PerlIO *f) } IV -PerlIOBase_eof(PerlIO *f) +PerlIOBase_eof(pTHX_ PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0; } return 1; } IV -PerlIOBase_error(PerlIO *f) +PerlIOBase_error(pTHX_ PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0; } return 1; } void -PerlIOBase_clearerr(PerlIO *f) +PerlIOBase_clearerr(pTHX_ PerlIO *f) { - if (f && *f) { + if (PerlIOValid(f)) { PerlIO *n = PerlIONext(f); PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR | PERLIO_F_EOF); - if (n) + if (PerlIOValid(n)) PerlIO_clearerr(n); } } void -PerlIOBase_setlinebuf(PerlIO *f) +PerlIOBase_setlinebuf(pTHX_ PerlIO *f) { - if (f) { + if (PerlIOValid(f)) { PerlIOBase(f)->flags |= PERLIO_F_LINEBUF; } } +SV * +PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param) +{ + if (!arg) + return Nullsv; +#ifdef sv_dup + if (param) { + return sv_dup(arg, param); + } + else { + return newSVsv(arg); + } +#else + return newSVsv(arg); +#endif +} + +PerlIO * +PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + PerlIO *nexto = PerlIONext(o); + if (PerlIOValid(nexto)) { + PerlIO_funcs *tab = PerlIOBase(nexto)->tab; + f = (*tab->Dup)(aTHX_ f, nexto, param, flags); + } + if (f) { + PerlIO_funcs *self = PerlIOBase(o)->tab; + SV *arg = Nullsv; + char buf[8]; + PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n", + self->name, (void*)f, (void*)o, (void*)param); + if (self->Getarg) { + arg = (*self->Getarg)(aTHX_ o,param,flags); + } + f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg); + if (arg) { + SvREFCNT_dec(arg); + } + } + return f; +} + +#define PERLIO_MAX_REFCOUNTABLE_FD 2048 +#ifdef USE_THREADS +perl_mutex PerlIO_mutex; +#endif +int PerlIO_fd_refcnt[PERLIO_MAX_REFCOUNTABLE_FD]; + +void +PerlIO_init(pTHX) +{ + /* Place holder for stdstreams call ??? */ +#ifdef USE_THREADS + MUTEX_INIT(&PerlIO_mutex); +#endif +} + +void +PerlIOUnix_refcnt_inc(int fd) +{ + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { +#ifdef USE_THREADS + MUTEX_LOCK(&PerlIO_mutex); +#endif + PerlIO_fd_refcnt[fd]++; + PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]); +#ifdef USE_THREADS + MUTEX_UNLOCK(&PerlIO_mutex); +#endif + } +} + +int +PerlIOUnix_refcnt_dec(int fd) +{ + int cnt = 0; + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { +#ifdef USE_THREADS + MUTEX_LOCK(&PerlIO_mutex); +#endif + cnt = --PerlIO_fd_refcnt[fd]; + PerlIO_debug("fd %d refcnt=%d\n",fd,cnt); +#ifdef USE_THREADS + MUTEX_UNLOCK(&PerlIO_mutex); +#endif + } + return cnt; +} + +void +PerlIO_cleanup(pTHX) +{ + int i; +#ifdef USE_ITHREADS + 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++) + PerlIOUnix_refcnt_inc(i); + PerlIO_cleantable(aTHX_ &PL_perlio); + /* 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; + } +} + + + /*--------------------------------------------------------------------------------------*/ /* - * Bottom-most level for UNIX-like case + * Bottom-most level for UNIX-like case */ 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 @@ -1903,7 +2177,7 @@ PerlIOUnix_oflags(const char *mode) mode++; } /* - * Always open in binary mode + * Always open in binary mode */ oflags |= O_BINARY; if (*mode || oflags == -1) { @@ -1914,22 +2188,24 @@ PerlIOUnix_oflags(const char *mode) } IV -PerlIOUnix_fileno(PerlIO *f) +PerlIOUnix_fileno(pTHX_ PerlIO *f) { return PerlIOSelf(f, PerlIOUnix)->fd; } IV -PerlIOUnix_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { - IV code = PerlIOBase_pushed(f, mode, arg); + IV code = PerlIOBase_pushed(aTHX_ f, mode, arg); + PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); if (*PerlIONext(f)) { - PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); + /* We never call down so any pending stuff now */ + PerlIO_flush(PerlIONext(f)); s->fd = PerlIO_fileno(PerlIONext(f)); /* - * XXX could (or should) we retrieve the oflags from the open file + * XXX could (or should) we retrieve the oflags from the open file * handle rather than believing the "mode" we are passed in? XXX - * Should the value on NULL mode be 0 or -1? + * Should the value on NULL mode be 0 or -1? */ s->oflags = mode ? PerlIOUnix_oflags(mode) : -1; } @@ -1942,9 +2218,9 @@ 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) (f); + (*PerlIOBase(f)->tab->Close)(aTHX_ f); } if (narg > 0) { char *path = SvPV_nolen(*args); @@ -1964,30 +2240,55 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, mode++; if (!f) { f = PerlIO_allocate(aTHX); + } + if (!PerlIOValid(f)) { s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg), PerlIOUnix); } - else + else { s = PerlIOSelf(f, PerlIOUnix); + } s->fd = fd; s->oflags = imode; PerlIOBase(f)->flags |= PERLIO_F_OPEN; + PerlIOUnix_refcnt_inc(fd); return f; } else { if (f) { /* - * FIXME: pop layers ??? + * FIXME: pop layers ??? */ } return NULL; } } +PerlIO * +PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + PerlIOUnix *os = PerlIOSelf(o, PerlIOUnix); + int fd = os->fd; + if (flags & PERLIO_DUP_FD) { + fd = PerlLIO_dup(fd); + } + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { + f = PerlIOBase_dup(aTHX_ f, o, param, flags); + if (f) { + /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */ + PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); + s->fd = fd; + PerlIOUnix_refcnt_inc(fd); + return f; + } + } + return NULL; +} + + SSize_t -PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count) +PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { - dTHX; int fd = PerlIOSelf(f, PerlIOUnix)->fd; if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) return 0; @@ -2005,9 +2306,8 @@ PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count) } SSize_t -PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count) +PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - dTHX; int fd = PerlIOSelf(f, PerlIOUnix)->fd; while (1) { SSize_t len = PerlLIO_write(fd, vbuf, count); @@ -2021,9 +2321,8 @@ PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count) } IV -PerlIOUnix_seek(PerlIO *f, Off_t offset, int whence) +PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence) { - dSYS; Off_t new = PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, offset, whence); PerlIOBase(f)->flags &= ~PERLIO_F_EOF; @@ -2031,18 +2330,27 @@ PerlIOUnix_seek(PerlIO *f, Off_t offset, int whence) } Off_t -PerlIOUnix_tell(PerlIO *f) +PerlIOUnix_tell(pTHX_ PerlIO *f) { - dSYS; return PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, 0, SEEK_CUR); } + IV -PerlIOUnix_close(PerlIO *f) +PerlIOUnix_close(pTHX_ PerlIO *f) { - dTHX; int fd = PerlIOSelf(f, PerlIOUnix)->fd; int code = 0; + if (PerlIOBase(f)->flags & PERLIO_F_OPEN) { + if (PerlIOUnix_refcnt_dec(fd) > 0) { + PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; + return 0; + } + } + else { + SETERRNO(EBADF,SS$_IVCHAN); + return -1; + } while (PerlLIO_close(fd) != 0) { if (errno != EINTR) { code = -1; @@ -2061,43 +2369,51 @@ PerlIO_funcs PerlIO_unix = { sizeof(PerlIOUnix), PERLIO_K_RAW, PerlIOUnix_pushed, - PerlIOBase_noop_ok, + PerlIOBase_popped, PerlIOUnix_open, NULL, PerlIOUnix_fileno, + PerlIOUnix_dup, PerlIOUnix_read, PerlIOBase_unread, PerlIOUnix_write, 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 */ }; /*--------------------------------------------------------------------------------------*/ /* - * stdio as a layer + * 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(PerlIO *f) +PerlIOStdio_fileno(pTHX_ PerlIO *f) { - dSYS; return PerlSIO_fileno(PerlIOSelf(f, PerlIOStdio)->stdio); } @@ -2108,45 +2424,71 @@ PerlIOStdio_mode(const char *mode, char *tmode) while (*mode) { *tmode++ = *mode++; } - if (O_BINARY != O_TEXT) { - *tmode++ = 'b'; - } +#ifdef PERLIO_USING_CRLF + *tmode++ = 'b'; +#endif *tmode = '\0'; return ret; } /* - * This isn't used yet ... + * This isn't used yet ... */ IV -PerlIOStdio_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { if (*PerlIONext(f)) { - dSYS; PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); char tmode[8]; FILE *stdio = PerlSIO_fdopen(PerlIO_fileno(PerlIONext(f)), mode = PerlIOStdio_mode(mode, tmode)); - if (stdio) + if (stdio) { s->stdio = stdio; + /* We never call down so any pending stuff now */ + PerlIO_flush(PerlIONext(f)); + } else return -1; } - return PerlIOBase_pushed(f, mode, arg); + return PerlIOBase_pushed(aTHX_ f, mode, arg); } -#undef PerlIO_importFILE + PerlIO * PerlIO_importFILE(FILE *stdio, int fl) { dTHX; PerlIO *f = NULL; if (stdio) { - PerlIOStdio *s = - PerlIOSelf(PerlIO_push - (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, - "r+", Nullsv), PerlIOStdio); + /* 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) { + mode = "w"; + f2 = fdopen(fd, mode); + } + 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); + s = PerlIOSelf(PerlIO_push + (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio, + mode, Nullsv), PerlIOStdio); s->stdio = stdio; } return f; @@ -2158,15 +2500,17 @@ 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 = - PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)), + FILE *stdio; + PerlIOUnix_refcnt_dec(fileno(s->stdio)); + stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)), s->stdio); if (!s->stdio) return NULL; s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); return f; } else { @@ -2179,13 +2523,16 @@ 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); + } + s = PerlIOSelf(PerlIO_push(aTHX_ f, self, (mode = PerlIOStdio_mode(mode, tmode)), PerlIOArg), PerlIOStdio); s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); } return f; } @@ -2215,11 +2562,13 @@ 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); + PerlIOStdio *s; + if (!f) { + f = PerlIO_allocate(aTHX); + } + s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg), PerlIOStdio); s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); return f; } } @@ -2227,17 +2576,69 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, return NULL; } +PerlIO * +PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + /* This assumes no layers underneath - which is what + happens, but is not how I remember it. NI-S 2001/10/16 + */ + if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) { + FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio; + if (flags & PERLIO_DUP_FD) { + int fd = PerlLIO_dup(fileno(stdio)); + if (fd >= 0) { + char mode[8]; + stdio = fdopen(fd, PerlIO_modestr(o,mode)); + } + else { + /* FIXME: To avoid messy error recovery if dup fails + re-use the existing stdio as though flag was not set + */ + } + } + PerlIOSelf(f, PerlIOStdio)->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(stdio)); + } + return f; +} + +IV +PerlIOStdio_close(pTHX_ PerlIO *f) +{ +#ifdef SOCKS5_VERSION_NAME + int optval; + Sock_size_t optlen = sizeof(int); +#endif + FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; + if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) { + /* Do not close it but do flush any buffers */ + return PerlIO_flush(f); + } + return ( +#ifdef SOCKS5_VERSION_NAME + (getsockopt + (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval, + &optlen) < + 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f)) +#else + PerlSIO_fclose(stdio) +#endif + ); + +} + + + SSize_t -PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count) +PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { - dSYS; FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio; SSize_t got = 0; if (count == 1) { STDCHAR *buf = (STDCHAR *) vbuf; /* * Perl is expecting PerlIO_getc() to fill the buffer Linux's - * stdio does not do that for fread() + * stdio does not do that for fread() */ int ch = PerlSIO_fgetc(s); if (ch != EOF) { @@ -2251,72 +2652,87 @@ PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count) } SSize_t -PerlIOStdio_unread(PerlIO *f, const void *vbuf, Size_t count) +PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - dSYS; - 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; } SSize_t -PerlIOStdio_write(PerlIO *f, const void *vbuf, Size_t count) +PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { - dSYS; return PerlSIO_fwrite(vbuf, 1, count, PerlIOSelf(f, PerlIOStdio)->stdio); } IV -PerlIOStdio_seek(PerlIO *f, Off_t offset, int whence) +PerlIOStdio_seek(pTHX_ PerlIO *f, Off_t offset, int whence) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; return PerlSIO_fseek(stdio, offset, whence); } Off_t -PerlIOStdio_tell(PerlIO *f) +PerlIOStdio_tell(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; return PerlSIO_ftell(stdio); } IV -PerlIOStdio_close(PerlIO *f) -{ - dSYS; -#ifdef SOCKS5_VERSION_NAME - int optval; - Sock_size_t optlen = sizeof(int); -#endif - FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; - return ( -#ifdef SOCKS5_VERSION_NAME - (getsockopt - (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval, - &optlen) < - 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f)) -#else - PerlSIO_fclose(stdio) -#endif - ); - -} - -IV -PerlIOStdio_flush(PerlIO *f) +PerlIOStdio_flush(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { return PerlSIO_fflush(stdio); @@ -2325,12 +2741,12 @@ PerlIOStdio_flush(PerlIO *f) #if 0 /* * FIXME: This discards ungetc() and pre-read stuff which is not - * right if this is just a "sync" from a layer above Suspect right + * right if this is just a "sync" from a layer above Suspect right * design is to do _this_ but not have layer above flush this - * layer read-to-read + * layer read-to-read */ /* - * Not writeable - sync by attempting a seek + * Not writeable - sync by attempting a seek */ int err = errno; if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0) @@ -2341,49 +2757,26 @@ PerlIOStdio_flush(PerlIO *f) } IV -PerlIOStdio_fill(PerlIO *f) -{ - dSYS; - 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(PerlIO *f) +PerlIOStdio_eof(pTHX_ PerlIO *f) { - dSYS; return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio); } IV -PerlIOStdio_error(PerlIO *f) +PerlIOStdio_error(pTHX_ PerlIO *f) { - dSYS; return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio); } void -PerlIOStdio_clearerr(PerlIO *f) +PerlIOStdio_clearerr(pTHX_ PerlIO *f) { - dSYS; PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio); } void -PerlIOStdio_setlinebuf(PerlIO *f) +PerlIOStdio_setlinebuf(pTHX_ PerlIO *f) { - dSYS; #ifdef HAS_SETLINEBUF PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio); #else @@ -2393,17 +2786,15 @@ PerlIOStdio_setlinebuf(PerlIO *f) #ifdef FILE_base STDCHAR * -PerlIOStdio_get_base(PerlIO *f) +PerlIOStdio_get_base(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; - return PerlSIO_get_base(stdio); + return (STDCHAR*)PerlSIO_get_base(stdio); } Size_t -PerlIOStdio_get_bufsiz(PerlIO *f) +PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; return PerlSIO_get_bufsiz(stdio); } @@ -2411,72 +2802,133 @@ PerlIOStdio_get_bufsiz(PerlIO *f) #ifdef USE_STDIO_PTR STDCHAR * -PerlIOStdio_get_ptr(PerlIO *f) +PerlIOStdio_get_ptr(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; - return PerlSIO_get_ptr(stdio); + return (STDCHAR*)PerlSIO_get_ptr(stdio); } SSize_t -PerlIOStdio_get_cnt(PerlIO *f) +PerlIOStdio_get_cnt(pTHX_ PerlIO *f) { - dSYS; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; return PerlSIO_get_cnt(stdio); } void -PerlIOStdio_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) +PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) { FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; - dSYS; if (ptr != NULL) { #ifdef STDIO_PTR_LVALUE - PerlSIO_set_ptr(stdio, ptr); + PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */ #ifdef STDIO_PTR_LVAL_SETS_CNT if (PerlSIO_get_cnt(stdio) != (cnt)) { - dTHX; assert(PerlSIO_get_cnt(stdio) == (cnt)); } #endif #if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT)) /* - * Setting ptr _does_ change cnt - we are done + * Setting ptr _does_ change cnt - we are done */ 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 + * 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 = { "stdio", sizeof(PerlIOStdio), PERLIO_K_BUFFERED, PerlIOBase_pushed, - PerlIOBase_noop_ok, + PerlIOBase_popped, PerlIOStdio_open, NULL, PerlIOStdio_fileno, + PerlIOStdio_dup, PerlIOStdio_read, PerlIOStdio_unread, PerlIOStdio_write, @@ -2501,34 +2953,33 @@ 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 */ }; -#undef PerlIO_exportFILE FILE * PerlIO_exportFILE(PerlIO *f, int fl) { + dTHX; FILE *stdio; + char buf[8]; PerlIO_flush(f); - stdio = fdopen(PerlIO_fileno(f), "r+"); + stdio = fdopen(PerlIO_fileno(f), PerlIO_modestr(f,buf)); if (stdio) { - dTHX; PerlIOStdio *s = - PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, "r+", Nullsv), + PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv), PerlIOStdio); s->stdio = stdio; } return stdio; } -#undef PerlIO_findFILE FILE * PerlIO_findFILE(PerlIO *f) { @@ -2543,21 +2994,32 @@ PerlIO_findFILE(PerlIO *f) return PerlIO_exportFILE(f, 0); } -#undef PerlIO_releaseFILE 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; } /*--------------------------------------------------------------------------------------*/ /* - * perlio buffer layer + * perlio buffer layer */ IV -PerlIOBuf_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { - dSYS; PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); int fd = PerlIO_fileno(f); Off_t posn; @@ -2568,7 +3030,7 @@ PerlIOBuf_pushed(PerlIO *f, const char *mode, SV *arg) if (posn != (Off_t) - 1) { b->posn = posn; } - return PerlIOBase_pushed(f, mode, arg); + return PerlIOBase_pushed(aTHX_ f, mode, arg); } PerlIO * @@ -2576,44 +3038,52 @@ PerlIOBuf_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)) { PerlIO *next = PerlIONext(f); - 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, + 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) (f, mode, PerlIOArg) != 0) { + if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg) != 0) { return NULL; } } else { - PerlIO_funcs *tab = - PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm()); + PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm()); int init = 0; if (*mode == 'I') { init = 1; /* - * mode++; + * mode++; */ } f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, - NULL, narg, args); + f, narg, args); if (f) { - PerlIO_push(aTHX_ f, self, mode, PerlIOArg); - fd = PerlIO_fileno(f); -#if O_BINARY != O_TEXT - /* - * do something about failing setmode()? --jhi - */ - PerlLIO_setmode(fd, O_BINARY); -#endif - if (init && fd == 2) { + if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { + /* + * if push fails during open, open fails. close will pop us. + */ + PerlIO_close (f); + return NULL; + } else { + fd = PerlIO_fileno(f); + if (init && fd == 2) { + /* + * Initial stderr is unbuffered + */ + PerlIOBase(f)->flags |= PERLIO_F_UNBUF; + } +#ifdef PERLIO_USING_CRLF +# ifdef PERLIO_IS_BINMODE_FD + if (PERLIO_IS_BINMODE_FD(fd)) + PerlIO_binmode(f, '<'/*not used*/, O_BINARY, Nullch); + else +# endif /* - * Initial stderr is unbuffered + * do something about failing setmode()? --jhi */ - PerlIOBase(f)->flags |= PERLIO_F_UNBUF; + PerlLIO_setmode(fd, O_BINARY); +#endif } } } @@ -2622,20 +3092,20 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, /* * This "flush" is akin to sfio's sync in that it handles files in either - * read or write state + * read or write state */ IV -PerlIOBuf_flush(PerlIO *f) +PerlIOBuf_flush(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); int code = 0; + PerlIO *n = PerlIONext(f); if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) { /* - * write() the buffer + * write() the buffer */ STDCHAR *buf = b->buf; STDCHAR *p = buf; - PerlIO *n = PerlIONext(f); while (p < b->ptr) { SSize_t count = PerlIO_write(n, p, b->ptr - p); if (count > 0) { @@ -2652,55 +3122,58 @@ PerlIOBuf_flush(PerlIO *f) else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) { STDCHAR *buf = PerlIO_get_base(f); /* - * Note position change + * Note position change */ b->posn += (b->ptr - buf); if (b->ptr < b->end) { /* - * We did not consume all of it + * We did not consume all of it */ - if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) == 0) { - b->posn = PerlIO_tell(PerlIONext(f)); + if (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 { + return code; } } } b->ptr = b->end = b->buf; PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF); - /* - * FIXME: Is this right for read case ? - */ - if (PerlIO_flush(PerlIONext(f)) != 0) + /* 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; } IV -PerlIOBuf_fill(PerlIO *f) +PerlIOBuf_fill(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); PerlIO *n = PerlIONext(f); SSize_t avail; /* - * FIXME: doing the down-stream flush is a bad idea if it causes - * pre-read data in stdio buffer to be discarded but this is too - * simplistic - as it skips _our_ hosekeeping and breaks tell tests. - * if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { } + * 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. */ if (PerlIO_flush(f) != 0) return -1; if (PerlIOBase(f)->flags & PERLIO_F_TTY) - PerlIOBase_flush_linebuf(); + 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 (PerlIO_fast_gets(n)) { /* - * Layer below is also buffered We do _NOT_ want to call its + * Layer below is also buffered. We do _NOT_ want to call its * ->Read() because that will loop till it gets what we asked for * which may hang on a pipe etc. Instead take anything it has to - * hand, or ask it to fill _once_. + * hand, or ask it to fill _once_. */ avail = PerlIO_get_cnt(n); if (avail <= 0) { @@ -2715,7 +3188,7 @@ PerlIOBuf_fill(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); @@ -2737,19 +3210,19 @@ PerlIOBuf_fill(PerlIO *f) } SSize_t -PerlIOBuf_read(PerlIO *f, void *vbuf, Size_t count) +PerlIOBuf_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); - if (f) { + if (PerlIOValid(f)) { if (!b->ptr) PerlIO_get_base(f); - return PerlIOBase_read(f, vbuf, count); + return PerlIOBase_read(aTHX_ f, vbuf, count); } return 0; } SSize_t -PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count) +PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { const STDCHAR *buf = (const STDCHAR *) vbuf + count; PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); @@ -2763,27 +3236,27 @@ PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count) if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) { /* * Buffer is already a read buffer, we can overwrite any chars - * which have been read back to buffer start + * which have been read back to buffer start */ avail = (b->ptr - b->buf); } else { /* * Buffer is idle, set it up so whole buffer is available for - * unread + * unread */ avail = b->bufsiz; b->end = b->buf + avail; b->ptr = b->end; PerlIOBase(f)->flags |= PERLIO_F_RDBUF; /* - * Buffer extends _back_ from where we are now + * Buffer extends _back_ from where we are now */ b->posn -= b->bufsiz; } if (avail > (SSize_t) count) { /* - * If we have space for more than count, just move count + * If we have space for more than count, just move count */ avail = count; } @@ -2792,7 +3265,7 @@ PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count) buf -= avail; /* * In simple stdio-like ungetc() case chars will be already - * there + * there */ if (buf != b->ptr) { Copy(buf, b->ptr, avail, STDCHAR); @@ -2802,11 +3275,14 @@ PerlIOBuf_unread(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; } SSize_t -PerlIOBuf_write(PerlIO *f, const void *vbuf, Size_t count) +PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); const STDCHAR *buf = (const STDCHAR *) vbuf; @@ -2851,7 +3327,7 @@ PerlIOBuf_write(PerlIO *f, const void *vbuf, Size_t count) } IV -PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence) +PerlIOBuf_seek(pTHX_ PerlIO *f, Off_t offset, int whence) { IV code; if ((code = PerlIO_flush(f)) == 0) { @@ -2866,16 +3342,16 @@ PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence) } Off_t -PerlIOBuf_tell(PerlIO *f) +PerlIOBuf_tell(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); /* - * b->posn is file position where b->buf was read, or will be written + * b->posn is file position where b->buf was read, or will be written */ Off_t posn = b->posn; if (b->buf) { /* - * If buffer is valid adjust position by amount in buffer + * If buffer is valid adjust position by amount in buffer */ posn += (b->ptr - b->buf); } @@ -2883,12 +3359,26 @@ PerlIOBuf_tell(PerlIO *f) } IV -PerlIOBuf_close(PerlIO *f) +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(f); + IV code = PerlIOBase_close(aTHX_ f); PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (b->buf && b->buf != (STDCHAR *) & b->oneword) { - PerlMemShared_free(b->buf); + Safefree(b->buf); } b->buf = NULL; b->ptr = b->end = b->buf; @@ -2897,7 +3387,7 @@ PerlIOBuf_close(PerlIO *f) } STDCHAR * -PerlIOBuf_get_ptr(PerlIO *f) +PerlIOBuf_get_ptr(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) @@ -2906,7 +3396,7 @@ PerlIOBuf_get_ptr(PerlIO *f) } SSize_t -PerlIOBuf_get_cnt(PerlIO *f) +PerlIOBuf_get_cnt(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) @@ -2917,13 +3407,14 @@ PerlIOBuf_get_cnt(PerlIO *f) } STDCHAR * -PerlIOBuf_get_base(PerlIO *f) +PerlIOBuf_get_base(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) { if (!b->bufsiz) b->bufsiz = 4096; - b->buf = PerlMemShared_calloc(b->bufsiz, sizeof(STDCHAR)); + b->buf = + Newz('B',b->buf,b->bufsiz, STDCHAR); if (!b->buf) { b->buf = (STDCHAR *) & b->oneword; b->bufsiz = sizeof(b->oneword); @@ -2935,7 +3426,7 @@ PerlIOBuf_get_base(PerlIO *f) } Size_t -PerlIOBuf_bufsiz(PerlIO *f) +PerlIOBuf_bufsiz(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) @@ -2944,29 +3435,37 @@ PerlIOBuf_bufsiz(PerlIO *f) } void -PerlIOBuf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) +PerlIOBuf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) PerlIO_get_base(f); b->ptr = ptr; if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf) { - dTHX; assert(PerlIO_get_cnt(f) == cnt); assert(b->ptr >= b->buf); } PerlIOBase(f)->flags |= PERLIO_F_RDBUF; } +PerlIO * +PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + return PerlIOBase_dup(aTHX_ f, o, param, flags); +} + + + PerlIO_funcs PerlIO_perlio = { "perlio", sizeof(PerlIOBuf), PERLIO_K_BUFFERED, PerlIOBuf_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, PerlIOBuf_open, NULL, PerlIOBase_fileno, + PerlIOBuf_dup, PerlIOBuf_read, PerlIOBuf_unread, PerlIOBuf_write, @@ -2988,34 +3487,34 @@ PerlIO_funcs PerlIO_perlio = { /*--------------------------------------------------------------------------------------*/ /* - * Temp layer to hold unread chars when cannot do it any other way + * Temp layer to hold unread chars when cannot do it any other way */ IV -PerlIOPending_fill(PerlIO *f) +PerlIOPending_fill(pTHX_ PerlIO *f) { /* - * Should never happen + * Should never happen */ PerlIO_flush(f); return 0; } IV -PerlIOPending_close(PerlIO *f) +PerlIOPending_close(pTHX_ PerlIO *f) { /* - * A tad tricky - flush pops us, then we close new top + * A tad tricky - flush pops us, then we close new top */ PerlIO_flush(f); return PerlIO_close(f); } IV -PerlIOPending_seek(PerlIO *f, Off_t offset, int whence) +PerlIOPending_seek(pTHX_ PerlIO *f, Off_t offset, int whence) { /* - * A tad tricky - flush pops us, then we seek new top + * A tad tricky - flush pops us, then we seek new top */ PerlIO_flush(f); return PerlIO_seek(f, offset, whence); @@ -3023,12 +3522,11 @@ PerlIOPending_seek(PerlIO *f, Off_t offset, int whence) IV -PerlIOPending_flush(PerlIO *f) +PerlIOPending_flush(pTHX_ PerlIO *f) { - dTHX; PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (b->buf && b->buf != (STDCHAR *) & b->oneword) { - PerlMemShared_free(b->buf); + Safefree(b->buf); b->buf = NULL; } PerlIO_pop(aTHX_ f); @@ -3036,24 +3534,24 @@ PerlIOPending_flush(PerlIO *f) } void -PerlIOPending_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) +PerlIOPending_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) { if (cnt <= 0) { PerlIO_flush(f); } else { - PerlIOBuf_set_ptrcnt(f, ptr, cnt); + PerlIOBuf_set_ptrcnt(aTHX_ f, ptr, cnt); } } IV -PerlIOPending_pushed(PerlIO *f, const char *mode, SV *arg) +PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { - IV code = PerlIOBase_pushed(f, mode, arg); + IV code = PerlIOBase_pushed(aTHX_ f, mode, arg); PerlIOl *l = PerlIOBase(f); /* - * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets() - * etc. get muddled when it changes mid-string when we auto-pop. + * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets() + * etc. get muddled when it changes mid-string when we auto-pop. */ l->flags = (l->flags & ~(PERLIO_F_FASTGETS | PERLIO_F_UTF8)) | (PerlIOBase(PerlIONext(f))-> @@ -3062,15 +3560,15 @@ PerlIOPending_pushed(PerlIO *f, const char *mode, SV *arg) } SSize_t -PerlIOPending_read(PerlIO *f, void *vbuf, Size_t count) +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(f, vbuf, avail); - if (got >= 0 && got < count) { + got = PerlIOBuf_read(aTHX_ f, vbuf, avail); + if (got >= 0 && got < (SSize_t)count) { SSize_t more = PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got); if (more >= 0 || got == 0) @@ -3084,10 +3582,11 @@ PerlIO_funcs PerlIO_pending = { sizeof(PerlIOBuf), PERLIO_K_BUFFERED, PerlIOPending_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, NULL, NULL, PerlIOBase_fileno, + PerlIOBuf_dup, PerlIOPending_read, PerlIOBuf_unread, PerlIOBuf_write, @@ -3113,21 +3612,21 @@ PerlIO_funcs PerlIO_pending = { /* * crlf - translation On read translate CR,LF to "\n" we do this by * overriding ptr/cnt entries to hand back a line at a time and keeping a - * record of which nl we "lied" about. On write translate "\n" to CR,LF + * record of which nl we "lied" about. On write translate "\n" to CR,LF */ 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(PerlIO *f, const char *mode, SV *arg) +PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg) { IV code; PerlIOBase(f)->flags |= PERLIO_F_CRLF; - code = PerlIOBuf_pushed(f, mode, arg); + code = PerlIOBuf_pushed(aTHX_ f, mode, arg); #if 0 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n", f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)", @@ -3138,7 +3637,7 @@ PerlIOCrlf_pushed(PerlIO *f, const char *mode, SV *arg) SSize_t -PerlIOCrlf_unread(PerlIO *f, const void *vbuf, Size_t count) +PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf); if (c->nl) { @@ -3146,7 +3645,7 @@ PerlIOCrlf_unread(PerlIO *f, const void *vbuf, Size_t count) c->nl = NULL; } if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) - return PerlIOBuf_unread(f, vbuf, count); + return PerlIOBuf_unread(aTHX_ f, vbuf, count); else { const STDCHAR *buf = (const STDCHAR *) vbuf + count; PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); @@ -3187,15 +3686,15 @@ PerlIOCrlf_unread(PerlIO *f, const void *vbuf, Size_t count) } SSize_t -PerlIOCrlf_get_cnt(PerlIO *f) +PerlIOCrlf_get_cnt(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); if (!b->buf) PerlIO_get_base(f); if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) { PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf); - if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && !c->nl) { - STDCHAR *nl = b->ptr; + if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) { + STDCHAR *nl = (c->nl) ? c->nl : b->ptr; scan: while (nl < b->end && *nl != 0xd) nl++; @@ -3208,7 +3707,7 @@ PerlIOCrlf_get_cnt(PerlIO *f) } else { /* - * Not CR,LF but just CR + * Not CR,LF but just CR */ nl++; goto scan; @@ -3216,33 +3715,36 @@ PerlIOCrlf_get_cnt(PerlIO *f) } else { /* - * Blast - found CR as last char in buffer + * Blast - found CR as last char in buffer */ + if (b->ptr < nl) { /* * They may not care, defer work as long as - * possible + * possible */ + c->nl = nl; return (nl - b->ptr); } 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 an 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 + * CR at EOF - just fall through */ + /* Should we clear EOF though ??? */ } } } @@ -3253,48 +3755,49 @@ PerlIOCrlf_get_cnt(PerlIO *f) } void -PerlIOCrlf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) +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) + if (c->nl) { ptr = c->nl + 1; + if (ptr == b->end && *c->nl == 0xd) { + /* Defered CR at end of buffer case - we lied about count */ + ptr--; + } + } else { ptr = b->end; - if ((flags & PERLIO_F_CRLF) && ptr > b->buf && ptr[-1] == 0xd) - ptr--; } ptr -= cnt; } else { +#if 0 /* - * Test code - delete when it works ... + * Test code - delete when it works ... */ - STDCHAR *chk; - if (c->nl) - chk = c->nl + 1; - else { - chk = b->end; - if ((flags & PERLIO_F_CRLF) && chk > b->buf && chk[-1] == 0xd) - chk--; + 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) { + /* Defered CR at end of buffer case - we lied about count */ + chk--; } chk -= cnt; - if (ptr != chk) { - dTHX; + if (ptr != chk ) { Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08" UVxf " nl=%p e=%p for %d", ptr, chk, flags, c->nl, b->end, cnt); } +#endif } if (c->nl) { if (ptr > c->nl) { /* - * They have taken what we lied about + * They have taken what we lied about */ *(c->nl) = 0xd; c->nl = NULL; @@ -3306,10 +3809,10 @@ PerlIOCrlf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) } SSize_t -PerlIOCrlf_write(PerlIO *f, const void *vbuf, Size_t count) +PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) - return PerlIOBuf_write(f, vbuf, count); + return PerlIOBuf_write(aTHX_ f, vbuf, count); else { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); const STDCHAR *buf = (const STDCHAR *) vbuf; @@ -3325,14 +3828,14 @@ PerlIOCrlf_write(PerlIO *f, const void *vbuf, Size_t count) if (*buf == '\n') { if ((b->ptr + 2) > eptr) { /* - * Not room for both + * Not room for both */ PerlIO_flush(f); 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); @@ -3357,14 +3860,14 @@ PerlIOCrlf_write(PerlIO *f, const void *vbuf, Size_t count) } IV -PerlIOCrlf_flush(PerlIO *f) +PerlIOCrlf_flush(pTHX_ PerlIO *f) { PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf); if (c->nl) { *(c->nl) = 0xd; c->nl = NULL; } - return PerlIOBuf_flush(f); + return PerlIOBuf_flush(aTHX_ f); } PerlIO_funcs PerlIO_crlf = { @@ -3372,14 +3875,15 @@ 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, - PerlIOBuf_read, /* generic read works with ptr/cnt lies + PerlIOBuf_dup, + 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, @@ -3399,22 +3903,21 @@ PerlIO_funcs PerlIO_crlf = { #ifdef HAS_MMAP /*--------------------------------------------------------------------------------------*/ /* - * mmap as "buffer" layer + * mmap as "buffer" layer */ 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; IV -PerlIOMmap_map(PerlIO *f) +PerlIOMmap_map(pTHX_ PerlIO *f) { - dTHX; PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); IV flags = PerlIOBase(f)->flags; IV code = 0; @@ -3423,8 +3926,8 @@ PerlIOMmap_map(PerlIO *f) if (flags & PERLIO_F_CANREAD) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); int fd = PerlIO_fileno(f); - struct stat st; - code = fstat(fd, &st); + Stat_t st; + code = Fstat(fd, &st); if (code == 0 && S_ISREG(st.st_mode)) { SSize_t len = st.st_size - b->posn; if (len > 0) { @@ -3458,7 +3961,7 @@ PerlIOMmap_map(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 @@ -3469,7 +3972,7 @@ PerlIOMmap_map(PerlIO *f) if (b->posn < 0) { /* * This is a hack - should never happen - open should - * have set it ! + * have set it ! */ b->posn = PerlIO_tell(PerlIONext(f)); } @@ -3507,7 +4010,7 @@ PerlIOMmap_map(PerlIO *f) } IV -PerlIOMmap_unmap(PerlIO *f) +PerlIOMmap_unmap(pTHX_ PerlIO *f) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; @@ -3528,28 +4031,28 @@ PerlIOMmap_unmap(PerlIO *f) } STDCHAR * -PerlIOMmap_get_base(PerlIO *f) +PerlIOMmap_get_base(pTHX_ PerlIO *f) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { /* - * Already have a readbuffer in progress + * Already have a readbuffer in progress */ return b->buf; } if (b->buf) { /* - * We have a write buffer or flushed PerlIOBuf read buffer + * 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(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 + * Map did not work - recover PerlIOBuf buffer if we have one */ b->buf = m->bbuf; } @@ -3557,11 +4060,11 @@ PerlIOMmap_get_base(PerlIO *f) b->ptr = b->end = b->buf; if (b->buf) return b->buf; - return PerlIOBuf_get_base(f); + return PerlIOBuf_get_base(aTHX_ f); } SSize_t -PerlIOMmap_unread(PerlIO *f, const void *vbuf, Size_t count) +PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; @@ -3575,69 +4078,69 @@ PerlIOMmap_unread(PerlIO *f, const void *vbuf, Size_t count) } if (m->len) { /* - * Loose the unwritable mapped buffer + * Loose the unwritable mapped buffer */ PerlIO_flush(f); /* - * If flush took the "buffer" see if we have one from before + * If flush took the "buffer" see if we have one from before */ if (!b->buf && m->bbuf) b->buf = m->bbuf; if (!b->buf) { - PerlIOBuf_get_base(f); + PerlIOBuf_get_base(aTHX_ f); m->bbuf = b->buf; } } - return PerlIOBuf_unread(f, vbuf, count); + return PerlIOBuf_unread(aTHX_ f, vbuf, count); } SSize_t -PerlIOMmap_write(PerlIO *f, const void *vbuf, Size_t count) +PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) { /* - * No, or wrong sort of, buffer + * No, or wrong sort of, buffer */ if (m->len) { - if (PerlIOMmap_unmap(f) != 0) + if (PerlIOMmap_unmap(aTHX_ f) != 0) return 0; } /* - * If unmap took the "buffer" see if we have one from before + * If unmap took the "buffer" see if we have one from before */ if (!b->buf && m->bbuf) b->buf = m->bbuf; if (!b->buf) { - PerlIOBuf_get_base(f); + PerlIOBuf_get_base(aTHX_ f); m->bbuf = b->buf; } } - return PerlIOBuf_write(f, vbuf, count); + return PerlIOBuf_write(aTHX_ f, vbuf, count); } IV -PerlIOMmap_flush(PerlIO *f) +PerlIOMmap_flush(pTHX_ PerlIO *f) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; - IV code = PerlIOBuf_flush(f); + IV code = PerlIOBuf_flush(aTHX_ f); /* - * Now we are "synced" at PerlIOBuf level + * Now we are "synced" at PerlIOBuf level */ if (b->buf) { if (m->len) { /* - * Unmap the buffer + * Unmap the buffer */ - if (PerlIOMmap_unmap(f) != 0) + if (PerlIOMmap_unmap(aTHX_ f) != 0) code = -1; } else { /* * We seem to have a PerlIOBuf buffer which was not mapped - * remember it in case we need one later + * remember it in case we need one later */ m->bbuf = b->buf; } @@ -3646,21 +4149,21 @@ PerlIOMmap_flush(PerlIO *f) } IV -PerlIOMmap_fill(PerlIO *f) +PerlIOMmap_fill(pTHX_ PerlIO *f) { PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf); IV code = PerlIO_flush(f); if (code == 0 && !b->buf) { - code = PerlIOMmap_map(f); + code = PerlIOMmap_map(aTHX_ f); } if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { - code = PerlIOBuf_fill(f); + code = PerlIOBuf_fill(aTHX_ f); } return code; } IV -PerlIOMmap_close(PerlIO *f) +PerlIOMmap_close(pTHX_ PerlIO *f) { PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap); PerlIOBuf *b = &m->base; @@ -3670,21 +4173,28 @@ PerlIOMmap_close(PerlIO *f) m->bbuf = NULL; b->ptr = b->end = b->buf; } - if (PerlIOBuf_close(f) != 0) + if (PerlIOBuf_close(aTHX_ f) != 0) code = -1; return code; } +PerlIO * +PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + return PerlIOBase_dup(aTHX_ f, o, param, flags); +} + PerlIO_funcs PerlIO_mmap = { "mmap", sizeof(PerlIOMmap), PERLIO_K_BUFFERED, PerlIOBuf_pushed, - PerlIOBase_noop_ok, + PerlIOBuf_popped, PerlIOBuf_open, NULL, PerlIOBase_fileno, + PerlIOMmap_dup, PerlIOBuf_read, PerlIOMmap_unread, PerlIOMmap_write, @@ -3704,58 +4214,37 @@ PerlIO_funcs PerlIO_mmap = { PerlIOBuf_set_ptrcnt, }; -#endif /* HAS_MMAP */ +#endif /* HAS_MMAP */ -void -PerlIO_init(void) -{ - dTHX; -#ifndef WIN32 - call_atexit(PerlIO_cleanup_layers, NULL); -#endif - if (!_perlio) { -#ifndef WIN32 - atexit(&PerlIO_cleanup); -#endif - } -} - -#undef PerlIO_stdin PerlIO * -PerlIO_stdin(void) +Perl_PerlIO_stdin(pTHX) { - if (!_perlio) { - dTHX; + if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &_perlio[1]; + return &PL_perlio[1]; } -#undef PerlIO_stdout PerlIO * -PerlIO_stdout(void) +Perl_PerlIO_stdout(pTHX) { - if (!_perlio) { - dTHX; + if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &_perlio[2]; + return &PL_perlio[2]; } -#undef PerlIO_stderr PerlIO * -PerlIO_stderr(void) +Perl_PerlIO_stderr(pTHX) { - if (!_perlio) { - dTHX; + if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &_perlio[3]; + return &PL_perlio[3]; } /*--------------------------------------------------------------------------------------*/ -#undef PerlIO_getname char * PerlIO_getname(PerlIO *f, char *buf) { @@ -3775,13 +4264,40 @@ PerlIO_getname(PerlIO *f, char *buf) /*--------------------------------------------------------------------------------------*/ /* * Functions which can be called on any kind of PerlIO implemented in - * terms of above + * terms of above */ +#undef PerlIO_fdopen +PerlIO * +PerlIO_fdopen(int fd, const char *mode) +{ + dTHX; + return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL); +} + +#undef PerlIO_open +PerlIO * +PerlIO_open(const char *path, const char *mode) +{ + dTHX; + SV *name = sv_2mortal(newSVpvn(path, strlen(path))); + return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name); +} + +#undef Perlio_reopen +PerlIO * +PerlIO_reopen(const char *path, const char *mode, PerlIO *f) +{ + dTHX; + SV *name = sv_2mortal(newSVpvn(path, strlen(path))); + return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name); +} + #undef PerlIO_getc int PerlIO_getc(PerlIO *f) { + dTHX; STDCHAR buf[1]; SSize_t count = PerlIO_read(f, buf, 1); if (count == 1) { @@ -3794,6 +4310,7 @@ PerlIO_getc(PerlIO *f) int PerlIO_ungetc(PerlIO *f, int ch) { + dTHX; if (ch != EOF) { STDCHAR buf = ch; if (PerlIO_unread(f, &buf, 1) == 1) @@ -3806,6 +4323,7 @@ PerlIO_ungetc(PerlIO *f, int ch) int PerlIO_putc(PerlIO *f, int ch) { + dTHX; STDCHAR buf = ch; return PerlIO_write(f, &buf, 1); } @@ -3814,6 +4332,7 @@ PerlIO_putc(PerlIO *f, int ch) int PerlIO_puts(PerlIO *f, const char *s) { + dTHX; STRLEN len = strlen(s); return PerlIO_write(f, s, len); } @@ -3822,6 +4341,7 @@ PerlIO_puts(PerlIO *f, const char *s) void PerlIO_rewind(PerlIO *f) { + dTHX; PerlIO_seek(f, (Off_t) 0, SEEK_SET); PerlIO_clearerr(f); } @@ -3864,6 +4384,7 @@ PerlIO_printf(PerlIO *f, const char *fmt, ...) int PerlIO_stdoutf(const char *fmt, ...) { + dTHX; va_list ap; int result; va_start(ap, fmt); @@ -3877,7 +4398,7 @@ PerlIO * PerlIO_tmpfile(void) { /* - * I have no idea how portable mkstemp() is ... + * I have no idea how portable mkstemp() is ... */ #if defined(WIN32) || !defined(HAVE_MKSTEMP) dTHX; @@ -3911,13 +4432,13 @@ PerlIO_tmpfile(void) #undef HAS_FSETPOS #undef HAS_FGETPOS -#endif /* USE_SFIO */ -#endif /* PERLIO_IS_STDIO */ +#endif /* USE_SFIO */ +#endif /* PERLIO_IS_STDIO */ /*======================================================================================*/ /* - * Now some functions in terms of above which may be needed even if we are - * not in true PerlIO mode + * Now some functions in terms of above which may be needed even if we are + * not in true PerlIO mode */ #ifndef HAS_FSETPOS @@ -3991,7 +4512,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 */ } @@ -3999,7 +4520,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 */ } @@ -4034,3 +4555,8 @@ PerlIO_sprintf(char *s, int n, const char *fmt, ...) return result; } #endif + + + + +