Add TOPm1s to peek at the second topmost stack item.
[p5sagit/p5-mst-13.2.git] / perlio.c
CommitLineData
760ac839 1/* perlio.c
2 *
1761cee5 3 * Copyright (c) 1996-2000, Nick Ing-Simmons
760ac839 4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10#define VOIDUSED 1
12ae5dfc 11#ifdef PERL_MICRO
12# include "uconfig.h"
13#else
14# include "config.h"
15#endif
760ac839 16
6f9d8c32 17#define PERLIO_NOT_STDIO 0
760ac839 18#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
6f9d8c32 19/* #define PerlIO FILE */
760ac839 20#endif
21/*
6f9d8c32 22 * This file provides those parts of PerlIO abstraction
88b61e10 23 * which are not #defined in perlio.h.
6f9d8c32 24 * Which these are depends on various Configure #ifdef's
760ac839 25 */
26
27#include "EXTERN.h"
864dbfa3 28#define PERL_IN_PERLIO_C
760ac839 29#include "perl.h"
30
ac27b0f5 31#ifndef PERLIO_LAYERS
32int
33PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
34{
95c70f20 35 if (!names || !*names || strEQ(names,":crlf") || strEQ(names,":raw"))
36 {
37 return 0;
88b61e10 38 }
ac27b0f5 39 Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl",names);
5a2dd417 40 /* NOTREACHED */
88b61e10 41 return -1;
ac27b0f5 42}
60382766 43
44int
f5b9d040 45perlsio_binmode(FILE *fp, int iotype, int mode)
60382766 46{
47/* This used to be contents of do_binmode in doio.c */
48#ifdef DOSISH
49# if defined(atarist) || defined(__MINT__)
f5b9d040 50 if (!fflush(fp)) {
60382766 51 if (mode & O_BINARY)
52 ((FILE*)fp)->_flag |= _IOBIN;
53 else
54 ((FILE*)fp)->_flag &= ~ _IOBIN;
55 return 1;
56 }
57 return 0;
58# else
f5b9d040 59 if (PerlLIO_setmode(fileno(fp), mode) != -1) {
60382766 60# if defined(WIN32) && defined(__BORLANDC__)
61 /* The translation mode of the stream is maintained independent
62 * of the translation mode of the fd in the Borland RTL (heavy
63 * digging through their runtime sources reveal). User has to
64 * set the mode explicitly for the stream (though they don't
65 * document this anywhere). GSAR 97-5-24
66 */
f5b9d040 67 fseek(fp,0L,0);
60382766 68 if (mode & O_BINARY)
f5b9d040 69 fp->flags |= _F_BIN;
60382766 70 else
f5b9d040 71 fp->flags &= ~ _F_BIN;
60382766 72# endif
73 return 1;
74 }
75 else
76 return 0;
77# endif
78#else
79# if defined(USEMYBINMODE)
80 if (my_binmode(fp, iotype, mode) != FALSE)
81 return 1;
82 else
83 return 0;
84# else
85 return 1;
86# endif
87#endif
88}
89
f5b9d040 90int
91PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
92{
93 return perlsio_binmode(fp,iotype,mode);
94}
60382766 95
ac27b0f5 96#endif
97
32e30700 98
6f9d8c32 99#ifdef PERLIO_IS_STDIO
760ac839 100
101void
8ac85365 102PerlIO_init(void)
760ac839 103{
6f9d8c32 104 /* Does nothing (yet) except force this file to be included
760ac839 105 in perl binary. That allows this file to force inclusion
6f9d8c32 106 of other functions that may be required by loadable
107 extensions e.g. for FileHandle::tmpfile
760ac839 108 */
109}
110
33dcbb9a 111#undef PerlIO_tmpfile
112PerlIO *
8ac85365 113PerlIO_tmpfile(void)
33dcbb9a 114{
115 return tmpfile();
116}
117
760ac839 118#else /* PERLIO_IS_STDIO */
119
120#ifdef USE_SFIO
121
122#undef HAS_FSETPOS
123#undef HAS_FGETPOS
124
6f9d8c32 125/* This section is just to make sure these functions
760ac839 126 get pulled in from libsfio.a
127*/
128
129#undef PerlIO_tmpfile
130PerlIO *
c78749f2 131PerlIO_tmpfile(void)
760ac839 132{
133 return sftmp(0);
134}
135
136void
c78749f2 137PerlIO_init(void)
760ac839 138{
6f9d8c32 139 /* Force this file to be included in perl binary. Which allows
140 * this file to force inclusion of other functions that may be
141 * required by loadable extensions e.g. for FileHandle::tmpfile
760ac839 142 */
143
144 /* Hack
145 * sfio does its own 'autoflush' on stdout in common cases.
6f9d8c32 146 * Flush results in a lot of lseek()s to regular files and
760ac839 147 * lot of small writes to pipes.
148 */
149 sfset(sfstdout,SF_SHARE,0);
150}
151
17c3b450 152#else /* USE_SFIO */
6f9d8c32 153/*======================================================================================*/
6f9d8c32 154/* Implement all the PerlIO interface ourselves.
9e353e3b 155 */
760ac839 156
76ced9ad 157#include "perliol.h"
158
b1ef6e3b 159/* We _MUST_ have <unistd.h> if we are using lseek() and may have large files */
02f66e2f 160#ifdef I_UNISTD
161#include <unistd.h>
162#endif
06da4f11 163#ifdef HAS_MMAP
164#include <sys/mman.h>
165#endif
166
f3862f8b 167#include "XSUB.h"
02f66e2f 168
88b61e10 169void PerlIO_debug(const char *fmt,...) __attribute__((format(__printf__,1,2)));
6f9d8c32 170
6f9d8c32 171void
88b61e10 172PerlIO_debug(const char *fmt,...)
6f9d8c32 173{
adb71456 174 dTHX;
6f9d8c32 175 static int dbg = 0;
88b61e10 176 va_list ap;
177 va_start(ap,fmt);
6f9d8c32 178 if (!dbg)
179 {
00b02797 180 char *s = PerlEnv_getenv("PERLIO_DEBUG");
6f9d8c32 181 if (s && *s)
00b02797 182 dbg = PerlLIO_open3(s,O_WRONLY|O_CREAT|O_APPEND,0666);
6f9d8c32 183 else
184 dbg = -1;
185 }
186 if (dbg > 0)
187 {
188 dTHX;
6f9d8c32 189 SV *sv = newSVpvn("",0);
190 char *s;
191 STRLEN len;
05d1247b 192 s = CopFILE(PL_curcop);
193 if (!s)
194 s = "(none)";
195 Perl_sv_catpvf(aTHX_ sv, "%s:%"IVdf" ", s, (IV)CopLINE(PL_curcop));
c7fc522f 196 Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
197
6f9d8c32 198 s = SvPV(sv,len);
00b02797 199 PerlLIO_write(dbg,s,len);
6f9d8c32 200 SvREFCNT_dec(sv);
201 }
88b61e10 202 va_end(ap);
6f9d8c32 203}
204
9e353e3b 205/*--------------------------------------------------------------------------------------*/
206
9e353e3b 207/* Inner level routines */
208
b1ef6e3b 209/* Table of pointers to the PerlIO structs (malloc'ed) */
05d1247b 210PerlIO *_perlio = NULL;
211#define PERLIO_TABLE_SIZE 64
6f9d8c32 212
760ac839 213PerlIO *
5f1a76d0 214PerlIO_allocate(pTHX)
6f9d8c32 215{
f3862f8b 216 /* Find a free slot in the table, allocating new table as necessary */
5f1a76d0 217 PerlIO **last;
6f9d8c32 218 PerlIO *f;
5f1a76d0 219 last = &_perlio;
05d1247b 220 while ((f = *last))
6f9d8c32 221 {
05d1247b 222 int i;
223 last = (PerlIO **)(f);
224 for (i=1; i < PERLIO_TABLE_SIZE; i++)
6f9d8c32 225 {
05d1247b 226 if (!*++f)
6f9d8c32 227 {
6f9d8c32 228 return f;
229 }
6f9d8c32 230 }
6f9d8c32 231 }
5f1a76d0 232 f = PerlMemShared_calloc(PERLIO_TABLE_SIZE,sizeof(PerlIO));
05d1247b 233 if (!f)
5f1a76d0 234 {
235 return NULL;
236 }
05d1247b 237 *last = f;
238 return f+1;
239}
240
241void
5f1a76d0 242PerlIO_cleantable(pTHX_ PerlIO **tablep)
05d1247b 243{
244 PerlIO *table = *tablep;
245 if (table)
246 {
247 int i;
5f1a76d0 248 PerlIO_cleantable(aTHX_ (PerlIO **) &(table[0]));
05d1247b 249 for (i=PERLIO_TABLE_SIZE-1; i > 0; i--)
250 {
251 PerlIO *f = table+i;
60382766 252 if (*f)
3789aae2 253 {
254 PerlIO_close(f);
255 }
05d1247b 256 }
5f1a76d0 257 PerlMemShared_free(table);
05d1247b 258 *tablep = NULL;
259 }
260}
261
4a4a6116 262HV *PerlIO_layer_hv;
263AV *PerlIO_layer_av;
264
05d1247b 265void
5f1a76d0 266PerlIO_cleanup()
05d1247b 267{
5f1a76d0 268 dTHX;
269 PerlIO_cleantable(aTHX_ &_perlio);
6f9d8c32 270}
271
9e353e3b 272void
273PerlIO_pop(PerlIO *f)
760ac839 274{
5f1a76d0 275 dTHX;
9e353e3b 276 PerlIOl *l = *f;
277 if (l)
6f9d8c32 278 {
86295796 279 PerlIO_debug("PerlIO_pop f=%p %s\n",f,l->tab->name);
06da4f11 280 (*l->tab->Popped)(f);
9e353e3b 281 *f = l->next;
5f1a76d0 282 PerlMemShared_free(l);
6f9d8c32 283 }
6f9d8c32 284}
285
9e353e3b 286/*--------------------------------------------------------------------------------------*/
b931b1d9 287/* XS Interface for perl code */
9e353e3b 288
b931b1d9 289XS(XS_perlio_import)
f3862f8b 290{
291 dXSARGS;
292 GV *gv = CvGV(cv);
293 char *s = GvNAME(gv);
294 STRLEN l = GvNAMELEN(gv);
295 PerlIO_debug("%.*s\n",(int) l,s);
296 XSRETURN_EMPTY;
297}
298
b931b1d9 299XS(XS_perlio_unimport)
f3862f8b 300{
301 dXSARGS;
302 GV *gv = CvGV(cv);
303 char *s = GvNAME(gv);
304 STRLEN l = GvNAMELEN(gv);
305 PerlIO_debug("%.*s\n",(int) l,s);
306 XSRETURN_EMPTY;
307}
308
f3862f8b 309SV *
ac27b0f5 310PerlIO_find_layer(const char *name, STRLEN len)
f3862f8b 311{
312 dTHX;
313 SV **svp;
314 SV *sv;
315 if (len <= 0)
316 len = strlen(name);
317 svp = hv_fetch(PerlIO_layer_hv,name,len,0);
318 if (svp && (sv = *svp) && SvROK(sv))
319 return *svp;
320 return NULL;
321}
322
b13b2135 323
324static int
325perlio_mg_set(pTHX_ SV *sv, MAGIC *mg)
326{
327 if (SvROK(sv))
328 {
b931b1d9 329 IO *io = GvIOn((GV *)SvRV(sv));
b13b2135 330 PerlIO *ifp = IoIFP(io);
331 PerlIO *ofp = IoOFP(io);
332 AV *av = (AV *) mg->mg_obj;
4659c93f 333 Perl_warn(aTHX_ "set %"SVf" %p %p %p",sv,io,ifp,ofp);
b13b2135 334 }
335 return 0;
336}
337
338static int
339perlio_mg_get(pTHX_ SV *sv, MAGIC *mg)
340{
341 if (SvROK(sv))
342 {
b931b1d9 343 IO *io = GvIOn((GV *)SvRV(sv));
b13b2135 344 PerlIO *ifp = IoIFP(io);
345 PerlIO *ofp = IoOFP(io);
346 AV *av = (AV *) mg->mg_obj;
4659c93f 347 Perl_warn(aTHX_ "get %"SVf" %p %p %p",sv,io,ifp,ofp);
b13b2135 348 }
349 return 0;
350}
351
352static int
353perlio_mg_clear(pTHX_ SV *sv, MAGIC *mg)
354{
4659c93f 355 Perl_warn(aTHX_ "clear %"SVf,sv);
b13b2135 356 return 0;
357}
358
359static int
360perlio_mg_free(pTHX_ SV *sv, MAGIC *mg)
361{
4659c93f 362 Perl_warn(aTHX_ "free %"SVf,sv);
b13b2135 363 return 0;
364}
365
366MGVTBL perlio_vtab = {
367 perlio_mg_get,
368 perlio_mg_set,
369 NULL, /* len */
370 NULL,
371 perlio_mg_free
372};
373
374XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
375{
376 dXSARGS;
377 SV *sv = SvRV(ST(1));
378 AV *av = newAV();
379 MAGIC *mg;
380 int count = 0;
381 int i;
382 sv_magic(sv, (SV *)av, '~', NULL, 0);
383 SvRMAGICAL_off(sv);
384 mg = mg_find(sv,'~');
385 mg->mg_virtual = &perlio_vtab;
386 mg_magical(sv);
4659c93f 387 Perl_warn(aTHX_ "attrib %"SVf,sv);
b13b2135 388 for (i=2; i < items; i++)
389 {
390 STRLEN len;
ac27b0f5 391 const char *name = SvPV(ST(i),len);
b13b2135 392 SV *layer = PerlIO_find_layer(name,len);
393 if (layer)
394 {
395 av_push(av,SvREFCNT_inc(layer));
396 }
397 else
398 {
399 ST(count) = ST(i);
400 count++;
401 }
402 }
403 SvREFCNT_dec(av);
404 XSRETURN(count);
405}
406
f3862f8b 407void
408PerlIO_define_layer(PerlIO_funcs *tab)
409{
410 dTHX;
b931b1d9 411 HV *stash = gv_stashpv("perlio::Layer", TRUE);
e7778b43 412 SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))),stash);
f3862f8b 413 hv_store(PerlIO_layer_hv,tab->name,strlen(tab->name),sv,0);
414}
415
416PerlIO_funcs *
417PerlIO_default_layer(I32 n)
418{
419 dTHX;
420 SV **svp;
421 SV *layer;
422 PerlIO_funcs *tab = &PerlIO_stdio;
423 int len;
424 if (!PerlIO_layer_hv)
425 {
ac27b0f5 426 const char *s = PerlEnv_getenv("PERLIO");
b931b1d9 427 newXS("perlio::import",XS_perlio_import,__FILE__);
428 newXS("perlio::unimport",XS_perlio_unimport,__FILE__);
429#if 0
b13b2135 430 newXS("io::MODIFY_SCALAR_ATTRIBUTES",XS_io_MODIFY_SCALAR_ATTRIBUTES,__FILE__);
b931b1d9 431#endif
432 PerlIO_layer_hv = get_hv("open::layers",GV_ADD|GV_ADDMULTI);
433 PerlIO_layer_av = get_av("open::layers",GV_ADD|GV_ADDMULTI);
f3862f8b 434 PerlIO_define_layer(&PerlIO_unix);
f3862f8b 435 PerlIO_define_layer(&PerlIO_perlio);
436 PerlIO_define_layer(&PerlIO_stdio);
66ecd56b 437 PerlIO_define_layer(&PerlIO_crlf);
06da4f11 438#ifdef HAS_MMAP
439 PerlIO_define_layer(&PerlIO_mmap);
440#endif
f3862f8b 441 av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_unix.name,0)));
442 if (s)
443 {
444 while (*s)
445 {
00b02797 446 while (*s && isSPACE((unsigned char)*s))
f3862f8b 447 s++;
448 if (*s)
449 {
ac27b0f5 450 const char *e = s;
f3862f8b 451 SV *layer;
00b02797 452 while (*e && !isSPACE((unsigned char)*e))
f3862f8b 453 e++;
ac27b0f5 454 if (*s == ':')
455 s++;
f3862f8b 456 layer = PerlIO_find_layer(s,e-s);
457 if (layer)
458 {
459 PerlIO_debug("Pushing %.*s\n",(e-s),s);
460 av_push(PerlIO_layer_av,SvREFCNT_inc(layer));
461 }
462 else
ef0f9817 463 Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",(e-s),s);
f3862f8b 464 s = e;
465 }
466 }
467 }
468 }
469 len = av_len(PerlIO_layer_av);
470 if (len < 1)
471 {
f5b9d040 472 if (O_BINARY != O_TEXT)
f3862f8b 473 {
f5b9d040 474 av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_crlf.name,0)));
f3862f8b 475 }
476 else
a4d3c1d3 477 {
f5b9d040 478 if (PerlIO_stdio.Set_ptrcnt)
479 {
480 av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_stdio.name,0)));
481 }
a4d3c1d3 482 else
f5b9d040 483 {
484 av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_perlio.name,0)));
485 }
a4d3c1d3 486 }
f3862f8b 487 len = av_len(PerlIO_layer_av);
488 }
489 if (n < 0)
490 n += len+1;
491 svp = av_fetch(PerlIO_layer_av,n,0);
492 if (svp && (layer = *svp) && SvROK(layer) && SvIOK((layer = SvRV(layer))))
493 {
e7778b43 494 tab = INT2PTR(PerlIO_funcs *, SvIV(layer));
f3862f8b 495 }
496 /* PerlIO_debug("Layer %d is %s\n",n,tab->name); */
497 return tab;
498}
499
60382766 500#define PerlIO_default_top() PerlIO_default_layer(-1)
501#define PerlIO_default_btm() PerlIO_default_layer(0)
502
503void
504PerlIO_stdstreams()
505{
506 if (!_perlio)
507 {
5f1a76d0 508 dTHX;
509 PerlIO_allocate(aTHX);
f5b9d040 510 PerlIO_fdopen(0,"Ir" PERLIO_STDTEXT);
511 PerlIO_fdopen(1,"Iw" PERLIO_STDTEXT);
512 PerlIO_fdopen(2,"Iw" PERLIO_STDTEXT);
60382766 513 }
514}
515
516PerlIO *
517PerlIO_push(PerlIO *f,PerlIO_funcs *tab,const char *mode)
518{
5f1a76d0 519 dTHX;
60382766 520 PerlIOl *l = NULL;
5f1a76d0 521 l = PerlMemShared_calloc(tab->size,sizeof(char));
60382766 522 if (l)
523 {
524 Zero(l,tab->size,char);
525 l->next = *f;
526 l->tab = tab;
527 *f = l;
a4d3c1d3 528 PerlIO_debug("PerlIO_push f=%p %s %s\n",f,tab->name,(mode) ? mode : "(Null)");
60382766 529 if ((*l->tab->Pushed)(f,mode) != 0)
530 {
531 PerlIO_pop(f);
532 return NULL;
533 }
534 }
535 return f;
536}
537
ac27b0f5 538int
539PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
540{
541 if (names)
542 {
543 const char *s = names;
544 while (*s)
545 {
546 while (isSPACE(*s))
547 s++;
548 if (*s == ':')
549 s++;
550 if (*s)
551 {
552 const char *e = s;
553 while (*e && *e != ':' && !isSPACE(*e))
554 e++;
555 if (e > s)
556 {
60382766 557 if ((e - s) == 3 && strncmp(s,"raw",3) == 0)
ac27b0f5 558 {
60382766 559 /* Pop back to bottom layer */
560 if (PerlIONext(f))
ac27b0f5 561 {
60382766 562 PerlIO_flush(f);
563 while (PerlIONext(f))
564 {
565 PerlIO_pop(f);
566 }
ac27b0f5 567 }
568 }
569 else
60382766 570 {
571 SV *layer = PerlIO_find_layer(s,e-s);
572 if (layer)
573 {
574 PerlIO_funcs *tab = INT2PTR(PerlIO_funcs *, SvIV(SvRV(layer)));
575 if (tab)
576 {
577 PerlIO *new = PerlIO_push(f,tab,mode);
578 if (!new)
579 return -1;
580 }
581 }
582 else
583 Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",(int)(e-s),s);
584 }
ac27b0f5 585 }
586 s = e;
587 }
588 }
589 }
590 return 0;
591}
592
f3862f8b 593
9e353e3b 594
60382766 595/*--------------------------------------------------------------------------------------*/
596/* Given the abstraction above the public API functions */
597
598int
f5b9d040 599PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
76ced9ad 600{
86295796 601 PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n",
a4d3c1d3 602 f,PerlIOBase(f)->tab->name,iotype,mode, (names) ? names : "(Null)");
60382766 603 if (!names || (O_TEXT != O_BINARY && mode & O_BINARY))
76ced9ad 604 {
f5b9d040 605 PerlIO *top = f;
60382766 606 PerlIOl *l;
607 while (l = *top)
76ced9ad 608 {
60382766 609 if (PerlIOBase(top)->tab == &PerlIO_crlf)
610 {
611 PerlIO_flush(top);
a4d3c1d3 612 PerlIOBase(top)->flags &= ~PERLIO_F_CRLF;
60382766 613 break;
614 }
615 top = PerlIONext(top);
76ced9ad 616 }
617 }
f5b9d040 618 return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE;
619}
620
621#undef PerlIO__close
622int
623PerlIO__close(PerlIO *f)
624{
625 return (*PerlIOBase(f)->tab->Close)(f);
76ced9ad 626}
627
5f1a76d0 628#undef PerlIO_fdupopen
629PerlIO *
630PerlIO_fdupopen(pTHX_ PerlIO *f)
631{
632 char buf[8];
633 int fd = PerlLIO_dup(PerlIO_fileno(f));
634 PerlIO *new = PerlIO_fdopen(fd,PerlIO_modestr(f,buf));
635 if (new)
636 {
637 Off_t posn = PerlIO_tell(f);
638 PerlIO_seek(new,posn,SEEK_SET);
639 }
640 return new;
641}
f5b9d040 642
b931b1d9 643#undef PerlIO_close
644int
645PerlIO_close(PerlIO *f)
646{
647 int code = (*PerlIOBase(f)->tab->Close)(f);
648 while (*f)
649 {
650 PerlIO_pop(f);
651 }
652 return code;
653}
654
655#undef PerlIO_fileno
656int
657PerlIO_fileno(PerlIO *f)
658{
659 return (*PerlIOBase(f)->tab->Fileno)(f);
660}
661
662
663
9e353e3b 664#undef PerlIO_fdopen
665PerlIO *
666PerlIO_fdopen(int fd, const char *mode)
667{
668 PerlIO_funcs *tab = PerlIO_default_top();
f3862f8b 669 if (!_perlio)
670 PerlIO_stdstreams();
06da4f11 671 return (*tab->Fdopen)(tab,fd,mode);
9e353e3b 672}
673
6f9d8c32 674#undef PerlIO_open
675PerlIO *
676PerlIO_open(const char *path, const char *mode)
677{
9e353e3b 678 PerlIO_funcs *tab = PerlIO_default_top();
f3862f8b 679 if (!_perlio)
680 PerlIO_stdstreams();
06da4f11 681 return (*tab->Open)(tab,path,mode);
6f9d8c32 682}
683
9e353e3b 684#undef PerlIO_reopen
685PerlIO *
686PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
6f9d8c32 687{
9e353e3b 688 if (f)
6f9d8c32 689 {
9e353e3b 690 PerlIO_flush(f);
691 if ((*PerlIOBase(f)->tab->Reopen)(path,mode,f) == 0)
692 {
06da4f11 693 if ((*PerlIOBase(f)->tab->Pushed)(f,mode) == 0)
694 return f;
9e353e3b 695 }
696 return NULL;
6f9d8c32 697 }
9e353e3b 698 else
699 return PerlIO_open(path,mode);
760ac839 700}
701
9e353e3b 702#undef PerlIO_read
703SSize_t
704PerlIO_read(PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 705{
9e353e3b 706 return (*PerlIOBase(f)->tab->Read)(f,vbuf,count);
760ac839 707}
708
313ca112 709#undef PerlIO_unread
710SSize_t
711PerlIO_unread(PerlIO *f, const void *vbuf, Size_t count)
760ac839 712{
313ca112 713 return (*PerlIOBase(f)->tab->Unread)(f,vbuf,count);
760ac839 714}
715
9e353e3b 716#undef PerlIO_write
717SSize_t
718PerlIO_write(PerlIO *f, const void *vbuf, Size_t count)
760ac839 719{
9e353e3b 720 return (*PerlIOBase(f)->tab->Write)(f,vbuf,count);
760ac839 721}
722
9e353e3b 723#undef PerlIO_seek
6f9d8c32 724int
9e353e3b 725PerlIO_seek(PerlIO *f, Off_t offset, int whence)
760ac839 726{
9e353e3b 727 return (*PerlIOBase(f)->tab->Seek)(f,offset,whence);
760ac839 728}
729
9e353e3b 730#undef PerlIO_tell
731Off_t
732PerlIO_tell(PerlIO *f)
760ac839 733{
9e353e3b 734 return (*PerlIOBase(f)->tab->Tell)(f);
760ac839 735}
736
9e353e3b 737#undef PerlIO_flush
6f9d8c32 738int
9e353e3b 739PerlIO_flush(PerlIO *f)
760ac839 740{
6f9d8c32 741 if (f)
742 {
9e353e3b 743 return (*PerlIOBase(f)->tab->Flush)(f);
6f9d8c32 744 }
9e353e3b 745 else
6f9d8c32 746 {
05d1247b 747 PerlIO **table = &_perlio;
9e353e3b 748 int code = 0;
05d1247b 749 while ((f = *table))
6f9d8c32 750 {
05d1247b 751 int i;
752 table = (PerlIO **)(f++);
753 for (i=1; i < PERLIO_TABLE_SIZE; i++)
9e353e3b 754 {
755 if (*f && PerlIO_flush(f) != 0)
756 code = -1;
05d1247b 757 f++;
9e353e3b 758 }
6f9d8c32 759 }
9e353e3b 760 return code;
6f9d8c32 761 }
760ac839 762}
763
06da4f11 764#undef PerlIO_fill
765int
766PerlIO_fill(PerlIO *f)
767{
768 return (*PerlIOBase(f)->tab->Fill)(f);
769}
770
f3862f8b 771#undef PerlIO_isutf8
772int
773PerlIO_isutf8(PerlIO *f)
774{
775 return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
776}
777
9e353e3b 778#undef PerlIO_eof
6f9d8c32 779int
9e353e3b 780PerlIO_eof(PerlIO *f)
760ac839 781{
9e353e3b 782 return (*PerlIOBase(f)->tab->Eof)(f);
783}
784
785#undef PerlIO_error
786int
787PerlIO_error(PerlIO *f)
788{
789 return (*PerlIOBase(f)->tab->Error)(f);
790}
791
792#undef PerlIO_clearerr
793void
794PerlIO_clearerr(PerlIO *f)
795{
f5b9d040 796 if (f && *f)
797 (*PerlIOBase(f)->tab->Clearerr)(f);
9e353e3b 798}
799
800#undef PerlIO_setlinebuf
801void
802PerlIO_setlinebuf(PerlIO *f)
803{
804 (*PerlIOBase(f)->tab->Setlinebuf)(f);
805}
806
807#undef PerlIO_has_base
808int
809PerlIO_has_base(PerlIO *f)
810{
811 if (f && *f)
6f9d8c32 812 {
9e353e3b 813 return (PerlIOBase(f)->tab->Get_base != NULL);
6f9d8c32 814 }
9e353e3b 815 return 0;
760ac839 816}
817
9e353e3b 818#undef PerlIO_fast_gets
819int
820PerlIO_fast_gets(PerlIO *f)
760ac839 821{
5e2ab84b 822 if (f && *f && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS))
6f9d8c32 823 {
5e2ab84b 824 PerlIO_funcs *tab = PerlIOBase(f)->tab;
825 return (tab->Set_ptrcnt != NULL);
6f9d8c32 826 }
9e353e3b 827 return 0;
828}
829
830#undef PerlIO_has_cntptr
831int
832PerlIO_has_cntptr(PerlIO *f)
833{
834 if (f && *f)
835 {
836 PerlIO_funcs *tab = PerlIOBase(f)->tab;
837 return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
838 }
839 return 0;
840}
841
842#undef PerlIO_canset_cnt
843int
844PerlIO_canset_cnt(PerlIO *f)
845{
846 if (f && *f)
847 {
c7fc522f 848 PerlIOl *l = PerlIOBase(f);
849 return (l->tab->Set_ptrcnt != NULL);
9e353e3b 850 }
c7fc522f 851 return 0;
760ac839 852}
853
854#undef PerlIO_get_base
888911fc 855STDCHAR *
a20bf0c3 856PerlIO_get_base(PerlIO *f)
760ac839 857{
9e353e3b 858 return (*PerlIOBase(f)->tab->Get_base)(f);
859}
860
861#undef PerlIO_get_bufsiz
862int
863PerlIO_get_bufsiz(PerlIO *f)
864{
865 return (*PerlIOBase(f)->tab->Get_bufsiz)(f);
866}
867
868#undef PerlIO_get_ptr
869STDCHAR *
870PerlIO_get_ptr(PerlIO *f)
871{
5e2ab84b 872 PerlIO_funcs *tab = PerlIOBase(f)->tab;
873 if (tab->Get_ptr == NULL)
874 return NULL;
875 return (*tab->Get_ptr)(f);
9e353e3b 876}
877
878#undef PerlIO_get_cnt
05d1247b 879int
9e353e3b 880PerlIO_get_cnt(PerlIO *f)
881{
5e2ab84b 882 PerlIO_funcs *tab = PerlIOBase(f)->tab;
883 if (tab->Get_cnt == NULL)
884 return 0;
885 return (*tab->Get_cnt)(f);
9e353e3b 886}
887
888#undef PerlIO_set_cnt
889void
05d1247b 890PerlIO_set_cnt(PerlIO *f,int cnt)
9e353e3b 891{
f3862f8b 892 (*PerlIOBase(f)->tab->Set_ptrcnt)(f,NULL,cnt);
9e353e3b 893}
894
895#undef PerlIO_set_ptrcnt
896void
05d1247b 897PerlIO_set_ptrcnt(PerlIO *f, STDCHAR *ptr, int cnt)
9e353e3b 898{
5e2ab84b 899 PerlIO_funcs *tab = PerlIOBase(f)->tab;
900 if (tab->Set_ptrcnt == NULL)
901 {
902 dTHX;
903 Perl_croak(aTHX_ "PerlIO buffer snooping abuse");
904 }
f3862f8b 905 (*PerlIOBase(f)->tab->Set_ptrcnt)(f,ptr,cnt);
9e353e3b 906}
907
908/*--------------------------------------------------------------------------------------*/
909/* "Methods" of the "base class" */
910
911IV
912PerlIOBase_fileno(PerlIO *f)
913{
914 return PerlIO_fileno(PerlIONext(f));
915}
916
f5b9d040 917char *
918PerlIO_modestr(PerlIO *f,char *buf)
919{
920 char *s = buf;
921 IV flags = PerlIOBase(f)->flags;
5f1a76d0 922 if (flags & PERLIO_F_APPEND)
923 {
924 *s++ = 'a';
925 if (flags & PERLIO_F_CANREAD)
926 {
927 *s++ = '+';
928 }
929 }
930 else if (flags & PERLIO_F_CANREAD)
931 {
932 *s++ = 'r';
933 if (flags & PERLIO_F_CANWRITE)
934 *s++ = '+';
935 }
936 else if (flags & PERLIO_F_CANWRITE)
937 {
938 *s++ = 'w';
939 if (flags & PERLIO_F_CANREAD)
940 {
941 *s++ = '+';
942 }
943 }
944#if O_TEXT != O_BINARY
945 if (!(flags & PERLIO_F_CRLF))
a4d3c1d3 946 *s++ = 'b';
5f1a76d0 947#endif
f5b9d040 948 *s = '\0';
949 return buf;
950}
951
76ced9ad 952IV
953PerlIOBase_pushed(PerlIO *f, const char *mode)
9e353e3b 954{
76ced9ad 955 PerlIOl *l = PerlIOBase(f);
f5b9d040 956 const char *omode = mode;
957 char temp[8];
5e2ab84b 958 PerlIO_funcs *tab = PerlIOBase(f)->tab;
76ced9ad 959 l->flags &= ~(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|
f5b9d040 960 PERLIO_F_TRUNCATE|PERLIO_F_APPEND);
5e2ab84b 961 if (tab->Set_ptrcnt != NULL)
962 l->flags |= PERLIO_F_FASTGETS;
76ced9ad 963 if (mode)
6f9d8c32 964 {
76ced9ad 965 switch (*mode++)
06da4f11 966 {
76ced9ad 967 case 'r':
f5b9d040 968 l->flags |= PERLIO_F_CANREAD;
76ced9ad 969 break;
970 case 'a':
f5b9d040 971 l->flags |= PERLIO_F_APPEND|PERLIO_F_CANWRITE;
76ced9ad 972 break;
973 case 'w':
f5b9d040 974 l->flags |= PERLIO_F_TRUNCATE|PERLIO_F_CANWRITE;
76ced9ad 975 break;
976 default:
977 errno = EINVAL;
978 return -1;
979 }
980 while (*mode)
981 {
982 switch (*mode++)
983 {
984 case '+':
985 l->flags |= PERLIO_F_CANREAD|PERLIO_F_CANWRITE;
986 break;
987 case 'b':
f5b9d040 988 l->flags &= ~PERLIO_F_CRLF;
989 break;
990 case 't':
991 l->flags |= PERLIO_F_CRLF;
76ced9ad 992 break;
993 default:
994 errno = EINVAL;
995 return -1;
996 }
06da4f11 997 }
6f9d8c32 998 }
76ced9ad 999 else
1000 {
1001 if (l->next)
1002 {
1003 l->flags |= l->next->flags &
f5b9d040 1004 (PERLIO_F_CANREAD|PERLIO_F_CANWRITE|PERLIO_F_TRUNCATE|PERLIO_F_APPEND);
76ced9ad 1005 }
1006 }
5e2ab84b 1007#if 0
4659c93f 1008 PerlIO_debug("PerlIOBase_pushed f=%p %s %s fl=%08"UVxf" (%s)\n",
f5b9d040 1009 f,PerlIOBase(f)->tab->name,(omode) ? omode : "(Null)",
a4d3c1d3 1010 l->flags,PerlIO_modestr(f,temp));
5e2ab84b 1011#endif
76ced9ad 1012 return 0;
1013}
1014
1015IV
1016PerlIOBase_popped(PerlIO *f)
1017{
1018 return 0;
760ac839 1019}
1020
5e2ab84b 1021extern PerlIO_funcs PerlIO_pending;
1022
9e353e3b 1023SSize_t
1024PerlIOBase_unread(PerlIO *f, const void *vbuf, Size_t count)
1025{
5e2ab84b 1026#if 0
9e353e3b 1027 Off_t old = PerlIO_tell(f);
5e2ab84b 1028 if (0 && PerlIO_seek(f,-((Off_t)count),SEEK_CUR) == 0)
9e353e3b 1029 {
1030 Off_t new = PerlIO_tell(f);
1031 return old - new;
1032 }
5e2ab84b 1033 else
1034 {
1035 return 0;
1036 }
1037#else
1038 PerlIO_push(f,&PerlIO_pending,"r");
1039 return PerlIOBuf_unread(f,vbuf,count);
1040#endif
9e353e3b 1041}
1042
1043IV
06da4f11 1044PerlIOBase_noop_ok(PerlIO *f)
9e353e3b 1045{
1046 return 0;
1047}
1048
1049IV
06da4f11 1050PerlIOBase_noop_fail(PerlIO *f)
1051{
1052 return -1;
1053}
1054
1055IV
9e353e3b 1056PerlIOBase_close(PerlIO *f)
1057{
1058 IV code = 0;
f5b9d040 1059 PerlIO *n = PerlIONext(f);
9e353e3b 1060 if (PerlIO_flush(f) != 0)
1061 code = -1;
f5b9d040 1062 if (n && (*PerlIOBase(n)->tab->Close)(n) != 0)
9e353e3b 1063 code = -1;
1064 PerlIOBase(f)->flags &= ~(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|PERLIO_F_OPEN);
1065 return code;
1066}
1067
1068IV
1069PerlIOBase_eof(PerlIO *f)
1070{
1071 if (f && *f)
1072 {
1073 return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
1074 }
1075 return 1;
1076}
1077
1078IV
1079PerlIOBase_error(PerlIO *f)
1080{
1081 if (f && *f)
1082 {
1083 return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
1084 }
1085 return 1;
1086}
1087
1088void
1089PerlIOBase_clearerr(PerlIO *f)
1090{
1091 if (f && *f)
1092 {
f5b9d040 1093 PerlIO *n = PerlIONext(f);
1094 PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR|PERLIO_F_EOF);
1095 if (n)
1096 PerlIO_clearerr(n);
9e353e3b 1097 }
1098}
1099
1100void
1101PerlIOBase_setlinebuf(PerlIO *f)
1102{
1103
1104}
1105
9e353e3b 1106/*--------------------------------------------------------------------------------------*/
1107/* Bottom-most level for UNIX-like case */
1108
1109typedef struct
1110{
1111 struct _PerlIO base; /* The generic part */
1112 int fd; /* UNIX like file descriptor */
1113 int oflags; /* open/fcntl flags */
1114} PerlIOUnix;
1115
6f9d8c32 1116int
9e353e3b 1117PerlIOUnix_oflags(const char *mode)
760ac839 1118{
9e353e3b 1119 int oflags = -1;
1120 switch(*mode)
1121 {
1122 case 'r':
1123 oflags = O_RDONLY;
1124 if (*++mode == '+')
1125 {
1126 oflags = O_RDWR;
1127 mode++;
1128 }
1129 break;
1130
1131 case 'w':
1132 oflags = O_CREAT|O_TRUNC;
1133 if (*++mode == '+')
1134 {
1135 oflags |= O_RDWR;
1136 mode++;
1137 }
1138 else
1139 oflags |= O_WRONLY;
1140 break;
1141
1142 case 'a':
1143 oflags = O_CREAT|O_APPEND;
1144 if (*++mode == '+')
1145 {
1146 oflags |= O_RDWR;
1147 mode++;
1148 }
1149 else
1150 oflags |= O_WRONLY;
1151 break;
1152 }
83b075c3 1153 if (*mode == 'b')
1154 {
f5b9d040 1155 oflags |= O_BINARY;
1156 oflags &= ~O_TEXT;
1157 mode++;
1158 }
1159 else if (*mode == 't')
1160 {
1161 oflags |= O_TEXT;
1162 oflags &= ~O_BINARY;
60382766 1163 mode++;
1164 }
99efab12 1165 /* Always open in binary mode */
1166 oflags |= O_BINARY;
9e353e3b 1167 if (*mode || oflags == -1)
6f9d8c32 1168 {
9e353e3b 1169 errno = EINVAL;
1170 oflags = -1;
6f9d8c32 1171 }
9e353e3b 1172 return oflags;
1173}
1174
1175IV
1176PerlIOUnix_fileno(PerlIO *f)
1177{
1178 return PerlIOSelf(f,PerlIOUnix)->fd;
1179}
1180
1181PerlIO *
06da4f11 1182PerlIOUnix_fdopen(PerlIO_funcs *self, int fd,const char *mode)
9e353e3b 1183{
5f1a76d0 1184 dTHX;
9e353e3b 1185 PerlIO *f = NULL;
c7fc522f 1186 if (*mode == 'I')
1187 mode++;
9e353e3b 1188 if (fd >= 0)
1189 {
1190 int oflags = PerlIOUnix_oflags(mode);
1191 if (oflags != -1)
1192 {
5f1a76d0 1193 PerlIOUnix *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),self,mode),PerlIOUnix);
9e353e3b 1194 s->fd = fd;
1195 s->oflags = oflags;
1196 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
1197 }
1198 }
1199 return f;
1200}
1201
1202PerlIO *
06da4f11 1203PerlIOUnix_open(PerlIO_funcs *self, const char *path,const char *mode)
9e353e3b 1204{
adb71456 1205 dTHX;
9e353e3b 1206 PerlIO *f = NULL;
1207 int oflags = PerlIOUnix_oflags(mode);
1208 if (oflags != -1)
1209 {
00b02797 1210 int fd = PerlLIO_open3(path,oflags,0666);
9e353e3b 1211 if (fd >= 0)
1212 {
5f1a76d0 1213 PerlIOUnix *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),self,mode),PerlIOUnix);
9e353e3b 1214 s->fd = fd;
1215 s->oflags = oflags;
1216 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
1217 }
1218 }
1219 return f;
760ac839 1220}
1221
760ac839 1222int
9e353e3b 1223PerlIOUnix_reopen(const char *path, const char *mode, PerlIO *f)
760ac839 1224{
9e353e3b 1225 PerlIOUnix *s = PerlIOSelf(f,PerlIOUnix);
1226 int oflags = PerlIOUnix_oflags(mode);
1227 if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
1228 (*PerlIOBase(f)->tab->Close)(f);
1229 if (oflags != -1)
1230 {
adb71456 1231 dTHX;
00b02797 1232 int fd = PerlLIO_open3(path,oflags,0666);
9e353e3b 1233 if (fd >= 0)
1234 {
1235 s->fd = fd;
1236 s->oflags = oflags;
1237 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
1238 return 0;
1239 }
1240 }
1241 return -1;
1242}
1243
1244SSize_t
1245PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count)
1246{
adb71456 1247 dTHX;
9e353e3b 1248 int fd = PerlIOSelf(f,PerlIOUnix)->fd;
8f24bd79 1249 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
1250 return 0;
9e353e3b 1251 while (1)
1252 {
00b02797 1253 SSize_t len = PerlLIO_read(fd,vbuf,count);
9e353e3b 1254 if (len >= 0 || errno != EINTR)
06da4f11 1255 {
1256 if (len < 0)
1257 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1258 else if (len == 0 && count != 0)
1259 PerlIOBase(f)->flags |= PERLIO_F_EOF;
1260 return len;
1261 }
9e353e3b 1262 }
1263}
1264
1265SSize_t
1266PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count)
1267{
adb71456 1268 dTHX;
9e353e3b 1269 int fd = PerlIOSelf(f,PerlIOUnix)->fd;
1270 while (1)
1271 {
00b02797 1272 SSize_t len = PerlLIO_write(fd,vbuf,count);
9e353e3b 1273 if (len >= 0 || errno != EINTR)
06da4f11 1274 {
1275 if (len < 0)
1276 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1277 return len;
1278 }
9e353e3b 1279 }
1280}
1281
1282IV
1283PerlIOUnix_seek(PerlIO *f, Off_t offset, int whence)
1284{
adb71456 1285 dTHX;
00b02797 1286 Off_t new = PerlLIO_lseek(PerlIOSelf(f,PerlIOUnix)->fd,offset,whence);
06da4f11 1287 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
9e353e3b 1288 return (new == (Off_t) -1) ? -1 : 0;
1289}
1290
1291Off_t
1292PerlIOUnix_tell(PerlIO *f)
1293{
adb71456 1294 dTHX;
00b02797 1295 return PerlLIO_lseek(PerlIOSelf(f,PerlIOUnix)->fd,0,SEEK_CUR);
9e353e3b 1296}
1297
1298IV
1299PerlIOUnix_close(PerlIO *f)
1300{
adb71456 1301 dTHX;
9e353e3b 1302 int fd = PerlIOSelf(f,PerlIOUnix)->fd;
1303 int code = 0;
00b02797 1304 while (PerlLIO_close(fd) != 0)
9e353e3b 1305 {
1306 if (errno != EINTR)
1307 {
1308 code = -1;
1309 break;
1310 }
1311 }
1312 if (code == 0)
1313 {
1314 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
1315 }
1316 return code;
1317}
1318
1319PerlIO_funcs PerlIO_unix = {
1320 "unix",
1321 sizeof(PerlIOUnix),
f5b9d040 1322 PERLIO_K_RAW,
9e353e3b 1323 PerlIOUnix_fileno,
1324 PerlIOUnix_fdopen,
1325 PerlIOUnix_open,
1326 PerlIOUnix_reopen,
06da4f11 1327 PerlIOBase_pushed,
1328 PerlIOBase_noop_ok,
9e353e3b 1329 PerlIOUnix_read,
1330 PerlIOBase_unread,
1331 PerlIOUnix_write,
1332 PerlIOUnix_seek,
1333 PerlIOUnix_tell,
1334 PerlIOUnix_close,
76ced9ad 1335 PerlIOBase_noop_ok, /* flush */
1336 PerlIOBase_noop_fail, /* fill */
9e353e3b 1337 PerlIOBase_eof,
1338 PerlIOBase_error,
1339 PerlIOBase_clearerr,
1340 PerlIOBase_setlinebuf,
1341 NULL, /* get_base */
1342 NULL, /* get_bufsiz */
1343 NULL, /* get_ptr */
1344 NULL, /* get_cnt */
1345 NULL, /* set_ptrcnt */
1346};
1347
1348/*--------------------------------------------------------------------------------------*/
1349/* stdio as a layer */
1350
1351typedef struct
1352{
1353 struct _PerlIO base;
1354 FILE * stdio; /* The stream */
1355} PerlIOStdio;
1356
1357IV
1358PerlIOStdio_fileno(PerlIO *f)
1359{
adb71456 1360 dTHX;
eaf8b698 1361 return PerlSIO_fileno(PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1362}
1363
f5b9d040 1364const char *
1365PerlIOStdio_mode(const char *mode,char *tmode)
1366{
1367 const char *ret = mode;
1368 if (O_BINARY != O_TEXT)
1369 {
1370 ret = (const char *) tmode;
1371 while (*mode)
1372 {
1373 *tmode++ = *mode++;
1374 }
1375 *tmode++ = 'b';
a4d3c1d3 1376 *tmode = '\0';
f5b9d040 1377 }
1378 return ret;
1379}
9e353e3b 1380
1381PerlIO *
06da4f11 1382PerlIOStdio_fdopen(PerlIO_funcs *self, int fd,const char *mode)
9e353e3b 1383{
adb71456 1384 dTHX;
9e353e3b 1385 PerlIO *f = NULL;
c7fc522f 1386 int init = 0;
f5b9d040 1387 char tmode[8];
c7fc522f 1388 if (*mode == 'I')
1389 {
1390 init = 1;
1391 mode++;
1392 }
9e353e3b 1393 if (fd >= 0)
1394 {
c7fc522f 1395 FILE *stdio = NULL;
1396 if (init)
1397 {
1398 switch(fd)
1399 {
1400 case 0:
eaf8b698 1401 stdio = PerlSIO_stdin;
c7fc522f 1402 break;
1403 case 1:
eaf8b698 1404 stdio = PerlSIO_stdout;
c7fc522f 1405 break;
1406 case 2:
eaf8b698 1407 stdio = PerlSIO_stderr;
c7fc522f 1408 break;
1409 }
1410 }
1411 else
f5b9d040 1412 {
eaf8b698 1413 stdio = PerlSIO_fdopen(fd,mode = PerlIOStdio_mode(mode,tmode));
f5b9d040 1414 }
9e353e3b 1415 if (stdio)
1416 {
5f1a76d0 1417 PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),self,mode),PerlIOStdio);
9e353e3b 1418 s->stdio = stdio;
1419 }
1420 }
1421 return f;
1422}
1423
1424#undef PerlIO_importFILE
1425PerlIO *
1426PerlIO_importFILE(FILE *stdio, int fl)
1427{
5f1a76d0 1428 dTHX;
9e353e3b 1429 PerlIO *f = NULL;
1430 if (stdio)
1431 {
5f1a76d0 1432 PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),&PerlIO_stdio,"r+"),PerlIOStdio);
9e353e3b 1433 s->stdio = stdio;
1434 }
1435 return f;
1436}
1437
1438PerlIO *
06da4f11 1439PerlIOStdio_open(PerlIO_funcs *self, const char *path,const char *mode)
9e353e3b 1440{
adb71456 1441 dTHX;
9e353e3b 1442 PerlIO *f = NULL;
eaf8b698 1443 FILE *stdio = PerlSIO_fopen(path,mode);
9e353e3b 1444 if (stdio)
1445 {
f5b9d040 1446 char tmode[8];
5f1a76d0 1447 PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX), self,
f5b9d040 1448 (mode = PerlIOStdio_mode(mode,tmode))),
1449 PerlIOStdio);
9e353e3b 1450 s->stdio = stdio;
1451 }
1452 return f;
760ac839 1453}
1454
6f9d8c32 1455int
9e353e3b 1456PerlIOStdio_reopen(const char *path, const char *mode, PerlIO *f)
1457{
adb71456 1458 dTHX;
9e353e3b 1459 PerlIOStdio *s = PerlIOSelf(f,PerlIOStdio);
f5b9d040 1460 char tmode[8];
eaf8b698 1461 FILE *stdio = PerlSIO_freopen(path,(mode = PerlIOStdio_mode(mode,tmode)),s->stdio);
9e353e3b 1462 if (!s->stdio)
1463 return -1;
1464 s->stdio = stdio;
1465 return 0;
1466}
1467
1468SSize_t
1469PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count)
1470{
adb71456 1471 dTHX;
9e353e3b 1472 FILE *s = PerlIOSelf(f,PerlIOStdio)->stdio;
c7fc522f 1473 SSize_t got = 0;
9e353e3b 1474 if (count == 1)
1475 {
1476 STDCHAR *buf = (STDCHAR *) vbuf;
1477 /* Perl is expecting PerlIO_getc() to fill the buffer
1478 * Linux's stdio does not do that for fread()
1479 */
eaf8b698 1480 int ch = PerlSIO_fgetc(s);
9e353e3b 1481 if (ch != EOF)
1482 {
1483 *buf = ch;
c7fc522f 1484 got = 1;
9e353e3b 1485 }
9e353e3b 1486 }
c7fc522f 1487 else
eaf8b698 1488 got = PerlSIO_fread(vbuf,1,count,s);
c7fc522f 1489 return got;
9e353e3b 1490}
1491
1492SSize_t
1493PerlIOStdio_unread(PerlIO *f, const void *vbuf, Size_t count)
1494{
adb71456 1495 dTHX;
9e353e3b 1496 FILE *s = PerlIOSelf(f,PerlIOStdio)->stdio;
1497 STDCHAR *buf = ((STDCHAR *)vbuf)+count-1;
1498 SSize_t unread = 0;
1499 while (count > 0)
1500 {
1501 int ch = *buf-- & 0xff;
eaf8b698 1502 if (PerlSIO_ungetc(ch,s) != ch)
9e353e3b 1503 break;
1504 unread++;
1505 count--;
1506 }
1507 return unread;
1508}
1509
1510SSize_t
1511PerlIOStdio_write(PerlIO *f, const void *vbuf, Size_t count)
1512{
adb71456 1513 dTHX;
eaf8b698 1514 return PerlSIO_fwrite(vbuf,1,count,PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1515}
1516
1517IV
1518PerlIOStdio_seek(PerlIO *f, Off_t offset, int whence)
1519{
adb71456 1520 dTHX;
c7fc522f 1521 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1522 return PerlSIO_fseek(stdio,offset,whence);
9e353e3b 1523}
1524
1525Off_t
1526PerlIOStdio_tell(PerlIO *f)
1527{
adb71456 1528 dTHX;
c7fc522f 1529 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1530 return PerlSIO_ftell(stdio);
9e353e3b 1531}
1532
1533IV
1534PerlIOStdio_close(PerlIO *f)
1535{
adb71456 1536 dTHX;
8e4bc33b 1537#ifdef HAS_SOCKET
cf829ab0 1538 int optval, optlen = sizeof(int);
8e4bc33b 1539#endif
3789aae2 1540 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
cf829ab0 1541 return(
8e4bc33b 1542#ifdef HAS_SOCKET
a4d3c1d3 1543 (getsockopt(PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (char *)&optval, &optlen) < 0) ?
eaf8b698 1544 PerlSIO_fclose(stdio) :
8e4bc33b 1545 close(PerlIO_fileno(f))
1546#else
1547 PerlSIO_fclose(stdio)
1548#endif
1549 );
1550
9e353e3b 1551}
1552
1553IV
1554PerlIOStdio_flush(PerlIO *f)
1555{
adb71456 1556 dTHX;
9e353e3b 1557 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
88b61e10 1558 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE)
1559 {
eaf8b698 1560 return PerlSIO_fflush(stdio);
88b61e10 1561 }
1562 else
1563 {
1564#if 0
1565 /* FIXME: This discards ungetc() and pre-read stuff which is
1566 not right if this is just a "sync" from a layer above
1567 Suspect right design is to do _this_ but not have layer above
1568 flush this layer read-to-read
1569 */
1570 /* Not writeable - sync by attempting a seek */
1571 int err = errno;
eaf8b698 1572 if (PerlSIO_fseek(stdio,(Off_t) 0, SEEK_CUR) != 0)
88b61e10 1573 errno = err;
1574#endif
1575 }
1576 return 0;
9e353e3b 1577}
1578
1579IV
06da4f11 1580PerlIOStdio_fill(PerlIO *f)
1581{
adb71456 1582 dTHX;
06da4f11 1583 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1584 int c;
3789aae2 1585 /* fflush()ing read-only streams can cause trouble on some stdio-s */
1586 if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
1587 {
eaf8b698 1588 if (PerlSIO_fflush(stdio) != 0)
3789aae2 1589 return EOF;
1590 }
eaf8b698 1591 c = PerlSIO_fgetc(stdio);
1592 if (c == EOF || PerlSIO_ungetc(c,stdio) != c)
06da4f11 1593 return EOF;
1594 return 0;
1595}
1596
1597IV
9e353e3b 1598PerlIOStdio_eof(PerlIO *f)
1599{
adb71456 1600 dTHX;
eaf8b698 1601 return PerlSIO_feof(PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1602}
1603
1604IV
1605PerlIOStdio_error(PerlIO *f)
1606{
adb71456 1607 dTHX;
eaf8b698 1608 return PerlSIO_ferror(PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1609}
1610
1611void
1612PerlIOStdio_clearerr(PerlIO *f)
1613{
adb71456 1614 dTHX;
eaf8b698 1615 PerlSIO_clearerr(PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1616}
1617
1618void
1619PerlIOStdio_setlinebuf(PerlIO *f)
1620{
adb71456 1621 dTHX;
9e353e3b 1622#ifdef HAS_SETLINEBUF
eaf8b698 1623 PerlSIO_setlinebuf(PerlIOSelf(f,PerlIOStdio)->stdio);
9e353e3b 1624#else
eaf8b698 1625 PerlSIO_setvbuf(PerlIOSelf(f,PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
9e353e3b 1626#endif
1627}
1628
1629#ifdef FILE_base
1630STDCHAR *
1631PerlIOStdio_get_base(PerlIO *f)
1632{
adb71456 1633 dTHX;
9e353e3b 1634 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1635 return PerlSIO_get_base(stdio);
9e353e3b 1636}
1637
1638Size_t
1639PerlIOStdio_get_bufsiz(PerlIO *f)
1640{
adb71456 1641 dTHX;
9e353e3b 1642 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1643 return PerlSIO_get_bufsiz(stdio);
9e353e3b 1644}
1645#endif
1646
1647#ifdef USE_STDIO_PTR
1648STDCHAR *
1649PerlIOStdio_get_ptr(PerlIO *f)
1650{
adb71456 1651 dTHX;
9e353e3b 1652 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1653 return PerlSIO_get_ptr(stdio);
9e353e3b 1654}
1655
1656SSize_t
1657PerlIOStdio_get_cnt(PerlIO *f)
1658{
adb71456 1659 dTHX;
9e353e3b 1660 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
eaf8b698 1661 return PerlSIO_get_cnt(stdio);
9e353e3b 1662}
1663
1664void
1665PerlIOStdio_set_ptrcnt(PerlIO *f,STDCHAR *ptr,SSize_t cnt)
1666{
adb71456 1667 dTHX;
9e353e3b 1668 FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1669 if (ptr != NULL)
1670 {
1671#ifdef STDIO_PTR_LVALUE
eaf8b698 1672 PerlSIO_set_ptr(stdio,ptr);
9e353e3b 1673#ifdef STDIO_PTR_LVAL_SETS_CNT
eaf8b698 1674 if (PerlSIO_get_cnt(stdio) != (cnt))
9e353e3b 1675 {
1676 dTHX;
eaf8b698 1677 assert(PerlSIO_get_cnt(stdio) == (cnt));
9e353e3b 1678 }
1679#endif
1680#if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
1681 /* Setting ptr _does_ change cnt - we are done */
1682 return;
1683#endif
1684#else /* STDIO_PTR_LVALUE */
eaf8b698 1685 PerlProc_abort();
9e353e3b 1686#endif /* STDIO_PTR_LVALUE */
1687 }
1688/* Now (or only) set cnt */
1689#ifdef STDIO_CNT_LVALUE
eaf8b698 1690 PerlSIO_set_cnt(stdio,cnt);
9e353e3b 1691#else /* STDIO_CNT_LVALUE */
1692#if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
eaf8b698 1693 PerlSIO_set_ptr(stdio,PerlSIO_get_ptr(stdio)+(PerlSIO_get_cnt(stdio)-cnt));
9e353e3b 1694#else /* STDIO_PTR_LVAL_SETS_CNT */
eaf8b698 1695 PerlProc_abort();
9e353e3b 1696#endif /* STDIO_PTR_LVAL_SETS_CNT */
1697#endif /* STDIO_CNT_LVALUE */
1698}
1699
1700#endif
1701
1702PerlIO_funcs PerlIO_stdio = {
1703 "stdio",
1704 sizeof(PerlIOStdio),
f5b9d040 1705 PERLIO_K_BUFFERED,
9e353e3b 1706 PerlIOStdio_fileno,
1707 PerlIOStdio_fdopen,
1708 PerlIOStdio_open,
1709 PerlIOStdio_reopen,
06da4f11 1710 PerlIOBase_pushed,
1711 PerlIOBase_noop_ok,
9e353e3b 1712 PerlIOStdio_read,
1713 PerlIOStdio_unread,
1714 PerlIOStdio_write,
1715 PerlIOStdio_seek,
1716 PerlIOStdio_tell,
1717 PerlIOStdio_close,
1718 PerlIOStdio_flush,
06da4f11 1719 PerlIOStdio_fill,
9e353e3b 1720 PerlIOStdio_eof,
1721 PerlIOStdio_error,
1722 PerlIOStdio_clearerr,
1723 PerlIOStdio_setlinebuf,
1724#ifdef FILE_base
1725 PerlIOStdio_get_base,
1726 PerlIOStdio_get_bufsiz,
1727#else
1728 NULL,
1729 NULL,
1730#endif
1731#ifdef USE_STDIO_PTR
1732 PerlIOStdio_get_ptr,
1733 PerlIOStdio_get_cnt,
0eb1d8a4 1734#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
9e353e3b 1735 PerlIOStdio_set_ptrcnt
1736#else /* STDIO_PTR_LVALUE */
1737 NULL
1738#endif /* STDIO_PTR_LVALUE */
1739#else /* USE_STDIO_PTR */
1740 NULL,
1741 NULL,
1742 NULL
1743#endif /* USE_STDIO_PTR */
1744};
1745
1746#undef PerlIO_exportFILE
1747FILE *
1748PerlIO_exportFILE(PerlIO *f, int fl)
1749{
1750 PerlIO_flush(f);
1751 /* Should really push stdio discipline when we have them */
1752 return fdopen(PerlIO_fileno(f),"r+");
1753}
1754
1755#undef PerlIO_findFILE
1756FILE *
1757PerlIO_findFILE(PerlIO *f)
1758{
1759 return PerlIO_exportFILE(f,0);
1760}
1761
1762#undef PerlIO_releaseFILE
1763void
1764PerlIO_releaseFILE(PerlIO *p, FILE *f)
1765{
1766}
1767
1768/*--------------------------------------------------------------------------------------*/
1769/* perlio buffer layer */
1770
5e2ab84b 1771IV
1772PerlIOBuf_pushed(PerlIO *f, const char *mode)
1773{
1774 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1775 b->posn = PerlIO_tell(PerlIONext(f));
1776 return PerlIOBase_pushed(f,mode);
1777}
1778
9e353e3b 1779PerlIO *
06da4f11 1780PerlIOBuf_fdopen(PerlIO_funcs *self, int fd, const char *mode)
9e353e3b 1781{
adb71456 1782 dTHX;
9e353e3b 1783 PerlIO_funcs *tab = PerlIO_default_btm();
c7fc522f 1784 int init = 0;
1785 PerlIO *f;
1786 if (*mode == 'I')
1787 {
1788 init = 1;
1789 mode++;
a77df51f 1790 }
10cbe18a 1791#if O_BINARY != O_TEXT
a4d3c1d3 1792 /* do something about failing setmode()? --jhi */
1793 PerlLIO_setmode(fd, O_BINARY);
10cbe18a 1794#endif
06da4f11 1795 f = (*tab->Fdopen)(tab,fd,mode);
6f9d8c32 1796 if (f)
1797 {
f5b9d040 1798 PerlIOBuf *b = PerlIOSelf(PerlIO_push(f,self,mode),PerlIOBuf);
f5b9d040 1799 if (init && fd == 2)
c7fc522f 1800 {
f5b9d040 1801 /* Initial stderr is unbuffered */
1802 PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
a4d3c1d3 1803 }
5e2ab84b 1804#if 0
4659c93f 1805 PerlIO_debug("PerlIOBuf_fdopen %s f=%p fd=%d m=%s fl=%08"UVxf"\n",
f5b9d040 1806 self->name,f,fd,mode,PerlIOBase(f)->flags);
5e2ab84b 1807#endif
6f9d8c32 1808 }
9e353e3b 1809 return f;
760ac839 1810}
1811
9e353e3b 1812PerlIO *
06da4f11 1813PerlIOBuf_open(PerlIO_funcs *self, const char *path, const char *mode)
8c86a920 1814{
9e353e3b 1815 PerlIO_funcs *tab = PerlIO_default_btm();
06da4f11 1816 PerlIO *f = (*tab->Open)(tab,path,mode);
9e353e3b 1817 if (f)
1818 {
5e2ab84b 1819 PerlIO_push(f,self,mode);
9e353e3b 1820 }
1821 return f;
1822}
1823
1824int
c3d7c7c9 1825PerlIOBuf_reopen(const char *path, const char *mode, PerlIO *f)
9e353e3b 1826{
c3d7c7c9 1827 PerlIO *next = PerlIONext(f);
1828 int code = (*PerlIOBase(next)->tab->Reopen)(path,mode,next);
1829 if (code = 0)
1830 code = (*PerlIOBase(f)->tab->Pushed)(f,mode);
c3d7c7c9 1831 return code;
9e353e3b 1832}
1833
9e353e3b 1834/* This "flush" is akin to sfio's sync in that it handles files in either
1835 read or write state
1836*/
1837IV
1838PerlIOBuf_flush(PerlIO *f)
6f9d8c32 1839{
9e353e3b 1840 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1841 int code = 0;
1842 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
1843 {
1844 /* write() the buffer */
1845 STDCHAR *p = b->buf;
1846 int count;
3789aae2 1847 PerlIO *n = PerlIONext(f);
9e353e3b 1848 while (p < b->ptr)
1849 {
3789aae2 1850 count = PerlIO_write(n,p,b->ptr - p);
9e353e3b 1851 if (count > 0)
1852 {
1853 p += count;
1854 }
3789aae2 1855 else if (count < 0 || PerlIO_error(n))
9e353e3b 1856 {
1857 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1858 code = -1;
1859 break;
1860 }
1861 }
1862 b->posn += (p - b->buf);
1863 }
1864 else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
6f9d8c32 1865 {
9e353e3b 1866 /* Note position change */
1867 b->posn += (b->ptr - b->buf);
1868 if (b->ptr < b->end)
1869 {
1870 /* We did not consume all of it */
1871 if (PerlIO_seek(PerlIONext(f),b->posn,SEEK_SET) == 0)
1872 {
1873 b->posn = PerlIO_tell(PerlIONext(f));
1874 }
1875 }
6f9d8c32 1876 }
9e353e3b 1877 b->ptr = b->end = b->buf;
1878 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF|PERLIO_F_WRBUF);
88b61e10 1879 /* FIXME: Is this right for read case ? */
9e353e3b 1880 if (PerlIO_flush(PerlIONext(f)) != 0)
1881 code = -1;
1882 return code;
6f9d8c32 1883}
1884
06da4f11 1885IV
1886PerlIOBuf_fill(PerlIO *f)
1887{
1888 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
88b61e10 1889 PerlIO *n = PerlIONext(f);
06da4f11 1890 SSize_t avail;
88b61e10 1891 /* FIXME: doing the down-stream flush is a bad idea if it causes
1892 pre-read data in stdio buffer to be discarded
1893 but this is too simplistic - as it skips _our_ hosekeeping
1894 and breaks tell tests.
1895 if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF))
1896 {
1897 }
1898 */
06da4f11 1899 if (PerlIO_flush(f) != 0)
1900 return -1;
88b61e10 1901
06da4f11 1902 b->ptr = b->end = b->buf;
88b61e10 1903 if (PerlIO_fast_gets(n))
1904 {
1905 /* Layer below is also buffered
1906 * We do _NOT_ want to call its ->Read() because that will loop
1907 * till it gets what we asked for which may hang on a pipe etc.
1908 * Instead take anything it has to hand, or ask it to fill _once_.
1909 */
1910 avail = PerlIO_get_cnt(n);
1911 if (avail <= 0)
1912 {
1913 avail = PerlIO_fill(n);
1914 if (avail == 0)
1915 avail = PerlIO_get_cnt(n);
1916 else
1917 {
1918 if (!PerlIO_error(n) && PerlIO_eof(n))
1919 avail = 0;
1920 }
1921 }
1922 if (avail > 0)
1923 {
1924 STDCHAR *ptr = PerlIO_get_ptr(n);
1925 SSize_t cnt = avail;
1926 if (avail > b->bufsiz)
1927 avail = b->bufsiz;
1928 Copy(ptr,b->buf,avail,STDCHAR);
1929 PerlIO_set_ptrcnt(n,ptr+avail,cnt-avail);
1930 }
1931 }
1932 else
1933 {
1934 avail = PerlIO_read(n,b->ptr,b->bufsiz);
1935 }
06da4f11 1936 if (avail <= 0)
1937 {
1938 if (avail == 0)
1939 PerlIOBase(f)->flags |= PERLIO_F_EOF;
1940 else
1941 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1942 return -1;
1943 }
1944 b->end = b->buf+avail;
1945 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
1946 return 0;
1947}
1948
6f9d8c32 1949SSize_t
9e353e3b 1950PerlIOBuf_read(PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 1951{
99efab12 1952 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1953 STDCHAR *buf = (STDCHAR *) vbuf;
6f9d8c32 1954 if (f)
1955 {
9e353e3b 1956 if (!b->ptr)
06da4f11 1957 PerlIO_get_base(f);
9e353e3b 1958 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
f89522bf 1959 return 0;
6f9d8c32 1960 while (count > 0)
1961 {
99efab12 1962 SSize_t avail = PerlIO_get_cnt(f);
60382766 1963 SSize_t take = (count < avail) ? count : avail;
99efab12 1964 if (take > 0)
6f9d8c32 1965 {
99efab12 1966 STDCHAR *ptr = PerlIO_get_ptr(f);
1967 Copy(ptr,buf,take,STDCHAR);
1968 PerlIO_set_ptrcnt(f,ptr+take,(avail -= take));
1969 count -= take;
1970 buf += take;
6f9d8c32 1971 }
99efab12 1972 if (count > 0 && avail <= 0)
6f9d8c32 1973 {
06da4f11 1974 if (PerlIO_fill(f) != 0)
1975 break;
6f9d8c32 1976 }
1977 }
99efab12 1978 return (buf - (STDCHAR *) vbuf);
6f9d8c32 1979 }
1980 return 0;
1981}
1982
9e353e3b 1983SSize_t
1984PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count)
760ac839 1985{
9e353e3b 1986 const STDCHAR *buf = (const STDCHAR *) vbuf+count;
1987 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1988 SSize_t unread = 0;
1989 SSize_t avail;
9e353e3b 1990 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
1991 PerlIO_flush(f);
06da4f11 1992 if (!b->buf)
1993 PerlIO_get_base(f);
9e353e3b 1994 if (b->buf)
1995 {
1996 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
1997 {
1998 avail = (b->ptr - b->buf);
9e353e3b 1999 }
2000 else
2001 {
2002 avail = b->bufsiz;
5e2ab84b 2003 b->end = b->buf + avail;
2004 b->ptr = b->end;
2005 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
2006 b->posn -= b->bufsiz;
9e353e3b 2007 }
5e2ab84b 2008 if (avail > (SSize_t) count)
2009 avail = count;
9e353e3b 2010 if (avail > 0)
2011 {
5e2ab84b 2012 b->ptr -= avail;
9e353e3b 2013 buf -= avail;
2014 if (buf != b->ptr)
2015 {
88b61e10 2016 Copy(buf,b->ptr,avail,STDCHAR);
9e353e3b 2017 }
2018 count -= avail;
2019 unread += avail;
2020 PerlIOBase(f)->flags &= ~ PERLIO_F_EOF;
2021 }
2022 }
2023 return unread;
760ac839 2024}
2025
9e353e3b 2026SSize_t
2027PerlIOBuf_write(PerlIO *f, const void *vbuf, Size_t count)
760ac839 2028{
9e353e3b 2029 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2030 const STDCHAR *buf = (const STDCHAR *) vbuf;
2031 Size_t written = 0;
2032 if (!b->buf)
06da4f11 2033 PerlIO_get_base(f);
9e353e3b 2034 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
2035 return 0;
2036 while (count > 0)
2037 {
2038 SSize_t avail = b->bufsiz - (b->ptr - b->buf);
2039 if ((SSize_t) count < avail)
2040 avail = count;
2041 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
2042 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF)
2043 {
2044 while (avail > 0)
2045 {
2046 int ch = *buf++;
2047 *(b->ptr)++ = ch;
2048 count--;
2049 avail--;
2050 written++;
2051 if (ch == '\n')
2052 {
2053 PerlIO_flush(f);
2054 break;
2055 }
2056 }
2057 }
2058 else
2059 {
2060 if (avail)
2061 {
88b61e10 2062 Copy(buf,b->ptr,avail,STDCHAR);
9e353e3b 2063 count -= avail;
2064 buf += avail;
2065 written += avail;
2066 b->ptr += avail;
2067 }
2068 }
2069 if (b->ptr >= (b->buf + b->bufsiz))
2070 PerlIO_flush(f);
2071 }
f5b9d040 2072 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
2073 PerlIO_flush(f);
9e353e3b 2074 return written;
2075}
2076
2077IV
2078PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence)
2079{
5e2ab84b 2080 IV code;
2081 if ((code = PerlIO_flush(f)) == 0)
9e353e3b 2082 {
5e2ab84b 2083 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
9e353e3b 2084 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2085 code = PerlIO_seek(PerlIONext(f),offset,whence);
2086 if (code == 0)
2087 {
2088 b->posn = PerlIO_tell(PerlIONext(f));
2089 }
2090 }
2091 return code;
2092}
2093
2094Off_t
2095PerlIOBuf_tell(PerlIO *f)
2096{
2097 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2098 Off_t posn = b->posn;
2099 if (b->buf)
2100 posn += (b->ptr - b->buf);
2101 return posn;
2102}
2103
2104IV
2105PerlIOBuf_close(PerlIO *f)
2106{
5f1a76d0 2107 dTHX;
9e353e3b 2108 IV code = PerlIOBase_close(f);
2109 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2110 if (b->buf && b->buf != (STDCHAR *) &b->oneword)
6f9d8c32 2111 {
5f1a76d0 2112 PerlMemShared_free(b->buf);
6f9d8c32 2113 }
9e353e3b 2114 b->buf = NULL;
2115 b->ptr = b->end = b->buf;
2116 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF|PERLIO_F_WRBUF);
2117 return code;
760ac839 2118}
2119
760ac839 2120void
9e353e3b 2121PerlIOBuf_setlinebuf(PerlIO *f)
760ac839 2122{
6f9d8c32 2123 if (f)
2124 {
9e353e3b 2125 PerlIOBase(f)->flags &= ~PERLIO_F_LINEBUF;
6f9d8c32 2126 }
760ac839 2127}
2128
9e353e3b 2129STDCHAR *
2130PerlIOBuf_get_ptr(PerlIO *f)
2131{
2132 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2133 if (!b->buf)
06da4f11 2134 PerlIO_get_base(f);
9e353e3b 2135 return b->ptr;
2136}
2137
05d1247b 2138SSize_t
9e353e3b 2139PerlIOBuf_get_cnt(PerlIO *f)
2140{
2141 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2142 if (!b->buf)
06da4f11 2143 PerlIO_get_base(f);
9e353e3b 2144 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
2145 return (b->end - b->ptr);
2146 return 0;
2147}
2148
2149STDCHAR *
2150PerlIOBuf_get_base(PerlIO *f)
2151{
2152 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2153 if (!b->buf)
06da4f11 2154 {
5f1a76d0 2155 dTHX;
06da4f11 2156 if (!b->bufsiz)
2157 b->bufsiz = 4096;
5f1a76d0 2158 b->buf = PerlMemShared_calloc(b->bufsiz,sizeof(STDCHAR));
06da4f11 2159 if (!b->buf)
2160 {
2161 b->buf = (STDCHAR *)&b->oneword;
2162 b->bufsiz = sizeof(b->oneword);
2163 }
2164 b->ptr = b->buf;
2165 b->end = b->ptr;
2166 }
9e353e3b 2167 return b->buf;
2168}
2169
2170Size_t
2171PerlIOBuf_bufsiz(PerlIO *f)
2172{
2173 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2174 if (!b->buf)
06da4f11 2175 PerlIO_get_base(f);
9e353e3b 2176 return (b->end - b->buf);
2177}
2178
2179void
05d1247b 2180PerlIOBuf_set_ptrcnt(PerlIO *f, STDCHAR *ptr, SSize_t cnt)
9e353e3b 2181{
2182 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2183 if (!b->buf)
06da4f11 2184 PerlIO_get_base(f);
9e353e3b 2185 b->ptr = ptr;
2186 if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf)
6f9d8c32 2187 {
9e353e3b 2188 dTHX;
2189 assert(PerlIO_get_cnt(f) == cnt);
2190 assert(b->ptr >= b->buf);
6f9d8c32 2191 }
9e353e3b 2192 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
760ac839 2193}
2194
9e353e3b 2195PerlIO_funcs PerlIO_perlio = {
2196 "perlio",
2197 sizeof(PerlIOBuf),
f5b9d040 2198 PERLIO_K_BUFFERED,
9e353e3b 2199 PerlIOBase_fileno,
2200 PerlIOBuf_fdopen,
2201 PerlIOBuf_open,
c3d7c7c9 2202 PerlIOBuf_reopen,
5e2ab84b 2203 PerlIOBuf_pushed,
06da4f11 2204 PerlIOBase_noop_ok,
9e353e3b 2205 PerlIOBuf_read,
2206 PerlIOBuf_unread,
2207 PerlIOBuf_write,
2208 PerlIOBuf_seek,
2209 PerlIOBuf_tell,
2210 PerlIOBuf_close,
2211 PerlIOBuf_flush,
06da4f11 2212 PerlIOBuf_fill,
9e353e3b 2213 PerlIOBase_eof,
2214 PerlIOBase_error,
2215 PerlIOBase_clearerr,
2216 PerlIOBuf_setlinebuf,
2217 PerlIOBuf_get_base,
2218 PerlIOBuf_bufsiz,
2219 PerlIOBuf_get_ptr,
2220 PerlIOBuf_get_cnt,
2221 PerlIOBuf_set_ptrcnt,
2222};
2223
66ecd56b 2224/*--------------------------------------------------------------------------------------*/
5e2ab84b 2225/* Temp layer to hold unread chars when cannot do it any other way */
2226
2227IV
2228PerlIOPending_fill(PerlIO *f)
2229{
2230 /* Should never happen */
2231 PerlIO_flush(f);
2232 return 0;
2233}
2234
2235IV
2236PerlIOPending_close(PerlIO *f)
2237{
2238 /* A tad tricky - flush pops us, then we close new top */
2239 PerlIO_flush(f);
2240 return PerlIO_close(f);
2241}
2242
2243IV
2244PerlIOPending_seek(PerlIO *f, Off_t offset, int whence)
2245{
2246 /* A tad tricky - flush pops us, then we seek new top */
2247 PerlIO_flush(f);
2248 return PerlIO_seek(f,offset,whence);
2249}
2250
2251
2252IV
2253PerlIOPending_flush(PerlIO *f)
2254{
2255 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2256 if (b->buf && b->buf != (STDCHAR *) &b->oneword)
2257 {
5f1a76d0 2258 dTHX;
2259 PerlMemShared_free(b->buf);
5e2ab84b 2260 b->buf = NULL;
2261 }
2262 PerlIO_pop(f);
2263 return 0;
2264}
2265
2266void
2267PerlIOPending_set_ptrcnt(PerlIO *f, STDCHAR *ptr, SSize_t cnt)
2268{
2269 if (cnt <= 0)
2270 {
2271 PerlIO_flush(f);
2272 }
2273 else
2274 {
2275 PerlIOBuf_set_ptrcnt(f,ptr,cnt);
2276 }
2277}
2278
2279IV
2280PerlIOPending_pushed(PerlIO *f,const char *mode)
2281{
2282 IV code = PerlIOBuf_pushed(f,mode);
2283 PerlIOl *l = PerlIOBase(f);
2284 /* Our PerlIO_fast_gets must match what we are pushed on,
2285 or sv_gets() etc. get muddled when it changes mid-string
2286 when we auto-pop.
2287 */
2288 l->flags = (l->flags & ~PERLIO_F_FASTGETS) |
2289 (PerlIOBase(PerlIONext(f))->flags & PERLIO_F_FASTGETS);
2290 return code;
2291}
2292
2293SSize_t
2294PerlIOPending_read(PerlIO *f, void *vbuf, Size_t count)
2295{
2296 SSize_t avail = PerlIO_get_cnt(f);
2297 SSize_t got = 0;
2298 if (count < avail)
2299 avail = count;
2300 if (avail > 0)
2301 got = PerlIOBuf_read(f,vbuf,avail);
2302 if (got < count)
2303 got += PerlIO_read(f,((STDCHAR *) vbuf)+got,count-got);
2304 return got;
2305}
2306
2307
2308PerlIO_funcs PerlIO_pending = {
2309 "pending",
2310 sizeof(PerlIOBuf),
2311 PERLIO_K_BUFFERED,
2312 PerlIOBase_fileno,
2313 NULL,
2314 NULL,
2315 NULL,
2316 PerlIOPending_pushed,
2317 PerlIOBase_noop_ok,
2318 PerlIOPending_read,
2319 PerlIOBuf_unread,
2320 PerlIOBuf_write,
2321 PerlIOPending_seek,
2322 PerlIOBuf_tell,
2323 PerlIOPending_close,
2324 PerlIOPending_flush,
2325 PerlIOPending_fill,
2326 PerlIOBase_eof,
2327 PerlIOBase_error,
2328 PerlIOBase_clearerr,
2329 PerlIOBuf_setlinebuf,
2330 PerlIOBuf_get_base,
2331 PerlIOBuf_bufsiz,
2332 PerlIOBuf_get_ptr,
2333 PerlIOBuf_get_cnt,
2334 PerlIOPending_set_ptrcnt,
2335};
2336
2337
2338
2339/*--------------------------------------------------------------------------------------*/
99efab12 2340/* crlf - translation
2341 On read translate CR,LF to "\n" we do this by overriding ptr/cnt entries
60382766 2342 to hand back a line at a time and keeping a record of which nl we "lied" about.
99efab12 2343 On write translate "\n" to CR,LF
66ecd56b 2344 */
2345
99efab12 2346typedef struct
2347{
2348 PerlIOBuf base; /* PerlIOBuf stuff */
60382766 2349 STDCHAR *nl; /* Position of crlf we "lied" about in the buffer */
99efab12 2350} PerlIOCrlf;
2351
f5b9d040 2352IV
2353PerlIOCrlf_pushed(PerlIO *f, const char *mode)
2354{
2355 IV code;
2356 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
5e2ab84b 2357 code = PerlIOBuf_pushed(f,mode);
2358#if 0
4659c93f 2359 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08"UVxf"\n",
f5b9d040 2360 f,PerlIOBase(f)->tab->name,(mode) ? mode : "(Null)",
a4d3c1d3 2361 PerlIOBase(f)->flags);
5e2ab84b 2362#endif
f5b9d040 2363 return code;
2364}
2365
2366
99efab12 2367SSize_t
2368PerlIOCrlf_unread(PerlIO *f, const void *vbuf, Size_t count)
2369{
60382766 2370 PerlIOCrlf *c = PerlIOSelf(f,PerlIOCrlf);
60382766 2371 if (c->nl)
2372 {
2373 *(c->nl) = 0xd;
2374 c->nl = NULL;
2375 }
f5b9d040 2376 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
2377 return PerlIOBuf_unread(f,vbuf,count);
2378 else
99efab12 2379 {
a4d3c1d3 2380 const STDCHAR *buf = (const STDCHAR *) vbuf+count;
f5b9d040 2381 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2382 SSize_t unread = 0;
2383 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
2384 PerlIO_flush(f);
2385 if (!b->buf)
2386 PerlIO_get_base(f);
2387 if (b->buf)
99efab12 2388 {
f5b9d040 2389 if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF))
99efab12 2390 {
f5b9d040 2391 b->end = b->ptr = b->buf + b->bufsiz;
2392 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
5e2ab84b 2393 b->posn -= b->bufsiz;
f5b9d040 2394 }
2395 while (count > 0 && b->ptr > b->buf)
2396 {
2397 int ch = *--buf;
2398 if (ch == '\n')
99efab12 2399 {
f5b9d040 2400 if (b->ptr - 2 >= b->buf)
2401 {
2402 *--(b->ptr) = 0xa;
2403 *--(b->ptr) = 0xd;
2404 unread++;
2405 count--;
2406 }
2407 else
2408 {
2409 buf++;
2410 break;
2411 }
99efab12 2412 }
2413 else
2414 {
f5b9d040 2415 *--(b->ptr) = ch;
2416 unread++;
2417 count--;
99efab12 2418 }
2419 }
99efab12 2420 }
f5b9d040 2421 return unread;
99efab12 2422 }
99efab12 2423}
2424
2425SSize_t
2426PerlIOCrlf_get_cnt(PerlIO *f)
2427{
2428 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2429 if (!b->buf)
2430 PerlIO_get_base(f);
2431 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
2432 {
2433 PerlIOCrlf *c = PerlIOSelf(f,PerlIOCrlf);
f5b9d040 2434 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && !c->nl)
99efab12 2435 {
2436 STDCHAR *nl = b->ptr;
60382766 2437 scan:
99efab12 2438 while (nl < b->end && *nl != 0xd)
2439 nl++;
2440 if (nl < b->end && *nl == 0xd)
2441 {
60382766 2442 test:
99efab12 2443 if (nl+1 < b->end)
2444 {
2445 if (nl[1] == 0xa)
2446 {
2447 *nl = '\n';
60382766 2448 c->nl = nl;
99efab12 2449 }
60382766 2450 else
99efab12 2451 {
2452 /* Not CR,LF but just CR */
2453 nl++;
60382766 2454 goto scan;
99efab12 2455 }
2456 }
2457 else
2458 {
60382766 2459 /* Blast - found CR as last char in buffer */
99efab12 2460 if (b->ptr < nl)
2461 {
2462 /* They may not care, defer work as long as possible */
60382766 2463 return (nl - b->ptr);
99efab12 2464 }
2465 else
2466 {
2467 int code;
2468 dTHX;
99efab12 2469 b->ptr++; /* say we have read it as far as flush() is concerned */
2470 b->buf++; /* Leave space an front of buffer */
2471 b->bufsiz--; /* Buffer is thus smaller */
2472 code = PerlIO_fill(f); /* Fetch some more */
2473 b->bufsiz++; /* Restore size for next time */
2474 b->buf--; /* Point at space */
2475 b->ptr = nl = b->buf; /* Which is what we hand off */
2476 b->posn--; /* Buffer starts here */
2477 *nl = 0xd; /* Fill in the CR */
60382766 2478 if (code == 0)
99efab12 2479 goto test; /* fill() call worked */
2480 /* CR at EOF - just fall through */
2481 }
2482 }
60382766 2483 }
2484 }
99efab12 2485 return (((c->nl) ? (c->nl+1) : b->end) - b->ptr);
2486 }
2487 return 0;
2488}
2489
2490void
2491PerlIOCrlf_set_ptrcnt(PerlIO *f, STDCHAR *ptr, SSize_t cnt)
2492{
2493 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2494 PerlIOCrlf *c = PerlIOSelf(f,PerlIOCrlf);
f5b9d040 2495 IV flags = PerlIOBase(f)->flags;
99efab12 2496 if (!b->buf)
2497 PerlIO_get_base(f);
2498 if (!ptr)
60382766 2499 {
63dbdb06 2500 if (c->nl)
2501 ptr = c->nl+1;
2502 else
2503 {
2504 ptr = b->end;
f5b9d040 2505 if ((flags & PERLIO_F_CRLF) && ptr > b->buf && ptr[-1] == 0xd)
63dbdb06 2506 ptr--;
2507 }
2508 ptr -= cnt;
60382766 2509 }
2510 else
2511 {
63dbdb06 2512 /* Test code - delete when it works ... */
2513 STDCHAR *chk;
2514 if (c->nl)
2515 chk = c->nl+1;
2516 else
2517 {
2518 chk = b->end;
f5b9d040 2519 if ((flags & PERLIO_F_CRLF) && chk > b->buf && chk[-1] == 0xd)
63dbdb06 2520 chk--;
2521 }
2522 chk -= cnt;
a4d3c1d3 2523
63dbdb06 2524 if (ptr != chk)
2525 {
2526 dTHX;
4659c93f 2527 Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08"UVxf" nl=%p e=%p for %d",
a4d3c1d3 2528 ptr, chk, flags, c->nl, b->end, cnt);
63dbdb06 2529 }
60382766 2530 }
99efab12 2531 if (c->nl)
2532 {
2533 if (ptr > c->nl)
2534 {
2535 /* They have taken what we lied about */
2536 *(c->nl) = 0xd;
2537 c->nl = NULL;
2538 ptr++;
60382766 2539 }
99efab12 2540 }
2541 b->ptr = ptr;
2542 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
2543}
2544
2545SSize_t
2546PerlIOCrlf_write(PerlIO *f, const void *vbuf, Size_t count)
2547{
f5b9d040 2548 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
2549 return PerlIOBuf_write(f,vbuf,count);
2550 else
99efab12 2551 {
a4d3c1d3 2552 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
f5b9d040 2553 const STDCHAR *buf = (const STDCHAR *) vbuf;
2554 const STDCHAR *ebuf = buf+count;
2555 if (!b->buf)
2556 PerlIO_get_base(f);
2557 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
2558 return 0;
2559 while (buf < ebuf)
99efab12 2560 {
f5b9d040 2561 STDCHAR *eptr = b->buf+b->bufsiz;
2562 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
2563 while (buf < ebuf && b->ptr < eptr)
99efab12 2564 {
f5b9d040 2565 if (*buf == '\n')
60382766 2566 {
f5b9d040 2567 if ((b->ptr + 2) > eptr)
60382766 2568 {
f5b9d040 2569 /* Not room for both */
60382766 2570 PerlIO_flush(f);
2571 break;
2572 }
f5b9d040 2573 else
2574 {
2575 *(b->ptr)++ = 0xd; /* CR */
2576 *(b->ptr)++ = 0xa; /* LF */
2577 buf++;
2578 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF)
2579 {
2580 PerlIO_flush(f);
2581 break;
2582 }
2583 }
2584 }
2585 else
2586 {
2587 int ch = *buf++;
2588 *(b->ptr)++ = ch;
2589 }
2590 if (b->ptr >= eptr)
2591 {
2592 PerlIO_flush(f);
2593 break;
99efab12 2594 }
99efab12 2595 }
2596 }
f5b9d040 2597 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
2598 PerlIO_flush(f);
2599 return (buf - (STDCHAR *) vbuf);
99efab12 2600 }
99efab12 2601}
2602
2603IV
2604PerlIOCrlf_flush(PerlIO *f)
2605{
2606 PerlIOCrlf *c = PerlIOSelf(f,PerlIOCrlf);
2607 if (c->nl)
2608 {
99efab12 2609 *(c->nl) = 0xd;
60382766 2610 c->nl = NULL;
99efab12 2611 }
2612 return PerlIOBuf_flush(f);
2613}
2614
66ecd56b 2615PerlIO_funcs PerlIO_crlf = {
2616 "crlf",
99efab12 2617 sizeof(PerlIOCrlf),
f5b9d040 2618 PERLIO_K_BUFFERED|PERLIO_K_CANCRLF,
66ecd56b 2619 PerlIOBase_fileno,
2620 PerlIOBuf_fdopen,
2621 PerlIOBuf_open,
2622 PerlIOBuf_reopen,
f5b9d040 2623 PerlIOCrlf_pushed,
99efab12 2624 PerlIOBase_noop_ok, /* popped */
2625 PerlIOBuf_read, /* generic read works with ptr/cnt lies ... */
2626 PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */
2627 PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */
66ecd56b 2628 PerlIOBuf_seek,
2629 PerlIOBuf_tell,
2630 PerlIOBuf_close,
99efab12 2631 PerlIOCrlf_flush,
66ecd56b 2632 PerlIOBuf_fill,
2633 PerlIOBase_eof,
2634 PerlIOBase_error,
2635 PerlIOBase_clearerr,
2636 PerlIOBuf_setlinebuf,
2637 PerlIOBuf_get_base,
2638 PerlIOBuf_bufsiz,
2639 PerlIOBuf_get_ptr,
99efab12 2640 PerlIOCrlf_get_cnt,
2641 PerlIOCrlf_set_ptrcnt,
66ecd56b 2642};
2643
06da4f11 2644#ifdef HAS_MMAP
2645/*--------------------------------------------------------------------------------------*/
2646/* mmap as "buffer" layer */
2647
2648typedef struct
2649{
2650 PerlIOBuf base; /* PerlIOBuf stuff */
c3d7c7c9 2651 Mmap_t mptr; /* Mapped address */
06da4f11 2652 Size_t len; /* mapped length */
2653 STDCHAR *bbuf; /* malloced buffer if map fails */
2654} PerlIOMmap;
2655
c3d7c7c9 2656static size_t page_size = 0;
2657
06da4f11 2658IV
2659PerlIOMmap_map(PerlIO *f)
2660{
68d873c6 2661 dTHX;
06da4f11 2662 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2663 PerlIOBuf *b = &m->base;
2664 IV flags = PerlIOBase(f)->flags;
2665 IV code = 0;
2666 if (m->len)
2667 abort();
2668 if (flags & PERLIO_F_CANREAD)
2669 {
2670 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2671 int fd = PerlIO_fileno(f);
2672 struct stat st;
2673 code = fstat(fd,&st);
2674 if (code == 0 && S_ISREG(st.st_mode))
2675 {
2676 SSize_t len = st.st_size - b->posn;
2677 if (len > 0)
2678 {
c3d7c7c9 2679 Off_t posn;
68d873c6 2680 if (!page_size) {
2681#if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE))
2682 {
2683 SETERRNO(0,SS$_NORMAL);
2684# ifdef _SC_PAGESIZE
2685 page_size = sysconf(_SC_PAGESIZE);
2686# else
2687 page_size = sysconf(_SC_PAGE_SIZE);
14aaf8e8 2688# endif
68d873c6 2689 if ((long)page_size < 0) {
2690 if (errno) {
2691 SV *error = ERRSV;
2692 char *msg;
2693 STRLEN n_a;
2694 (void)SvUPGRADE(error, SVt_PV);
2695 msg = SvPVx(error, n_a);
14aaf8e8 2696 Perl_croak(aTHX_ "panic: sysconf: %s", msg);
68d873c6 2697 }
2698 else
14aaf8e8 2699 Perl_croak(aTHX_ "panic: sysconf: pagesize unknown");
68d873c6 2700 }
2701 }
2702#else
2703# ifdef HAS_GETPAGESIZE
c3d7c7c9 2704 page_size = getpagesize();
68d873c6 2705# else
2706# if defined(I_SYS_PARAM) && defined(PAGESIZE)
2707 page_size = PAGESIZE; /* compiletime, bad */
2708# endif
2709# endif
2710#endif
2711 if ((IV)page_size <= 0)
14aaf8e8 2712 Perl_croak(aTHX_ "panic: bad pagesize %"IVdf, (IV)page_size);
68d873c6 2713 }
c3d7c7c9 2714 if (b->posn < 0)
2715 {
2716 /* This is a hack - should never happen - open should have set it ! */
2717 b->posn = PerlIO_tell(PerlIONext(f));
2718 }
2719 posn = (b->posn / page_size) * page_size;
2720 len = st.st_size - posn;
2721 m->mptr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, posn);
2722 if (m->mptr && m->mptr != (Mmap_t) -1)
06da4f11 2723 {
2724#if defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
c3d7c7c9 2725 madvise(m->mptr, len, MADV_SEQUENTIAL);
06da4f11 2726#endif
c3d7c7c9 2727 PerlIOBase(f)->flags = (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
2728 b->end = ((STDCHAR *)m->mptr) + len;
2729 b->buf = ((STDCHAR *)m->mptr) + (b->posn - posn);
2730 b->ptr = b->buf;
2731 m->len = len;
06da4f11 2732 }
2733 else
2734 {
2735 b->buf = NULL;
2736 }
2737 }
2738 else
2739 {
2740 PerlIOBase(f)->flags = flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
2741 b->buf = NULL;
2742 b->ptr = b->end = b->ptr;
2743 code = -1;
2744 }
2745 }
2746 }
2747 return code;
2748}
2749
2750IV
2751PerlIOMmap_unmap(PerlIO *f)
2752{
2753 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2754 PerlIOBuf *b = &m->base;
2755 IV code = 0;
2756 if (m->len)
2757 {
2758 if (b->buf)
2759 {
c3d7c7c9 2760 code = munmap(m->mptr, m->len);
2761 b->buf = NULL;
2762 m->len = 0;
2763 m->mptr = NULL;
06da4f11 2764 if (PerlIO_seek(PerlIONext(f),b->posn,SEEK_SET) != 0)
2765 code = -1;
06da4f11 2766 }
2767 b->ptr = b->end = b->buf;
2768 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF|PERLIO_F_WRBUF);
2769 }
2770 return code;
2771}
2772
2773STDCHAR *
2774PerlIOMmap_get_base(PerlIO *f)
2775{
2776 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2777 PerlIOBuf *b = &m->base;
2778 if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF))
2779 {
2780 /* Already have a readbuffer in progress */
2781 return b->buf;
2782 }
2783 if (b->buf)
2784 {
2785 /* We have a write buffer or flushed PerlIOBuf read buffer */
2786 m->bbuf = b->buf; /* save it in case we need it again */
2787 b->buf = NULL; /* Clear to trigger below */
2788 }
2789 if (!b->buf)
2790 {
2791 PerlIOMmap_map(f); /* Try and map it */
2792 if (!b->buf)
2793 {
2794 /* Map did not work - recover PerlIOBuf buffer if we have one */
2795 b->buf = m->bbuf;
2796 }
2797 }
2798 b->ptr = b->end = b->buf;
2799 if (b->buf)
2800 return b->buf;
2801 return PerlIOBuf_get_base(f);
2802}
2803
2804SSize_t
2805PerlIOMmap_unread(PerlIO *f, const void *vbuf, Size_t count)
2806{
2807 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2808 PerlIOBuf *b = &m->base;
2809 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
2810 PerlIO_flush(f);
2811 if (b->ptr && (b->ptr - count) >= b->buf && memEQ(b->ptr - count,vbuf,count))
2812 {
2813 b->ptr -= count;
2814 PerlIOBase(f)->flags &= ~ PERLIO_F_EOF;
2815 return count;
2816 }
2817 if (m->len)
2818 {
4a4a6116 2819 /* Loose the unwritable mapped buffer */
06da4f11 2820 PerlIO_flush(f);
c3d7c7c9 2821 /* If flush took the "buffer" see if we have one from before */
2822 if (!b->buf && m->bbuf)
2823 b->buf = m->bbuf;
2824 if (!b->buf)
2825 {
2826 PerlIOBuf_get_base(f);
2827 m->bbuf = b->buf;
2828 }
06da4f11 2829 }
5e2ab84b 2830return PerlIOBuf_unread(f,vbuf,count);
06da4f11 2831}
2832
2833SSize_t
2834PerlIOMmap_write(PerlIO *f, const void *vbuf, Size_t count)
2835{
2836 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2837 PerlIOBuf *b = &m->base;
2838 if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF))
2839 {
2840 /* No, or wrong sort of, buffer */
2841 if (m->len)
2842 {
2843 if (PerlIOMmap_unmap(f) != 0)
2844 return 0;
2845 }
2846 /* If unmap took the "buffer" see if we have one from before */
2847 if (!b->buf && m->bbuf)
2848 b->buf = m->bbuf;
2849 if (!b->buf)
2850 {
2851 PerlIOBuf_get_base(f);
2852 m->bbuf = b->buf;
2853 }
2854 }
2855 return PerlIOBuf_write(f,vbuf,count);
2856}
2857
2858IV
2859PerlIOMmap_flush(PerlIO *f)
2860{
2861 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2862 PerlIOBuf *b = &m->base;
2863 IV code = PerlIOBuf_flush(f);
2864 /* Now we are "synced" at PerlIOBuf level */
2865 if (b->buf)
2866 {
2867 if (m->len)
2868 {
2869 /* Unmap the buffer */
2870 if (PerlIOMmap_unmap(f) != 0)
2871 code = -1;
2872 }
2873 else
2874 {
2875 /* We seem to have a PerlIOBuf buffer which was not mapped
2876 * remember it in case we need one later
2877 */
2878 m->bbuf = b->buf;
2879 }
2880 }
06da4f11 2881 return code;
2882}
2883
2884IV
2885PerlIOMmap_fill(PerlIO *f)
2886{
2887 PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
2888 IV code = PerlIO_flush(f);
06da4f11 2889 if (code == 0 && !b->buf)
2890 {
2891 code = PerlIOMmap_map(f);
06da4f11 2892 }
2893 if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF))
2894 {
2895 code = PerlIOBuf_fill(f);
06da4f11 2896 }
2897 return code;
2898}
2899
2900IV
2901PerlIOMmap_close(PerlIO *f)
2902{
2903 PerlIOMmap *m = PerlIOSelf(f,PerlIOMmap);
2904 PerlIOBuf *b = &m->base;
2905 IV code = PerlIO_flush(f);
2906 if (m->bbuf)
2907 {
2908 b->buf = m->bbuf;
2909 m->bbuf = NULL;
2910 b->ptr = b->end = b->buf;
2911 }
2912 if (PerlIOBuf_close(f) != 0)
2913 code = -1;
06da4f11 2914 return code;
2915}
2916
2917
2918PerlIO_funcs PerlIO_mmap = {
2919 "mmap",
2920 sizeof(PerlIOMmap),
f5b9d040 2921 PERLIO_K_BUFFERED,
06da4f11 2922 PerlIOBase_fileno,
2923 PerlIOBuf_fdopen,
2924 PerlIOBuf_open,
c3d7c7c9 2925 PerlIOBuf_reopen,
5e2ab84b 2926 PerlIOBuf_pushed,
06da4f11 2927 PerlIOBase_noop_ok,
2928 PerlIOBuf_read,
2929 PerlIOMmap_unread,
2930 PerlIOMmap_write,
2931 PerlIOBuf_seek,
2932 PerlIOBuf_tell,
2933 PerlIOBuf_close,
2934 PerlIOMmap_flush,
2935 PerlIOMmap_fill,
2936 PerlIOBase_eof,
2937 PerlIOBase_error,
2938 PerlIOBase_clearerr,
2939 PerlIOBuf_setlinebuf,
2940 PerlIOMmap_get_base,
2941 PerlIOBuf_bufsiz,
2942 PerlIOBuf_get_ptr,
2943 PerlIOBuf_get_cnt,
2944 PerlIOBuf_set_ptrcnt,
2945};
2946
2947#endif /* HAS_MMAP */
2948
9e353e3b 2949void
2950PerlIO_init(void)
760ac839 2951{
9e353e3b 2952 if (!_perlio)
6f9d8c32 2953 {
9e353e3b 2954 atexit(&PerlIO_cleanup);
6f9d8c32 2955 }
760ac839 2956}
2957
9e353e3b 2958#undef PerlIO_stdin
2959PerlIO *
2960PerlIO_stdin(void)
2961{
2962 if (!_perlio)
f3862f8b 2963 PerlIO_stdstreams();
05d1247b 2964 return &_perlio[1];
9e353e3b 2965}
2966
2967#undef PerlIO_stdout
2968PerlIO *
2969PerlIO_stdout(void)
2970{
2971 if (!_perlio)
f3862f8b 2972 PerlIO_stdstreams();
05d1247b 2973 return &_perlio[2];
9e353e3b 2974}
2975
2976#undef PerlIO_stderr
2977PerlIO *
2978PerlIO_stderr(void)
2979{
2980 if (!_perlio)
f3862f8b 2981 PerlIO_stdstreams();
05d1247b 2982 return &_perlio[3];
9e353e3b 2983}
2984
2985/*--------------------------------------------------------------------------------------*/
2986
2987#undef PerlIO_getname
2988char *
2989PerlIO_getname(PerlIO *f, char *buf)
2990{
2991 dTHX;
2992 Perl_croak(aTHX_ "Don't know how to get file name");
2993 return NULL;
2994}
2995
2996
2997/*--------------------------------------------------------------------------------------*/
2998/* Functions which can be called on any kind of PerlIO implemented
2999 in terms of above
3000*/
3001
3002#undef PerlIO_getc
6f9d8c32 3003int
9e353e3b 3004PerlIO_getc(PerlIO *f)
760ac839 3005{
313ca112 3006 STDCHAR buf[1];
3007 SSize_t count = PerlIO_read(f,buf,1);
9e353e3b 3008 if (count == 1)
313ca112 3009 {
3010 return (unsigned char) buf[0];
3011 }
3012 return EOF;
3013}
3014
3015#undef PerlIO_ungetc
3016int
3017PerlIO_ungetc(PerlIO *f, int ch)
3018{
3019 if (ch != EOF)
3020 {
3021 STDCHAR buf = ch;
3022 if (PerlIO_unread(f,&buf,1) == 1)
3023 return ch;
3024 }
3025 return EOF;
760ac839 3026}
3027
9e353e3b 3028#undef PerlIO_putc
3029int
3030PerlIO_putc(PerlIO *f, int ch)
760ac839 3031{
9e353e3b 3032 STDCHAR buf = ch;
3033 return PerlIO_write(f,&buf,1);
760ac839 3034}
3035
9e353e3b 3036#undef PerlIO_puts
760ac839 3037int
9e353e3b 3038PerlIO_puts(PerlIO *f, const char *s)
760ac839 3039{
9e353e3b 3040 STRLEN len = strlen(s);
3041 return PerlIO_write(f,s,len);
760ac839 3042}
3043
3044#undef PerlIO_rewind
3045void
c78749f2 3046PerlIO_rewind(PerlIO *f)
760ac839 3047{
6f9d8c32 3048 PerlIO_seek(f,(Off_t)0,SEEK_SET);
9e353e3b 3049 PerlIO_clearerr(f);
6f9d8c32 3050}
3051
3052#undef PerlIO_vprintf
3053int
3054PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
3055{
3056 dTHX;
bb9950b7 3057 SV *sv = newSVpvn("",0);
6f9d8c32 3058 char *s;
3059 STRLEN len;
2cc61e15 3060#ifdef NEED_VA_COPY
3061 va_list apc;
3062 Perl_va_copy(ap, apc);
3063 sv_vcatpvf(sv, fmt, &apc);
3064#else
6f9d8c32 3065 sv_vcatpvf(sv, fmt, &ap);
2cc61e15 3066#endif
6f9d8c32 3067 s = SvPV(sv,len);
bb9950b7 3068 return PerlIO_write(f,s,len);
760ac839 3069}
3070
3071#undef PerlIO_printf
6f9d8c32 3072int
760ac839 3073PerlIO_printf(PerlIO *f,const char *fmt,...)
760ac839 3074{
3075 va_list ap;
3076 int result;
760ac839 3077 va_start(ap,fmt);
6f9d8c32 3078 result = PerlIO_vprintf(f,fmt,ap);
760ac839 3079 va_end(ap);
3080 return result;
3081}
3082
3083#undef PerlIO_stdoutf
6f9d8c32 3084int
760ac839 3085PerlIO_stdoutf(const char *fmt,...)
760ac839 3086{
3087 va_list ap;
3088 int result;
760ac839 3089 va_start(ap,fmt);
760ac839 3090 result = PerlIO_vprintf(PerlIO_stdout(),fmt,ap);
3091 va_end(ap);
3092 return result;
3093}
3094
3095#undef PerlIO_tmpfile
3096PerlIO *
c78749f2 3097PerlIO_tmpfile(void)
760ac839 3098{
b1ef6e3b 3099 /* I have no idea how portable mkstemp() is ... */
83b075c3 3100#if defined(WIN32) || !defined(HAVE_MKSTEMP)
adb71456 3101 dTHX;
83b075c3 3102 PerlIO *f = NULL;
eaf8b698 3103 FILE *stdio = PerlSIO_tmpfile();
83b075c3 3104 if (stdio)
3105 {
5f1a76d0 3106 PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(aTHX),&PerlIO_stdio,"w+"),PerlIOStdio);
83b075c3 3107 s->stdio = stdio;
3108 }
3109 return f;
3110#else
3111 dTHX;
6f9d8c32 3112 SV *sv = newSVpv("/tmp/PerlIO_XXXXXX",0);
3113 int fd = mkstemp(SvPVX(sv));
3114 PerlIO *f = NULL;
3115 if (fd >= 0)
3116 {
b1ef6e3b 3117 f = PerlIO_fdopen(fd,"w+");
6f9d8c32 3118 if (f)
3119 {
9e353e3b 3120 PerlIOBase(f)->flags |= PERLIO_F_TEMP;
6f9d8c32 3121 }
00b02797 3122 PerlLIO_unlink(SvPVX(sv));
6f9d8c32 3123 SvREFCNT_dec(sv);
3124 }
3125 return f;
83b075c3 3126#endif
760ac839 3127}
3128
6f9d8c32 3129#undef HAS_FSETPOS
3130#undef HAS_FGETPOS
3131
760ac839 3132#endif /* USE_SFIO */
3133#endif /* PERLIO_IS_STDIO */
3134
9e353e3b 3135/*======================================================================================*/
3136/* Now some functions in terms of above which may be needed even if
3137 we are not in true PerlIO mode
3138 */
3139
760ac839 3140#ifndef HAS_FSETPOS
3141#undef PerlIO_setpos
3142int
c78749f2 3143PerlIO_setpos(PerlIO *f, const Fpos_t *pos)
760ac839 3144{
6f9d8c32 3145 return PerlIO_seek(f,*pos,0);
760ac839 3146}
c411622e 3147#else
3148#ifndef PERLIO_IS_STDIO
3149#undef PerlIO_setpos
3150int
c78749f2 3151PerlIO_setpos(PerlIO *f, const Fpos_t *pos)
c411622e 3152{
2d4389e4 3153#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
d9b3e12d 3154 return fsetpos64(f, pos);
3155#else
c411622e 3156 return fsetpos(f, pos);
d9b3e12d 3157#endif
c411622e 3158}
3159#endif
760ac839 3160#endif
3161
3162#ifndef HAS_FGETPOS
3163#undef PerlIO_getpos
3164int
c78749f2 3165PerlIO_getpos(PerlIO *f, Fpos_t *pos)
760ac839 3166{
3167 *pos = PerlIO_tell(f);
a17c7222 3168 return *pos == -1 ? -1 : 0;
760ac839 3169}
c411622e 3170#else
3171#ifndef PERLIO_IS_STDIO
3172#undef PerlIO_getpos
3173int
c78749f2 3174PerlIO_getpos(PerlIO *f, Fpos_t *pos)
c411622e 3175{
2d4389e4 3176#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
d9b3e12d 3177 return fgetpos64(f, pos);
3178#else
c411622e 3179 return fgetpos(f, pos);
d9b3e12d 3180#endif
c411622e 3181}
3182#endif
760ac839 3183#endif
3184
3185#if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
3186
3187int
c78749f2 3188vprintf(char *pat, char *args)
662a7e3f 3189{
3190 _doprnt(pat, args, stdout);
3191 return 0; /* wrong, but perl doesn't use the return value */
3192}
3193
3194int
c78749f2 3195vfprintf(FILE *fd, char *pat, char *args)
760ac839 3196{
3197 _doprnt(pat, args, fd);
3198 return 0; /* wrong, but perl doesn't use the return value */
3199}
3200
3201#endif
3202
3203#ifndef PerlIO_vsprintf
6f9d8c32 3204int
8ac85365 3205PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
760ac839 3206{
3207 int val = vsprintf(s, fmt, ap);
3208 if (n >= 0)
3209 {
8c86a920 3210 if (strlen(s) >= (STRLEN)n)
760ac839 3211 {
bf49b057 3212 dTHX;
fb4a9925 3213 (void)PerlIO_puts(Perl_error_log,
3214 "panic: sprintf overflow - memory corrupted!\n");
bf49b057 3215 my_exit(1);
760ac839 3216 }
3217 }
3218 return val;
3219}
3220#endif
3221
3222#ifndef PerlIO_sprintf
6f9d8c32 3223int
760ac839 3224PerlIO_sprintf(char *s, int n, const char *fmt,...)
760ac839 3225{
3226 va_list ap;
3227 int result;
760ac839 3228 va_start(ap,fmt);
760ac839 3229 result = PerlIO_vsprintf(s, n, fmt, ap);
3230 va_end(ap);
3231 return result;
3232}
3233#endif
3234
c5be433b 3235