X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perlio.c;h=c8047f80d2cbf0b11d4df591e53e1a50cbd0f903;hb=ec861bc19fa3da942464628dd3e86e9b82994ca4;hp=a6b45be4f58e3b2f64c82409f5cbfc98b8c3ebe3;hpb=72e44f29ea535faa4a4afab64f5101668334125d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perlio.c b/perlio.c index a6b45be..c8047f8 100644 --- a/perlio.c +++ b/perlio.c @@ -1,6 +1,6 @@ /* perlio.c * - * Copyright (c) 1996-2000, Nick Ing-Simmons + * Copyright (c) 1996-2001, 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. @@ -33,20 +33,6 @@ #undef PerlMemShared_free #define PerlMemShared_free(x) free(x) - -#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")) - { - return 0; - } - Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl",names); - /* NOTREACHED */ - return -1; -} - int perlsio_binmode(FILE *fp, int iotype, int mode) { @@ -62,6 +48,7 @@ perlsio_binmode(FILE *fp, int iotype, int mode) } return 0; # else + dTHX; if (PerlLIO_setmode(fileno(fp), mode) != -1) { # if defined(WIN32) && defined(__BORLANDC__) /* The translation mode of the stream is maintained independent @@ -93,6 +80,19 @@ perlsio_binmode(FILE *fp, int iotype, int mode) #endif } +#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")) + { + return 0; + } + Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl",names); + /* NOTREACHED */ + return -1; +} + int PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names) { @@ -283,7 +283,8 @@ PerlIO_pop(PerlIO *f) if (l) { PerlIO_debug("PerlIO_pop f=%p %s\n",f,l->tab->name); - (*l->tab->Popped)(f); + if (l->tab->Popped) + (*l->tab->Popped)(f); *f = l->next; PerlMemShared_free(l); } @@ -416,9 +417,34 @@ PerlIO_define_layer(PerlIO_funcs *tab) dTHX; HV *stash = gv_stashpv("perlio::Layer", TRUE); SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))),stash); + if (!PerlIO_layer_hv) + { + PerlIO_layer_hv = get_hv("open::layers",GV_ADD|GV_ADDMULTI); + } hv_store(PerlIO_layer_hv,tab->name,strlen(tab->name),sv,0); + PerlIO_debug("define %s %p\n",tab->name,tab); +} + +void +PerlIO_default_buffer(pTHX) +{ + PerlIO_funcs *tab = &PerlIO_perlio; + if (O_BINARY != O_TEXT) + { + tab = &PerlIO_crlf; + } + else + { + if (PerlIO_stdio.Set_ptrcnt) + { + tab = &PerlIO_stdio; + } + } + PerlIO_debug("Pushing %s\n",tab->name); + av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(tab->name,0))); } + PerlIO_funcs * PerlIO_default_layer(I32 n) { @@ -427,16 +453,16 @@ PerlIO_default_layer(I32 n) SV *layer; PerlIO_funcs *tab = &PerlIO_stdio; int len; - if (!PerlIO_layer_hv) + if (!PerlIO_layer_av) { const char *s = PerlEnv_getenv("PERLIO"); + PerlIO_layer_av = get_av("open::layers",GV_ADD|GV_ADDMULTI); newXS("perlio::import",XS_perlio_import,__FILE__); newXS("perlio::unimport",XS_perlio_unimport,__FILE__); #if 0 newXS("io::MODIFY_SCALAR_ATTRIBUTES",XS_io_MODIFY_SCALAR_ATTRIBUTES,__FILE__); #endif - PerlIO_layer_hv = get_hv("open::layers",GV_ADD|GV_ADDMULTI); - PerlIO_layer_av = get_av("open::layers",GV_ADD|GV_ADDMULTI); + PerlIO_define_layer(&PerlIO_raw); PerlIO_define_layer(&PerlIO_unix); PerlIO_define_layer(&PerlIO_perlio); PerlIO_define_layer(&PerlIO_stdio); @@ -444,9 +470,12 @@ PerlIO_default_layer(I32 n) #ifdef HAS_MMAP PerlIO_define_layer(&PerlIO_mmap); #endif + PerlIO_define_layer(&PerlIO_utf8); + PerlIO_define_layer(&PerlIO_byte); av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_unix.name,0))); if (s) { + IV buffered = 0; while (*s) { while (*s && isSPACE((unsigned char)*s)) @@ -462,8 +491,15 @@ PerlIO_default_layer(I32 n) layer = PerlIO_find_layer(s,e-s); if (layer) { + PerlIO_funcs *tab = INT2PTR(PerlIO_funcs *, SvIV(SvRV(layer))); + if ((tab->kind & PERLIO_K_DUMMY) && (tab->kind & PERLIO_K_BUFFERED)) + { + if (!buffered) + PerlIO_default_buffer(aTHX); + } PerlIO_debug("Pushing %.*s\n",(e-s),s); av_push(PerlIO_layer_av,SvREFCNT_inc(layer)); + buffered |= (tab->kind & PERLIO_K_BUFFERED); } else Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",(e-s),s); @@ -475,21 +511,7 @@ PerlIO_default_layer(I32 n) len = av_len(PerlIO_layer_av); if (len < 1) { - if (O_BINARY != O_TEXT) - { - av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_crlf.name,0))); - } - else - { - if (PerlIO_stdio.Set_ptrcnt) - { - av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_stdio.name,0))); - } - else - { - av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_perlio.name,0))); - } - } + PerlIO_default_buffer(aTHX); len = av_len(PerlIO_layer_av); } if (n < 0) @@ -531,7 +553,8 @@ PerlIO_push(PerlIO *f,PerlIO_funcs *tab,const char *mode,const char *arg,STRLEN l->next = *f; l->tab = tab; *f = l; - PerlIO_debug("PerlIO_push f=%p %s %s\n",f,tab->name,(mode) ? mode : "(Null)"); + PerlIO_debug("PerlIO_push f=%p %s %s '%.*s'\n", + f,tab->name,(mode) ? mode : "(Null)",(int) len,arg); if ((*l->tab->Pushed)(f,mode,arg,len) != 0) { PerlIO_pop(f); @@ -541,6 +564,51 @@ PerlIO_push(PerlIO *f,PerlIO_funcs *tab,const char *mode,const char *arg,STRLEN return f; } +IV +PerlIOPop_pushed(PerlIO *f, const char *mode, const char *arg, STRLEN len) +{ + PerlIO_pop(f); + if (*f) + { + PerlIO_flush(f); + PerlIO_pop(f); + return 0; + } + return -1; +} + +IV +PerlIORaw_pushed(PerlIO *f, const char *mode, const char *arg, STRLEN len) +{ + /* Remove the dummy layer */ + PerlIO_pop(f); + /* Pop back to bottom layer */ + if (f && *f) + { + int code = 0; + PerlIO_flush(f); + while (!(PerlIOBase(f)->tab->kind & PERLIO_K_RAW)) + { + if (*PerlIONext(f)) + { + PerlIO_pop(f); + } + else + { + /* Nothing bellow - push unix on top then remove it */ + if (PerlIO_push(f,PerlIO_default_btm(),mode,arg,len)) + { + PerlIO_pop(PerlIONext(f)); + } + break; + } + } + PerlIO_debug(":raw f=%p :%s\n",f,PerlIOBase(f)->tab->name); + return 0; + } + return -1; +} + int PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) { @@ -549,70 +617,77 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) const char *s = names; while (*s) { - while (isSPACE(*s)) - s++; - if (*s == ':') + while (isSPACE(*s) || *s == ':') s++; if (*s) { + STRLEN llen = 0; const char *e = s; const char *as = Nullch; - const char *ae = Nullch; - int count = 0; - while (*e && *e != ':' && !isSPACE(*e)) + STRLEN alen = 0; + if (!isIDFIRST(*s)) { - if (*e == '(') - { - if (!as) - as = e; - count++; - } - else if (*e == ')') - { - if (as && --count == 0) - ae = e; - } - e++; + /* Message is consistent with how attribute lists are passed. + Even though this means "foo : : bar" is 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); + return -1; } - if (e > s) + do { - if ((e - s) == 3 && strncmp(s,"raw",3) == 0) + e++; + } while (isALNUM(*e)); + llen = e-s; + if (*e == '(') + { + int nesting = 1; + as = ++e; + while (nesting) { - /* Pop back to bottom layer */ - if (PerlIONext(f)) + switch (*e++) { - PerlIO_flush(f); - while (PerlIONext(f)) - { - PerlIO_pop(f); - } + case ')': + if (--nesting == 0) + alen = (e-1)-as; + break; + case '(': + ++nesting; + break; + case '\\': + /* It's a nul terminated string, not allowed to \ the terminating null. + Anything other character is passed over. */ + if (*e++) + { + break; + } + /* Drop through */ + case '\0': + e--; + Perl_warn(aTHX_ "perlio: argument list not closed for layer \"%.*s\"",(int)(e - s),s); + return -1; + default: + /* boring. */ + break; } } - else if ((e - s) == 4 && strncmp(s,"utf8",4) == 0) - { - PerlIOBase(f)->flags |= PERLIO_F_UTF8; - } - else if ((e - s) == 5 && strncmp(s,"bytes",5) == 0) - { - PerlIOBase(f)->flags &= ~PERLIO_F_UTF8; - } - else + } + if (e > s) + { + SV *layer = PerlIO_find_layer(s,llen); + if (layer) { - STRLEN len = ((as) ? as : e)-s; - SV *layer = PerlIO_find_layer(s,len); - if (layer) + PerlIO_funcs *tab = INT2PTR(PerlIO_funcs *, SvIV(SvRV(layer))); + if (tab) { - PerlIO_funcs *tab = INT2PTR(PerlIO_funcs *, SvIV(SvRV(layer))); - if (tab) - { - len = (as) ? (ae-(as++)-1) : 0; - if (!PerlIO_push(f,tab,mode,as,len)) - return -1; - } + if (!PerlIO_push(f,tab,mode,as,alen)) + return -1; } - else - Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",(int)len,s); } + else { + Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",(int)llen,s); + return -1; + } } s = e; } @@ -771,7 +846,17 @@ PerlIO_flush(PerlIO *f) { if (f) { - return (*PerlIOBase(f)->tab->Flush)(f); + PerlIO_funcs *tab = PerlIOBase(f)->tab; + if (tab && tab->Flush) + { + return (*tab->Flush)(f); + } + else + { + PerlIO_debug("Cannot flush f=%p :%s\n",f,tab->name); + errno = EINVAL; + return -1; + } } else { @@ -937,6 +1022,158 @@ PerlIO_set_ptrcnt(PerlIO *f, STDCHAR *ptr, int cnt) } /*--------------------------------------------------------------------------------------*/ +/* utf8 and raw dummy layers */ + +IV +PerlIOUtf8_pushed(PerlIO *f, const char *mode, const char *arg, STRLEN len) +{ + if (PerlIONext(f)) + { + PerlIO_funcs *tab = PerlIOBase(f)->tab; + PerlIO_pop(f); + if (tab->kind & PERLIO_K_UTF8) + PerlIOBase(f)->flags |= PERLIO_F_UTF8; + else + PerlIOBase(f)->flags &= ~PERLIO_F_UTF8; + return 0; + } + return -1; +} + +PerlIO * +PerlIOUtf8_fdopen(PerlIO_funcs *self, int fd,const char *mode) +{ + PerlIO_funcs *tab = PerlIO_default_layer(-2); + PerlIO *f = (*tab->Fdopen)(tab,fd,mode); + if (f) + { + PerlIOl *l = PerlIOBase(f); + if (tab->kind & PERLIO_K_UTF8) + l->flags |= PERLIO_F_UTF8; + else + l->flags &= ~PERLIO_F_UTF8; + } + return f; +} + +PerlIO * +PerlIOUtf8_open(PerlIO_funcs *self, const char *path,const char *mode) +{ + PerlIO_funcs *tab = PerlIO_default_layer(-2); + PerlIO *f = (*tab->Open)(tab,path,mode); + if (f) + { + PerlIOl *l = PerlIOBase(f); + if (tab->kind & PERLIO_K_UTF8) + l->flags |= PERLIO_F_UTF8; + else + l->flags &= ~PERLIO_F_UTF8; + } + return f; +} + +PerlIO_funcs PerlIO_utf8 = { + "utf8", + sizeof(PerlIOl), + PERLIO_K_DUMMY|PERLIO_F_UTF8, + NULL, + PerlIOUtf8_fdopen, + PerlIOUtf8_open, + NULL, + PerlIOUtf8_pushed, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* flush */ + NULL, /* fill */ + NULL, + NULL, + NULL, + NULL, + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ +}; + +PerlIO_funcs PerlIO_byte = { + "bytes", + sizeof(PerlIOl), + PERLIO_K_DUMMY, + NULL, + PerlIOUtf8_fdopen, + PerlIOUtf8_open, + NULL, + PerlIOUtf8_pushed, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* flush */ + NULL, /* fill */ + NULL, + NULL, + NULL, + NULL, + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ +}; + +PerlIO * +PerlIORaw_fdopen(PerlIO_funcs *self, int fd,const char *mode) +{ + PerlIO_funcs *tab = PerlIO_default_btm(); + return (*tab->Fdopen)(tab,fd,mode); +} + +PerlIO * +PerlIORaw_open(PerlIO_funcs *self, const char *path,const char *mode) +{ + PerlIO_funcs *tab = PerlIO_default_btm(); + return (*tab->Open)(tab,path,mode); +} + +PerlIO_funcs PerlIO_raw = { + "raw", + sizeof(PerlIOl), + PERLIO_K_DUMMY, + NULL, + PerlIORaw_fdopen, + PerlIORaw_open, + NULL, + PerlIORaw_pushed, + PerlIOBase_popped, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* flush */ + NULL, /* fill */ + NULL, + NULL, + NULL, + NULL, + NULL, /* get_base */ + NULL, /* get_bufsiz */ + NULL, /* get_ptr */ + NULL, /* get_cnt */ + NULL, /* set_ptrcnt */ +}; +/*--------------------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------*/ /* "Methods" of the "base class" */ IV @@ -1198,6 +1435,20 @@ PerlIOUnix_fileno(PerlIO *f) return PerlIOSelf(f,PerlIOUnix)->fd; } +IV +PerlIOUnix_pushed(PerlIO *f, const char *mode, const char *arg, STRLEN len) +{ + IV code = PerlIOBase_pushed(f,mode,arg,len); + if (*PerlIONext(f)) + { + PerlIOUnix *s = PerlIOSelf(f,PerlIOUnix); + s->fd = PerlIO_fileno(PerlIONext(f)); + s->oflags = PerlIOUnix_oflags(mode); + } + PerlIOBase(f)->flags |= PERLIO_F_OPEN; + return code; +} + PerlIO * PerlIOUnix_fdopen(PerlIO_funcs *self, int fd,const char *mode) { @@ -1213,7 +1464,6 @@ PerlIOUnix_fdopen(PerlIO_funcs *self, int fd,const char *mode) PerlIOUnix *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),self,mode,Nullch,0),PerlIOUnix); s->fd = fd; s->oflags = oflags; - PerlIOBase(f)->flags |= PERLIO_F_OPEN; } } return f; @@ -1279,6 +1529,7 @@ PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count) PerlIOBase(f)->flags |= PERLIO_F_EOF; return len; } + PERL_ASYNC_CHECK(); } } @@ -1296,6 +1547,7 @@ PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count) PerlIOBase(f)->flags |= PERLIO_F_ERROR; return len; } + PERL_ASYNC_CHECK(); } } @@ -1329,6 +1581,7 @@ PerlIOUnix_close(PerlIO *f) code = -1; break; } + PERL_ASYNC_CHECK(); } if (code == 0) { @@ -1345,7 +1598,7 @@ PerlIO_funcs PerlIO_unix = { PerlIOUnix_fdopen, PerlIOUnix_open, PerlIOUnix_reopen, - PerlIOBase_pushed, + PerlIOUnix_pushed, PerlIOBase_noop_ok, PerlIOUnix_read, PerlIOBase_unread, @@ -1441,6 +1694,24 @@ PerlIOStdio_fdopen(PerlIO_funcs *self, int fd,const char *mode) return f; } +/* This isn't used yet ... */ +IV +PerlIOStdio_pushed(PerlIO *f, const char *mode, const char *arg, STRLEN len) +{ + dTHX; + if (*PerlIONext(f)) + { + PerlIOStdio *s = PerlIOSelf(f,PerlIOStdio); + char tmode[8]; + FILE *stdio = PerlSIO_fdopen(PerlIO_fileno(PerlIONext(f)),mode = PerlIOStdio_mode(mode,tmode)); + if (stdio) + s->stdio = stdio; + else + return -1; + } + return PerlIOBase_pushed(f,mode,arg,len); +} + #undef PerlIO_importFILE PerlIO * PerlIO_importFILE(FILE *stdio, int fl) @@ -1554,12 +1825,12 @@ IV PerlIOStdio_close(PerlIO *f) { dTHX; -#ifdef HAS_SOCKET +#ifdef HAS_SOCKS5_INIT int optval, optlen = sizeof(int); #endif FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio; return( -#ifdef HAS_SOCKET +#ifdef HAS_SOCKS5_INIT (getsockopt(PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (char *)&optval, &optlen) < 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f)) @@ -1767,15 +2038,31 @@ PerlIO_funcs PerlIO_stdio = { FILE * PerlIO_exportFILE(PerlIO *f, int fl) { + FILE *stdio; PerlIO_flush(f); - /* Should really push stdio discipline when we have them */ - return fdopen(PerlIO_fileno(f),"r+"); + stdio = fdopen(PerlIO_fileno(f),"r+"); + if (stdio) + { + PerlIOStdio *s = PerlIOSelf(PerlIO_push(f,&PerlIO_stdio,"r+",Nullch,0),PerlIOStdio); + s->stdio = stdio; + } + return stdio; } #undef PerlIO_findFILE FILE * PerlIO_findFILE(PerlIO *f) { + PerlIOl *l = *f; + while (l) + { + if (l->tab == &PerlIO_stdio) + { + PerlIOStdio *s = PerlIOSelf(&l,PerlIOStdio); + return s->stdio; + } + l = *PerlIONext(&l); + } return PerlIO_exportFILE(f,0); } @@ -1864,11 +2151,10 @@ PerlIOBuf_flush(PerlIO *f) /* write() the buffer */ STDCHAR *buf = b->buf; STDCHAR *p = buf; - int count; PerlIO *n = PerlIONext(f); while (p < b->ptr) { - count = PerlIO_write(n,p,b->ptr - p); + SSize_t count = PerlIO_write(n,p,b->ptr - p); if (count > 0) { p += count; @@ -2985,6 +3271,8 @@ PerlIO_init(void) } } + + #undef PerlIO_stdin PerlIO * PerlIO_stdin(void)