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
+ else
{
av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_perlio.name,0)));
}
- }
+ }
len = av_len(PerlIO_layer_av);
}
if (n < 0)
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\n",f,tab->name,(mode) ? mode : "(Null)");
if ((*l->tab->Pushed)(f,mode) != 0)
{
PerlIO_pop(f);
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, (names) ? names : "(Null)");
+ f,PerlIOBase(f)->tab->name,iotype,mode, (names) ? names : "(Null)");
if (!names || (O_TEXT != O_BINARY && mode & O_BINARY))
{
PerlIO *top = f;
if (PerlIOBase(top)->tab == &PerlIO_crlf)
{
PerlIO_flush(top);
- PerlIOBase(top)->flags &= ~PERLIO_F_CRLF;
+ PerlIOBase(top)->flags &= ~PERLIO_F_CRLF;
break;
}
top = PerlIONext(top);
int
PerlIO_fast_gets(PerlIO *f)
{
- if (f && *f)
+ if (f && *f && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS))
{
- PerlIOl *l = PerlIOBase(f);
- return (l->tab->Set_ptrcnt != NULL);
+ PerlIO_funcs *tab = PerlIOBase(f)->tab;
+ return (tab->Set_ptrcnt != NULL);
}
return 0;
}
STDCHAR *
PerlIO_get_ptr(PerlIO *f)
{
- return (*PerlIOBase(f)->tab->Get_ptr)(f);
+ PerlIO_funcs *tab = PerlIOBase(f)->tab;
+ if (tab->Get_ptr == NULL)
+ return NULL;
+ return (*tab->Get_ptr)(f);
}
#undef PerlIO_get_cnt
int
PerlIO_get_cnt(PerlIO *f)
{
- return (*PerlIOBase(f)->tab->Get_cnt)(f);
+ PerlIO_funcs *tab = PerlIOBase(f)->tab;
+ if (tab->Get_cnt == NULL)
+ return 0;
+ return (*tab->Get_cnt)(f);
}
#undef PerlIO_set_cnt
void
PerlIO_set_ptrcnt(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");
+ }
(*PerlIOBase(f)->tab->Set_ptrcnt)(f,ptr,cnt);
}
char *s = buf;
IV flags = PerlIOBase(f)->flags;
if (flags & PERLIO_F_CANREAD)
- *s++ = 'r';
+ *s++ = 'r';
if (flags & PERLIO_F_CANWRITE)
- *s++ = 'w';
+ *s++ = 'w';
if (flags & PERLIO_F_CRLF)
- *s++ = 't';
+ *s++ = 't';
else
- *s++ = 'b';
+ *s++ = 'b';
*s = '\0';
return buf;
}
PerlIOl *l = PerlIOBase(f);
const char *omode = mode;
char temp[8];
+ PerlIO_funcs *tab = PerlIOBase(f)->tab;
l->flags &= ~(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|
PERLIO_F_TRUNCATE|PERLIO_F_APPEND);
+ if (tab->Set_ptrcnt != NULL)
+ l->flags |= PERLIO_F_FASTGETS;
if (mode)
{
switch (*mode++)
(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|PERLIO_F_TRUNCATE|PERLIO_F_APPEND);
}
}
+#if 0
PerlIO_debug("PerlIOBase_pushed f=%p %s %s fl=%08x (%s)\n",
f,PerlIOBase(f)->tab->name,(omode) ? omode : "(Null)",
- l->flags,PerlIO_modestr(f,temp));
+ l->flags,PerlIO_modestr(f,temp));
+#endif
return 0;
}
return 0;
}
+extern PerlIO_funcs PerlIO_pending;
+
SSize_t
PerlIOBase_unread(PerlIO *f, const void *vbuf, Size_t count)
{
+#if 0
Off_t old = PerlIO_tell(f);
- if (PerlIO_seek(f,-((Off_t)count),SEEK_CUR) == 0)
+ if (0 && PerlIO_seek(f,-((Off_t)count),SEEK_CUR) == 0)
{
Off_t new = PerlIO_tell(f);
return old - new;
}
- return 0;
+ else
+ {
+ return 0;
+ }
+#else
+ PerlIO_push(f,&PerlIO_pending,"r");
+ return PerlIOBuf_unread(f,vbuf,count);
+#endif
}
IV
*tmode++ = *mode++;
}
*tmode++ = 'b';
- *tmode = '\0';
+ *tmode = '\0';
}
return ret;
}
if (stdio)
{
char tmode[8];
- PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(), self,
+ PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(), self,
(mode = PerlIOStdio_mode(mode,tmode))),
PerlIOStdio);
s->stdio = stdio;
int optval, optlen = sizeof(int);
FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
return(
- (getsockopt(PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (char *)&optval, &optlen) < 0) ?
+ (getsockopt(PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (char *)&optval, &optlen) < 0) ?
fclose(stdio) :
close(PerlIO_fileno(f)));
}
/*--------------------------------------------------------------------------------------*/
/* perlio buffer layer */
+IV
+PerlIOBuf_pushed(PerlIO *f, const char *mode)
+{
+ PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
+ b->posn = PerlIO_tell(PerlIONext(f));
+ return PerlIOBase_pushed(f,mode);
+}
+
PerlIO *
PerlIOBuf_fdopen(PerlIO_funcs *self, int fd, const char *mode)
{
init = 1;
mode++;
}
- if (O_BINARY != O_TEXT)
- {
- int code = PerlLIO_setmode(fd, O_BINARY);
- PerlIO_debug("PerlIOBuf_fdopen %s fd=%d m=%s c=%d\n",tab->name,fd,mode,code);
- }
+#if O_BINARY != O_TEXT
+ /* do something about failing setmode()? --jhi */
+ PerlLIO_setmode(fd, O_BINARY);
+#endif
f = (*tab->Fdopen)(tab,fd,mode);
if (f)
{
PerlIOBuf *b = PerlIOSelf(PerlIO_push(f,self,mode),PerlIOBuf);
- b->posn = PerlIO_tell(PerlIONext(f));
if (init && fd == 2)
{
/* Initial stderr is unbuffered */
PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
- }
+ }
+#if 0
PerlIO_debug("PerlIOBuf_fdopen %s f=%p fd=%d m=%s fl=%08x\n",
self->name,f,fd,mode,PerlIOBase(f)->flags);
+#endif
}
return f;
}
PerlIO *f = (*tab->Open)(tab,path,mode);
if (f)
{
- PerlIOBuf *b = PerlIOSelf(PerlIO_push(f,self,mode),PerlIOBuf);
- b->posn = PerlIO_tell(PerlIONext(f));
+ PerlIO_push(f,self,mode);
}
return f;
}
int code = (*PerlIOBase(next)->tab->Reopen)(path,mode,next);
if (code = 0)
code = (*PerlIOBase(f)->tab->Pushed)(f,mode);
- if (code == 0)
- {
- PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
- b->posn = PerlIO_tell(PerlIONext(f));
- }
return code;
}
if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
{
avail = (b->ptr - b->buf);
- if (avail > (SSize_t) count)
- avail = count;
- b->ptr -= avail;
}
else
{
avail = b->bufsiz;
- if (avail > (SSize_t) count)
- avail = count;
- b->end = b->ptr + avail;
+ b->end = b->buf + avail;
+ b->ptr = b->end;
+ PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
+ b->posn -= b->bufsiz;
}
+ if (avail > (SSize_t) count)
+ avail = count;
if (avail > 0)
{
+ b->ptr -= avail;
buf -= avail;
if (buf != b->ptr)
{
IV
PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence)
{
- PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
- int code = PerlIO_flush(f);
- if (code == 0)
+ IV code;
+ if ((code = PerlIO_flush(f)) == 0)
{
+ PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
code = PerlIO_seek(PerlIONext(f),offset,whence);
if (code == 0)
PerlIOBuf_fdopen,
PerlIOBuf_open,
PerlIOBuf_reopen,
- PerlIOBase_pushed,
+ PerlIOBuf_pushed,
PerlIOBase_noop_ok,
PerlIOBuf_read,
PerlIOBuf_unread,
};
/*--------------------------------------------------------------------------------------*/
+/* Temp layer to hold unread chars when cannot do it any other way */
+
+IV
+PerlIOPending_fill(PerlIO *f)
+{
+ /* Should never happen */
+ PerlIO_flush(f);
+ return 0;
+}
+
+IV
+PerlIOPending_close(PerlIO *f)
+{
+ /* 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)
+{
+ /* A tad tricky - flush pops us, then we seek new top */
+ PerlIO_flush(f);
+ return PerlIO_seek(f,offset,whence);
+}
+
+
+IV
+PerlIOPending_flush(PerlIO *f)
+{
+ PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
+ if (b->buf && b->buf != (STDCHAR *) &b->oneword)
+ {
+ Safefree(b->buf);
+ b->buf = NULL;
+ }
+ PerlIO_pop(f);
+ return 0;
+}
+
+void
+PerlIOPending_set_ptrcnt(PerlIO *f, STDCHAR *ptr, SSize_t cnt)
+{
+ if (cnt <= 0)
+ {
+ PerlIO_flush(f);
+ }
+ else
+ {
+ PerlIOBuf_set_ptrcnt(f,ptr,cnt);
+ }
+}
+
+IV
+PerlIOPending_pushed(PerlIO *f,const char *mode)
+{
+ IV code = PerlIOBuf_pushed(f,mode);
+ 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.
+ */
+ l->flags = (l->flags & ~PERLIO_F_FASTGETS) |
+ (PerlIOBase(PerlIONext(f))->flags & PERLIO_F_FASTGETS);
+ return code;
+}
+
+SSize_t
+PerlIOPending_read(PerlIO *f, void *vbuf, Size_t count)
+{
+ SSize_t avail = PerlIO_get_cnt(f);
+ SSize_t got = 0;
+ if (count < avail)
+ avail = count;
+ if (avail > 0)
+ got = PerlIOBuf_read(f,vbuf,avail);
+ if (got < count)
+ got += PerlIO_read(f,((STDCHAR *) vbuf)+got,count-got);
+ return got;
+}
+
+
+PerlIO_funcs PerlIO_pending = {
+ "pending",
+ sizeof(PerlIOBuf),
+ PERLIO_K_BUFFERED,
+ PerlIOBase_fileno,
+ NULL,
+ NULL,
+ NULL,
+ PerlIOPending_pushed,
+ PerlIOBase_noop_ok,
+ PerlIOPending_read,
+ PerlIOBuf_unread,
+ PerlIOBuf_write,
+ PerlIOPending_seek,
+ PerlIOBuf_tell,
+ PerlIOPending_close,
+ PerlIOPending_flush,
+ PerlIOPending_fill,
+ PerlIOBase_eof,
+ PerlIOBase_error,
+ PerlIOBase_clearerr,
+ PerlIOBuf_setlinebuf,
+ PerlIOBuf_get_base,
+ PerlIOBuf_bufsiz,
+ PerlIOBuf_get_ptr,
+ PerlIOBuf_get_cnt,
+ PerlIOPending_set_ptrcnt,
+};
+
+
+
+/*--------------------------------------------------------------------------------------*/
/* 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.
{
IV code;
PerlIOBase(f)->flags |= PERLIO_F_CRLF;
- code = PerlIOBase_pushed(f,mode);
+ code = PerlIOBuf_pushed(f,mode);
+#if 0
PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08x\n",
f,PerlIOBase(f)->tab->name,(mode) ? mode : "(Null)",
- PerlIOBase(f)->flags);
+ PerlIOBase(f)->flags);
+#endif
return code;
}
return PerlIOBuf_unread(f,vbuf,count);
else
{
- const STDCHAR *buf = (const STDCHAR *) vbuf+count;
+ const STDCHAR *buf = (const STDCHAR *) vbuf+count;
PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
SSize_t unread = 0;
if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
{
b->end = b->ptr = b->buf + b->bufsiz;
PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
+ b->posn -= b->bufsiz;
}
while (count > 0 && b->ptr > b->buf)
{
chk--;
}
chk -= cnt;
-
+
if (ptr != chk)
{
dTHX;
Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08x nl=%p e=%p for %d",
- ptr, chk, flags, c->nl, b->end, cnt);
+ ptr, chk, flags, c->nl, b->end, cnt);
}
}
if (c->nl)
return PerlIOBuf_write(f,vbuf,count);
else
{
- PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
+ PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
const STDCHAR *buf = (const STDCHAR *) vbuf;
const STDCHAR *ebuf = buf+count;
if (!b->buf)
m->bbuf = b->buf;
}
}
- return PerlIOBuf_unread(f,vbuf,count);
+return PerlIOBuf_unread(f,vbuf,count);
}
SSize_t
PerlIOBuf_fdopen,
PerlIOBuf_open,
PerlIOBuf_reopen,
- PerlIOBase_pushed,
+ PerlIOBuf_pushed,
PerlIOBase_noop_ok,
PerlIOBuf_read,
PerlIOMmap_unread,