This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate mainline
[perl5.git] / perlio.c
CommitLineData
14a5cf38 1/*
be3c0a43 2 * perlio.c Copyright (c) 1996-2002, Nick Ing-Simmons You may distribute
14a5cf38 3 * under the terms of either the GNU General Public License or the
71200d45 4 * Artistic License, as specified in the README file.
760ac839
LW
5 */
6
14a5cf38 7/*
d31a8517
AT
8 * Hour after hour for nearly three weary days he had jogged up and down,
9 * over passes, and through long dales, and across many streams.
10 */
11
12/*
71200d45 13 * If we have ActivePerl-like PERL_IMPLICIT_SYS then we need a dTHX to get
14a5cf38 14 * at the dispatch tables, even when we do not need it for other reasons.
71200d45 15 * Invent a dSYS macro to abstract this out
14a5cf38 16 */
7bcba3d4
NIS
17#ifdef PERL_IMPLICIT_SYS
18#define dSYS dTHX
19#else
20#define dSYS dNOOP
21#endif
22
760ac839 23#define VOIDUSED 1
12ae5dfc
JH
24#ifdef PERL_MICRO
25# include "uconfig.h"
26#else
27# include "config.h"
28#endif
760ac839 29
6f9d8c32 30#define PERLIO_NOT_STDIO 0
760ac839 31#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
14a5cf38 32/*
71200d45 33 * #define PerlIO FILE
14a5cf38 34 */
760ac839
LW
35#endif
36/*
6f9d8c32 37 * This file provides those parts of PerlIO abstraction
88b61e10 38 * which are not #defined in perlio.h.
6f9d8c32 39 * Which these are depends on various Configure #ifdef's
760ac839
LW
40 */
41
42#include "EXTERN.h"
864dbfa3 43#define PERL_IN_PERLIO_C
760ac839
LW
44#include "perl.h"
45
32af7c23
CL
46#ifdef PERL_IMPLICIT_CONTEXT
47#undef dSYS
48#define dSYS dTHX
49#endif
50
0c4f7ff0
NIS
51#include "XSUB.h"
52
60382766 53int
f5b9d040 54perlsio_binmode(FILE *fp, int iotype, int mode)
60382766 55{
14a5cf38 56 /*
71200d45 57 * This used to be contents of do_binmode in doio.c
14a5cf38 58 */
60382766
NIS
59#ifdef DOSISH
60# if defined(atarist) || defined(__MINT__)
f5b9d040 61 if (!fflush(fp)) {
60382766 62 if (mode & O_BINARY)
14a5cf38 63 ((FILE *) fp)->_flag |= _IOBIN;
60382766 64 else
14a5cf38 65 ((FILE *) fp)->_flag &= ~_IOBIN;
60382766
NIS
66 return 1;
67 }
68 return 0;
69# else
eb73beca 70 dTHX;
14a5cf38
JH
71#ifdef NETWARE
72 if (PerlLIO_setmode(fp, mode) != -1) {
73#else
f5b9d040 74 if (PerlLIO_setmode(fileno(fp), mode) != -1) {
14a5cf38 75#endif
60382766 76# if defined(WIN32) && defined(__BORLANDC__)
14a5cf38 77 /*
71200d45 78 * The translation mode of the stream is maintained independent of
14a5cf38 79 * the translation mode of the fd in the Borland RTL (heavy
71200d45 80 * digging through their runtime sources reveal). User has to set
14a5cf38 81 * the mode explicitly for the stream (though they don't document
71200d45 82 * this anywhere). GSAR 97-5-24
60382766 83 */
14a5cf38 84 fseek(fp, 0L, 0);
60382766 85 if (mode & O_BINARY)
f5b9d040 86 fp->flags |= _F_BIN;
60382766 87 else
14a5cf38 88 fp->flags &= ~_F_BIN;
60382766
NIS
89# endif
90 return 1;
91 }
92 else
93 return 0;
94# endif
95#else
96# if defined(USEMYBINMODE)
04a0f00b 97 dTHX;
60382766
NIS
98 if (my_binmode(fp, iotype, mode) != FALSE)
99 return 1;
100 else
101 return 0;
102# else
103 return 1;
104# endif
105#endif
106}
107
06c7082d 108#ifndef O_ACCMODE
22569500 109#define O_ACCMODE 3 /* Assume traditional implementation */
06c7082d
NIS
110#endif
111
112int
113PerlIO_intmode2str(int rawmode, char *mode, int *writing)
114{
115 int result = rawmode & O_ACCMODE;
116 int ix = 0;
117 int ptype;
118 switch (result) {
119 case O_RDONLY:
120 ptype = IoTYPE_RDONLY;
121 break;
122 case O_WRONLY:
123 ptype = IoTYPE_WRONLY;
124 break;
125 case O_RDWR:
126 default:
127 ptype = IoTYPE_RDWR;
128 break;
129 }
130 if (writing)
131 *writing = (result != O_RDONLY);
132
133 if (result == O_RDONLY) {
134 mode[ix++] = 'r';
135 }
136#ifdef O_APPEND
137 else if (rawmode & O_APPEND) {
138 mode[ix++] = 'a';
139 if (result != O_WRONLY)
140 mode[ix++] = '+';
141 }
142#endif
143 else {
144 if (result == O_WRONLY)
145 mode[ix++] = 'w';
146 else {
147 mode[ix++] = 'r';
148 mode[ix++] = '+';
149 }
150 }
151 if (rawmode & O_BINARY)
152 mode[ix++] = 'b';
153 mode[ix] = '\0';
154 return ptype;
155}
156
eb73beca
NIS
157#ifndef PERLIO_LAYERS
158int
159PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
160{
14a5cf38
JH
161 if (!names || !*names || strEQ(names, ":crlf") || strEQ(names, ":raw")) {
162 return 0;
163 }
164 Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl", names);
165 /*
71200d45 166 * NOTREACHED
14a5cf38
JH
167 */
168 return -1;
eb73beca
NIS
169}
170
13621cfb
NIS
171void
172PerlIO_destruct(pTHX)
173{
174}
175
f5b9d040
NIS
176int
177PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
178{
92bff44d 179#ifdef USE_SFIO
14a5cf38 180 return 1;
92bff44d 181#else
14a5cf38 182 return perlsio_binmode(fp, iotype, mode);
92bff44d 183#endif
f5b9d040 184}
60382766 185
e0fa5af2 186PerlIO *
ecdeb87c 187PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
e0fa5af2 188{
0553478e
NIS
189#ifdef PERL_MICRO
190 return NULL;
191#else
192#ifdef PERL_IMPLICIT_SYS
22569500 193 return PerlSIO_fdupopen(f);
0553478e 194#else
30753f56
NIS
195#ifdef WIN32
196 return win32_fdupopen(f);
197#else
e0fa5af2
NIS
198 if (f) {
199 int fd = PerlLIO_dup(PerlIO_fileno(f));
200 if (fd >= 0) {
06c7082d
NIS
201 char mode[8];
202 int omode = fcntl(fd, F_GETFL);
a5936e02
JH
203#ifdef DJGPP
204 omode = djgpp_get_stream_mode(f);
205#endif
06c7082d 206 PerlIO_intmode2str(omode,mode,NULL);
e0fa5af2 207 /* the r+ is a hack */
06c7082d 208 return PerlIO_fdopen(fd, mode);
e0fa5af2
NIS
209 }
210 return NULL;
211 }
212 else {
213 SETERRNO(EBADF, SS$_IVCHAN);
214 }
7114a2d2 215#endif
e0fa5af2 216 return NULL;
0553478e 217#endif
30753f56 218#endif
e0fa5af2
NIS
219}
220
221
14a5cf38 222/*
71200d45 223 * De-mux PerlIO_openn() into fdopen, freopen and fopen type entries
14a5cf38 224 */
ee518936
NIS
225
226PerlIO *
14a5cf38
JH
227PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
228 int imode, int perm, PerlIO *old, int narg, SV **args)
229{
7cf31beb
NIS
230 if (narg) {
231 if (narg > 1) {
3b8752bb 232 Perl_croak(aTHX_ "More than one argument to open");
7cf31beb 233 }
14a5cf38
JH
234 if (*args == &PL_sv_undef)
235 return PerlIO_tmpfile();
236 else {
237 char *name = SvPV_nolen(*args);
238 if (*mode == '#') {
239 fd = PerlLIO_open3(name, imode, perm);
240 if (fd >= 0)
241 return PerlIO_fdopen(fd, (char *) mode + 1);
242 }
243 else if (old) {
244 return PerlIO_reopen(name, mode, old);
245 }
246 else {
247 return PerlIO_open(name, mode);
248 }
249 }
250 }
251 else {
252 return PerlIO_fdopen(fd, (char *) mode);
253 }
254 return NULL;
ee518936
NIS
255}
256
0c4f7ff0
NIS
257XS(XS_PerlIO__Layer__find)
258{
14a5cf38
JH
259 dXSARGS;
260 if (items < 2)
261 Perl_croak(aTHX_ "Usage class->find(name[,load])");
262 else {
263 char *name = SvPV_nolen(ST(1));
264 ST(0) = (strEQ(name, "crlf")
265 || strEQ(name, "raw")) ? &PL_sv_yes : &PL_sv_undef;
266 XSRETURN(1);
267 }
0c4f7ff0
NIS
268}
269
270
271void
272Perl_boot_core_PerlIO(pTHX)
273{
14a5cf38 274 newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
0c4f7ff0
NIS
275}
276
ac27b0f5
NIS
277#endif
278
32e30700 279
6f9d8c32 280#ifdef PERLIO_IS_STDIO
760ac839
LW
281
282void
e8632036 283PerlIO_init(pTHX)
760ac839 284{
14a5cf38
JH
285 /*
286 * Does nothing (yet) except force this file to be included in perl
71200d45 287 * binary. That allows this file to force inclusion of other functions
14a5cf38 288 * that may be required by loadable extensions e.g. for
71200d45 289 * FileHandle::tmpfile
14a5cf38 290 */
760ac839
LW
291}
292
33dcbb9a 293#undef PerlIO_tmpfile
294PerlIO *
8ac85365 295PerlIO_tmpfile(void)
33dcbb9a 296{
14a5cf38 297 return tmpfile();
33dcbb9a 298}
299
22569500 300#else /* PERLIO_IS_STDIO */
760ac839
LW
301
302#ifdef USE_SFIO
303
304#undef HAS_FSETPOS
305#undef HAS_FGETPOS
306
14a5cf38
JH
307/*
308 * This section is just to make sure these functions get pulled in from
71200d45 309 * libsfio.a
14a5cf38 310 */
760ac839
LW
311
312#undef PerlIO_tmpfile
313PerlIO *
c78749f2 314PerlIO_tmpfile(void)
760ac839 315{
14a5cf38 316 return sftmp(0);
760ac839
LW
317}
318
319void
e8632036 320PerlIO_init(pTHX)
760ac839 321{
14a5cf38
JH
322 /*
323 * Force this file to be included in perl binary. Which allows this
324 * file to force inclusion of other functions that may be required by
71200d45 325 * loadable extensions e.g. for FileHandle::tmpfile
14a5cf38 326 */
760ac839 327
14a5cf38 328 /*
71200d45 329 * Hack sfio does its own 'autoflush' on stdout in common cases. Flush
14a5cf38 330 * results in a lot of lseek()s to regular files and lot of small
71200d45 331 * writes to pipes.
14a5cf38
JH
332 */
333 sfset(sfstdout, SF_SHARE, 0);
760ac839
LW
334}
335
92bff44d
NIS
336PerlIO *
337PerlIO_importFILE(FILE *stdio, int fl)
338{
14a5cf38
JH
339 int fd = fileno(stdio);
340 PerlIO *r = PerlIO_fdopen(fd, "r+");
341 return r;
92bff44d
NIS
342}
343
344FILE *
345PerlIO_findFILE(PerlIO *pio)
346{
14a5cf38
JH
347 int fd = PerlIO_fileno(pio);
348 FILE *f = fdopen(fd, "r+");
349 PerlIO_flush(pio);
350 if (!f && errno == EINVAL)
351 f = fdopen(fd, "w");
352 if (!f && errno == EINVAL)
353 f = fdopen(fd, "r");
354 return f;
92bff44d
NIS
355}
356
357
22569500 358#else /* USE_SFIO */
6f9d8c32 359/*======================================================================================*/
14a5cf38 360/*
71200d45 361 * Implement all the PerlIO interface ourselves.
9e353e3b 362 */
760ac839 363
76ced9ad
NIS
364#include "perliol.h"
365
14a5cf38
JH
366/*
367 * We _MUST_ have <unistd.h> if we are using lseek() and may have large
71200d45 368 * files
14a5cf38 369 */
02f66e2f
NIS
370#ifdef I_UNISTD
371#include <unistd.h>
372#endif
06da4f11
NIS
373#ifdef HAS_MMAP
374#include <sys/mman.h>
375#endif
376
02f66e2f 377
14a5cf38
JH
378void PerlIO_debug(const char *fmt, ...)
379 __attribute__ ((format(__printf__, 1, 2)));
6f9d8c32 380
6f9d8c32 381void
14a5cf38
JH
382PerlIO_debug(const char *fmt, ...)
383{
384 static int dbg = 0;
385 va_list ap;
386 dSYS;
387 va_start(ap, fmt);
388 if (!dbg) {
389 char *s = PerlEnv_getenv("PERLIO_DEBUG");
390 if (s && *s)
391 dbg = PerlLIO_open3(s, O_WRONLY | O_CREAT | O_APPEND, 0666);
392 else
393 dbg = -1;
394 }
395 if (dbg > 0) {
396 dTHX;
70ace5da
NIS
397#ifdef USE_ITHREADS
398 /* Use fixed buffer as sv_catpvf etc. needs SVs */
399 char buffer[1024];
400 char *s;
401 STRLEN len;
402 s = CopFILE(PL_curcop);
403 if (!s)
404 s = "(none)";
405 sprintf(buffer, "%s:%" IVdf " ", s, (IV) CopLINE(PL_curcop));
22569500 406 len = strlen(buffer);
70ace5da
NIS
407 vsprintf(buffer+len, fmt, ap);
408 PerlLIO_write(dbg, buffer, strlen(buffer));
409#else
14a5cf38
JH
410 SV *sv = newSVpvn("", 0);
411 char *s;
412 STRLEN len;
413 s = CopFILE(PL_curcop);
414 if (!s)
415 s = "(none)";
416 Perl_sv_catpvf(aTHX_ sv, "%s:%" IVdf " ", s,
417 (IV) CopLINE(PL_curcop));
418 Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
419
420 s = SvPV(sv, len);
421 PerlLIO_write(dbg, s, len);
422 SvREFCNT_dec(sv);
70ace5da 423#endif
14a5cf38
JH
424 }
425 va_end(ap);
6f9d8c32
NIS
426}
427
9e353e3b
NIS
428/*--------------------------------------------------------------------------------------*/
429
14a5cf38 430/*
71200d45 431 * Inner level routines
14a5cf38 432 */
9e353e3b 433
14a5cf38 434/*
71200d45 435 * Table of pointers to the PerlIO structs (malloc'ed)
14a5cf38 436 */
05d1247b 437#define PERLIO_TABLE_SIZE 64
6f9d8c32 438
760ac839 439PerlIO *
5f1a76d0 440PerlIO_allocate(pTHX)
6f9d8c32 441{
14a5cf38 442 /*
71200d45 443 * Find a free slot in the table, allocating new table as necessary
14a5cf38
JH
444 */
445 PerlIO **last;
446 PerlIO *f;
a1ea730d 447 last = &PL_perlio;
14a5cf38
JH
448 while ((f = *last)) {
449 int i;
450 last = (PerlIO **) (f);
451 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
452 if (!*++f) {
453 return f;
454 }
455 }
456 }
3a1ee7e8 457 Newz('I',f,PERLIO_TABLE_SIZE,PerlIO);
14a5cf38
JH
458 if (!f) {
459 return NULL;
460 }
461 *last = f;
462 return f + 1;
05d1247b
NIS
463}
464
a1ea730d
NIS
465#undef PerlIO_fdupopen
466PerlIO *
ecdeb87c 467PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
a1ea730d 468{
04892f78 469 if (PerlIOValid(f)) {
a1ea730d
NIS
470 PerlIO_funcs *tab = PerlIOBase(f)->tab;
471 PerlIO *new;
fe5a182c 472 PerlIO_debug("fdupopen f=%p param=%p\n",(void*)f,(void*)param);
22569500 473 new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags);
a1ea730d
NIS
474 return new;
475 }
476 else {
477 SETERRNO(EBADF, SS$_IVCHAN);
478 return NULL;
479 }
480}
481
482void
5f1a76d0 483PerlIO_cleantable(pTHX_ PerlIO **tablep)
05d1247b 484{
14a5cf38
JH
485 PerlIO *table = *tablep;
486 if (table) {
487 int i;
488 PerlIO_cleantable(aTHX_(PerlIO **) & (table[0]));
489 for (i = PERLIO_TABLE_SIZE - 1; i > 0; i--) {
490 PerlIO *f = table + i;
491 if (*f) {
492 PerlIO_close(f);
493 }
494 }
3a1ee7e8 495 Safefree(table);
14a5cf38 496 *tablep = NULL;
05d1247b 497 }
05d1247b
NIS
498}
499
fcf2db38
NIS
500
501PerlIO_list_t *
3a1ee7e8 502PerlIO_list_alloc(pTHX)
fcf2db38 503{
14a5cf38
JH
504 PerlIO_list_t *list;
505 Newz('L', list, 1, PerlIO_list_t);
506 list->refcnt = 1;
507 return list;
fcf2db38
NIS
508}
509
510void
3a1ee7e8 511PerlIO_list_free(pTHX_ PerlIO_list_t *list)
fcf2db38 512{
14a5cf38
JH
513 if (list) {
514 if (--list->refcnt == 0) {
515 if (list->array) {
14a5cf38
JH
516 IV i;
517 for (i = 0; i < list->cur; i++) {
518 if (list->array[i].arg)
519 SvREFCNT_dec(list->array[i].arg);
520 }
521 Safefree(list->array);
522 }
523 Safefree(list);
524 }
525 }
fcf2db38
NIS
526}
527
528void
3a1ee7e8 529PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg)
14a5cf38 530{
14a5cf38
JH
531 PerlIO_pair_t *p;
532 if (list->cur >= list->len) {
533 list->len += 8;
534 if (list->array)
535 Renew(list->array, list->len, PerlIO_pair_t);
536 else
537 New('l', list->array, list->len, PerlIO_pair_t);
538 }
539 p = &(list->array[list->cur++]);
540 p->funcs = funcs;
541 if ((p->arg = arg)) {
542 SvREFCNT_inc(arg);
543 }
fcf2db38
NIS
544}
545
3a1ee7e8
NIS
546PerlIO_list_t *
547PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param)
548{
694c95cf
JH
549 PerlIO_list_t *list = (PerlIO_list_t *) NULL;
550 if (proto) {
551 int i;
552 list = PerlIO_list_alloc(aTHX);
553 for (i=0; i < proto->cur; i++) {
554 SV *arg = Nullsv;
555 if (proto->array[i].arg)
556 arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param);
557 PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg);
558 }
3a1ee7e8
NIS
559 }
560 return list;
561}
4a4a6116 562
05d1247b 563void
3a1ee7e8 564PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
9a6404c5 565{
3aaf42a7 566#ifdef USE_ITHREADS
3a1ee7e8
NIS
567 PerlIO **table = &proto->Iperlio;
568 PerlIO *f;
569 PL_perlio = NULL;
570 PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param);
571 PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param);
572 PerlIO_allocate(aTHX); /* root slot is never used */
694c95cf 573 PerlIO_debug("Clone %p from %p\n",aTHX,proto);
3a1ee7e8
NIS
574 while ((f = *table)) {
575 int i;
576 table = (PerlIO **) (f++);
577 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
578 if (*f) {
93a8090d 579 (void) fp_dup(f, 0, param);
3a1ee7e8
NIS
580 }
581 f++;
582 }
583 }
3aaf42a7 584#endif
9a6404c5
DM
585}
586
587void
13621cfb
NIS
588PerlIO_destruct(pTHX)
589{
a1ea730d 590 PerlIO **table = &PL_perlio;
14a5cf38 591 PerlIO *f;
694c95cf
JH
592#ifdef USE_ITHREADS
593 PerlIO_debug("Destruct %p\n",aTHX);
594#endif
14a5cf38
JH
595 while ((f = *table)) {
596 int i;
597 table = (PerlIO **) (f++);
598 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
599 PerlIO *x = f;
600 PerlIOl *l;
601 while ((l = *x)) {
602 if (l->tab->kind & PERLIO_K_DESTRUCT) {
603 PerlIO_debug("Destruct popping %s\n", l->tab->name);
604 PerlIO_flush(x);
605 PerlIO_pop(aTHX_ x);
606 }
607 else {
608 x = PerlIONext(x);
609 }
610 }
611 f++;
612 }
613 }
13621cfb
NIS
614}
615
616void
a999f61b 617PerlIO_pop(pTHX_ PerlIO *f)
760ac839 618{
14a5cf38
JH
619 PerlIOl *l = *f;
620 if (l) {
fe5a182c 621 PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, l->tab->name);
14a5cf38
JH
622 if (l->tab->Popped) {
623 /*
624 * If popped returns non-zero do not free its layer structure
625 * it has either done so itself, or it is shared and still in
71200d45 626 * use
14a5cf38 627 */
f62ce20a 628 if ((*l->tab->Popped) (aTHX_ f) != 0)
14a5cf38
JH
629 return;
630 }
631 *f = l->next;;
3a1ee7e8 632 Safefree(l);
a8c08ecd 633 }
6f9d8c32
NIS
634}
635
9e353e3b 636/*--------------------------------------------------------------------------------------*/
14a5cf38 637/*
71200d45 638 * XS Interface for perl code
14a5cf38 639 */
9e353e3b 640
fcf2db38 641PerlIO_funcs *
2edd7e44 642PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
f3862f8b 643{
14a5cf38
JH
644 IV i;
645 if ((SSize_t) len <= 0)
646 len = strlen(name);
3a1ee7e8
NIS
647 for (i = 0; i < PL_known_layers->cur; i++) {
648 PerlIO_funcs *f = PL_known_layers->array[i].funcs;
14a5cf38 649 if (memEQ(f->name, name, len)) {
fe5a182c 650 PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f);
14a5cf38
JH
651 return f;
652 }
653 }
3a1ee7e8
NIS
654 if (load && PL_subname && PL_def_layerlist
655 && PL_def_layerlist->cur >= 2) {
14a5cf38
JH
656 SV *pkgsv = newSVpvn("PerlIO", 6);
657 SV *layer = newSVpvn(name, len);
658 ENTER;
659 /*
71200d45 660 * The two SVs are magically freed by load_module
14a5cf38
JH
661 */
662 Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv);
663 LEAVE;
664 return PerlIO_find_layer(aTHX_ name, len, 0);
665 }
666 PerlIO_debug("Cannot find %.*s\n", (int) len, name);
667 return NULL;
f3862f8b
NIS
668}
669
2a1bc955 670#ifdef USE_ATTRIBUTES_FOR_PERLIO
b13b2135
NIS
671
672static int
673perlio_mg_set(pTHX_ SV *sv, MAGIC *mg)
674{
14a5cf38
JH
675 if (SvROK(sv)) {
676 IO *io = GvIOn((GV *) SvRV(sv));
677 PerlIO *ifp = IoIFP(io);
678 PerlIO *ofp = IoOFP(io);
679 Perl_warn(aTHX_ "set %" SVf " %p %p %p", sv, io, ifp, ofp);
680 }
681 return 0;
b13b2135
NIS
682}
683
684static int
685perlio_mg_get(pTHX_ SV *sv, MAGIC *mg)
686{
14a5cf38
JH
687 if (SvROK(sv)) {
688 IO *io = GvIOn((GV *) SvRV(sv));
689 PerlIO *ifp = IoIFP(io);
690 PerlIO *ofp = IoOFP(io);
691 Perl_warn(aTHX_ "get %" SVf " %p %p %p", sv, io, ifp, ofp);
692 }
693 return 0;
b13b2135
NIS
694}
695
696static int
697perlio_mg_clear(pTHX_ SV *sv, MAGIC *mg)
698{
14a5cf38
JH
699 Perl_warn(aTHX_ "clear %" SVf, sv);
700 return 0;
b13b2135
NIS
701}
702
703static int
704perlio_mg_free(pTHX_ SV *sv, MAGIC *mg)
705{
14a5cf38
JH
706 Perl_warn(aTHX_ "free %" SVf, sv);
707 return 0;
b13b2135
NIS
708}
709
710MGVTBL perlio_vtab = {
14a5cf38
JH
711 perlio_mg_get,
712 perlio_mg_set,
22569500 713 NULL, /* len */
14a5cf38
JH
714 perlio_mg_clear,
715 perlio_mg_free
b13b2135
NIS
716};
717
718XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
719{
14a5cf38
JH
720 dXSARGS;
721 SV *sv = SvRV(ST(1));
722 AV *av = newAV();
723 MAGIC *mg;
724 int count = 0;
725 int i;
726 sv_magic(sv, (SV *) av, PERL_MAGIC_ext, NULL, 0);
727 SvRMAGICAL_off(sv);
728 mg = mg_find(sv, PERL_MAGIC_ext);
729 mg->mg_virtual = &perlio_vtab;
730 mg_magical(sv);
731 Perl_warn(aTHX_ "attrib %" SVf, sv);
732 for (i = 2; i < items; i++) {
733 STRLEN len;
734 const char *name = SvPV(ST(i), len);
735 SV *layer = PerlIO_find_layer(aTHX_ name, len, 1);
736 if (layer) {
737 av_push(av, SvREFCNT_inc(layer));
738 }
739 else {
740 ST(count) = ST(i);
741 count++;
742 }
743 }
744 SvREFCNT_dec(av);
745 XSRETURN(count);
746}
747
22569500 748#endif /* USE_ATTIBUTES_FOR_PERLIO */
2a1bc955 749
e3f3bf95
NIS
750SV *
751PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
f3862f8b 752{
14a5cf38
JH
753 HV *stash = gv_stashpv("PerlIO::Layer", TRUE);
754 SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
755 return sv;
e3f3bf95
NIS
756}
757
0c4f7ff0
NIS
758XS(XS_PerlIO__Layer__find)
759{
14a5cf38
JH
760 dXSARGS;
761 if (items < 2)
762 Perl_croak(aTHX_ "Usage class->find(name[,load])");
763 else {
764 STRLEN len = 0;
765 char *name = SvPV(ST(1), len);
766 bool load = (items > 2) ? SvTRUE(ST(2)) : 0;
767 PerlIO_funcs *layer = PerlIO_find_layer(aTHX_ name, len, load);
768 ST(0) =
769 (layer) ? sv_2mortal(PerlIO_tab_sv(aTHX_ layer)) :
770 &PL_sv_undef;
771 XSRETURN(1);
772 }
0c4f7ff0
NIS
773}
774
e3f3bf95
NIS
775void
776PerlIO_define_layer(pTHX_ PerlIO_funcs *tab)
777{
3a1ee7e8
NIS
778 if (!PL_known_layers)
779 PL_known_layers = PerlIO_list_alloc(aTHX);
780 PerlIO_list_push(aTHX_ PL_known_layers, tab, Nullsv);
fe5a182c 781 PerlIO_debug("define %s %p\n", tab->name, (void*)tab);
f3862f8b
NIS
782}
783
1141d9f8 784int
fcf2db38 785PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
1141d9f8 786{
14a5cf38
JH
787 if (names) {
788 const char *s = names;
789 while (*s) {
790 while (isSPACE(*s) || *s == ':')
791 s++;
792 if (*s) {
793 STRLEN llen = 0;
794 const char *e = s;
795 const char *as = Nullch;
796 STRLEN alen = 0;
797 if (!isIDFIRST(*s)) {
798 /*
799 * Message is consistent with how attribute lists are
800 * passed. Even though this means "foo : : bar" is
71200d45 801 * seen as an invalid separator character.
14a5cf38
JH
802 */
803 char q = ((*s == '\'') ? '"' : '\'');
99ef548b 804 if (ckWARN(WARN_LAYER))
22569500 805 Perl_warner(aTHX_ packWARN(WARN_LAYER),
1e616cf5
JH
806 "perlio: invalid separator character %c%c%c in layer specification list %s",
807 q, *s, q, s);
0cff2cf3 808 SETERRNO(EINVAL, LIB$_INVARG);
14a5cf38
JH
809 return -1;
810 }
811 do {
812 e++;
813 } while (isALNUM(*e));
814 llen = e - s;
815 if (*e == '(') {
816 int nesting = 1;
817 as = ++e;
818 while (nesting) {
819 switch (*e++) {
820 case ')':
821 if (--nesting == 0)
822 alen = (e - 1) - as;
823 break;
824 case '(':
825 ++nesting;
826 break;
827 case '\\':
828 /*
829 * It's a nul terminated string, not allowed
830 * to \ the terminating null. Anything other
71200d45 831 * character is passed over.
14a5cf38
JH
832 */
833 if (*e++) {
834 break;
835 }
836 /*
71200d45 837 * Drop through
14a5cf38
JH
838 */
839 case '\0':
840 e--;
22569500
NIS
841 if (ckWARN(WARN_LAYER))
842 Perl_warner(aTHX_ packWARN(WARN_LAYER),
14a5cf38
JH
843 "perlio: argument list not closed for layer \"%.*s\"",
844 (int) (e - s), s);
845 return -1;
846 default:
847 /*
71200d45 848 * boring.
14a5cf38
JH
849 */
850 break;
851 }
852 }
853 }
854 if (e > s) {
99ef548b 855 bool warn_layer = ckWARN(WARN_LAYER);
14a5cf38
JH
856 PerlIO_funcs *layer =
857 PerlIO_find_layer(aTHX_ s, llen, 1);
858 if (layer) {
3a1ee7e8 859 PerlIO_list_push(aTHX_ av, layer,
14a5cf38
JH
860 (as) ? newSVpvn(as,
861 alen) :
862 &PL_sv_undef);
863 }
864 else {
22569500 865 if (warn_layer)
99ef548b 866 Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: unknown layer \"%.*s\"",
14a5cf38
JH
867 (int) llen, s);
868 return -1;
869 }
870 }
871 s = e;
872 }
873 }
874 }
875 return 0;
1141d9f8
NIS
876}
877
dfebf958 878void
fcf2db38 879PerlIO_default_buffer(pTHX_ PerlIO_list_t *av)
dfebf958 880{
14a5cf38 881 PerlIO_funcs *tab = &PerlIO_perlio;
35990314 882#ifdef PERLIO_USING_CRLF
6ce75a77 883 tab = &PerlIO_crlf;
846be114 884#else
6ce75a77 885 if (PerlIO_stdio.Set_ptrcnt)
22569500 886 tab = &PerlIO_stdio;
846be114 887#endif
14a5cf38 888 PerlIO_debug("Pushing %s\n", tab->name);
3a1ee7e8 889 PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0),
14a5cf38 890 &PL_sv_undef);
dfebf958
NIS
891}
892
e3f3bf95 893SV *
14a5cf38 894PerlIO_arg_fetch(PerlIO_list_t *av, IV n)
e3f3bf95 895{
14a5cf38 896 return av->array[n].arg;
e3f3bf95
NIS
897}
898
f3862f8b 899PerlIO_funcs *
14a5cf38 900PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def)
f3862f8b 901{
14a5cf38
JH
902 if (n >= 0 && n < av->cur) {
903 PerlIO_debug("Layer %" IVdf " is %s\n", n,
904 av->array[n].funcs->name);
905 return av->array[n].funcs;
906 }
907 if (!def)
908 Perl_croak(aTHX_ "panic: PerlIO layer array corrupt");
909 return def;
e3f3bf95
NIS
910}
911
fcf2db38 912PerlIO_list_t *
e3f3bf95
NIS
913PerlIO_default_layers(pTHX)
914{
3a1ee7e8 915 if (!PL_def_layerlist) {
14a5cf38
JH
916 const char *s = (PL_tainting) ? Nullch : PerlEnv_getenv("PERLIO");
917 PerlIO_funcs *osLayer = &PerlIO_unix;
3a1ee7e8 918 PL_def_layerlist = PerlIO_list_alloc(aTHX);
14a5cf38 919 PerlIO_define_layer(aTHX_ & PerlIO_unix);
e1caacb4 920#if defined(WIN32) && !defined(UNDER_CE)
14a5cf38 921 PerlIO_define_layer(aTHX_ & PerlIO_win32);
2f8118af 922#if 0
14a5cf38 923 osLayer = &PerlIO_win32;
0c4128ad 924#endif
2f8118af 925#endif
14a5cf38
JH
926 PerlIO_define_layer(aTHX_ & PerlIO_raw);
927 PerlIO_define_layer(aTHX_ & PerlIO_perlio);
928 PerlIO_define_layer(aTHX_ & PerlIO_stdio);
929 PerlIO_define_layer(aTHX_ & PerlIO_crlf);
06da4f11 930#ifdef HAS_MMAP
14a5cf38 931 PerlIO_define_layer(aTHX_ & PerlIO_mmap);
06da4f11 932#endif
14a5cf38
JH
933 PerlIO_define_layer(aTHX_ & PerlIO_utf8);
934 PerlIO_define_layer(aTHX_ & PerlIO_byte);
3a1ee7e8 935 PerlIO_list_push(aTHX_ PL_def_layerlist,
14a5cf38
JH
936 PerlIO_find_layer(aTHX_ osLayer->name, 0, 0),
937 &PL_sv_undef);
938 if (s) {
3a1ee7e8 939 PerlIO_parse_layers(aTHX_ PL_def_layerlist, s);
14a5cf38
JH
940 }
941 else {
3a1ee7e8 942 PerlIO_default_buffer(aTHX_ PL_def_layerlist);
14a5cf38 943 }
1141d9f8 944 }
3a1ee7e8
NIS
945 if (PL_def_layerlist->cur < 2) {
946 PerlIO_default_buffer(aTHX_ PL_def_layerlist);
f3862f8b 947 }
3a1ee7e8 948 return PL_def_layerlist;
e3f3bf95
NIS
949}
950
0c4f7ff0
NIS
951void
952Perl_boot_core_PerlIO(pTHX)
953{
954#ifdef USE_ATTRIBUTES_FOR_PERLIO
14a5cf38
JH
955 newXS("io::MODIFY_SCALAR_ATTRIBUTES", XS_io_MODIFY_SCALAR_ATTRIBUTES,
956 __FILE__);
0c4f7ff0 957#endif
14a5cf38 958 newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
0c4f7ff0 959}
e3f3bf95
NIS
960
961PerlIO_funcs *
962PerlIO_default_layer(pTHX_ I32 n)
963{
14a5cf38
JH
964 PerlIO_list_t *av = PerlIO_default_layers(aTHX);
965 if (n < 0)
966 n += av->cur;
967 return PerlIO_layer_fetch(aTHX_ av, n, &PerlIO_stdio);
f3862f8b
NIS
968}
969
a999f61b
NIS
970#define PerlIO_default_top() PerlIO_default_layer(aTHX_ -1)
971#define PerlIO_default_btm() PerlIO_default_layer(aTHX_ 0)
60382766
NIS
972
973void
1141d9f8 974PerlIO_stdstreams(pTHX)
60382766 975{
a1ea730d 976 if (!PL_perlio) {
14a5cf38
JH
977 PerlIO_allocate(aTHX);
978 PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT);
979 PerlIO_fdopen(1, "Iw" PERLIO_STDTEXT);
980 PerlIO_fdopen(2, "Iw" PERLIO_STDTEXT);
981 }
60382766
NIS
982}
983
984PerlIO *
14a5cf38
JH
985PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg)
986{
987 PerlIOl *l = NULL;
3a1ee7e8 988 Newc('L',l,tab->size,char,PerlIOl);
53f1b6d2 989 if (l && f) {
14a5cf38
JH
990 Zero(l, tab->size, char);
991 l->next = *f;
992 l->tab = tab;
993 *f = l;
fe5a182c
JH
994 PerlIO_debug("PerlIO_push f=%p %s %s %p\n", (void*)f, tab->name,
995 (mode) ? mode : "(Null)", (void*)arg);
f62ce20a 996 if ((*l->tab->Pushed) (aTHX_ f, mode, arg) != 0) {
14a5cf38
JH
997 PerlIO_pop(aTHX_ f);
998 return NULL;
999 }
1000 }
1001 return f;
60382766
NIS
1002}
1003
dfebf958 1004IV
f62ce20a 1005PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
4b803d04 1006{
14a5cf38
JH
1007 PerlIO_pop(aTHX_ f);
1008 if (*f) {
1009 PerlIO_flush(f);
1010 PerlIO_pop(aTHX_ f);
1011 return 0;
1012 }
1013 return -1;
4b803d04
NIS
1014}
1015
1016IV
f62ce20a 1017PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
dfebf958 1018{
14a5cf38 1019 /*
71200d45 1020 * Remove the dummy layer
14a5cf38 1021 */
14a5cf38
JH
1022 PerlIO_pop(aTHX_ f);
1023 /*
71200d45 1024 * Pop back to bottom layer
14a5cf38 1025 */
04892f78 1026 if (PerlIOValid(f)) {
14a5cf38
JH
1027 PerlIO_flush(f);
1028 while (!(PerlIOBase(f)->tab->kind & PERLIO_K_RAW)) {
1029 if (*PerlIONext(f)) {
1030 PerlIO_pop(aTHX_ f);
1031 }
1032 else {
1033 /*
71200d45 1034 * Nothing bellow - push unix on top then remove it
14a5cf38
JH
1035 */
1036 if (PerlIO_push(aTHX_ f, PerlIO_default_btm(), mode, arg)) {
1037 PerlIO_pop(aTHX_ PerlIONext(f));
1038 }
1039 break;
1040 }
1041 }
fe5a182c 1042 PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name);
14a5cf38
JH
1043 return 0;
1044 }
1045 return -1;
dfebf958
NIS
1046}
1047
ac27b0f5 1048int
14a5cf38 1049PerlIO_apply_layera(pTHX_ PerlIO *f, const char *mode,
d9dac8cd 1050 PerlIO_list_t *layers, IV n, IV max)
14a5cf38 1051{
14a5cf38
JH
1052 int code = 0;
1053 while (n < max) {
1054 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL);
1055 if (tab) {
1056 if (!PerlIO_push(aTHX_ f, tab, mode, PerlIOArg)) {
1057 code = -1;
1058 break;
1059 }
1060 }
1061 n++;
1062 }
1063 return code;
e3f3bf95
NIS
1064}
1065
1066int
ac27b0f5
NIS
1067PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
1068{
14a5cf38 1069 int code = 0;
53f1b6d2 1070 if (f && names) {
3a1ee7e8 1071 PerlIO_list_t *layers = PerlIO_list_alloc(aTHX);
14a5cf38
JH
1072 code = PerlIO_parse_layers(aTHX_ layers, names);
1073 if (code == 0) {
d9dac8cd 1074 code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0, layers->cur);
14a5cf38 1075 }
3a1ee7e8 1076 PerlIO_list_free(aTHX_ layers);
ac27b0f5 1077 }
14a5cf38 1078 return code;
ac27b0f5
NIS
1079}
1080
f3862f8b 1081
60382766 1082/*--------------------------------------------------------------------------------------*/
14a5cf38 1083/*
71200d45 1084 * Given the abstraction above the public API functions
14a5cf38 1085 */
60382766
NIS
1086
1087int
f5b9d040 1088PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
76ced9ad 1089{
14a5cf38 1090 PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n",
fe5a182c 1091 (void*)f, PerlIOBase(f)->tab->name, iotype, mode,
14a5cf38 1092 (names) ? names : "(Null)");
03c0554d
NIS
1093 if (names) {
1094 /* Do not flush etc. if (e.g.) switching encodings.
1095 if a pushed layer knows it needs to flush lower layers
1096 (for example :unix which is never going to call them)
1097 it can do the flush when it is pushed.
1098 */
1099 return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE;
1100 }
1101 else {
1102 /* FIXME?: Looking down the layer stack seems wrong,
1103 but is a way of reaching past (say) an encoding layer
1104 to flip CRLF-ness of the layer(s) below
1105 */
35990314 1106#ifdef PERLIO_USING_CRLF
03c0554d
NIS
1107 /* Legacy binmode only has meaning if O_TEXT has a value distinct from
1108 O_BINARY so we can look for it in mode.
1109 */
1110 if (!(mode & O_BINARY)) {
1111 /* Text mode */
1112 while (*f) {
1113 /* Perhaps we should turn on bottom-most aware layer
1114 e.g. Ilya's idea that UNIX TTY could serve
1115 */
1116 if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) {
1117 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) {
1118 /* Not in text mode - flush any pending stuff and flip it */
1119 PerlIO_flush(f);
1120 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
1121 }
1122 /* Only need to turn it on in one layer so we are done */
1123 return TRUE;
ed53a2bb 1124 }
03c0554d 1125 f = PerlIONext(f);
14a5cf38 1126 }
03c0554d
NIS
1127 /* Not finding a CRLF aware layer presumably means we are binary
1128 which is not what was requested - so we failed
1129 We _could_ push :crlf layer but so could caller
1130 */
1131 return FALSE;
14a5cf38 1132 }
6ce75a77 1133#endif
03c0554d
NIS
1134 /* Either asked for BINMODE or that is normal on this platform
1135 see if any CRLF aware layers are present and turn off the flag
1136 and possibly remove layer.
1137 */
1138 while (*f) {
1139 if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) {
1140 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF)) {
1141 /* In text mode - flush any pending stuff and flip it */
1142 PerlIO_flush(f);
1143 PerlIOBase(f)->flags &= ~PERLIO_F_CRLF;
1144#ifndef PERLIO_USING_CRLF
1145 /* CRLF is unusual case - if this is just the :crlf layer pop it */
1146 if (PerlIOBase(f)->tab == &PerlIO_crlf) {
1147 PerlIO_pop(aTHX_ f);
1148 }
1149#endif
1150 /* Normal case is only one layer doing this, so exit on first
1151 abnormal case can always do multiple binmode calls
1152 */
1153 return TRUE;
1154 }
1155 }
1156 f = PerlIONext(f);
1157 }
1158 return TRUE;
14a5cf38 1159 }
f5b9d040
NIS
1160}
1161
f5b9d040 1162int
e87a358a 1163PerlIO__close(pTHX_ PerlIO *f)
f5b9d040 1164{
04892f78 1165 if (PerlIOValid(f))
f62ce20a 1166 return (*PerlIOBase(f)->tab->Close) (aTHX_ f);
14a5cf38
JH
1167 else {
1168 SETERRNO(EBADF, SS$_IVCHAN);
1169 return -1;
1170 }
76ced9ad
NIS
1171}
1172
b931b1d9 1173int
e87a358a 1174Perl_PerlIO_close(pTHX_ PerlIO *f)
b931b1d9 1175{
14a5cf38 1176 int code = -1;
04892f78 1177 if (PerlIOValid(f)) {
f62ce20a 1178 code = (*PerlIOBase(f)->tab->Close) (aTHX_ f);
14a5cf38
JH
1179 while (*f) {
1180 PerlIO_pop(aTHX_ f);
1181 }
f6c77cf1 1182 }
14a5cf38 1183 return code;
b931b1d9
NIS
1184}
1185
b931b1d9 1186int
e87a358a 1187Perl_PerlIO_fileno(pTHX_ PerlIO *f)
b931b1d9 1188{
04892f78 1189 if (PerlIOValid(f))
f62ce20a 1190 return (*PerlIOBase(f)->tab->Fileno) (aTHX_ f);
14a5cf38
JH
1191 else {
1192 SETERRNO(EBADF, SS$_IVCHAN);
1193 return -1;
1194 }
b931b1d9
NIS
1195}
1196
1141d9f8
NIS
1197static const char *
1198PerlIO_context_layers(pTHX_ const char *mode)
1199{
14a5cf38
JH
1200 const char *type = NULL;
1201 /*
71200d45 1202 * Need to supply default layer info from open.pm
14a5cf38
JH
1203 */
1204 if (PL_curcop) {
1205 SV *layers = PL_curcop->cop_io;
1206 if (layers) {
1207 STRLEN len;
1208 type = SvPV(layers, len);
1209 if (type && mode[0] != 'r') {
1210 /*
71200d45 1211 * Skip to write part
14a5cf38
JH
1212 */
1213 const char *s = strchr(type, 0);
eb160463 1214 if (s && (STRLEN)(s - type) < len) {
14a5cf38
JH
1215 type = s + 1;
1216 }
1217 }
1218 }
1219 }
1220 return type;
1141d9f8
NIS
1221}
1222
fcf2db38 1223static PerlIO_funcs *
2edd7e44
NIS
1224PerlIO_layer_from_ref(pTHX_ SV *sv)
1225{
14a5cf38 1226 /*
71200d45 1227 * For any scalar type load the handler which is bundled with perl
14a5cf38
JH
1228 */
1229 if (SvTYPE(sv) < SVt_PVAV)
1230 return PerlIO_find_layer(aTHX_ "Scalar", 6, 1);
1231
1232 /*
71200d45 1233 * For other types allow if layer is known but don't try and load it
14a5cf38
JH
1234 */
1235 switch (SvTYPE(sv)) {
1236 case SVt_PVAV:
1237 return PerlIO_find_layer(aTHX_ "Array", 5, 0);
1238 case SVt_PVHV:
1239 return PerlIO_find_layer(aTHX_ "Hash", 4, 0);
1240 case SVt_PVCV:
1241 return PerlIO_find_layer(aTHX_ "Code", 4, 0);
1242 case SVt_PVGV:
1243 return PerlIO_find_layer(aTHX_ "Glob", 4, 0);
1244 }
1245 return NULL;
2edd7e44
NIS
1246}
1247
fcf2db38 1248PerlIO_list_t *
14a5cf38
JH
1249PerlIO_resolve_layers(pTHX_ const char *layers,
1250 const char *mode, int narg, SV **args)
1251{
1252 PerlIO_list_t *def = PerlIO_default_layers(aTHX);
1253 int incdef = 1;
a1ea730d 1254 if (!PL_perlio)
14a5cf38
JH
1255 PerlIO_stdstreams(aTHX);
1256 if (narg) {
1257 SV *arg = *args;
1258 /*
71200d45
NIS
1259 * If it is a reference but not an object see if we have a handler
1260 * for it
14a5cf38
JH
1261 */
1262 if (SvROK(arg) && !sv_isobject(arg)) {
1263 PerlIO_funcs *handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
1264 if (handler) {
3a1ee7e8
NIS
1265 def = PerlIO_list_alloc(aTHX);
1266 PerlIO_list_push(aTHX_ def, handler, &PL_sv_undef);
14a5cf38
JH
1267 incdef = 0;
1268 }
1269 /*
71200d45 1270 * Don't fail if handler cannot be found :Via(...) etc. may do
14a5cf38 1271 * something sensible else we will just stringfy and open
71200d45 1272 * resulting string.
14a5cf38
JH
1273 */
1274 }
1275 }
1276 if (!layers)
1277 layers = PerlIO_context_layers(aTHX_ mode);
1278 if (layers && *layers) {
1279 PerlIO_list_t *av;
1280 if (incdef) {
1281 IV i = def->cur;
3a1ee7e8 1282 av = PerlIO_list_alloc(aTHX);
14a5cf38 1283 for (i = 0; i < def->cur; i++) {
3a1ee7e8 1284 PerlIO_list_push(aTHX_ av, def->array[i].funcs,
14a5cf38
JH
1285 def->array[i].arg);
1286 }
1287 }
1288 else {
1289 av = def;
1290 }
0cff2cf3
NIS
1291 if (PerlIO_parse_layers(aTHX_ av, layers) == 0) {
1292 return av;
1293 }
1294 else {
1295 PerlIO_list_free(aTHX_ av);
1296 return (PerlIO_list_t *) NULL;
1297 }
14a5cf38
JH
1298 }
1299 else {
1300 if (incdef)
1301 def->refcnt++;
1302 return def;
1303 }
ee518936
NIS
1304}
1305
1306PerlIO *
14a5cf38
JH
1307PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
1308 int imode, int perm, PerlIO *f, int narg, SV **args)
1309{
1310 if (!f && narg == 1 && *args == &PL_sv_undef) {
1311 if ((f = PerlIO_tmpfile())) {
1312 if (!layers)
1313 layers = PerlIO_context_layers(aTHX_ mode);
1314 if (layers && *layers)
1315 PerlIO_apply_layers(aTHX_ f, mode, layers);
1316 }
1317 }
1318 else {
1319 PerlIO_list_t *layera = NULL;
1320 IV n;
1321 PerlIO_funcs *tab = NULL;
04892f78 1322 if (PerlIOValid(f)) {
14a5cf38 1323 /*
71200d45
NIS
1324 * This is "reopen" - it is not tested as perl does not use it
1325 * yet
14a5cf38
JH
1326 */
1327 PerlIOl *l = *f;
3a1ee7e8 1328 layera = PerlIO_list_alloc(aTHX);
14a5cf38 1329 while (l) {
04892f78
NIS
1330 SV *arg = (l->tab->Getarg)
1331 ? (*l->tab->Getarg) (aTHX_ &l, NULL, 0)
1332 : &PL_sv_undef;
3a1ee7e8 1333 PerlIO_list_push(aTHX_ layera, l->tab, arg);
14a5cf38
JH
1334 l = *PerlIONext(&l);
1335 }
1336 }
1337 else {
1338 layera = PerlIO_resolve_layers(aTHX_ layers, mode, narg, args);
0cff2cf3
NIS
1339 if (!layera) {
1340 return NULL;
1341 }
14a5cf38
JH
1342 }
1343 /*
71200d45 1344 * Start at "top" of layer stack
14a5cf38
JH
1345 */
1346 n = layera->cur - 1;
1347 while (n >= 0) {
1348 PerlIO_funcs *t = PerlIO_layer_fetch(aTHX_ layera, n, NULL);
1349 if (t && t->Open) {
1350 tab = t;
1351 break;
1352 }
1353 n--;
1354 }
1355 if (tab) {
1356 /*
71200d45 1357 * Found that layer 'n' can do opens - call it
14a5cf38 1358 */
7cf31beb 1359 if (narg > 1 && !(tab->kind & PERLIO_K_MULTIARG)) {
3b8752bb 1360 Perl_croak(aTHX_ "More than one argument to open(,':%s')",tab->name);
7cf31beb 1361 }
14a5cf38 1362 PerlIO_debug("openn(%s,'%s','%s',%d,%x,%o,%p,%d,%p)\n",
fe5a182c
JH
1363 tab->name, layers, mode, fd, imode, perm,
1364 (void*)f, narg, (void*)args);
14a5cf38
JH
1365 f = (*tab->Open) (aTHX_ tab, layera, n, mode, fd, imode, perm,
1366 f, narg, args);
1367 if (f) {
1368 if (n + 1 < layera->cur) {
1369 /*
1370 * More layers above the one that we used to open -
71200d45 1371 * apply them now
14a5cf38 1372 */
d9dac8cd
NIS
1373 if (PerlIO_apply_layera(aTHX_ f, mode, layera, n + 1, layera->cur) != 0) {
1374 /* If pushing layers fails close the file */
1375 PerlIO_close(f);
14a5cf38
JH
1376 f = NULL;
1377 }
1378 }
1379 }
1380 }
3a1ee7e8 1381 PerlIO_list_free(aTHX_ layera);
14a5cf38
JH
1382 }
1383 return f;
ee518936 1384}
b931b1d9
NIS
1385
1386
9e353e3b 1387SSize_t
e87a358a 1388Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 1389{
04892f78 1390 if (PerlIOValid(f))
f62ce20a 1391 return (*PerlIOBase(f)->tab->Read) (aTHX_ f, vbuf, count);
14a5cf38
JH
1392 else {
1393 SETERRNO(EBADF, SS$_IVCHAN);
1394 return -1;
1395 }
760ac839
LW
1396}
1397
313ca112 1398SSize_t
e87a358a 1399Perl_PerlIO_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 1400{
04892f78 1401 if (PerlIOValid(f))
f62ce20a 1402 return (*PerlIOBase(f)->tab->Unread) (aTHX_ f, vbuf, count);
14a5cf38
JH
1403 else {
1404 SETERRNO(EBADF, SS$_IVCHAN);
1405 return -1;
1406 }
760ac839
LW
1407}
1408
9e353e3b 1409SSize_t
e87a358a 1410Perl_PerlIO_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 1411{
04892f78 1412 if (PerlIOValid(f))
f62ce20a 1413 return (*PerlIOBase(f)->tab->Write) (aTHX_ f, vbuf, count);
14a5cf38
JH
1414 else {
1415 SETERRNO(EBADF, SS$_IVCHAN);
1416 return -1;
1417 }
760ac839
LW
1418}
1419
6f9d8c32 1420int
e87a358a 1421Perl_PerlIO_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
760ac839 1422{
04892f78 1423 if (PerlIOValid(f))
f62ce20a 1424 return (*PerlIOBase(f)->tab->Seek) (aTHX_ f, offset, whence);
14a5cf38
JH
1425 else {
1426 SETERRNO(EBADF, SS$_IVCHAN);
1427 return -1;
1428 }
760ac839
LW
1429}
1430
9e353e3b 1431Off_t
e87a358a 1432Perl_PerlIO_tell(pTHX_ PerlIO *f)
760ac839 1433{
04892f78 1434 if (PerlIOValid(f))
f62ce20a 1435 return (*PerlIOBase(f)->tab->Tell) (aTHX_ f);
14a5cf38
JH
1436 else {
1437 SETERRNO(EBADF, SS$_IVCHAN);
1438 return -1;
1439 }
760ac839
LW
1440}
1441
6f9d8c32 1442int
e87a358a 1443Perl_PerlIO_flush(pTHX_ PerlIO *f)
760ac839 1444{
14a5cf38
JH
1445 if (f) {
1446 if (*f) {
1447 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1448 if (tab && tab->Flush) {
f62ce20a 1449 return (*tab->Flush) (aTHX_ f);
14a5cf38
JH
1450 }
1451 else {
fe5a182c 1452 PerlIO_debug("Cannot flush f=%p :%s\n", (void*)f, tab->name);
14a5cf38
JH
1453 SETERRNO(EBADF, SS$_IVCHAN);
1454 return -1;
1455 }
1456 }
1457 else {
fe5a182c 1458 PerlIO_debug("Cannot flush f=%p\n", (void*)f);
14a5cf38
JH
1459 SETERRNO(EBADF, SS$_IVCHAN);
1460 return -1;
1461 }
1462 }
1463 else {
1464 /*
1465 * Is it good API design to do flush-all on NULL, a potentially
1466 * errorneous input? Maybe some magical value (PerlIO*
1467 * PERLIO_FLUSH_ALL = (PerlIO*)-1;)? Yes, stdio does similar
1468 * things on fflush(NULL), but should we be bound by their design
71200d45 1469 * decisions? --jhi
14a5cf38 1470 */
a1ea730d 1471 PerlIO **table = &PL_perlio;
14a5cf38
JH
1472 int code = 0;
1473 while ((f = *table)) {
1474 int i;
1475 table = (PerlIO **) (f++);
1476 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1477 if (*f && PerlIO_flush(f) != 0)
1478 code = -1;
1479 f++;
1480 }
1481 }
1482 return code;
1483 }
760ac839
LW
1484}
1485
a9c883f6 1486void
f62ce20a 1487PerlIOBase_flush_linebuf(pTHX)
a9c883f6 1488{
a1ea730d 1489 PerlIO **table = &PL_perlio;
14a5cf38
JH
1490 PerlIO *f;
1491 while ((f = *table)) {
1492 int i;
1493 table = (PerlIO **) (f++);
1494 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1495 if (*f
1496 && (PerlIOBase(f)->
1497 flags & (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1498 == (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1499 PerlIO_flush(f);
1500 f++;
1501 }
a9c883f6 1502 }
a9c883f6
NIS
1503}
1504
06da4f11 1505int
e87a358a 1506Perl_PerlIO_fill(pTHX_ PerlIO *f)
06da4f11 1507{
04892f78 1508 if (PerlIOValid(f))
f62ce20a 1509 return (*PerlIOBase(f)->tab->Fill) (aTHX_ f);
14a5cf38
JH
1510 else {
1511 SETERRNO(EBADF, SS$_IVCHAN);
1512 return -1;
1513 }
06da4f11
NIS
1514}
1515
f3862f8b
NIS
1516int
1517PerlIO_isutf8(PerlIO *f)
1518{
04892f78 1519 if (PerlIOValid(f))
14a5cf38
JH
1520 return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
1521 else {
1522 SETERRNO(EBADF, SS$_IVCHAN);
1523 return -1;
1524 }
f3862f8b
NIS
1525}
1526
6f9d8c32 1527int
e87a358a 1528Perl_PerlIO_eof(pTHX_ PerlIO *f)
760ac839 1529{
04892f78 1530 if (PerlIOValid(f))
f62ce20a 1531 return (*PerlIOBase(f)->tab->Eof) (aTHX_ f);
14a5cf38
JH
1532 else {
1533 SETERRNO(EBADF, SS$_IVCHAN);
1534 return -1;
1535 }
9e353e3b
NIS
1536}
1537
9e353e3b 1538int
e87a358a 1539Perl_PerlIO_error(pTHX_ PerlIO *f)
9e353e3b 1540{
04892f78 1541 if (PerlIOValid(f))
f62ce20a 1542 return (*PerlIOBase(f)->tab->Error) (aTHX_ f);
14a5cf38
JH
1543 else {
1544 SETERRNO(EBADF, SS$_IVCHAN);
1545 return -1;
1546 }
9e353e3b
NIS
1547}
1548
9e353e3b 1549void
e87a358a 1550Perl_PerlIO_clearerr(pTHX_ PerlIO *f)
9e353e3b 1551{
04892f78 1552 if (PerlIOValid(f))
f62ce20a 1553 (*PerlIOBase(f)->tab->Clearerr) (aTHX_ f);
14a5cf38
JH
1554 else
1555 SETERRNO(EBADF, SS$_IVCHAN);
9e353e3b
NIS
1556}
1557
9e353e3b 1558void
e87a358a 1559Perl_PerlIO_setlinebuf(pTHX_ PerlIO *f)
9e353e3b 1560{
04892f78 1561 if (PerlIOValid(f))
f62ce20a 1562 (*PerlIOBase(f)->tab->Setlinebuf) (aTHX_ f);
14a5cf38
JH
1563 else
1564 SETERRNO(EBADF, SS$_IVCHAN);
9e353e3b
NIS
1565}
1566
9e353e3b
NIS
1567int
1568PerlIO_has_base(PerlIO *f)
1569{
04892f78 1570 if (PerlIOValid(f)) {
14a5cf38
JH
1571 return (PerlIOBase(f)->tab->Get_base != NULL);
1572 }
1573 return 0;
760ac839
LW
1574}
1575
9e353e3b
NIS
1576int
1577PerlIO_fast_gets(PerlIO *f)
760ac839 1578{
04892f78 1579 if (PerlIOValid(f) && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) {
14a5cf38
JH
1580 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1581 return (tab->Set_ptrcnt != NULL);
1582 }
1583 return 0;
9e353e3b
NIS
1584}
1585
9e353e3b
NIS
1586int
1587PerlIO_has_cntptr(PerlIO *f)
1588{
04892f78 1589 if (PerlIOValid(f)) {
14a5cf38
JH
1590 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1591 return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
1592 }
1593 return 0;
9e353e3b
NIS
1594}
1595
9e353e3b
NIS
1596int
1597PerlIO_canset_cnt(PerlIO *f)
1598{
04892f78 1599 if (PerlIOValid(f)) {
14a5cf38
JH
1600 PerlIOl *l = PerlIOBase(f);
1601 return (l->tab->Set_ptrcnt != NULL);
1602 }
1603 return 0;
760ac839
LW
1604}
1605
888911fc 1606STDCHAR *
e87a358a 1607Perl_PerlIO_get_base(pTHX_ PerlIO *f)
760ac839 1608{
04892f78 1609 if (PerlIOValid(f))
f62ce20a 1610 return (*PerlIOBase(f)->tab->Get_base) (aTHX_ f);
14a5cf38 1611 return NULL;
9e353e3b
NIS
1612}
1613
9e353e3b 1614int
e87a358a 1615Perl_PerlIO_get_bufsiz(pTHX_ PerlIO *f)
9e353e3b 1616{
04892f78 1617 if (PerlIOValid(f))
f62ce20a 1618 return (*PerlIOBase(f)->tab->Get_bufsiz) (aTHX_ f);
14a5cf38 1619 return 0;
9e353e3b
NIS
1620}
1621
9e353e3b 1622STDCHAR *
e87a358a 1623Perl_PerlIO_get_ptr(pTHX_ PerlIO *f)
9e353e3b 1624{
04892f78
NIS
1625 if (PerlIOValid(f)) {
1626 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1627 if (tab->Get_ptr == NULL)
1628 return NULL;
1629 return (*tab->Get_ptr) (aTHX_ f);
1630 }
1631 return NULL;
9e353e3b
NIS
1632}
1633
05d1247b 1634int
e87a358a 1635Perl_PerlIO_get_cnt(pTHX_ PerlIO *f)
9e353e3b 1636{
04892f78
NIS
1637 if (PerlIOValid(f)) {
1638 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1639 if (tab->Get_cnt == NULL)
1640 return 0;
1641 return (*tab->Get_cnt) (aTHX_ f);
1642 }
1643 return 0;
9e353e3b
NIS
1644}
1645
9e353e3b 1646void
e87a358a 1647Perl_PerlIO_set_cnt(pTHX_ PerlIO *f, int cnt)
9e353e3b 1648{
04892f78
NIS
1649 if (PerlIOValid(f)) {
1650 (*PerlIOBase(f)->tab->Set_ptrcnt) (aTHX_ f, NULL, cnt);
1651 }
9e353e3b
NIS
1652}
1653
9e353e3b 1654void
e87a358a 1655Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt)
9e353e3b 1656{
04892f78
NIS
1657 if (PerlIOValid(f)) {
1658 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1659 if (tab->Set_ptrcnt == NULL) {
1660 Perl_croak(aTHX_ "PerlIO buffer snooping abuse");
1661 }
1662 (*PerlIOBase(f)->tab->Set_ptrcnt) (aTHX_ f, ptr, cnt);
14a5cf38 1663 }
9e353e3b
NIS
1664}
1665
1666/*--------------------------------------------------------------------------------------*/
14a5cf38 1667/*
71200d45 1668 * utf8 and raw dummy layers
14a5cf38 1669 */
dfebf958 1670
26fb694e 1671IV
f62ce20a 1672PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
26fb694e 1673{
04892f78 1674 if (*PerlIONext(f)) {
14a5cf38
JH
1675 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1676 PerlIO_pop(aTHX_ f);
1677 if (tab->kind & PERLIO_K_UTF8)
1678 PerlIOBase(f)->flags |= PERLIO_F_UTF8;
1679 else
1680 PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
1681 return 0;
1682 }
1683 return -1;
26fb694e
NIS
1684}
1685
dfebf958 1686PerlIO_funcs PerlIO_utf8 = {
14a5cf38
JH
1687 "utf8",
1688 sizeof(PerlIOl),
1689 PERLIO_K_DUMMY | PERLIO_F_UTF8,
1690 PerlIOUtf8_pushed,
1691 NULL,
1692 NULL,
1693 NULL,
1694 NULL,
1695 NULL,
1696 NULL,
1697 NULL,
1698 NULL,
1699 NULL,
1700 NULL,
22569500
NIS
1701 NULL, /* flush */
1702 NULL, /* fill */
14a5cf38
JH
1703 NULL,
1704 NULL,
1705 NULL,
1706 NULL,
22569500
NIS
1707 NULL, /* get_base */
1708 NULL, /* get_bufsiz */
1709 NULL, /* get_ptr */
1710 NULL, /* get_cnt */
1711 NULL, /* set_ptrcnt */
26fb694e
NIS
1712};
1713
1714PerlIO_funcs PerlIO_byte = {
14a5cf38
JH
1715 "bytes",
1716 sizeof(PerlIOl),
1717 PERLIO_K_DUMMY,
1718 PerlIOUtf8_pushed,
1719 NULL,
1720 NULL,
1721 NULL,
1722 NULL,
1723 NULL,
1724 NULL,
1725 NULL,
1726 NULL,
1727 NULL,
1728 NULL,
22569500
NIS
1729 NULL, /* flush */
1730 NULL, /* fill */
14a5cf38
JH
1731 NULL,
1732 NULL,
1733 NULL,
1734 NULL,
22569500
NIS
1735 NULL, /* get_base */
1736 NULL, /* get_bufsiz */
1737 NULL, /* get_ptr */
1738 NULL, /* get_cnt */
1739 NULL, /* set_ptrcnt */
dfebf958
NIS
1740};
1741
1742PerlIO *
14a5cf38
JH
1743PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
1744 IV n, const char *mode, int fd, int imode, int perm,
1745 PerlIO *old, int narg, SV **args)
dfebf958 1746{
14a5cf38
JH
1747 PerlIO_funcs *tab = PerlIO_default_btm();
1748 return (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
1749 old, narg, args);
dfebf958
NIS
1750}
1751
1752PerlIO_funcs PerlIO_raw = {
14a5cf38
JH
1753 "raw",
1754 sizeof(PerlIOl),
1755 PERLIO_K_DUMMY,
1756 PerlIORaw_pushed,
1757 PerlIOBase_popped,
1758 PerlIORaw_open,
1759 NULL,
1760 NULL,
1761 NULL,
1762 NULL,
1763 NULL,
1764 NULL,
1765 NULL,
1766 NULL,
22569500
NIS
1767 NULL, /* flush */
1768 NULL, /* fill */
14a5cf38
JH
1769 NULL,
1770 NULL,
1771 NULL,
1772 NULL,
22569500
NIS
1773 NULL, /* get_base */
1774 NULL, /* get_bufsiz */
1775 NULL, /* get_ptr */
1776 NULL, /* get_cnt */
1777 NULL, /* set_ptrcnt */
dfebf958
NIS
1778};
1779/*--------------------------------------------------------------------------------------*/
1780/*--------------------------------------------------------------------------------------*/
14a5cf38 1781/*
71200d45 1782 * "Methods" of the "base class"
14a5cf38 1783 */
9e353e3b
NIS
1784
1785IV
f62ce20a 1786PerlIOBase_fileno(pTHX_ PerlIO *f)
9e353e3b 1787{
04892f78 1788 return PerlIOValid(f) ? PerlIO_fileno(PerlIONext(f)) : -1;
9e353e3b
NIS
1789}
1790
f5b9d040 1791char *
14a5cf38
JH
1792PerlIO_modestr(PerlIO *f, char *buf)
1793{
1794 char *s = buf;
1795 IV flags = PerlIOBase(f)->flags;
1796 if (flags & PERLIO_F_APPEND) {
1797 *s++ = 'a';
1798 if (flags & PERLIO_F_CANREAD) {
1799 *s++ = '+';
1800 }
1801 }
1802 else if (flags & PERLIO_F_CANREAD) {
1803 *s++ = 'r';
1804 if (flags & PERLIO_F_CANWRITE)
1805 *s++ = '+';
1806 }
1807 else if (flags & PERLIO_F_CANWRITE) {
1808 *s++ = 'w';
1809 if (flags & PERLIO_F_CANREAD) {
1810 *s++ = '+';
1811 }
1812 }
35990314 1813#ifdef PERLIO_USING_CRLF
14a5cf38
JH
1814 if (!(flags & PERLIO_F_CRLF))
1815 *s++ = 'b';
5f1a76d0 1816#endif
14a5cf38
JH
1817 *s = '\0';
1818 return buf;
f5b9d040
NIS
1819}
1820
76ced9ad 1821IV
f62ce20a 1822PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
9e353e3b 1823{
14a5cf38 1824 PerlIOl *l = PerlIOBase(f);
b7953727 1825#if 0
14a5cf38
JH
1826 const char *omode = mode;
1827 char temp[8];
b7953727 1828#endif
14a5cf38
JH
1829 PerlIO_funcs *tab = PerlIOBase(f)->tab;
1830 l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE |
1831 PERLIO_F_TRUNCATE | PERLIO_F_APPEND);
1832 if (tab->Set_ptrcnt != NULL)
1833 l->flags |= PERLIO_F_FASTGETS;
1834 if (mode) {
1835 if (*mode == '#' || *mode == 'I')
1836 mode++;
1837 switch (*mode++) {
1838 case 'r':
1839 l->flags |= PERLIO_F_CANREAD;
1840 break;
1841 case 'a':
1842 l->flags |= PERLIO_F_APPEND | PERLIO_F_CANWRITE;
1843 break;
1844 case 'w':
1845 l->flags |= PERLIO_F_TRUNCATE | PERLIO_F_CANWRITE;
1846 break;
1847 default:
1848 SETERRNO(EINVAL, LIB$_INVARG);
1849 return -1;
1850 }
1851 while (*mode) {
1852 switch (*mode++) {
1853 case '+':
1854 l->flags |= PERLIO_F_CANREAD | PERLIO_F_CANWRITE;
1855 break;
1856 case 'b':
1857 l->flags &= ~PERLIO_F_CRLF;
1858 break;
1859 case 't':
1860 l->flags |= PERLIO_F_CRLF;
1861 break;
1862 default:
1863 SETERRNO(EINVAL, LIB$_INVARG);
1864 return -1;
1865 }
1866 }
1867 }
1868 else {
1869 if (l->next) {
1870 l->flags |= l->next->flags &
1871 (PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_TRUNCATE |
1872 PERLIO_F_APPEND);
1873 }
1874 }
5e2ab84b 1875#if 0
14a5cf38
JH
1876 PerlIO_debug("PerlIOBase_pushed f=%p %s %s fl=%08" UVxf " (%s)\n",
1877 f, PerlIOBase(f)->tab->name, (omode) ? omode : "(Null)",
1878 l->flags, PerlIO_modestr(f, temp));
5e2ab84b 1879#endif
14a5cf38 1880 return 0;
76ced9ad
NIS
1881}
1882
1883IV
f62ce20a 1884PerlIOBase_popped(pTHX_ PerlIO *f)
76ced9ad 1885{
14a5cf38 1886 return 0;
760ac839
LW
1887}
1888
9e353e3b 1889SSize_t
f62ce20a 1890PerlIOBase_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 1891{
14a5cf38 1892 /*
71200d45 1893 * Save the position as current head considers it
14a5cf38
JH
1894 */
1895 Off_t old = PerlIO_tell(f);
1896 SSize_t done;
1897 PerlIO_push(aTHX_ f, &PerlIO_pending, "r", Nullsv);
1898 PerlIOSelf(f, PerlIOBuf)->posn = old;
f62ce20a 1899 done = PerlIOBuf_unread(aTHX_ f, vbuf, count);
14a5cf38 1900 return done;
9e353e3b
NIS
1901}
1902
f6c77cf1 1903SSize_t
f62ce20a 1904PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
f6c77cf1 1905{
14a5cf38
JH
1906 STDCHAR *buf = (STDCHAR *) vbuf;
1907 if (f) {
1908 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
1909 return 0;
1910 while (count > 0) {
1911 SSize_t avail = PerlIO_get_cnt(f);
1912 SSize_t take = 0;
1913 if (avail > 0)
eb160463 1914 take = ((SSize_t)count < avail) ? count : avail;
14a5cf38
JH
1915 if (take > 0) {
1916 STDCHAR *ptr = PerlIO_get_ptr(f);
1917 Copy(ptr, buf, take, STDCHAR);
1918 PerlIO_set_ptrcnt(f, ptr + take, (avail -= take));
1919 count -= take;
1920 buf += take;
1921 }
1922 if (count > 0 && avail <= 0) {
1923 if (PerlIO_fill(f) != 0)
1924 break;
1925 }
1926 }
1927 return (buf - (STDCHAR *) vbuf);
1928 }
f6c77cf1 1929 return 0;
f6c77cf1
NIS
1930}
1931
9e353e3b 1932IV
f62ce20a 1933PerlIOBase_noop_ok(pTHX_ PerlIO *f)
9e353e3b 1934{
14a5cf38 1935 return 0;
9e353e3b
NIS
1936}
1937
1938IV
f62ce20a 1939PerlIOBase_noop_fail(pTHX_ PerlIO *f)
06da4f11 1940{
14a5cf38 1941 return -1;
06da4f11
NIS
1942}
1943
1944IV
f62ce20a 1945PerlIOBase_close(pTHX_ PerlIO *f)
9e353e3b 1946{
14a5cf38
JH
1947 IV code = 0;
1948 PerlIO *n = PerlIONext(f);
1949 if (PerlIO_flush(f) != 0)
1950 code = -1;
04892f78 1951 if (PerlIOValid(n) && (*PerlIOBase(n)->tab->Close)(aTHX_ n) != 0)
14a5cf38
JH
1952 code = -1;
1953 PerlIOBase(f)->flags &=
1954 ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_OPEN);
1955 return code;
9e353e3b
NIS
1956}
1957
1958IV
f62ce20a 1959PerlIOBase_eof(pTHX_ PerlIO *f)
9e353e3b 1960{
04892f78 1961 if (PerlIOValid(f)) {
14a5cf38
JH
1962 return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
1963 }
1964 return 1;
9e353e3b
NIS
1965}
1966
1967IV
f62ce20a 1968PerlIOBase_error(pTHX_ PerlIO *f)
9e353e3b 1969{
04892f78 1970 if (PerlIOValid(f)) {
14a5cf38
JH
1971 return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
1972 }
1973 return 1;
9e353e3b
NIS
1974}
1975
1976void
f62ce20a 1977PerlIOBase_clearerr(pTHX_ PerlIO *f)
9e353e3b 1978{
04892f78 1979 if (PerlIOValid(f)) {
14a5cf38
JH
1980 PerlIO *n = PerlIONext(f);
1981 PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR | PERLIO_F_EOF);
04892f78 1982 if (PerlIOValid(n))
14a5cf38
JH
1983 PerlIO_clearerr(n);
1984 }
9e353e3b
NIS
1985}
1986
1987void
f62ce20a 1988PerlIOBase_setlinebuf(pTHX_ PerlIO *f)
9e353e3b 1989{
04892f78 1990 if (PerlIOValid(f)) {
14a5cf38
JH
1991 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF;
1992 }
9e353e3b
NIS
1993}
1994
93a8090d
NIS
1995SV *
1996PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
1997{
1998 if (!arg)
1999 return Nullsv;
2000#ifdef sv_dup
2001 if (param) {
2002 return sv_dup(arg, param);
2003 }
2004 else {
2005 return newSVsv(arg);
2006 }
2007#else
2008 return newSVsv(arg);
2009#endif
2010}
2011
2012PerlIO *
ecdeb87c 2013PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
93a8090d
NIS
2014{
2015 PerlIO *nexto = PerlIONext(o);
04892f78 2016 if (PerlIOValid(nexto)) {
93a8090d 2017 PerlIO_funcs *tab = PerlIOBase(nexto)->tab;
ecdeb87c 2018 f = (*tab->Dup)(aTHX_ f, nexto, param, flags);
93a8090d
NIS
2019 }
2020 if (f) {
2021 PerlIO_funcs *self = PerlIOBase(o)->tab;
2022 SV *arg = Nullsv;
2023 char buf[8];
fe5a182c
JH
2024 PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n",
2025 self->name, (void*)f, (void*)o, (void*)param);
93a8090d 2026 if (self->Getarg) {
ecdeb87c 2027 arg = (*self->Getarg)(aTHX_ o,param,flags);
93a8090d
NIS
2028 }
2029 f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg);
ecdeb87c 2030 if (arg) {
93a8090d
NIS
2031 SvREFCNT_dec(arg);
2032 }
2033 }
2034 return f;
2035}
2036
2037#define PERLIO_MAX_REFCOUNTABLE_FD 2048
168d5872 2038#ifdef USE_THREADS
93a8090d 2039perl_mutex PerlIO_mutex;
93a8090d 2040#endif
168d5872 2041int PerlIO_fd_refcnt[PERLIO_MAX_REFCOUNTABLE_FD];
93a8090d
NIS
2042
2043void
2044PerlIO_init(pTHX)
2045{
2046 /* Place holder for stdstreams call ??? */
168d5872 2047#ifdef USE_THREADS
93a8090d
NIS
2048 MUTEX_INIT(&PerlIO_mutex);
2049#endif
2050}
2051
168d5872
NIS
2052void
2053PerlIOUnix_refcnt_inc(int fd)
2054{
2055 if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
2056#ifdef USE_THREADS
2057 MUTEX_LOCK(&PerlIO_mutex);
2058#endif
2059 PerlIO_fd_refcnt[fd]++;
2060 PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]);
2061#ifdef USE_THREADS
2062 MUTEX_UNLOCK(&PerlIO_mutex);
2063#endif
2064 }
2065}
2066
168d5872
NIS
2067int
2068PerlIOUnix_refcnt_dec(int fd)
2069{
2070 int cnt = 0;
2071 if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
2072#ifdef USE_THREADS
2073 MUTEX_LOCK(&PerlIO_mutex);
2074#endif
2075 cnt = --PerlIO_fd_refcnt[fd];
2076 PerlIO_debug("fd %d refcnt=%d\n",fd,cnt);
2077#ifdef USE_THREADS
2078 MUTEX_UNLOCK(&PerlIO_mutex);
2079#endif
2080 }
2081 return cnt;
2082}
2083
694c95cf
JH
2084void
2085PerlIO_cleanup(pTHX)
2086{
2087 int i;
2088#ifdef USE_ITHREADS
9f4bd222
NIS
2089 PerlIO_debug("Cleanup layers for %p\n",aTHX);
2090#else
2091 PerlIO_debug("Cleanup layers\n");
694c95cf
JH
2092#endif
2093 /* Raise STDIN..STDERR refcount so we don't close them */
2094 for (i=0; i < 3; i++)
2095 PerlIOUnix_refcnt_inc(i);
2096 PerlIO_cleantable(aTHX_ &PL_perlio);
2097 /* Restore STDIN..STDERR refcount */
2098 for (i=0; i < 3; i++)
2099 PerlIOUnix_refcnt_dec(i);
9f4bd222
NIS
2100
2101 if (PL_known_layers) {
2102 PerlIO_list_free(aTHX_ PL_known_layers);
2103 PL_known_layers = NULL;
2104 }
2105 if(PL_def_layerlist) {
2106 PerlIO_list_free(aTHX_ PL_def_layerlist);
2107 PL_def_layerlist = NULL;
2108 }
694c95cf
JH
2109}
2110
2111
2112
9e353e3b 2113/*--------------------------------------------------------------------------------------*/
14a5cf38 2114/*
71200d45 2115 * Bottom-most level for UNIX-like case
14a5cf38 2116 */
9e353e3b 2117
14a5cf38 2118typedef struct {
22569500
NIS
2119 struct _PerlIO base; /* The generic part */
2120 int fd; /* UNIX like file descriptor */
2121 int oflags; /* open/fcntl flags */
9e353e3b
NIS
2122} PerlIOUnix;
2123
6f9d8c32 2124int
9e353e3b 2125PerlIOUnix_oflags(const char *mode)
760ac839 2126{
14a5cf38
JH
2127 int oflags = -1;
2128 if (*mode == 'I' || *mode == '#')
2129 mode++;
2130 switch (*mode) {
2131 case 'r':
2132 oflags = O_RDONLY;
2133 if (*++mode == '+') {
2134 oflags = O_RDWR;
2135 mode++;
2136 }
2137 break;
2138
2139 case 'w':
2140 oflags = O_CREAT | O_TRUNC;
2141 if (*++mode == '+') {
2142 oflags |= O_RDWR;
2143 mode++;
2144 }
2145 else
2146 oflags |= O_WRONLY;
2147 break;
2148
2149 case 'a':
2150 oflags = O_CREAT | O_APPEND;
2151 if (*++mode == '+') {
2152 oflags |= O_RDWR;
2153 mode++;
2154 }
2155 else
2156 oflags |= O_WRONLY;
2157 break;
2158 }
2159 if (*mode == 'b') {
2160 oflags |= O_BINARY;
2161 oflags &= ~O_TEXT;
2162 mode++;
2163 }
2164 else if (*mode == 't') {
2165 oflags |= O_TEXT;
2166 oflags &= ~O_BINARY;
2167 mode++;
2168 }
2169 /*
71200d45 2170 * Always open in binary mode
14a5cf38
JH
2171 */
2172 oflags |= O_BINARY;
2173 if (*mode || oflags == -1) {
2174 SETERRNO(EINVAL, LIB$_INVARG);
2175 oflags = -1;
2176 }
2177 return oflags;
9e353e3b
NIS
2178}
2179
2180IV
f62ce20a 2181PerlIOUnix_fileno(pTHX_ PerlIO *f)
9e353e3b 2182{
14a5cf38 2183 return PerlIOSelf(f, PerlIOUnix)->fd;
9e353e3b
NIS
2184}
2185
4b803d04 2186IV
f62ce20a 2187PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
4b803d04 2188{
f62ce20a 2189 IV code = PerlIOBase_pushed(aTHX_ f, mode, arg);
93a8090d 2190 PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix);
14a5cf38 2191 if (*PerlIONext(f)) {
03c0554d
NIS
2192 /* We never call down so any pending stuff now */
2193 PerlIO_flush(PerlIONext(f));
14a5cf38
JH
2194 s->fd = PerlIO_fileno(PerlIONext(f));
2195 /*
71200d45 2196 * XXX could (or should) we retrieve the oflags from the open file
14a5cf38 2197 * handle rather than believing the "mode" we are passed in? XXX
71200d45 2198 * Should the value on NULL mode be 0 or -1?
14a5cf38
JH
2199 */
2200 s->oflags = mode ? PerlIOUnix_oflags(mode) : -1;
2201 }
2202 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
2203 return code;
4b803d04
NIS
2204}
2205
9e353e3b 2206PerlIO *
14a5cf38
JH
2207PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2208 IV n, const char *mode, int fd, int imode,
2209 int perm, PerlIO *f, int narg, SV **args)
2210{
d9dac8cd 2211 if (PerlIOValid(f)) {
14a5cf38 2212 if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
f62ce20a 2213 (*PerlIOBase(f)->tab->Close)(aTHX_ f);
14a5cf38
JH
2214 }
2215 if (narg > 0) {
2216 char *path = SvPV_nolen(*args);
2217 if (*mode == '#')
2218 mode++;
2219 else {
2220 imode = PerlIOUnix_oflags(mode);
2221 perm = 0666;
2222 }
2223 if (imode != -1) {
2224 fd = PerlLIO_open3(path, imode, perm);
2225 }
2226 }
2227 if (fd >= 0) {
2228 PerlIOUnix *s;
2229 if (*mode == 'I')
2230 mode++;
2231 if (!f) {
2232 f = PerlIO_allocate(aTHX);
d9dac8cd
NIS
2233 }
2234 if (!PerlIOValid(f)) {
14a5cf38
JH
2235 s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg),
2236 PerlIOUnix);
2237 }
d9dac8cd 2238 else {
14a5cf38 2239 s = PerlIOSelf(f, PerlIOUnix);
d9dac8cd 2240 }
14a5cf38
JH
2241 s->fd = fd;
2242 s->oflags = imode;
2243 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
22569500 2244 PerlIOUnix_refcnt_inc(fd);
14a5cf38
JH
2245 return f;
2246 }
2247 else {
2248 if (f) {
2249 /*
71200d45 2250 * FIXME: pop layers ???
14a5cf38
JH
2251 */
2252 }
2253 return NULL;
2254 }
9e353e3b
NIS
2255}
2256
71200d45 2257PerlIO *
ecdeb87c 2258PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45
NIS
2259{
2260 PerlIOUnix *os = PerlIOSelf(o, PerlIOUnix);
93a8090d 2261 int fd = os->fd;
ecdeb87c
NIS
2262 if (flags & PERLIO_DUP_FD) {
2263 fd = PerlLIO_dup(fd);
2264 }
93a8090d 2265 if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) {
ecdeb87c 2266 f = PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
2267 if (f) {
2268 /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */
2269 PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix);
2270 s->fd = fd;
93a8090d 2271 PerlIOUnix_refcnt_inc(fd);
71200d45
NIS
2272 return f;
2273 }
71200d45
NIS
2274 }
2275 return NULL;
2276}
2277
2278
9e353e3b 2279SSize_t
f62ce20a 2280PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
9e353e3b 2281{
14a5cf38
JH
2282 int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2283 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
2284 return 0;
2285 while (1) {
2286 SSize_t len = PerlLIO_read(fd, vbuf, count);
2287 if (len >= 0 || errno != EINTR) {
2288 if (len < 0)
2289 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2290 else if (len == 0 && count != 0)
2291 PerlIOBase(f)->flags |= PERLIO_F_EOF;
2292 return len;
2293 }
2294 PERL_ASYNC_CHECK();
2295 }
9e353e3b
NIS
2296}
2297
2298SSize_t
f62ce20a 2299PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2300{
14a5cf38
JH
2301 int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2302 while (1) {
2303 SSize_t len = PerlLIO_write(fd, vbuf, count);
2304 if (len >= 0 || errno != EINTR) {
2305 if (len < 0)
2306 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2307 return len;
2308 }
2309 PERL_ASYNC_CHECK();
06da4f11 2310 }
9e353e3b
NIS
2311}
2312
2313IV
f62ce20a 2314PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 2315{
14a5cf38
JH
2316 Off_t new =
2317 PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, offset, whence);
2318 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2319 return (new == (Off_t) - 1) ? -1 : 0;
9e353e3b
NIS
2320}
2321
2322Off_t
f62ce20a 2323PerlIOUnix_tell(pTHX_ PerlIO *f)
9e353e3b 2324{
14a5cf38 2325 return PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, 0, SEEK_CUR);
9e353e3b
NIS
2326}
2327
71200d45 2328
9e353e3b 2329IV
f62ce20a 2330PerlIOUnix_close(pTHX_ PerlIO *f)
9e353e3b 2331{
14a5cf38
JH
2332 int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2333 int code = 0;
168d5872
NIS
2334 if (PerlIOBase(f)->flags & PERLIO_F_OPEN) {
2335 if (PerlIOUnix_refcnt_dec(fd) > 0) {
93a8090d
NIS
2336 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
2337 return 0;
22569500 2338 }
93a8090d
NIS
2339 }
2340 else {
2341 SETERRNO(EBADF,SS$_IVCHAN);
2342 return -1;
2343 }
14a5cf38
JH
2344 while (PerlLIO_close(fd) != 0) {
2345 if (errno != EINTR) {
2346 code = -1;
2347 break;
2348 }
2349 PERL_ASYNC_CHECK();
2350 }
2351 if (code == 0) {
2352 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
2353 }
2354 return code;
9e353e3b
NIS
2355}
2356
2357PerlIO_funcs PerlIO_unix = {
14a5cf38
JH
2358 "unix",
2359 sizeof(PerlIOUnix),
2360 PERLIO_K_RAW,
2361 PerlIOUnix_pushed,
44798d05 2362 PerlIOBase_popped,
14a5cf38
JH
2363 PerlIOUnix_open,
2364 NULL,
2365 PerlIOUnix_fileno,
71200d45 2366 PerlIOUnix_dup,
14a5cf38
JH
2367 PerlIOUnix_read,
2368 PerlIOBase_unread,
2369 PerlIOUnix_write,
2370 PerlIOUnix_seek,
2371 PerlIOUnix_tell,
2372 PerlIOUnix_close,
22569500
NIS
2373 PerlIOBase_noop_ok, /* flush */
2374 PerlIOBase_noop_fail, /* fill */
14a5cf38
JH
2375 PerlIOBase_eof,
2376 PerlIOBase_error,
2377 PerlIOBase_clearerr,
2378 PerlIOBase_setlinebuf,
22569500
NIS
2379 NULL, /* get_base */
2380 NULL, /* get_bufsiz */
2381 NULL, /* get_ptr */
2382 NULL, /* get_cnt */
2383 NULL, /* set_ptrcnt */
9e353e3b
NIS
2384};
2385
2386/*--------------------------------------------------------------------------------------*/
14a5cf38 2387/*
71200d45 2388 * stdio as a layer
14a5cf38 2389 */
9e353e3b 2390
14a5cf38
JH
2391typedef struct {
2392 struct _PerlIO base;
22569500 2393 FILE *stdio; /* The stream */
9e353e3b
NIS
2394} PerlIOStdio;
2395
2396IV
f62ce20a 2397PerlIOStdio_fileno(pTHX_ PerlIO *f)
9e353e3b 2398{
14a5cf38 2399 return PerlSIO_fileno(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2400}
2401
766a733e 2402char *
14a5cf38
JH
2403PerlIOStdio_mode(const char *mode, char *tmode)
2404{
2405 char *ret = tmode;
2406 while (*mode) {
2407 *tmode++ = *mode++;
2408 }
35990314 2409#ifdef PERLIO_USING_CRLF
6ce75a77
JH
2410 *tmode++ = 'b';
2411#endif
14a5cf38
JH
2412 *tmode = '\0';
2413 return ret;
2414}
2415
2416/*
71200d45 2417 * This isn't used yet ...
14a5cf38 2418 */
4b803d04 2419IV
f62ce20a 2420PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
4b803d04 2421{
14a5cf38 2422 if (*PerlIONext(f)) {
14a5cf38
JH
2423 PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
2424 char tmode[8];
2425 FILE *stdio =
2426 PerlSIO_fdopen(PerlIO_fileno(PerlIONext(f)), mode =
2427 PerlIOStdio_mode(mode, tmode));
03c0554d 2428 if (stdio) {
14a5cf38 2429 s->stdio = stdio;
03c0554d
NIS
2430 /* We never call down so any pending stuff now */
2431 PerlIO_flush(PerlIONext(f));
2432 }
14a5cf38
JH
2433 else
2434 return -1;
2435 }
f62ce20a 2436 return PerlIOBase_pushed(aTHX_ f, mode, arg);
4b803d04
NIS
2437}
2438
22569500 2439
9e353e3b
NIS
2440PerlIO *
2441PerlIO_importFILE(FILE *stdio, int fl)
2442{
14a5cf38
JH
2443 dTHX;
2444 PerlIO *f = NULL;
2445 if (stdio) {
22569500
NIS
2446 /* We need to probe to see how we can open the stream
2447 so start with read/write and then try write and read
2448 we dup() so that we can fclose without loosing the fd.
f504ae08
LC
2449
2450 Note that the errno value set by a failing fdopen
2451 varies between stdio implementations.
22569500
NIS
2452 */
2453 int fd = PerlLIO_dup(fileno(stdio));
2454 char *mode = "r+";
2455 FILE *f2 = fdopen(fd, mode);
2456 PerlIOStdio *s;
f504ae08 2457 if (!f2) {
22569500
NIS
2458 mode = "w";
2459 f2 = fdopen(fd, mode);
2460 }
f504ae08 2461 if (!f2) {
22569500
NIS
2462 mode = "r";
2463 f2 = fdopen(fd, mode);
2464 }
2465 if (!f2) {
2466 /* Don't seem to be able to open */
f504ae08 2467 PerlLIO_close(fd);
22569500
NIS
2468 return f;
2469 }
2470 fclose(f2);
2471 s = PerlIOSelf(PerlIO_push
2472 (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
2473 mode, Nullsv), PerlIOStdio);
14a5cf38
JH
2474 s->stdio = stdio;
2475 }
2476 return f;
9e353e3b
NIS
2477}
2478
2479PerlIO *
14a5cf38
JH
2480PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2481 IV n, const char *mode, int fd, int imode,
2482 int perm, PerlIO *f, int narg, SV **args)
2483{
2484 char tmode[8];
d9dac8cd 2485 if (PerlIOValid(f)) {
14a5cf38
JH
2486 char *path = SvPV_nolen(*args);
2487 PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
1751d015
NIS
2488 FILE *stdio;
2489 PerlIOUnix_refcnt_dec(fileno(s->stdio));
2490 stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
14a5cf38
JH
2491 s->stdio);
2492 if (!s->stdio)
2493 return NULL;
2494 s->stdio = stdio;
1751d015 2495 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2496 return f;
2497 }
2498 else {
2499 if (narg > 0) {
2500 char *path = SvPV_nolen(*args);
2501 if (*mode == '#') {
2502 mode++;
2503 fd = PerlLIO_open3(path, imode, perm);
2504 }
2505 else {
2506 FILE *stdio = PerlSIO_fopen(path, mode);
2507 if (stdio) {
d9dac8cd
NIS
2508 PerlIOStdio *s;
2509 if (!f) {
2510 f = PerlIO_allocate(aTHX);
2511 }
2512 s = PerlIOSelf(PerlIO_push(aTHX_ f, self,
14a5cf38
JH
2513 (mode = PerlIOStdio_mode(mode, tmode)),
2514 PerlIOArg),
2515 PerlIOStdio);
2516 s->stdio = stdio;
1751d015 2517 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2518 }
2519 return f;
2520 }
2521 }
2522 if (fd >= 0) {
2523 FILE *stdio = NULL;
2524 int init = 0;
2525 if (*mode == 'I') {
2526 init = 1;
2527 mode++;
2528 }
2529 if (init) {
2530 switch (fd) {
2531 case 0:
2532 stdio = PerlSIO_stdin;
2533 break;
2534 case 1:
2535 stdio = PerlSIO_stdout;
2536 break;
2537 case 2:
2538 stdio = PerlSIO_stderr;
2539 break;
2540 }
2541 }
2542 else {
2543 stdio = PerlSIO_fdopen(fd, mode =
2544 PerlIOStdio_mode(mode, tmode));
2545 }
2546 if (stdio) {
d9dac8cd
NIS
2547 PerlIOStdio *s;
2548 if (!f) {
2549 f = PerlIO_allocate(aTHX);
2550 }
2551 s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg), PerlIOStdio);
14a5cf38 2552 s->stdio = stdio;
1751d015 2553 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2554 return f;
2555 }
2556 }
2557 }
ee518936 2558 return NULL;
9e353e3b
NIS
2559}
2560
1751d015 2561PerlIO *
ecdeb87c 2562PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
1751d015
NIS
2563{
2564 /* This assumes no layers underneath - which is what
2565 happens, but is not how I remember it. NI-S 2001/10/16
2566 */
ecdeb87c 2567 if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
694c95cf 2568 FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio;
ecdeb87c
NIS
2569 if (flags & PERLIO_DUP_FD) {
2570 int fd = PerlLIO_dup(fileno(stdio));
2571 if (fd >= 0) {
2572 char mode[8];
293ed4d2 2573 stdio = fdopen(fd, PerlIO_modestr(o,mode));
ecdeb87c
NIS
2574 }
2575 else {
2576 /* FIXME: To avoid messy error recovery if dup fails
2577 re-use the existing stdio as though flag was not set
2578 */
2579 }
2580 }
694c95cf
JH
2581 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
2582 PerlIOUnix_refcnt_inc(fileno(stdio));
1751d015
NIS
2583 }
2584 return f;
2585}
2586
2587IV
f62ce20a 2588PerlIOStdio_close(pTHX_ PerlIO *f)
1751d015 2589{
1751d015
NIS
2590#ifdef SOCKS5_VERSION_NAME
2591 int optval;
2592 Sock_size_t optlen = sizeof(int);
2593#endif
2594 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2595 if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) {
694c95cf 2596 /* Do not close it but do flush any buffers */
22569500 2597 return PerlIO_flush(f);
1751d015
NIS
2598 }
2599 return (
2600#ifdef SOCKS5_VERSION_NAME
2601 (getsockopt
2602 (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
2603 &optlen) <
2604 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
2605#else
2606 PerlSIO_fclose(stdio)
2607#endif
2608 );
2609
2610}
2611
2612
2613
9e353e3b 2614SSize_t
f62ce20a 2615PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
9e353e3b 2616{
14a5cf38
JH
2617 FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2618 SSize_t got = 0;
2619 if (count == 1) {
2620 STDCHAR *buf = (STDCHAR *) vbuf;
2621 /*
2622 * Perl is expecting PerlIO_getc() to fill the buffer Linux's
71200d45 2623 * stdio does not do that for fread()
14a5cf38
JH
2624 */
2625 int ch = PerlSIO_fgetc(s);
2626 if (ch != EOF) {
2627 *buf = ch;
2628 got = 1;
2629 }
2630 }
2631 else
2632 got = PerlSIO_fread(vbuf, 1, count, s);
2633 return got;
9e353e3b
NIS
2634}
2635
2636SSize_t
f62ce20a 2637PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2638{
14a5cf38 2639 SSize_t unread = 0;
93679785
NIS
2640 FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2641
9f7cd136 2642 if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
93679785
NIS
2643 STDCHAR *buf = ((STDCHAR *) vbuf) + count;
2644 STDCHAR *base = PerlIO_get_base(f);
2645 SSize_t cnt = PerlIO_get_cnt(f);
2646 STDCHAR *ptr = PerlIO_get_ptr(f);
2647 SSize_t avail = ptr - base;
2648 if (avail > 0) {
2649 if (avail > count) {
2650 avail = count;
2651 }
2652 ptr -= avail;
2653 Move(buf-avail,ptr,avail,STDCHAR);
2654 count -= avail;
2655 unread += avail;
2656 PerlIO_set_ptrcnt(f,ptr,cnt+avail);
9f7cd136
NIS
2657 if (PerlSIO_feof(s) && unread >= 0)
2658 PerlSIO_clearerr(s);
2659 }
2660 }
2661 else if (PerlIO_has_cntptr(f)) {
2662 /* We can get pointer to buffer but not its base
2663 Do ungetc() but check chars are ending up in the
2664 buffer
2665 */
2666 STDCHAR *eptr = (STDCHAR*)PerlSIO_get_ptr(s);
2667 STDCHAR *buf = ((STDCHAR *) vbuf) + count;
2668 while (count > 0) {
2669 int ch = *--buf & 0xFF;
2670 if (ungetc(ch,s) != ch) {
2671 /* ungetc did not work */
2672 break;
2673 }
2674 if ((STDCHAR*)PerlSIO_get_ptr(s) != --eptr || ((*eptr & 0xFF) != ch)) {
2675 /* Did not change pointer as expected */
2676 fgetc(s); /* get char back again */
2677 break;
2678 }
2679 /* It worked ! */
2680 count--;
2681 unread++;
93679785
NIS
2682 }
2683 }
2684
2685 if (count > 0) {
2686 unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
14a5cf38
JH
2687 }
2688 return unread;
9e353e3b
NIS
2689}
2690
2691SSize_t
f62ce20a 2692PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2693{
14a5cf38
JH
2694 return PerlSIO_fwrite(vbuf, 1, count,
2695 PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2696}
2697
2698IV
f62ce20a 2699PerlIOStdio_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 2700{
14a5cf38
JH
2701 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2702 return PerlSIO_fseek(stdio, offset, whence);
9e353e3b
NIS
2703}
2704
2705Off_t
f62ce20a 2706PerlIOStdio_tell(pTHX_ PerlIO *f)
9e353e3b 2707{
14a5cf38
JH
2708 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2709 return PerlSIO_ftell(stdio);
9e353e3b
NIS
2710}
2711
2712IV
f62ce20a 2713PerlIOStdio_flush(pTHX_ PerlIO *f)
9e353e3b 2714{
14a5cf38
JH
2715 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2716 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
2717 return PerlSIO_fflush(stdio);
2718 }
2719 else {
88b61e10 2720#if 0
14a5cf38
JH
2721 /*
2722 * FIXME: This discards ungetc() and pre-read stuff which is not
71200d45 2723 * right if this is just a "sync" from a layer above Suspect right
14a5cf38 2724 * design is to do _this_ but not have layer above flush this
71200d45 2725 * layer read-to-read
14a5cf38
JH
2726 */
2727 /*
71200d45 2728 * Not writeable - sync by attempting a seek
14a5cf38
JH
2729 */
2730 int err = errno;
2731 if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0)
2732 errno = err;
88b61e10 2733#endif
14a5cf38
JH
2734 }
2735 return 0;
9e353e3b
NIS
2736}
2737
2738IV
f62ce20a 2739PerlIOStdio_eof(pTHX_ PerlIO *f)
9e353e3b 2740{
14a5cf38 2741 return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2742}
2743
2744IV
f62ce20a 2745PerlIOStdio_error(pTHX_ PerlIO *f)
9e353e3b 2746{
14a5cf38 2747 return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2748}
2749
2750void
f62ce20a 2751PerlIOStdio_clearerr(pTHX_ PerlIO *f)
9e353e3b 2752{
14a5cf38 2753 PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2754}
2755
2756void
f62ce20a 2757PerlIOStdio_setlinebuf(pTHX_ PerlIO *f)
9e353e3b
NIS
2758{
2759#ifdef HAS_SETLINEBUF
14a5cf38 2760 PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b 2761#else
14a5cf38 2762 PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
9e353e3b
NIS
2763#endif
2764}
2765
2766#ifdef FILE_base
2767STDCHAR *
f62ce20a 2768PerlIOStdio_get_base(pTHX_ PerlIO *f)
9e353e3b 2769{
14a5cf38 2770 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 2771 return (STDCHAR*)PerlSIO_get_base(stdio);
9e353e3b
NIS
2772}
2773
2774Size_t
f62ce20a 2775PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f)
9e353e3b 2776{
14a5cf38
JH
2777 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2778 return PerlSIO_get_bufsiz(stdio);
9e353e3b
NIS
2779}
2780#endif
2781
2782#ifdef USE_STDIO_PTR
2783STDCHAR *
f62ce20a 2784PerlIOStdio_get_ptr(pTHX_ PerlIO *f)
9e353e3b 2785{
14a5cf38 2786 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 2787 return (STDCHAR*)PerlSIO_get_ptr(stdio);
9e353e3b
NIS
2788}
2789
2790SSize_t
f62ce20a 2791PerlIOStdio_get_cnt(pTHX_ PerlIO *f)
9e353e3b 2792{
14a5cf38
JH
2793 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2794 return PerlSIO_get_cnt(stdio);
9e353e3b
NIS
2795}
2796
2797void
f62ce20a 2798PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 2799{
14a5cf38 2800 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 2801 if (ptr != NULL) {
9e353e3b 2802#ifdef STDIO_PTR_LVALUE
22569500 2803 PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */
9e353e3b 2804#ifdef STDIO_PTR_LVAL_SETS_CNT
14a5cf38 2805 if (PerlSIO_get_cnt(stdio) != (cnt)) {
14a5cf38
JH
2806 assert(PerlSIO_get_cnt(stdio) == (cnt));
2807 }
9e353e3b
NIS
2808#endif
2809#if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
14a5cf38 2810 /*
71200d45 2811 * Setting ptr _does_ change cnt - we are done
14a5cf38
JH
2812 */
2813 return;
9e353e3b 2814#endif
22569500 2815#else /* STDIO_PTR_LVALUE */
14a5cf38 2816 PerlProc_abort();
22569500 2817#endif /* STDIO_PTR_LVALUE */
14a5cf38
JH
2818 }
2819 /*
71200d45 2820 * Now (or only) set cnt
14a5cf38 2821 */
9e353e3b 2822#ifdef STDIO_CNT_LVALUE
14a5cf38 2823 PerlSIO_set_cnt(stdio, cnt);
22569500 2824#else /* STDIO_CNT_LVALUE */
9e353e3b 2825#if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
14a5cf38
JH
2826 PerlSIO_set_ptr(stdio,
2827 PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) -
2828 cnt));
22569500 2829#else /* STDIO_PTR_LVAL_SETS_CNT */
14a5cf38 2830 PerlProc_abort();
22569500
NIS
2831#endif /* STDIO_PTR_LVAL_SETS_CNT */
2832#endif /* STDIO_CNT_LVALUE */
9e353e3b
NIS
2833}
2834
93679785 2835
9e353e3b
NIS
2836#endif
2837
93679785
NIS
2838IV
2839PerlIOStdio_fill(pTHX_ PerlIO *f)
2840{
2841 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2842 int c;
2843 /*
2844 * fflush()ing read-only streams can cause trouble on some stdio-s
2845 */
2846 if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
2847 if (PerlSIO_fflush(stdio) != 0)
2848 return EOF;
2849 }
2850 c = PerlSIO_fgetc(stdio);
2851 if (c == EOF)
2852 return EOF;
2853
2854#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
9f7cd136 2855 if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
93679785
NIS
2856 /* Fake ungetc() to the real buffer in case system's ungetc
2857 goes elsewhere
2858 */
2859 STDCHAR *base = (STDCHAR*)PerlSIO_get_base(stdio);
2860 SSize_t cnt = PerlSIO_get_cnt(stdio);
2861 STDCHAR *ptr = (STDCHAR*)PerlSIO_get_ptr(stdio);
2862 if (ptr == base+1) {
2863 *--ptr = (STDCHAR) c;
2864 PerlIOStdio_set_ptrcnt(aTHX_ f,ptr,cnt+1);
2865 if (PerlSIO_feof(stdio))
2866 PerlSIO_clearerr(stdio);
2867 return 0;
2868 }
2869 }
9f7cd136
NIS
2870 else if (PerlIO_has_cntptr(f)) {
2871 STDCHAR ch = c;
2872 if (PerlIOStdio_unread(aTHX_ f,&ch,1) == 1) {
2873 return 0;
2874 }
2875 }
93679785
NIS
2876#endif
2877
2878#if defined(VMS)
2879 /* An ungetc()d char is handled separately from the regular
2880 * buffer, so we stuff it in the buffer ourselves.
2881 * Should never get called as should hit code above
2882 */
bad9695d
NIS
2883 *(--((*stdio)->_ptr)) = (unsigned char) c;
2884 (*stdio)->_cnt++;
93679785
NIS
2885#else
2886 /* If buffer snoop scheme above fails fall back to
9f7cd136 2887 using ungetc().
93679785
NIS
2888 */
2889 if (PerlSIO_ungetc(c, stdio) != c)
2890 return EOF;
2891#endif
2892 return 0;
2893}
2894
2895
2896
9e353e3b 2897PerlIO_funcs PerlIO_stdio = {
14a5cf38
JH
2898 "stdio",
2899 sizeof(PerlIOStdio),
2900 PERLIO_K_BUFFERED,
2901 PerlIOBase_pushed,
44798d05 2902 PerlIOBase_popped,
14a5cf38
JH
2903 PerlIOStdio_open,
2904 NULL,
2905 PerlIOStdio_fileno,
71200d45 2906 PerlIOStdio_dup,
14a5cf38
JH
2907 PerlIOStdio_read,
2908 PerlIOStdio_unread,
2909 PerlIOStdio_write,
2910 PerlIOStdio_seek,
2911 PerlIOStdio_tell,
2912 PerlIOStdio_close,
2913 PerlIOStdio_flush,
2914 PerlIOStdio_fill,
2915 PerlIOStdio_eof,
2916 PerlIOStdio_error,
2917 PerlIOStdio_clearerr,
2918 PerlIOStdio_setlinebuf,
9e353e3b 2919#ifdef FILE_base
14a5cf38
JH
2920 PerlIOStdio_get_base,
2921 PerlIOStdio_get_bufsiz,
9e353e3b 2922#else
14a5cf38
JH
2923 NULL,
2924 NULL,
9e353e3b
NIS
2925#endif
2926#ifdef USE_STDIO_PTR
14a5cf38
JH
2927 PerlIOStdio_get_ptr,
2928 PerlIOStdio_get_cnt,
0eb1d8a4 2929#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
14a5cf38 2930 PerlIOStdio_set_ptrcnt
22569500 2931#else /* STDIO_PTR_LVALUE */
14a5cf38 2932 NULL
22569500
NIS
2933#endif /* STDIO_PTR_LVALUE */
2934#else /* USE_STDIO_PTR */
14a5cf38
JH
2935 NULL,
2936 NULL,
2937 NULL
22569500 2938#endif /* USE_STDIO_PTR */
9e353e3b
NIS
2939};
2940
9e353e3b
NIS
2941FILE *
2942PerlIO_exportFILE(PerlIO *f, int fl)
2943{
e87a358a 2944 dTHX;
14a5cf38 2945 FILE *stdio;
8dcb5783 2946 char buf[8];
14a5cf38 2947 PerlIO_flush(f);
8dcb5783 2948 stdio = fdopen(PerlIO_fileno(f), PerlIO_modestr(f,buf));
14a5cf38 2949 if (stdio) {
14a5cf38 2950 PerlIOStdio *s =
8dcb5783 2951 PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv),
14a5cf38
JH
2952 PerlIOStdio);
2953 s->stdio = stdio;
2954 }
2955 return stdio;
9e353e3b
NIS
2956}
2957
9e353e3b
NIS
2958FILE *
2959PerlIO_findFILE(PerlIO *f)
2960{
14a5cf38
JH
2961 PerlIOl *l = *f;
2962 while (l) {
2963 if (l->tab == &PerlIO_stdio) {
2964 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
2965 return s->stdio;
2966 }
2967 l = *PerlIONext(&l);
f7e7eb72 2968 }
14a5cf38 2969 return PerlIO_exportFILE(f, 0);
9e353e3b
NIS
2970}
2971
9e353e3b
NIS
2972void
2973PerlIO_releaseFILE(PerlIO *p, FILE *f)
2974{
22569500
NIS
2975 PerlIOl *l;
2976 while ((l = *p)) {
2977 if (l->tab == &PerlIO_stdio) {
2978 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
2979 if (s->stdio == f) {
2980 dTHX;
2981 PerlIO_pop(aTHX_ p);
2982 return;
2983 }
2984 }
2985 p = PerlIONext(p);
2986 }
2987 return;
9e353e3b
NIS
2988}
2989
2990/*--------------------------------------------------------------------------------------*/
14a5cf38 2991/*
71200d45 2992 * perlio buffer layer
14a5cf38 2993 */
9e353e3b 2994
5e2ab84b 2995IV
f62ce20a 2996PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
5e2ab84b 2997{
14a5cf38
JH
2998 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2999 int fd = PerlIO_fileno(f);
3000 Off_t posn;
3001 if (fd >= 0 && PerlLIO_isatty(fd)) {
3002 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
3003 }
3004 posn = PerlIO_tell(PerlIONext(f));
3005 if (posn != (Off_t) - 1) {
3006 b->posn = posn;
3007 }
f62ce20a 3008 return PerlIOBase_pushed(aTHX_ f, mode, arg);
5e2ab84b
NIS
3009}
3010
9e353e3b 3011PerlIO *
14a5cf38
JH
3012PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
3013 IV n, const char *mode, int fd, int imode, int perm,
3014 PerlIO *f, int narg, SV **args)
3015{
04892f78 3016 if (PerlIOValid(f)) {
14a5cf38 3017 PerlIO *next = PerlIONext(f);
04892f78
NIS
3018 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
3019 next = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
14a5cf38 3020 next, narg, args);
04892f78 3021 if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg) != 0) {
14a5cf38
JH
3022 return NULL;
3023 }
3024 }
3025 else {
04892f78 3026 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm());
14a5cf38
JH
3027 int init = 0;
3028 if (*mode == 'I') {
3029 init = 1;
3030 /*
71200d45 3031 * mode++;
14a5cf38
JH
3032 */
3033 }
3034 f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
d9dac8cd 3035 f, narg, args);
14a5cf38 3036 if (f) {
22569500 3037 if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) {
b26b1ab5
NC
3038 /*
3039 * if push fails during open, open fails. close will pop us.
3040 */
3041 PerlIO_close (f);
3042 return NULL;
3043 } else {
3044 fd = PerlIO_fileno(f);
b26b1ab5
NC
3045 if (init && fd == 2) {
3046 /*
3047 * Initial stderr is unbuffered
3048 */
3049 PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
3050 }
23b84778
IZ
3051#ifdef PERLIO_USING_CRLF
3052# ifdef PERLIO_IS_BINMODE_FD
3053 if (PERLIO_IS_BINMODE_FD(fd))
3054 PerlIO_binmode(f, '<'/*not used*/, O_BINARY, Nullch);
3055 else
3056# endif
3057 /*
3058 * do something about failing setmode()? --jhi
3059 */
3060 PerlLIO_setmode(fd, O_BINARY);
3061#endif
14a5cf38
JH
3062 }
3063 }
ee518936 3064 }
14a5cf38 3065 return f;
9e353e3b
NIS
3066}
3067
14a5cf38
JH
3068/*
3069 * This "flush" is akin to sfio's sync in that it handles files in either
71200d45 3070 * read or write state
14a5cf38 3071 */
9e353e3b 3072IV
f62ce20a 3073PerlIOBuf_flush(pTHX_ PerlIO *f)
6f9d8c32 3074{
14a5cf38
JH
3075 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3076 int code = 0;
04892f78 3077 PerlIO *n = PerlIONext(f);
14a5cf38
JH
3078 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
3079 /*
71200d45 3080 * write() the buffer
14a5cf38
JH
3081 */
3082 STDCHAR *buf = b->buf;
3083 STDCHAR *p = buf;
14a5cf38
JH
3084 while (p < b->ptr) {
3085 SSize_t count = PerlIO_write(n, p, b->ptr - p);
3086 if (count > 0) {
3087 p += count;
3088 }
3089 else if (count < 0 || PerlIO_error(n)) {
3090 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3091 code = -1;
3092 break;
3093 }
3094 }
3095 b->posn += (p - buf);
3096 }
3097 else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3098 STDCHAR *buf = PerlIO_get_base(f);
3099 /*
71200d45 3100 * Note position change
14a5cf38
JH
3101 */
3102 b->posn += (b->ptr - buf);
3103 if (b->ptr < b->end) {
3104 /*
71200d45 3105 * We did not consume all of it
14a5cf38 3106 */
04892f78
NIS
3107 if (PerlIO_seek(n, b->posn, SEEK_SET) == 0) {
3108 /* Reload n as some layers may pop themselves on seek */
3109 b->posn = PerlIO_tell(n = PerlIONext(f));
14a5cf38
JH
3110 }
3111 }
3112 }
3113 b->ptr = b->end = b->buf;
3114 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
04892f78
NIS
3115 /* We check for Valid because of dubious decision to make PerlIO_flush(NULL) flush all */
3116 /* FIXME: Doing downstream flush may be sub-optimal see PerlIOBuf_fill() below */
3117 if (PerlIOValid(n) && PerlIO_flush(n) != 0)
14a5cf38
JH
3118 code = -1;
3119 return code;
6f9d8c32
NIS
3120}
3121
06da4f11 3122IV
f62ce20a 3123PerlIOBuf_fill(pTHX_ PerlIO *f)
06da4f11 3124{
14a5cf38
JH
3125 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3126 PerlIO *n = PerlIONext(f);
3127 SSize_t avail;
3128 /*
04892f78
NIS
3129 * FIXME: doing the down-stream flush maybe sub-optimal if it causes
3130 * pre-read data in stdio buffer to be discarded.
3131 * However, skipping the flush also skips _our_ hosekeeping
3132 * and breaks tell tests. So we do the flush.
14a5cf38
JH
3133 */
3134 if (PerlIO_flush(f) != 0)
3135 return -1;
3136 if (PerlIOBase(f)->flags & PERLIO_F_TTY)
f62ce20a 3137 PerlIOBase_flush_linebuf(aTHX);
14a5cf38
JH
3138
3139 if (!b->buf)
22569500 3140 PerlIO_get_base(f); /* allocate via vtable */
14a5cf38
JH
3141
3142 b->ptr = b->end = b->buf;
3143 if (PerlIO_fast_gets(n)) {
3144 /*
04892f78 3145 * Layer below is also buffered. We do _NOT_ want to call its
14a5cf38
JH
3146 * ->Read() because that will loop till it gets what we asked for
3147 * which may hang on a pipe etc. Instead take anything it has to
71200d45 3148 * hand, or ask it to fill _once_.
14a5cf38
JH
3149 */
3150 avail = PerlIO_get_cnt(n);
3151 if (avail <= 0) {
3152 avail = PerlIO_fill(n);
3153 if (avail == 0)
3154 avail = PerlIO_get_cnt(n);
3155 else {
3156 if (!PerlIO_error(n) && PerlIO_eof(n))
3157 avail = 0;
3158 }
3159 }
3160 if (avail > 0) {
3161 STDCHAR *ptr = PerlIO_get_ptr(n);
3162 SSize_t cnt = avail;
eb160463 3163 if (avail > (SSize_t)b->bufsiz)
14a5cf38
JH
3164 avail = b->bufsiz;
3165 Copy(ptr, b->buf, avail, STDCHAR);
3166 PerlIO_set_ptrcnt(n, ptr + avail, cnt - avail);
3167 }
3168 }
3169 else {
3170 avail = PerlIO_read(n, b->ptr, b->bufsiz);
3171 }
3172 if (avail <= 0) {
3173 if (avail == 0)
3174 PerlIOBase(f)->flags |= PERLIO_F_EOF;
3175 else
3176 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3177 return -1;
3178 }
3179 b->end = b->buf + avail;
3180 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3181 return 0;
06da4f11
NIS
3182}
3183
6f9d8c32 3184SSize_t
f62ce20a 3185PerlIOBuf_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 3186{
14a5cf38 3187 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
04892f78 3188 if (PerlIOValid(f)) {
14a5cf38
JH
3189 if (!b->ptr)
3190 PerlIO_get_base(f);
f62ce20a 3191 return PerlIOBase_read(aTHX_ f, vbuf, count);
14a5cf38
JH
3192 }
3193 return 0;
6f9d8c32
NIS
3194}
3195
9e353e3b 3196SSize_t
f62ce20a 3197PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3198{
14a5cf38
JH
3199 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
3200 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3201 SSize_t unread = 0;
3202 SSize_t avail;
3203 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3204 PerlIO_flush(f);
3205 if (!b->buf)
3206 PerlIO_get_base(f);
3207 if (b->buf) {
3208 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3209 /*
3210 * Buffer is already a read buffer, we can overwrite any chars
71200d45 3211 * which have been read back to buffer start
14a5cf38
JH
3212 */
3213 avail = (b->ptr - b->buf);
3214 }
3215 else {
3216 /*
3217 * Buffer is idle, set it up so whole buffer is available for
71200d45 3218 * unread
14a5cf38
JH
3219 */
3220 avail = b->bufsiz;
3221 b->end = b->buf + avail;
3222 b->ptr = b->end;
3223 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3224 /*
71200d45 3225 * Buffer extends _back_ from where we are now
14a5cf38
JH
3226 */
3227 b->posn -= b->bufsiz;
3228 }
3229 if (avail > (SSize_t) count) {
3230 /*
71200d45 3231 * If we have space for more than count, just move count
14a5cf38
JH
3232 */
3233 avail = count;
3234 }
3235 if (avail > 0) {
3236 b->ptr -= avail;
3237 buf -= avail;
3238 /*
3239 * In simple stdio-like ungetc() case chars will be already
71200d45 3240 * there
14a5cf38
JH
3241 */
3242 if (buf != b->ptr) {
3243 Copy(buf, b->ptr, avail, STDCHAR);
3244 }
3245 count -= avail;
3246 unread += avail;
3247 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3248 }
3249 }
93679785
NIS
3250 if (count > 0) {
3251 unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
3252 }
14a5cf38 3253 return unread;
760ac839
LW
3254}
3255
9e353e3b 3256SSize_t
f62ce20a 3257PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3258{
14a5cf38
JH
3259 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3260 const STDCHAR *buf = (const STDCHAR *) vbuf;
3261 Size_t written = 0;
3262 if (!b->buf)
3263 PerlIO_get_base(f);
3264 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3265 return 0;
3266 while (count > 0) {
3267 SSize_t avail = b->bufsiz - (b->ptr - b->buf);
3268 if ((SSize_t) count < avail)
3269 avail = count;
3270 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
3271 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3272 while (avail > 0) {
3273 int ch = *buf++;
3274 *(b->ptr)++ = ch;
3275 count--;
3276 avail--;
3277 written++;
3278 if (ch == '\n') {
3279 PerlIO_flush(f);
3280 break;
3281 }
3282 }
3283 }
3284 else {
3285 if (avail) {
3286 Copy(buf, b->ptr, avail, STDCHAR);
3287 count -= avail;
3288 buf += avail;
3289 written += avail;
3290 b->ptr += avail;
3291 }
3292 }
3293 if (b->ptr >= (b->buf + b->bufsiz))
3294 PerlIO_flush(f);
3295 }
3296 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3297 PerlIO_flush(f);
3298 return written;
9e353e3b
NIS
3299}
3300
3301IV
f62ce20a 3302PerlIOBuf_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 3303{
14a5cf38
JH
3304 IV code;
3305 if ((code = PerlIO_flush(f)) == 0) {
3306 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3307 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3308 code = PerlIO_seek(PerlIONext(f), offset, whence);
3309 if (code == 0) {
3310 b->posn = PerlIO_tell(PerlIONext(f));
3311 }
9e353e3b 3312 }
14a5cf38 3313 return code;
9e353e3b
NIS
3314}
3315
3316Off_t
f62ce20a 3317PerlIOBuf_tell(pTHX_ PerlIO *f)
9e353e3b 3318{
14a5cf38
JH
3319 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3320 /*
71200d45 3321 * b->posn is file position where b->buf was read, or will be written
14a5cf38
JH
3322 */
3323 Off_t posn = b->posn;
3324 if (b->buf) {
3325 /*
71200d45 3326 * If buffer is valid adjust position by amount in buffer
14a5cf38
JH
3327 */
3328 posn += (b->ptr - b->buf);
3329 }
3330 return posn;
9e353e3b
NIS
3331}
3332
3333IV
44798d05
NIS
3334PerlIOBuf_popped(pTHX_ PerlIO *f)
3335{
3336 IV code = PerlIOBase_popped(aTHX_ f);
3337 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3338 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3339 Safefree(b->buf);
3340 }
3341 b->buf = NULL;
3342 b->ptr = b->end = b->buf;
3343 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3344 return code;
3345}
3346
3347IV
f62ce20a 3348PerlIOBuf_close(pTHX_ PerlIO *f)
9e353e3b 3349{
f62ce20a 3350 IV code = PerlIOBase_close(aTHX_ f);
14a5cf38
JH
3351 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3352 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 3353 Safefree(b->buf);
14a5cf38
JH
3354 }
3355 b->buf = NULL;
3356 b->ptr = b->end = b->buf;
3357 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3358 return code;
760ac839
LW
3359}
3360
9e353e3b 3361STDCHAR *
f62ce20a 3362PerlIOBuf_get_ptr(pTHX_ PerlIO *f)
9e353e3b 3363{
14a5cf38
JH
3364 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3365 if (!b->buf)
3366 PerlIO_get_base(f);
3367 return b->ptr;
9e353e3b
NIS
3368}
3369
05d1247b 3370SSize_t
f62ce20a 3371PerlIOBuf_get_cnt(pTHX_ PerlIO *f)
9e353e3b 3372{
14a5cf38
JH
3373 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3374 if (!b->buf)
3375 PerlIO_get_base(f);
3376 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
3377 return (b->end - b->ptr);
3378 return 0;
9e353e3b
NIS
3379}
3380
3381STDCHAR *
f62ce20a 3382PerlIOBuf_get_base(pTHX_ PerlIO *f)
9e353e3b 3383{
14a5cf38
JH
3384 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3385 if (!b->buf) {
3386 if (!b->bufsiz)
3387 b->bufsiz = 4096;
a1ea730d 3388 b->buf =
7fcdafbd 3389 Newz('B',b->buf,b->bufsiz, STDCHAR);
14a5cf38
JH
3390 if (!b->buf) {
3391 b->buf = (STDCHAR *) & b->oneword;
3392 b->bufsiz = sizeof(b->oneword);
3393 }
3394 b->ptr = b->buf;
3395 b->end = b->ptr;
06da4f11 3396 }
14a5cf38 3397 return b->buf;
9e353e3b
NIS
3398}
3399
3400Size_t
f62ce20a 3401PerlIOBuf_bufsiz(pTHX_ PerlIO *f)
9e353e3b 3402{
14a5cf38
JH
3403 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3404 if (!b->buf)
3405 PerlIO_get_base(f);
3406 return (b->end - b->buf);
9e353e3b
NIS
3407}
3408
3409void
f62ce20a 3410PerlIOBuf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 3411{
14a5cf38
JH
3412 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3413 if (!b->buf)
3414 PerlIO_get_base(f);
3415 b->ptr = ptr;
3416 if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf) {
14a5cf38
JH
3417 assert(PerlIO_get_cnt(f) == cnt);
3418 assert(b->ptr >= b->buf);
3419 }
3420 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
760ac839
LW
3421}
3422
71200d45 3423PerlIO *
ecdeb87c 3424PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 3425{
ecdeb87c 3426 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
3427}
3428
3429
3430
9e353e3b 3431PerlIO_funcs PerlIO_perlio = {
14a5cf38
JH
3432 "perlio",
3433 sizeof(PerlIOBuf),
3434 PERLIO_K_BUFFERED,
3435 PerlIOBuf_pushed,
44798d05 3436 PerlIOBuf_popped,
14a5cf38
JH
3437 PerlIOBuf_open,
3438 NULL,
3439 PerlIOBase_fileno,
71200d45 3440 PerlIOBuf_dup,
14a5cf38
JH
3441 PerlIOBuf_read,
3442 PerlIOBuf_unread,
3443 PerlIOBuf_write,
3444 PerlIOBuf_seek,
3445 PerlIOBuf_tell,
3446 PerlIOBuf_close,
3447 PerlIOBuf_flush,
3448 PerlIOBuf_fill,
3449 PerlIOBase_eof,
3450 PerlIOBase_error,
3451 PerlIOBase_clearerr,
3452 PerlIOBase_setlinebuf,
3453 PerlIOBuf_get_base,
3454 PerlIOBuf_bufsiz,
3455 PerlIOBuf_get_ptr,
3456 PerlIOBuf_get_cnt,
3457 PerlIOBuf_set_ptrcnt,
9e353e3b
NIS
3458};
3459
66ecd56b 3460/*--------------------------------------------------------------------------------------*/
14a5cf38 3461/*
71200d45 3462 * Temp layer to hold unread chars when cannot do it any other way
14a5cf38 3463 */
5e2ab84b
NIS
3464
3465IV
f62ce20a 3466PerlIOPending_fill(pTHX_ PerlIO *f)
5e2ab84b 3467{
14a5cf38 3468 /*
71200d45 3469 * Should never happen
14a5cf38
JH
3470 */
3471 PerlIO_flush(f);
3472 return 0;
5e2ab84b
NIS
3473}
3474
3475IV
f62ce20a 3476PerlIOPending_close(pTHX_ PerlIO *f)
5e2ab84b 3477{
14a5cf38 3478 /*
71200d45 3479 * A tad tricky - flush pops us, then we close new top
14a5cf38
JH
3480 */
3481 PerlIO_flush(f);
3482 return PerlIO_close(f);
5e2ab84b
NIS
3483}
3484
3485IV
f62ce20a 3486PerlIOPending_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
5e2ab84b 3487{
14a5cf38 3488 /*
71200d45 3489 * A tad tricky - flush pops us, then we seek new top
14a5cf38
JH
3490 */
3491 PerlIO_flush(f);
3492 return PerlIO_seek(f, offset, whence);
5e2ab84b
NIS
3493}
3494
3495
3496IV
f62ce20a 3497PerlIOPending_flush(pTHX_ PerlIO *f)
5e2ab84b 3498{
14a5cf38
JH
3499 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3500 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 3501 Safefree(b->buf);
14a5cf38
JH
3502 b->buf = NULL;
3503 }
3504 PerlIO_pop(aTHX_ f);
3505 return 0;
5e2ab84b
NIS
3506}
3507
3508void
f62ce20a 3509PerlIOPending_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
5e2ab84b 3510{
14a5cf38
JH
3511 if (cnt <= 0) {
3512 PerlIO_flush(f);
3513 }
3514 else {
f62ce20a 3515 PerlIOBuf_set_ptrcnt(aTHX_ f, ptr, cnt);
14a5cf38 3516 }
5e2ab84b
NIS
3517}
3518
3519IV
f62ce20a 3520PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
5e2ab84b 3521{
f62ce20a 3522 IV code = PerlIOBase_pushed(aTHX_ f, mode, arg);
14a5cf38
JH
3523 PerlIOl *l = PerlIOBase(f);
3524 /*
71200d45
NIS
3525 * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets()
3526 * etc. get muddled when it changes mid-string when we auto-pop.
14a5cf38
JH
3527 */
3528 l->flags = (l->flags & ~(PERLIO_F_FASTGETS | PERLIO_F_UTF8)) |
3529 (PerlIOBase(PerlIONext(f))->
3530 flags & (PERLIO_F_FASTGETS | PERLIO_F_UTF8));
3531 return code;
5e2ab84b
NIS
3532}
3533
3534SSize_t
f62ce20a 3535PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
5e2ab84b 3536{
14a5cf38
JH
3537 SSize_t avail = PerlIO_get_cnt(f);
3538 SSize_t got = 0;
eb160463 3539 if ((SSize_t)count < avail)
14a5cf38
JH
3540 avail = count;
3541 if (avail > 0)
f62ce20a 3542 got = PerlIOBuf_read(aTHX_ f, vbuf, avail);
eb160463 3543 if (got >= 0 && got < (SSize_t)count) {
14a5cf38
JH
3544 SSize_t more =
3545 PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got);
3546 if (more >= 0 || got == 0)
3547 got += more;
3548 }
3549 return got;
5e2ab84b
NIS
3550}
3551
5e2ab84b 3552PerlIO_funcs PerlIO_pending = {
14a5cf38
JH
3553 "pending",
3554 sizeof(PerlIOBuf),
3555 PERLIO_K_BUFFERED,
3556 PerlIOPending_pushed,
44798d05 3557 PerlIOBuf_popped,
14a5cf38
JH
3558 NULL,
3559 NULL,
3560 PerlIOBase_fileno,
71200d45 3561 PerlIOBuf_dup,
14a5cf38
JH
3562 PerlIOPending_read,
3563 PerlIOBuf_unread,
3564 PerlIOBuf_write,
3565 PerlIOPending_seek,
3566 PerlIOBuf_tell,
3567 PerlIOPending_close,
3568 PerlIOPending_flush,
3569 PerlIOPending_fill,
3570 PerlIOBase_eof,
3571 PerlIOBase_error,
3572 PerlIOBase_clearerr,
3573 PerlIOBase_setlinebuf,
3574 PerlIOBuf_get_base,
3575 PerlIOBuf_bufsiz,
3576 PerlIOBuf_get_ptr,
3577 PerlIOBuf_get_cnt,
3578 PerlIOPending_set_ptrcnt,
5e2ab84b
NIS
3579};
3580
3581
3582
3583/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
3584/*
3585 * crlf - translation On read translate CR,LF to "\n" we do this by
3586 * overriding ptr/cnt entries to hand back a line at a time and keeping a
71200d45 3587 * record of which nl we "lied" about. On write translate "\n" to CR,LF
66ecd56b
NIS
3588 */
3589
14a5cf38 3590typedef struct {
22569500
NIS
3591 PerlIOBuf base; /* PerlIOBuf stuff */
3592 STDCHAR *nl; /* Position of crlf we "lied" about in the
14a5cf38 3593 * buffer */
99efab12
NIS
3594} PerlIOCrlf;
3595
f5b9d040 3596IV
f62ce20a 3597PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
f5b9d040 3598{
14a5cf38
JH
3599 IV code;
3600 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
f62ce20a 3601 code = PerlIOBuf_pushed(aTHX_ f, mode, arg);
5e2ab84b 3602#if 0
14a5cf38
JH
3603 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n",
3604 f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)",
3605 PerlIOBase(f)->flags);
5e2ab84b 3606#endif
14a5cf38 3607 return code;
f5b9d040
NIS
3608}
3609
3610
99efab12 3611SSize_t
f62ce20a 3612PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 3613{
14a5cf38
JH
3614 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3615 if (c->nl) {
3616 *(c->nl) = 0xd;
3617 c->nl = NULL;
3618 }
3619 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 3620 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
14a5cf38
JH
3621 else {
3622 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
3623 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3624 SSize_t unread = 0;
3625 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3626 PerlIO_flush(f);
3627 if (!b->buf)
3628 PerlIO_get_base(f);
3629 if (b->buf) {
3630 if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3631 b->end = b->ptr = b->buf + b->bufsiz;
3632 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3633 b->posn -= b->bufsiz;
3634 }
3635 while (count > 0 && b->ptr > b->buf) {
3636 int ch = *--buf;
3637 if (ch == '\n') {
3638 if (b->ptr - 2 >= b->buf) {
3639 *--(b->ptr) = 0xa;
3640 *--(b->ptr) = 0xd;
3641 unread++;
3642 count--;
3643 }
3644 else {
3645 buf++;
3646 break;
3647 }
3648 }
3649 else {
3650 *--(b->ptr) = ch;
3651 unread++;
3652 count--;
3653 }
3654 }
3655 }
3656 return unread;
3657 }
99efab12
NIS
3658}
3659
3660SSize_t
f62ce20a 3661PerlIOCrlf_get_cnt(pTHX_ PerlIO *f)
99efab12 3662{
14a5cf38
JH
3663 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3664 if (!b->buf)
3665 PerlIO_get_base(f);
3666 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3667 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
23b3c6af
NIS
3668 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) {
3669 STDCHAR *nl = (c->nl) ? c->nl : b->ptr;
14a5cf38
JH
3670 scan:
3671 while (nl < b->end && *nl != 0xd)
3672 nl++;
3673 if (nl < b->end && *nl == 0xd) {
3674 test:
3675 if (nl + 1 < b->end) {
3676 if (nl[1] == 0xa) {
3677 *nl = '\n';
3678 c->nl = nl;
3679 }
3680 else {
3681 /*
71200d45 3682 * Not CR,LF but just CR
14a5cf38
JH
3683 */
3684 nl++;
3685 goto scan;
3686 }
3687 }
3688 else {
3689 /*
71200d45 3690 * Blast - found CR as last char in buffer
14a5cf38 3691 */
e87a358a 3692
14a5cf38
JH
3693 if (b->ptr < nl) {
3694 /*
3695 * They may not care, defer work as long as
71200d45 3696 * possible
14a5cf38 3697 */
a0d1d361 3698 c->nl = nl;
14a5cf38
JH
3699 return (nl - b->ptr);
3700 }
3701 else {
3702 int code;
22569500 3703 b->ptr++; /* say we have read it as far as
14a5cf38 3704 * flush() is concerned */
22569500
NIS
3705 b->buf++; /* Leave space in front of buffer */
3706 b->bufsiz--; /* Buffer is thus smaller */
3707 code = PerlIO_fill(f); /* Fetch some more */
3708 b->bufsiz++; /* Restore size for next time */
3709 b->buf--; /* Point at space */
3710 b->ptr = nl = b->buf; /* Which is what we hand
14a5cf38 3711 * off */
22569500
NIS
3712 b->posn--; /* Buffer starts here */
3713 *nl = 0xd; /* Fill in the CR */
14a5cf38 3714 if (code == 0)
22569500 3715 goto test; /* fill() call worked */
14a5cf38 3716 /*
71200d45 3717 * CR at EOF - just fall through
14a5cf38 3718 */
a0d1d361 3719 /* Should we clear EOF though ??? */
14a5cf38
JH
3720 }
3721 }
3722 }
3723 }
3724 return (((c->nl) ? (c->nl + 1) : b->end) - b->ptr);
3725 }
3726 return 0;
99efab12
NIS
3727}
3728
3729void
f62ce20a 3730PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
14a5cf38
JH
3731{
3732 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3733 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
14a5cf38
JH
3734 if (!b->buf)
3735 PerlIO_get_base(f);
3736 if (!ptr) {
a0d1d361 3737 if (c->nl) {
14a5cf38 3738 ptr = c->nl + 1;
22569500 3739 if (ptr == b->end && *c->nl == 0xd) {
a0d1d361 3740 /* Defered CR at end of buffer case - we lied about count */
22569500
NIS
3741 ptr--;
3742 }
3743 }
14a5cf38
JH
3744 else {
3745 ptr = b->end;
14a5cf38
JH
3746 }
3747 ptr -= cnt;
3748 }
3749 else {
3b4bd3fd 3750#if 0
14a5cf38 3751 /*
71200d45 3752 * Test code - delete when it works ...
14a5cf38 3753 */
3b4bd3fd 3754 IV flags = PerlIOBase(f)->flags;
ba7abf9d 3755 STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end;
22569500 3756 if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) {
a0d1d361
NIS
3757 /* Defered CR at end of buffer case - we lied about count */
3758 chk--;
22569500 3759 }
14a5cf38
JH
3760 chk -= cnt;
3761
a0d1d361 3762 if (ptr != chk ) {
99ef548b 3763 Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08" UVxf
14a5cf38
JH
3764 " nl=%p e=%p for %d", ptr, chk, flags, c->nl,
3765 b->end, cnt);
3766 }
99ef548b 3767#endif
14a5cf38
JH
3768 }
3769 if (c->nl) {
3770 if (ptr > c->nl) {
3771 /*
71200d45 3772 * They have taken what we lied about
14a5cf38
JH
3773 */
3774 *(c->nl) = 0xd;
3775 c->nl = NULL;
3776 ptr++;
3777 }
3778 }
3779 b->ptr = ptr;
3780 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
99efab12
NIS
3781}
3782
3783SSize_t
f62ce20a 3784PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 3785{
14a5cf38 3786 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 3787 return PerlIOBuf_write(aTHX_ f, vbuf, count);
14a5cf38
JH
3788 else {
3789 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3790 const STDCHAR *buf = (const STDCHAR *) vbuf;
3791 const STDCHAR *ebuf = buf + count;
3792 if (!b->buf)
3793 PerlIO_get_base(f);
3794 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3795 return 0;
3796 while (buf < ebuf) {
3797 STDCHAR *eptr = b->buf + b->bufsiz;
3798 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
3799 while (buf < ebuf && b->ptr < eptr) {
3800 if (*buf == '\n') {
3801 if ((b->ptr + 2) > eptr) {
3802 /*
71200d45 3803 * Not room for both
14a5cf38
JH
3804 */
3805 PerlIO_flush(f);
3806 break;
3807 }
3808 else {
22569500
NIS
3809 *(b->ptr)++ = 0xd; /* CR */
3810 *(b->ptr)++ = 0xa; /* LF */
14a5cf38
JH
3811 buf++;
3812 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3813 PerlIO_flush(f);
3814 break;
3815 }
3816 }
3817 }
3818 else {
3819 int ch = *buf++;
3820 *(b->ptr)++ = ch;
3821 }
3822 if (b->ptr >= eptr) {
3823 PerlIO_flush(f);
3824 break;
3825 }
3826 }
3827 }
3828 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3829 PerlIO_flush(f);
3830 return (buf - (STDCHAR *) vbuf);
3831 }
99efab12
NIS
3832}
3833
3834IV
f62ce20a 3835PerlIOCrlf_flush(pTHX_ PerlIO *f)
99efab12 3836{
14a5cf38
JH
3837 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3838 if (c->nl) {
3839 *(c->nl) = 0xd;
3840 c->nl = NULL;
3841 }
f62ce20a 3842 return PerlIOBuf_flush(aTHX_ f);
99efab12
NIS
3843}
3844
66ecd56b 3845PerlIO_funcs PerlIO_crlf = {
14a5cf38
JH
3846 "crlf",
3847 sizeof(PerlIOCrlf),
3848 PERLIO_K_BUFFERED | PERLIO_K_CANCRLF,
3849 PerlIOCrlf_pushed,
44798d05 3850 PerlIOBuf_popped, /* popped */
14a5cf38
JH
3851 PerlIOBuf_open,
3852 NULL,
3853 PerlIOBase_fileno,
71200d45 3854 PerlIOBuf_dup,
22569500 3855 PerlIOBuf_read, /* generic read works with ptr/cnt lies
14a5cf38 3856 * ... */
22569500
NIS
3857 PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */
3858 PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */
14a5cf38
JH
3859 PerlIOBuf_seek,
3860 PerlIOBuf_tell,
3861 PerlIOBuf_close,
3862 PerlIOCrlf_flush,
3863 PerlIOBuf_fill,
3864 PerlIOBase_eof,
3865 PerlIOBase_error,
3866 PerlIOBase_clearerr,
3867 PerlIOBase_setlinebuf,
3868 PerlIOBuf_get_base,
3869 PerlIOBuf_bufsiz,
3870 PerlIOBuf_get_ptr,
3871 PerlIOCrlf_get_cnt,
3872 PerlIOCrlf_set_ptrcnt,
66ecd56b
NIS
3873};
3874
06da4f11
NIS
3875#ifdef HAS_MMAP
3876/*--------------------------------------------------------------------------------------*/
14a5cf38 3877/*
71200d45 3878 * mmap as "buffer" layer
14a5cf38 3879 */
06da4f11 3880
14a5cf38 3881typedef struct {
22569500
NIS
3882 PerlIOBuf base; /* PerlIOBuf stuff */
3883 Mmap_t mptr; /* Mapped address */
3884 Size_t len; /* mapped length */
3885 STDCHAR *bbuf; /* malloced buffer if map fails */
06da4f11
NIS
3886} PerlIOMmap;
3887
c3d7c7c9
NIS
3888static size_t page_size = 0;
3889
06da4f11 3890IV
f62ce20a 3891PerlIOMmap_map(pTHX_ PerlIO *f)
06da4f11 3892{
14a5cf38
JH
3893 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3894 IV flags = PerlIOBase(f)->flags;
3895 IV code = 0;
3896 if (m->len)
3897 abort();
3898 if (flags & PERLIO_F_CANREAD) {
3899 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3900 int fd = PerlIO_fileno(f);
10eefe7f
CB
3901 Stat_t st;
3902 code = Fstat(fd, &st);
14a5cf38
JH
3903 if (code == 0 && S_ISREG(st.st_mode)) {
3904 SSize_t len = st.st_size - b->posn;
3905 if (len > 0) {
3906 Off_t posn;
3907 if (!page_size) {
68d873c6 3908#if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE))
14a5cf38
JH
3909 {
3910 SETERRNO(0, SS$_NORMAL);
68d873c6 3911# ifdef _SC_PAGESIZE
14a5cf38 3912 page_size = sysconf(_SC_PAGESIZE);
68d873c6 3913# else
14a5cf38 3914 page_size = sysconf(_SC_PAGE_SIZE);
14aaf8e8 3915# endif
14a5cf38
JH
3916 if ((long) page_size < 0) {
3917 if (errno) {
3918 SV *error = ERRSV;
3919 char *msg;
3920 STRLEN n_a;
3921 (void) SvUPGRADE(error, SVt_PV);
3922 msg = SvPVx(error, n_a);
3923 Perl_croak(aTHX_ "panic: sysconf: %s",
3924 msg);
3925 }
3926 else
3927 Perl_croak(aTHX_
3928 "panic: sysconf: pagesize unknown");
3929 }
3930 }
68d873c6
JH
3931#else
3932# ifdef HAS_GETPAGESIZE
14a5cf38 3933 page_size = getpagesize();
68d873c6
JH
3934# else
3935# if defined(I_SYS_PARAM) && defined(PAGESIZE)
22569500 3936 page_size = PAGESIZE; /* compiletime, bad */
68d873c6
JH
3937# endif
3938# endif
3939#endif
14a5cf38
JH
3940 if ((IV) page_size <= 0)
3941 Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
3942 (IV) page_size);
3943 }
3944 if (b->posn < 0) {
3945 /*
3946 * This is a hack - should never happen - open should
71200d45 3947 * have set it !
14a5cf38
JH
3948 */
3949 b->posn = PerlIO_tell(PerlIONext(f));
3950 }
3951 posn = (b->posn / page_size) * page_size;
3952 len = st.st_size - posn;
3953 m->mptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
3954 if (m->mptr && m->mptr != (Mmap_t) - 1) {
a5262162 3955#if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
14a5cf38 3956 madvise(m->mptr, len, MADV_SEQUENTIAL);
06da4f11 3957#endif
a5262162 3958#if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED)
14a5cf38 3959 madvise(m->mptr, len, MADV_WILLNEED);
a5262162 3960#endif
14a5cf38
JH
3961 PerlIOBase(f)->flags =
3962 (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
3963 b->end = ((STDCHAR *) m->mptr) + len;
3964 b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn);
3965 b->ptr = b->buf;
3966 m->len = len;
3967 }
3968 else {
3969 b->buf = NULL;
3970 }
3971 }
3972 else {
3973 PerlIOBase(f)->flags =
3974 flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
3975 b->buf = NULL;
3976 b->ptr = b->end = b->ptr;
3977 code = -1;
3978 }
3979 }
3980 }
3981 return code;
06da4f11
NIS
3982}
3983
3984IV
e87a358a 3985PerlIOMmap_unmap(pTHX_ PerlIO *f)
06da4f11 3986{
14a5cf38
JH
3987 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3988 PerlIOBuf *b = &m->base;
3989 IV code = 0;
3990 if (m->len) {
3991 if (b->buf) {
3992 code = munmap(m->mptr, m->len);
3993 b->buf = NULL;
3994 m->len = 0;
3995 m->mptr = NULL;
3996 if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0)
3997 code = -1;
3998 }
3999 b->ptr = b->end = b->buf;
4000 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
4001 }
4002 return code;
06da4f11
NIS
4003}
4004
4005STDCHAR *
f62ce20a 4006PerlIOMmap_get_base(pTHX_ PerlIO *f)
06da4f11 4007{
14a5cf38
JH
4008 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4009 PerlIOBuf *b = &m->base;
4010 if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
4011 /*
71200d45 4012 * Already have a readbuffer in progress
14a5cf38
JH
4013 */
4014 return b->buf;
4015 }
4016 if (b->buf) {
4017 /*
71200d45 4018 * We have a write buffer or flushed PerlIOBuf read buffer
14a5cf38 4019 */
22569500
NIS
4020 m->bbuf = b->buf; /* save it in case we need it again */
4021 b->buf = NULL; /* Clear to trigger below */
14a5cf38
JH
4022 }
4023 if (!b->buf) {
22569500 4024 PerlIOMmap_map(aTHX_ f); /* Try and map it */
14a5cf38
JH
4025 if (!b->buf) {
4026 /*
71200d45 4027 * Map did not work - recover PerlIOBuf buffer if we have one
14a5cf38
JH
4028 */
4029 b->buf = m->bbuf;
4030 }
4031 }
4032 b->ptr = b->end = b->buf;
4033 if (b->buf)
4034 return b->buf;
f62ce20a 4035 return PerlIOBuf_get_base(aTHX_ f);
06da4f11
NIS
4036}
4037
4038SSize_t
f62ce20a 4039PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 4040{
14a5cf38
JH
4041 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4042 PerlIOBuf *b = &m->base;
4043 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
4044 PerlIO_flush(f);
4045 if (b->ptr && (b->ptr - count) >= b->buf
4046 && memEQ(b->ptr - count, vbuf, count)) {
4047 b->ptr -= count;
4048 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
4049 return count;
4050 }
4051 if (m->len) {
4052 /*
71200d45 4053 * Loose the unwritable mapped buffer
14a5cf38
JH
4054 */
4055 PerlIO_flush(f);
4056 /*
71200d45 4057 * If flush took the "buffer" see if we have one from before
14a5cf38
JH
4058 */
4059 if (!b->buf && m->bbuf)
4060 b->buf = m->bbuf;
4061 if (!b->buf) {
f62ce20a 4062 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
4063 m->bbuf = b->buf;
4064 }
4065 }
f62ce20a 4066 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
06da4f11
NIS
4067}
4068
4069SSize_t
f62ce20a 4070PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 4071{
14a5cf38
JH
4072 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4073 PerlIOBuf *b = &m->base;
4074 if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
4075 /*
71200d45 4076 * No, or wrong sort of, buffer
14a5cf38
JH
4077 */
4078 if (m->len) {
e87a358a 4079 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
4080 return 0;
4081 }
4082 /*
71200d45 4083 * If unmap took the "buffer" see if we have one from before
14a5cf38
JH
4084 */
4085 if (!b->buf && m->bbuf)
4086 b->buf = m->bbuf;
4087 if (!b->buf) {
f62ce20a 4088 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
4089 m->bbuf = b->buf;
4090 }
06da4f11 4091 }
f62ce20a 4092 return PerlIOBuf_write(aTHX_ f, vbuf, count);
06da4f11
NIS
4093}
4094
4095IV
f62ce20a 4096PerlIOMmap_flush(pTHX_ PerlIO *f)
06da4f11 4097{
14a5cf38
JH
4098 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4099 PerlIOBuf *b = &m->base;
f62ce20a 4100 IV code = PerlIOBuf_flush(aTHX_ f);
14a5cf38 4101 /*
71200d45 4102 * Now we are "synced" at PerlIOBuf level
14a5cf38
JH
4103 */
4104 if (b->buf) {
4105 if (m->len) {
4106 /*
71200d45 4107 * Unmap the buffer
14a5cf38 4108 */
e87a358a 4109 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
4110 code = -1;
4111 }
4112 else {
4113 /*
4114 * We seem to have a PerlIOBuf buffer which was not mapped
71200d45 4115 * remember it in case we need one later
14a5cf38
JH
4116 */
4117 m->bbuf = b->buf;
4118 }
4119 }
4120 return code;
06da4f11
NIS
4121}
4122
4123IV
f62ce20a 4124PerlIOMmap_fill(pTHX_ PerlIO *f)
06da4f11 4125{
14a5cf38
JH
4126 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
4127 IV code = PerlIO_flush(f);
4128 if (code == 0 && !b->buf) {
f62ce20a 4129 code = PerlIOMmap_map(aTHX_ f);
14a5cf38
JH
4130 }
4131 if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
f62ce20a 4132 code = PerlIOBuf_fill(aTHX_ f);
14a5cf38
JH
4133 }
4134 return code;
06da4f11
NIS
4135}
4136
4137IV
f62ce20a 4138PerlIOMmap_close(pTHX_ PerlIO *f)
06da4f11 4139{
14a5cf38
JH
4140 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4141 PerlIOBuf *b = &m->base;
4142 IV code = PerlIO_flush(f);
4143 if (m->bbuf) {
4144 b->buf = m->bbuf;
4145 m->bbuf = NULL;
4146 b->ptr = b->end = b->buf;
4147 }
f62ce20a 4148 if (PerlIOBuf_close(aTHX_ f) != 0)
14a5cf38
JH
4149 code = -1;
4150 return code;
06da4f11
NIS
4151}
4152
71200d45 4153PerlIO *
ecdeb87c 4154PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 4155{
ecdeb87c 4156 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
4157}
4158
06da4f11
NIS
4159
4160PerlIO_funcs PerlIO_mmap = {
14a5cf38
JH
4161 "mmap",
4162 sizeof(PerlIOMmap),
4163 PERLIO_K_BUFFERED,
4164 PerlIOBuf_pushed,
44798d05 4165 PerlIOBuf_popped,
14a5cf38
JH
4166 PerlIOBuf_open,
4167 NULL,
4168 PerlIOBase_fileno,
71200d45 4169 PerlIOMmap_dup,
14a5cf38
JH
4170 PerlIOBuf_read,
4171 PerlIOMmap_unread,
4172 PerlIOMmap_write,
4173 PerlIOBuf_seek,
4174 PerlIOBuf_tell,
4175 PerlIOBuf_close,
4176 PerlIOMmap_flush,
4177 PerlIOMmap_fill,
4178 PerlIOBase_eof,
4179 PerlIOBase_error,
4180 PerlIOBase_clearerr,
4181 PerlIOBase_setlinebuf,
4182 PerlIOMmap_get_base,
4183 PerlIOBuf_bufsiz,
4184 PerlIOBuf_get_ptr,
4185 PerlIOBuf_get_cnt,
4186 PerlIOBuf_set_ptrcnt,
06da4f11
NIS
4187};
4188
22569500 4189#endif /* HAS_MMAP */
06da4f11 4190
9e353e3b 4191PerlIO *
e87a358a 4192Perl_PerlIO_stdin(pTHX)
9e353e3b 4193{
a1ea730d 4194 if (!PL_perlio) {
14a5cf38
JH
4195 PerlIO_stdstreams(aTHX);
4196 }
a1ea730d 4197 return &PL_perlio[1];
9e353e3b
NIS
4198}
4199
9e353e3b 4200PerlIO *
e87a358a 4201Perl_PerlIO_stdout(pTHX)
9e353e3b 4202{
a1ea730d 4203 if (!PL_perlio) {
14a5cf38
JH
4204 PerlIO_stdstreams(aTHX);
4205 }
a1ea730d 4206 return &PL_perlio[2];
9e353e3b
NIS
4207}
4208
9e353e3b 4209PerlIO *
e87a358a 4210Perl_PerlIO_stderr(pTHX)
9e353e3b 4211{
a1ea730d 4212 if (!PL_perlio) {
14a5cf38
JH
4213 PerlIO_stdstreams(aTHX);
4214 }
a1ea730d 4215 return &PL_perlio[3];
9e353e3b
NIS
4216}
4217
4218/*--------------------------------------------------------------------------------------*/
4219
9e353e3b
NIS
4220char *
4221PerlIO_getname(PerlIO *f, char *buf)
4222{
14a5cf38
JH
4223 dTHX;
4224 char *name = NULL;
a15cef0c 4225#ifdef VMS
14a5cf38
JH
4226 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
4227 if (stdio)
4228 name = fgetname(stdio, buf);
a15cef0c 4229#else
14a5cf38 4230 Perl_croak(aTHX_ "Don't know how to get file name");
a15cef0c 4231#endif
14a5cf38 4232 return name;
9e353e3b
NIS
4233}
4234
4235
4236/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
4237/*
4238 * Functions which can be called on any kind of PerlIO implemented in
71200d45 4239 * terms of above
14a5cf38 4240 */
9e353e3b 4241
e87a358a
NIS
4242#undef PerlIO_fdopen
4243PerlIO *
4244PerlIO_fdopen(int fd, const char *mode)
4245{
4246 dTHX;
4247 return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL);
4248}
4249
4250#undef PerlIO_open
4251PerlIO *
4252PerlIO_open(const char *path, const char *mode)
4253{
4254 dTHX;
4255 SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
4256 return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name);
4257}
4258
4259#undef Perlio_reopen
4260PerlIO *
4261PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
4262{
4263 dTHX;
4264 SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
4265 return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name);
4266}
4267
9e353e3b 4268#undef PerlIO_getc
6f9d8c32 4269int
9e353e3b 4270PerlIO_getc(PerlIO *f)
760ac839 4271{
e87a358a 4272 dTHX;
14a5cf38
JH
4273 STDCHAR buf[1];
4274 SSize_t count = PerlIO_read(f, buf, 1);
4275 if (count == 1) {
4276 return (unsigned char) buf[0];
4277 }
4278 return EOF;
313ca112
NIS
4279}
4280
4281#undef PerlIO_ungetc
4282int
4283PerlIO_ungetc(PerlIO *f, int ch)
4284{
e87a358a 4285 dTHX;
14a5cf38
JH
4286 if (ch != EOF) {
4287 STDCHAR buf = ch;
4288 if (PerlIO_unread(f, &buf, 1) == 1)
4289 return ch;
4290 }
4291 return EOF;
760ac839
LW
4292}
4293
9e353e3b
NIS
4294#undef PerlIO_putc
4295int
4296PerlIO_putc(PerlIO *f, int ch)
760ac839 4297{
e87a358a 4298 dTHX;
14a5cf38
JH
4299 STDCHAR buf = ch;
4300 return PerlIO_write(f, &buf, 1);
760ac839
LW
4301}
4302
9e353e3b 4303#undef PerlIO_puts
760ac839 4304int
9e353e3b 4305PerlIO_puts(PerlIO *f, const char *s)
760ac839 4306{
e87a358a 4307 dTHX;
14a5cf38
JH
4308 STRLEN len = strlen(s);
4309 return PerlIO_write(f, s, len);
760ac839
LW
4310}
4311
4312#undef PerlIO_rewind
4313void
c78749f2 4314PerlIO_rewind(PerlIO *f)
760ac839 4315{
e87a358a 4316 dTHX;
14a5cf38
JH
4317 PerlIO_seek(f, (Off_t) 0, SEEK_SET);
4318 PerlIO_clearerr(f);
6f9d8c32
NIS
4319}
4320
4321#undef PerlIO_vprintf
4322int
4323PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
4324{
14a5cf38
JH
4325 dTHX;
4326 SV *sv = newSVpvn("", 0);
4327 char *s;
4328 STRLEN len;
4329 SSize_t wrote;
2cc61e15 4330#ifdef NEED_VA_COPY
14a5cf38
JH
4331 va_list apc;
4332 Perl_va_copy(ap, apc);
4333 sv_vcatpvf(sv, fmt, &apc);
2cc61e15 4334#else
14a5cf38 4335 sv_vcatpvf(sv, fmt, &ap);
2cc61e15 4336#endif
14a5cf38
JH
4337 s = SvPV(sv, len);
4338 wrote = PerlIO_write(f, s, len);
4339 SvREFCNT_dec(sv);
4340 return wrote;
760ac839
LW
4341}
4342
4343#undef PerlIO_printf
6f9d8c32 4344int
14a5cf38 4345PerlIO_printf(PerlIO *f, const char *fmt, ...)
760ac839 4346{
14a5cf38
JH
4347 va_list ap;
4348 int result;
4349 va_start(ap, fmt);
4350 result = PerlIO_vprintf(f, fmt, ap);
4351 va_end(ap);
4352 return result;
760ac839
LW
4353}
4354
4355#undef PerlIO_stdoutf
6f9d8c32 4356int
14a5cf38 4357PerlIO_stdoutf(const char *fmt, ...)
760ac839 4358{
e87a358a 4359 dTHX;
14a5cf38
JH
4360 va_list ap;
4361 int result;
4362 va_start(ap, fmt);
4363 result = PerlIO_vprintf(PerlIO_stdout(), fmt, ap);
4364 va_end(ap);
4365 return result;
760ac839
LW
4366}
4367
4368#undef PerlIO_tmpfile
4369PerlIO *
c78749f2 4370PerlIO_tmpfile(void)
760ac839 4371{
14a5cf38 4372 /*
71200d45 4373 * I have no idea how portable mkstemp() is ...
14a5cf38 4374 */
83b075c3 4375#if defined(WIN32) || !defined(HAVE_MKSTEMP)
14a5cf38
JH
4376 dTHX;
4377 PerlIO *f = NULL;
4378 FILE *stdio = PerlSIO_tmpfile();
4379 if (stdio) {
4380 PerlIOStdio *s =
4381 PerlIOSelf(PerlIO_push
4382 (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
4383 "w+", Nullsv), PerlIOStdio);
4384 s->stdio = stdio;
4385 }
4386 return f;
83b075c3 4387#else
14a5cf38
JH
4388 dTHX;
4389 SV *sv = newSVpv("/tmp/PerlIO_XXXXXX", 0);
4390 int fd = mkstemp(SvPVX(sv));
4391 PerlIO *f = NULL;
4392 if (fd >= 0) {
4393 f = PerlIO_fdopen(fd, "w+");
4394 if (f) {
4395 PerlIOBase(f)->flags |= PERLIO_F_TEMP;
4396 }
4397 PerlLIO_unlink(SvPVX(sv));
4398 SvREFCNT_dec(sv);
4399 }
4400 return f;
83b075c3 4401#endif
760ac839
LW
4402}
4403
6f9d8c32
NIS
4404#undef HAS_FSETPOS
4405#undef HAS_FGETPOS
4406
22569500
NIS
4407#endif /* USE_SFIO */
4408#endif /* PERLIO_IS_STDIO */
760ac839 4409
9e353e3b 4410/*======================================================================================*/
14a5cf38 4411/*
71200d45
NIS
4412 * Now some functions in terms of above which may be needed even if we are
4413 * not in true PerlIO mode
9e353e3b
NIS
4414 */
4415
760ac839
LW
4416#ifndef HAS_FSETPOS
4417#undef PerlIO_setpos
4418int
766a733e 4419PerlIO_setpos(PerlIO *f, SV *pos)
760ac839 4420{
14a5cf38
JH
4421 dTHX;
4422 if (SvOK(pos)) {
4423 STRLEN len;
4424 Off_t *posn = (Off_t *) SvPV(pos, len);
4425 if (f && len == sizeof(Off_t))
4426 return PerlIO_seek(f, *posn, SEEK_SET);
4427 }
4428 SETERRNO(EINVAL, SS$_IVCHAN);
4429 return -1;
760ac839 4430}
c411622e 4431#else
c411622e 4432#undef PerlIO_setpos
4433int
766a733e 4434PerlIO_setpos(PerlIO *f, SV *pos)
c411622e 4435{
14a5cf38
JH
4436 dTHX;
4437 if (SvOK(pos)) {
4438 STRLEN len;
4439 Fpos_t *fpos = (Fpos_t *) SvPV(pos, len);
4440 if (f && len == sizeof(Fpos_t)) {
2d4389e4 4441#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 4442 return fsetpos64(f, fpos);
d9b3e12d 4443#else
14a5cf38 4444 return fsetpos(f, fpos);
d9b3e12d 4445#endif
14a5cf38 4446 }
766a733e 4447 }
14a5cf38
JH
4448 SETERRNO(EINVAL, SS$_IVCHAN);
4449 return -1;
c411622e 4450}
4451#endif
760ac839
LW
4452
4453#ifndef HAS_FGETPOS
4454#undef PerlIO_getpos
4455int
766a733e 4456PerlIO_getpos(PerlIO *f, SV *pos)
760ac839 4457{
14a5cf38
JH
4458 dTHX;
4459 Off_t posn = PerlIO_tell(f);
4460 sv_setpvn(pos, (char *) &posn, sizeof(posn));
4461 return (posn == (Off_t) - 1) ? -1 : 0;
760ac839 4462}
c411622e 4463#else
c411622e 4464#undef PerlIO_getpos
4465int
766a733e 4466PerlIO_getpos(PerlIO *f, SV *pos)
c411622e 4467{
14a5cf38
JH
4468 dTHX;
4469 Fpos_t fpos;
4470 int code;
2d4389e4 4471#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 4472 code = fgetpos64(f, &fpos);
d9b3e12d 4473#else
14a5cf38 4474 code = fgetpos(f, &fpos);
d9b3e12d 4475#endif
14a5cf38
JH
4476 sv_setpvn(pos, (char *) &fpos, sizeof(fpos));
4477 return code;
c411622e 4478}
4479#endif
760ac839
LW
4480
4481#if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
4482
4483int
c78749f2 4484vprintf(char *pat, char *args)
662a7e3f
CS
4485{
4486 _doprnt(pat, args, stdout);
22569500 4487 return 0; /* wrong, but perl doesn't use the return
14a5cf38 4488 * value */
662a7e3f
CS
4489}
4490
4491int
c78749f2 4492vfprintf(FILE *fd, char *pat, char *args)
760ac839
LW
4493{
4494 _doprnt(pat, args, fd);
22569500 4495 return 0; /* wrong, but perl doesn't use the return
14a5cf38 4496 * value */
760ac839
LW
4497}
4498
4499#endif
4500
4501#ifndef PerlIO_vsprintf
6f9d8c32 4502int
8ac85365 4503PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
760ac839 4504{
14a5cf38
JH
4505 int val = vsprintf(s, fmt, ap);
4506 if (n >= 0) {
4507 if (strlen(s) >= (STRLEN) n) {
4508 dTHX;
4509 (void) PerlIO_puts(Perl_error_log,
4510 "panic: sprintf overflow - memory corrupted!\n");
4511 my_exit(1);
4512 }
760ac839 4513 }
14a5cf38 4514 return val;
760ac839
LW
4515}
4516#endif
4517
4518#ifndef PerlIO_sprintf
6f9d8c32 4519int
14a5cf38 4520PerlIO_sprintf(char *s, int n, const char *fmt, ...)
760ac839 4521{
14a5cf38
JH
4522 va_list ap;
4523 int result;
4524 va_start(ap, fmt);
4525 result = PerlIO_vsprintf(s, n, fmt, ap);
4526 va_end(ap);
4527 return result;
760ac839
LW
4528}
4529#endif
7fcdafbd 4530
93a8090d
NIS
4531
4532
4533
4534