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.
2449 */
2450 int fd = PerlLIO_dup(fileno(stdio));
2451 char *mode = "r+";
2452 FILE *f2 = fdopen(fd, mode);
2453 PerlIOStdio *s;
2454 if (!f2 && errno == EINVAL) {
2455 mode = "w";
2456 f2 = fdopen(fd, mode);
2457 }
2458 if (!f2 && errno == EINVAL) {
2459 mode = "r";
2460 f2 = fdopen(fd, mode);
2461 }
2462 if (!f2) {
2463 /* Don't seem to be able to open */
2464 return f;
2465 }
2466 fclose(f2);
2467 s = PerlIOSelf(PerlIO_push
2468 (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
2469 mode, Nullsv), PerlIOStdio);
14a5cf38
JH
2470 s->stdio = stdio;
2471 }
2472 return f;
9e353e3b
NIS
2473}
2474
2475PerlIO *
14a5cf38
JH
2476PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2477 IV n, const char *mode, int fd, int imode,
2478 int perm, PerlIO *f, int narg, SV **args)
2479{
2480 char tmode[8];
d9dac8cd 2481 if (PerlIOValid(f)) {
14a5cf38
JH
2482 char *path = SvPV_nolen(*args);
2483 PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
1751d015
NIS
2484 FILE *stdio;
2485 PerlIOUnix_refcnt_dec(fileno(s->stdio));
2486 stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
14a5cf38
JH
2487 s->stdio);
2488 if (!s->stdio)
2489 return NULL;
2490 s->stdio = stdio;
1751d015 2491 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2492 return f;
2493 }
2494 else {
2495 if (narg > 0) {
2496 char *path = SvPV_nolen(*args);
2497 if (*mode == '#') {
2498 mode++;
2499 fd = PerlLIO_open3(path, imode, perm);
2500 }
2501 else {
2502 FILE *stdio = PerlSIO_fopen(path, mode);
2503 if (stdio) {
d9dac8cd
NIS
2504 PerlIOStdio *s;
2505 if (!f) {
2506 f = PerlIO_allocate(aTHX);
2507 }
2508 s = PerlIOSelf(PerlIO_push(aTHX_ f, self,
14a5cf38
JH
2509 (mode = PerlIOStdio_mode(mode, tmode)),
2510 PerlIOArg),
2511 PerlIOStdio);
2512 s->stdio = stdio;
1751d015 2513 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2514 }
2515 return f;
2516 }
2517 }
2518 if (fd >= 0) {
2519 FILE *stdio = NULL;
2520 int init = 0;
2521 if (*mode == 'I') {
2522 init = 1;
2523 mode++;
2524 }
2525 if (init) {
2526 switch (fd) {
2527 case 0:
2528 stdio = PerlSIO_stdin;
2529 break;
2530 case 1:
2531 stdio = PerlSIO_stdout;
2532 break;
2533 case 2:
2534 stdio = PerlSIO_stderr;
2535 break;
2536 }
2537 }
2538 else {
2539 stdio = PerlSIO_fdopen(fd, mode =
2540 PerlIOStdio_mode(mode, tmode));
2541 }
2542 if (stdio) {
d9dac8cd
NIS
2543 PerlIOStdio *s;
2544 if (!f) {
2545 f = PerlIO_allocate(aTHX);
2546 }
2547 s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg), PerlIOStdio);
14a5cf38 2548 s->stdio = stdio;
1751d015 2549 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2550 return f;
2551 }
2552 }
2553 }
ee518936 2554 return NULL;
9e353e3b
NIS
2555}
2556
1751d015 2557PerlIO *
ecdeb87c 2558PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
1751d015
NIS
2559{
2560 /* This assumes no layers underneath - which is what
2561 happens, but is not how I remember it. NI-S 2001/10/16
2562 */
ecdeb87c 2563 if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
694c95cf 2564 FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio;
ecdeb87c
NIS
2565 if (flags & PERLIO_DUP_FD) {
2566 int fd = PerlLIO_dup(fileno(stdio));
2567 if (fd >= 0) {
2568 char mode[8];
293ed4d2 2569 stdio = fdopen(fd, PerlIO_modestr(o,mode));
ecdeb87c
NIS
2570 }
2571 else {
2572 /* FIXME: To avoid messy error recovery if dup fails
2573 re-use the existing stdio as though flag was not set
2574 */
2575 }
2576 }
694c95cf
JH
2577 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
2578 PerlIOUnix_refcnt_inc(fileno(stdio));
1751d015
NIS
2579 }
2580 return f;
2581}
2582
2583IV
f62ce20a 2584PerlIOStdio_close(pTHX_ PerlIO *f)
1751d015 2585{
1751d015
NIS
2586#ifdef SOCKS5_VERSION_NAME
2587 int optval;
2588 Sock_size_t optlen = sizeof(int);
2589#endif
2590 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2591 if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) {
694c95cf 2592 /* Do not close it but do flush any buffers */
22569500 2593 return PerlIO_flush(f);
1751d015
NIS
2594 }
2595 return (
2596#ifdef SOCKS5_VERSION_NAME
2597 (getsockopt
2598 (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
2599 &optlen) <
2600 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
2601#else
2602 PerlSIO_fclose(stdio)
2603#endif
2604 );
2605
2606}
2607
2608
2609
9e353e3b 2610SSize_t
f62ce20a 2611PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
9e353e3b 2612{
14a5cf38
JH
2613 FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2614 SSize_t got = 0;
2615 if (count == 1) {
2616 STDCHAR *buf = (STDCHAR *) vbuf;
2617 /*
2618 * Perl is expecting PerlIO_getc() to fill the buffer Linux's
71200d45 2619 * stdio does not do that for fread()
14a5cf38
JH
2620 */
2621 int ch = PerlSIO_fgetc(s);
2622 if (ch != EOF) {
2623 *buf = ch;
2624 got = 1;
2625 }
2626 }
2627 else
2628 got = PerlSIO_fread(vbuf, 1, count, s);
2629 return got;
9e353e3b
NIS
2630}
2631
2632SSize_t
f62ce20a 2633PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2634{
14a5cf38
JH
2635 FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2636 STDCHAR *buf = ((STDCHAR *) vbuf) + count - 1;
2637 SSize_t unread = 0;
2638 while (count > 0) {
2639 int ch = *buf-- & 0xff;
2640 if (PerlSIO_ungetc(ch, s) != ch)
2641 break;
2642 unread++;
2643 count--;
2644 }
2645 return unread;
9e353e3b
NIS
2646}
2647
2648SSize_t
f62ce20a 2649PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2650{
14a5cf38
JH
2651 return PerlSIO_fwrite(vbuf, 1, count,
2652 PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2653}
2654
2655IV
f62ce20a 2656PerlIOStdio_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 2657{
14a5cf38
JH
2658 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2659 return PerlSIO_fseek(stdio, offset, whence);
9e353e3b
NIS
2660}
2661
2662Off_t
f62ce20a 2663PerlIOStdio_tell(pTHX_ PerlIO *f)
9e353e3b 2664{
14a5cf38
JH
2665 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2666 return PerlSIO_ftell(stdio);
9e353e3b
NIS
2667}
2668
2669IV
f62ce20a 2670PerlIOStdio_flush(pTHX_ PerlIO *f)
9e353e3b 2671{
14a5cf38
JH
2672 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2673 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
2674 return PerlSIO_fflush(stdio);
2675 }
2676 else {
88b61e10 2677#if 0
14a5cf38
JH
2678 /*
2679 * FIXME: This discards ungetc() and pre-read stuff which is not
71200d45 2680 * right if this is just a "sync" from a layer above Suspect right
14a5cf38 2681 * design is to do _this_ but not have layer above flush this
71200d45 2682 * layer read-to-read
14a5cf38
JH
2683 */
2684 /*
71200d45 2685 * Not writeable - sync by attempting a seek
14a5cf38
JH
2686 */
2687 int err = errno;
2688 if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0)
2689 errno = err;
88b61e10 2690#endif
14a5cf38
JH
2691 }
2692 return 0;
9e353e3b
NIS
2693}
2694
2695IV
f62ce20a 2696PerlIOStdio_fill(pTHX_ PerlIO *f)
06da4f11 2697{
14a5cf38
JH
2698 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2699 int c;
2700 /*
71200d45 2701 * fflush()ing read-only streams can cause trouble on some stdio-s
14a5cf38
JH
2702 */
2703 if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
2704 if (PerlSIO_fflush(stdio) != 0)
2705 return EOF;
2706 }
2707 c = PerlSIO_fgetc(stdio);
2708 if (c == EOF || PerlSIO_ungetc(c, stdio) != c)
2709 return EOF;
2710 return 0;
06da4f11
NIS
2711}
2712
2713IV
f62ce20a 2714PerlIOStdio_eof(pTHX_ PerlIO *f)
9e353e3b 2715{
14a5cf38 2716 return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2717}
2718
2719IV
f62ce20a 2720PerlIOStdio_error(pTHX_ PerlIO *f)
9e353e3b 2721{
14a5cf38 2722 return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2723}
2724
2725void
f62ce20a 2726PerlIOStdio_clearerr(pTHX_ PerlIO *f)
9e353e3b 2727{
14a5cf38 2728 PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
2729}
2730
2731void
f62ce20a 2732PerlIOStdio_setlinebuf(pTHX_ PerlIO *f)
9e353e3b
NIS
2733{
2734#ifdef HAS_SETLINEBUF
14a5cf38 2735 PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b 2736#else
14a5cf38 2737 PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
9e353e3b
NIS
2738#endif
2739}
2740
2741#ifdef FILE_base
2742STDCHAR *
f62ce20a 2743PerlIOStdio_get_base(pTHX_ PerlIO *f)
9e353e3b 2744{
14a5cf38 2745 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 2746 return (STDCHAR*)PerlSIO_get_base(stdio);
9e353e3b
NIS
2747}
2748
2749Size_t
f62ce20a 2750PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f)
9e353e3b 2751{
14a5cf38
JH
2752 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2753 return PerlSIO_get_bufsiz(stdio);
9e353e3b
NIS
2754}
2755#endif
2756
2757#ifdef USE_STDIO_PTR
2758STDCHAR *
f62ce20a 2759PerlIOStdio_get_ptr(pTHX_ PerlIO *f)
9e353e3b 2760{
14a5cf38 2761 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 2762 return (STDCHAR*)PerlSIO_get_ptr(stdio);
9e353e3b
NIS
2763}
2764
2765SSize_t
f62ce20a 2766PerlIOStdio_get_cnt(pTHX_ PerlIO *f)
9e353e3b 2767{
14a5cf38
JH
2768 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2769 return PerlSIO_get_cnt(stdio);
9e353e3b
NIS
2770}
2771
2772void
f62ce20a 2773PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 2774{
14a5cf38 2775 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 2776 if (ptr != NULL) {
9e353e3b 2777#ifdef STDIO_PTR_LVALUE
22569500 2778 PerlSIO_set_ptr(stdio, (void*)ptr); /* LHS STDCHAR* cast non-portable */
9e353e3b 2779#ifdef STDIO_PTR_LVAL_SETS_CNT
14a5cf38 2780 if (PerlSIO_get_cnt(stdio) != (cnt)) {
14a5cf38
JH
2781 assert(PerlSIO_get_cnt(stdio) == (cnt));
2782 }
9e353e3b
NIS
2783#endif
2784#if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
14a5cf38 2785 /*
71200d45 2786 * Setting ptr _does_ change cnt - we are done
14a5cf38
JH
2787 */
2788 return;
9e353e3b 2789#endif
22569500 2790#else /* STDIO_PTR_LVALUE */
14a5cf38 2791 PerlProc_abort();
22569500 2792#endif /* STDIO_PTR_LVALUE */
14a5cf38
JH
2793 }
2794 /*
71200d45 2795 * Now (or only) set cnt
14a5cf38 2796 */
9e353e3b 2797#ifdef STDIO_CNT_LVALUE
14a5cf38 2798 PerlSIO_set_cnt(stdio, cnt);
22569500 2799#else /* STDIO_CNT_LVALUE */
9e353e3b 2800#if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
14a5cf38
JH
2801 PerlSIO_set_ptr(stdio,
2802 PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) -
2803 cnt));
22569500 2804#else /* STDIO_PTR_LVAL_SETS_CNT */
14a5cf38 2805 PerlProc_abort();
22569500
NIS
2806#endif /* STDIO_PTR_LVAL_SETS_CNT */
2807#endif /* STDIO_CNT_LVALUE */
9e353e3b
NIS
2808}
2809
2810#endif
2811
2812PerlIO_funcs PerlIO_stdio = {
14a5cf38
JH
2813 "stdio",
2814 sizeof(PerlIOStdio),
2815 PERLIO_K_BUFFERED,
2816 PerlIOBase_pushed,
44798d05 2817 PerlIOBase_popped,
14a5cf38
JH
2818 PerlIOStdio_open,
2819 NULL,
2820 PerlIOStdio_fileno,
71200d45 2821 PerlIOStdio_dup,
14a5cf38
JH
2822 PerlIOStdio_read,
2823 PerlIOStdio_unread,
2824 PerlIOStdio_write,
2825 PerlIOStdio_seek,
2826 PerlIOStdio_tell,
2827 PerlIOStdio_close,
2828 PerlIOStdio_flush,
2829 PerlIOStdio_fill,
2830 PerlIOStdio_eof,
2831 PerlIOStdio_error,
2832 PerlIOStdio_clearerr,
2833 PerlIOStdio_setlinebuf,
9e353e3b 2834#ifdef FILE_base
14a5cf38
JH
2835 PerlIOStdio_get_base,
2836 PerlIOStdio_get_bufsiz,
9e353e3b 2837#else
14a5cf38
JH
2838 NULL,
2839 NULL,
9e353e3b
NIS
2840#endif
2841#ifdef USE_STDIO_PTR
14a5cf38
JH
2842 PerlIOStdio_get_ptr,
2843 PerlIOStdio_get_cnt,
0eb1d8a4 2844#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
14a5cf38 2845 PerlIOStdio_set_ptrcnt
22569500 2846#else /* STDIO_PTR_LVALUE */
14a5cf38 2847 NULL
22569500
NIS
2848#endif /* STDIO_PTR_LVALUE */
2849#else /* USE_STDIO_PTR */
14a5cf38
JH
2850 NULL,
2851 NULL,
2852 NULL
22569500 2853#endif /* USE_STDIO_PTR */
9e353e3b
NIS
2854};
2855
9e353e3b
NIS
2856FILE *
2857PerlIO_exportFILE(PerlIO *f, int fl)
2858{
e87a358a 2859 dTHX;
14a5cf38 2860 FILE *stdio;
8dcb5783 2861 char buf[8];
14a5cf38 2862 PerlIO_flush(f);
8dcb5783 2863 stdio = fdopen(PerlIO_fileno(f), PerlIO_modestr(f,buf));
14a5cf38 2864 if (stdio) {
14a5cf38 2865 PerlIOStdio *s =
8dcb5783 2866 PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv),
14a5cf38
JH
2867 PerlIOStdio);
2868 s->stdio = stdio;
2869 }
2870 return stdio;
9e353e3b
NIS
2871}
2872
9e353e3b
NIS
2873FILE *
2874PerlIO_findFILE(PerlIO *f)
2875{
14a5cf38
JH
2876 PerlIOl *l = *f;
2877 while (l) {
2878 if (l->tab == &PerlIO_stdio) {
2879 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
2880 return s->stdio;
2881 }
2882 l = *PerlIONext(&l);
f7e7eb72 2883 }
14a5cf38 2884 return PerlIO_exportFILE(f, 0);
9e353e3b
NIS
2885}
2886
9e353e3b
NIS
2887void
2888PerlIO_releaseFILE(PerlIO *p, FILE *f)
2889{
22569500
NIS
2890 PerlIOl *l;
2891 while ((l = *p)) {
2892 if (l->tab == &PerlIO_stdio) {
2893 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
2894 if (s->stdio == f) {
2895 dTHX;
2896 PerlIO_pop(aTHX_ p);
2897 return;
2898 }
2899 }
2900 p = PerlIONext(p);
2901 }
2902 return;
9e353e3b
NIS
2903}
2904
2905/*--------------------------------------------------------------------------------------*/
14a5cf38 2906/*
71200d45 2907 * perlio buffer layer
14a5cf38 2908 */
9e353e3b 2909
5e2ab84b 2910IV
f62ce20a 2911PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
5e2ab84b 2912{
14a5cf38
JH
2913 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2914 int fd = PerlIO_fileno(f);
2915 Off_t posn;
2916 if (fd >= 0 && PerlLIO_isatty(fd)) {
2917 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
2918 }
2919 posn = PerlIO_tell(PerlIONext(f));
2920 if (posn != (Off_t) - 1) {
2921 b->posn = posn;
2922 }
f62ce20a 2923 return PerlIOBase_pushed(aTHX_ f, mode, arg);
5e2ab84b
NIS
2924}
2925
9e353e3b 2926PerlIO *
14a5cf38
JH
2927PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2928 IV n, const char *mode, int fd, int imode, int perm,
2929 PerlIO *f, int narg, SV **args)
2930{
04892f78 2931 if (PerlIOValid(f)) {
14a5cf38 2932 PerlIO *next = PerlIONext(f);
04892f78
NIS
2933 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
2934 next = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
14a5cf38 2935 next, narg, args);
04892f78 2936 if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg) != 0) {
14a5cf38
JH
2937 return NULL;
2938 }
2939 }
2940 else {
04892f78 2941 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm());
14a5cf38
JH
2942 int init = 0;
2943 if (*mode == 'I') {
2944 init = 1;
2945 /*
71200d45 2946 * mode++;
14a5cf38
JH
2947 */
2948 }
2949 f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
d9dac8cd 2950 f, narg, args);
14a5cf38 2951 if (f) {
22569500 2952 if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) {
b26b1ab5
NC
2953 /*
2954 * if push fails during open, open fails. close will pop us.
2955 */
2956 PerlIO_close (f);
2957 return NULL;
2958 } else {
2959 fd = PerlIO_fileno(f);
b26b1ab5
NC
2960 if (init && fd == 2) {
2961 /*
2962 * Initial stderr is unbuffered
2963 */
2964 PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
2965 }
23b84778
IZ
2966#ifdef PERLIO_USING_CRLF
2967# ifdef PERLIO_IS_BINMODE_FD
2968 if (PERLIO_IS_BINMODE_FD(fd))
2969 PerlIO_binmode(f, '<'/*not used*/, O_BINARY, Nullch);
2970 else
2971# endif
2972 /*
2973 * do something about failing setmode()? --jhi
2974 */
2975 PerlLIO_setmode(fd, O_BINARY);
2976#endif
14a5cf38
JH
2977 }
2978 }
ee518936 2979 }
14a5cf38 2980 return f;
9e353e3b
NIS
2981}
2982
14a5cf38
JH
2983/*
2984 * This "flush" is akin to sfio's sync in that it handles files in either
71200d45 2985 * read or write state
14a5cf38 2986 */
9e353e3b 2987IV
f62ce20a 2988PerlIOBuf_flush(pTHX_ PerlIO *f)
6f9d8c32 2989{
14a5cf38
JH
2990 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2991 int code = 0;
04892f78 2992 PerlIO *n = PerlIONext(f);
14a5cf38
JH
2993 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
2994 /*
71200d45 2995 * write() the buffer
14a5cf38
JH
2996 */
2997 STDCHAR *buf = b->buf;
2998 STDCHAR *p = buf;
14a5cf38
JH
2999 while (p < b->ptr) {
3000 SSize_t count = PerlIO_write(n, p, b->ptr - p);
3001 if (count > 0) {
3002 p += count;
3003 }
3004 else if (count < 0 || PerlIO_error(n)) {
3005 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3006 code = -1;
3007 break;
3008 }
3009 }
3010 b->posn += (p - buf);
3011 }
3012 else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3013 STDCHAR *buf = PerlIO_get_base(f);
3014 /*
71200d45 3015 * Note position change
14a5cf38
JH
3016 */
3017 b->posn += (b->ptr - buf);
3018 if (b->ptr < b->end) {
3019 /*
71200d45 3020 * We did not consume all of it
14a5cf38 3021 */
04892f78
NIS
3022 if (PerlIO_seek(n, b->posn, SEEK_SET) == 0) {
3023 /* Reload n as some layers may pop themselves on seek */
3024 b->posn = PerlIO_tell(n = PerlIONext(f));
14a5cf38
JH
3025 }
3026 }
3027 }
3028 b->ptr = b->end = b->buf;
3029 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
04892f78
NIS
3030 /* We check for Valid because of dubious decision to make PerlIO_flush(NULL) flush all */
3031 /* FIXME: Doing downstream flush may be sub-optimal see PerlIOBuf_fill() below */
3032 if (PerlIOValid(n) && PerlIO_flush(n) != 0)
14a5cf38
JH
3033 code = -1;
3034 return code;
6f9d8c32
NIS
3035}
3036
06da4f11 3037IV
f62ce20a 3038PerlIOBuf_fill(pTHX_ PerlIO *f)
06da4f11 3039{
14a5cf38
JH
3040 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3041 PerlIO *n = PerlIONext(f);
3042 SSize_t avail;
3043 /*
04892f78
NIS
3044 * FIXME: doing the down-stream flush maybe sub-optimal if it causes
3045 * pre-read data in stdio buffer to be discarded.
3046 * However, skipping the flush also skips _our_ hosekeeping
3047 * and breaks tell tests. So we do the flush.
14a5cf38
JH
3048 */
3049 if (PerlIO_flush(f) != 0)
3050 return -1;
3051 if (PerlIOBase(f)->flags & PERLIO_F_TTY)
f62ce20a 3052 PerlIOBase_flush_linebuf(aTHX);
14a5cf38
JH
3053
3054 if (!b->buf)
22569500 3055 PerlIO_get_base(f); /* allocate via vtable */
14a5cf38
JH
3056
3057 b->ptr = b->end = b->buf;
3058 if (PerlIO_fast_gets(n)) {
3059 /*
04892f78 3060 * Layer below is also buffered. We do _NOT_ want to call its
14a5cf38
JH
3061 * ->Read() because that will loop till it gets what we asked for
3062 * which may hang on a pipe etc. Instead take anything it has to
71200d45 3063 * hand, or ask it to fill _once_.
14a5cf38
JH
3064 */
3065 avail = PerlIO_get_cnt(n);
3066 if (avail <= 0) {
3067 avail = PerlIO_fill(n);
3068 if (avail == 0)
3069 avail = PerlIO_get_cnt(n);
3070 else {
3071 if (!PerlIO_error(n) && PerlIO_eof(n))
3072 avail = 0;
3073 }
3074 }
3075 if (avail > 0) {
3076 STDCHAR *ptr = PerlIO_get_ptr(n);
3077 SSize_t cnt = avail;
eb160463 3078 if (avail > (SSize_t)b->bufsiz)
14a5cf38
JH
3079 avail = b->bufsiz;
3080 Copy(ptr, b->buf, avail, STDCHAR);
3081 PerlIO_set_ptrcnt(n, ptr + avail, cnt - avail);
3082 }
3083 }
3084 else {
3085 avail = PerlIO_read(n, b->ptr, b->bufsiz);
3086 }
3087 if (avail <= 0) {
3088 if (avail == 0)
3089 PerlIOBase(f)->flags |= PERLIO_F_EOF;
3090 else
3091 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3092 return -1;
3093 }
3094 b->end = b->buf + avail;
3095 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3096 return 0;
06da4f11
NIS
3097}
3098
6f9d8c32 3099SSize_t
f62ce20a 3100PerlIOBuf_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 3101{
14a5cf38 3102 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
04892f78 3103 if (PerlIOValid(f)) {
14a5cf38
JH
3104 if (!b->ptr)
3105 PerlIO_get_base(f);
f62ce20a 3106 return PerlIOBase_read(aTHX_ f, vbuf, count);
14a5cf38
JH
3107 }
3108 return 0;
6f9d8c32
NIS
3109}
3110
9e353e3b 3111SSize_t
f62ce20a 3112PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3113{
14a5cf38
JH
3114 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
3115 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3116 SSize_t unread = 0;
3117 SSize_t avail;
3118 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3119 PerlIO_flush(f);
3120 if (!b->buf)
3121 PerlIO_get_base(f);
3122 if (b->buf) {
3123 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3124 /*
3125 * Buffer is already a read buffer, we can overwrite any chars
71200d45 3126 * which have been read back to buffer start
14a5cf38
JH
3127 */
3128 avail = (b->ptr - b->buf);
3129 }
3130 else {
3131 /*
3132 * Buffer is idle, set it up so whole buffer is available for
71200d45 3133 * unread
14a5cf38
JH
3134 */
3135 avail = b->bufsiz;
3136 b->end = b->buf + avail;
3137 b->ptr = b->end;
3138 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3139 /*
71200d45 3140 * Buffer extends _back_ from where we are now
14a5cf38
JH
3141 */
3142 b->posn -= b->bufsiz;
3143 }
3144 if (avail > (SSize_t) count) {
3145 /*
71200d45 3146 * If we have space for more than count, just move count
14a5cf38
JH
3147 */
3148 avail = count;
3149 }
3150 if (avail > 0) {
3151 b->ptr -= avail;
3152 buf -= avail;
3153 /*
3154 * In simple stdio-like ungetc() case chars will be already
71200d45 3155 * there
14a5cf38
JH
3156 */
3157 if (buf != b->ptr) {
3158 Copy(buf, b->ptr, avail, STDCHAR);
3159 }
3160 count -= avail;
3161 unread += avail;
3162 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3163 }
3164 }
3165 return unread;
760ac839
LW
3166}
3167
9e353e3b 3168SSize_t
f62ce20a 3169PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3170{
14a5cf38
JH
3171 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3172 const STDCHAR *buf = (const STDCHAR *) vbuf;
3173 Size_t written = 0;
3174 if (!b->buf)
3175 PerlIO_get_base(f);
3176 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3177 return 0;
3178 while (count > 0) {
3179 SSize_t avail = b->bufsiz - (b->ptr - b->buf);
3180 if ((SSize_t) count < avail)
3181 avail = count;
3182 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
3183 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3184 while (avail > 0) {
3185 int ch = *buf++;
3186 *(b->ptr)++ = ch;
3187 count--;
3188 avail--;
3189 written++;
3190 if (ch == '\n') {
3191 PerlIO_flush(f);
3192 break;
3193 }
3194 }
3195 }
3196 else {
3197 if (avail) {
3198 Copy(buf, b->ptr, avail, STDCHAR);
3199 count -= avail;
3200 buf += avail;
3201 written += avail;
3202 b->ptr += avail;
3203 }
3204 }
3205 if (b->ptr >= (b->buf + b->bufsiz))
3206 PerlIO_flush(f);
3207 }
3208 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3209 PerlIO_flush(f);
3210 return written;
9e353e3b
NIS
3211}
3212
3213IV
f62ce20a 3214PerlIOBuf_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 3215{
14a5cf38
JH
3216 IV code;
3217 if ((code = PerlIO_flush(f)) == 0) {
3218 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3219 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3220 code = PerlIO_seek(PerlIONext(f), offset, whence);
3221 if (code == 0) {
3222 b->posn = PerlIO_tell(PerlIONext(f));
3223 }
9e353e3b 3224 }
14a5cf38 3225 return code;
9e353e3b
NIS
3226}
3227
3228Off_t
f62ce20a 3229PerlIOBuf_tell(pTHX_ PerlIO *f)
9e353e3b 3230{
14a5cf38
JH
3231 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3232 /*
71200d45 3233 * b->posn is file position where b->buf was read, or will be written
14a5cf38
JH
3234 */
3235 Off_t posn = b->posn;
3236 if (b->buf) {
3237 /*
71200d45 3238 * If buffer is valid adjust position by amount in buffer
14a5cf38
JH
3239 */
3240 posn += (b->ptr - b->buf);
3241 }
3242 return posn;
9e353e3b
NIS
3243}
3244
3245IV
44798d05
NIS
3246PerlIOBuf_popped(pTHX_ PerlIO *f)
3247{
3248 IV code = PerlIOBase_popped(aTHX_ f);
3249 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3250 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3251 Safefree(b->buf);
3252 }
3253 b->buf = NULL;
3254 b->ptr = b->end = b->buf;
3255 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3256 return code;
3257}
3258
3259IV
f62ce20a 3260PerlIOBuf_close(pTHX_ PerlIO *f)
9e353e3b 3261{
f62ce20a 3262 IV code = PerlIOBase_close(aTHX_ f);
14a5cf38
JH
3263 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3264 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 3265 Safefree(b->buf);
14a5cf38
JH
3266 }
3267 b->buf = NULL;
3268 b->ptr = b->end = b->buf;
3269 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3270 return code;
760ac839
LW
3271}
3272
9e353e3b 3273STDCHAR *
f62ce20a 3274PerlIOBuf_get_ptr(pTHX_ PerlIO *f)
9e353e3b 3275{
14a5cf38
JH
3276 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3277 if (!b->buf)
3278 PerlIO_get_base(f);
3279 return b->ptr;
9e353e3b
NIS
3280}
3281
05d1247b 3282SSize_t
f62ce20a 3283PerlIOBuf_get_cnt(pTHX_ PerlIO *f)
9e353e3b 3284{
14a5cf38
JH
3285 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3286 if (!b->buf)
3287 PerlIO_get_base(f);
3288 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
3289 return (b->end - b->ptr);
3290 return 0;
9e353e3b
NIS
3291}
3292
3293STDCHAR *
f62ce20a 3294PerlIOBuf_get_base(pTHX_ PerlIO *f)
9e353e3b 3295{
14a5cf38
JH
3296 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3297 if (!b->buf) {
3298 if (!b->bufsiz)
3299 b->bufsiz = 4096;
a1ea730d 3300 b->buf =
7fcdafbd 3301 Newz('B',b->buf,b->bufsiz, STDCHAR);
14a5cf38
JH
3302 if (!b->buf) {
3303 b->buf = (STDCHAR *) & b->oneword;
3304 b->bufsiz = sizeof(b->oneword);
3305 }
3306 b->ptr = b->buf;
3307 b->end = b->ptr;
06da4f11 3308 }
14a5cf38 3309 return b->buf;
9e353e3b
NIS
3310}
3311
3312Size_t
f62ce20a 3313PerlIOBuf_bufsiz(pTHX_ PerlIO *f)
9e353e3b 3314{
14a5cf38
JH
3315 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3316 if (!b->buf)
3317 PerlIO_get_base(f);
3318 return (b->end - b->buf);
9e353e3b
NIS
3319}
3320
3321void
f62ce20a 3322PerlIOBuf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 3323{
14a5cf38
JH
3324 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3325 if (!b->buf)
3326 PerlIO_get_base(f);
3327 b->ptr = ptr;
3328 if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf) {
14a5cf38
JH
3329 assert(PerlIO_get_cnt(f) == cnt);
3330 assert(b->ptr >= b->buf);
3331 }
3332 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
760ac839
LW
3333}
3334
71200d45 3335PerlIO *
ecdeb87c 3336PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 3337{
ecdeb87c 3338 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
3339}
3340
3341
3342
9e353e3b 3343PerlIO_funcs PerlIO_perlio = {
14a5cf38
JH
3344 "perlio",
3345 sizeof(PerlIOBuf),
3346 PERLIO_K_BUFFERED,
3347 PerlIOBuf_pushed,
44798d05 3348 PerlIOBuf_popped,
14a5cf38
JH
3349 PerlIOBuf_open,
3350 NULL,
3351 PerlIOBase_fileno,
71200d45 3352 PerlIOBuf_dup,
14a5cf38
JH
3353 PerlIOBuf_read,
3354 PerlIOBuf_unread,
3355 PerlIOBuf_write,
3356 PerlIOBuf_seek,
3357 PerlIOBuf_tell,
3358 PerlIOBuf_close,
3359 PerlIOBuf_flush,
3360 PerlIOBuf_fill,
3361 PerlIOBase_eof,
3362 PerlIOBase_error,
3363 PerlIOBase_clearerr,
3364 PerlIOBase_setlinebuf,
3365 PerlIOBuf_get_base,
3366 PerlIOBuf_bufsiz,
3367 PerlIOBuf_get_ptr,
3368 PerlIOBuf_get_cnt,
3369 PerlIOBuf_set_ptrcnt,
9e353e3b
NIS
3370};
3371
66ecd56b 3372/*--------------------------------------------------------------------------------------*/
14a5cf38 3373/*
71200d45 3374 * Temp layer to hold unread chars when cannot do it any other way
14a5cf38 3375 */
5e2ab84b
NIS
3376
3377IV
f62ce20a 3378PerlIOPending_fill(pTHX_ PerlIO *f)
5e2ab84b 3379{
14a5cf38 3380 /*
71200d45 3381 * Should never happen
14a5cf38
JH
3382 */
3383 PerlIO_flush(f);
3384 return 0;
5e2ab84b
NIS
3385}
3386
3387IV
f62ce20a 3388PerlIOPending_close(pTHX_ PerlIO *f)
5e2ab84b 3389{
14a5cf38 3390 /*
71200d45 3391 * A tad tricky - flush pops us, then we close new top
14a5cf38
JH
3392 */
3393 PerlIO_flush(f);
3394 return PerlIO_close(f);
5e2ab84b
NIS
3395}
3396
3397IV
f62ce20a 3398PerlIOPending_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
5e2ab84b 3399{
14a5cf38 3400 /*
71200d45 3401 * A tad tricky - flush pops us, then we seek new top
14a5cf38
JH
3402 */
3403 PerlIO_flush(f);
3404 return PerlIO_seek(f, offset, whence);
5e2ab84b
NIS
3405}
3406
3407
3408IV
f62ce20a 3409PerlIOPending_flush(pTHX_ PerlIO *f)
5e2ab84b 3410{
14a5cf38
JH
3411 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3412 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 3413 Safefree(b->buf);
14a5cf38
JH
3414 b->buf = NULL;
3415 }
3416 PerlIO_pop(aTHX_ f);
3417 return 0;
5e2ab84b
NIS
3418}
3419
3420void
f62ce20a 3421PerlIOPending_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
5e2ab84b 3422{
14a5cf38
JH
3423 if (cnt <= 0) {
3424 PerlIO_flush(f);
3425 }
3426 else {
f62ce20a 3427 PerlIOBuf_set_ptrcnt(aTHX_ f, ptr, cnt);
14a5cf38 3428 }
5e2ab84b
NIS
3429}
3430
3431IV
f62ce20a 3432PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
5e2ab84b 3433{
f62ce20a 3434 IV code = PerlIOBase_pushed(aTHX_ f, mode, arg);
14a5cf38
JH
3435 PerlIOl *l = PerlIOBase(f);
3436 /*
71200d45
NIS
3437 * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets()
3438 * etc. get muddled when it changes mid-string when we auto-pop.
14a5cf38
JH
3439 */
3440 l->flags = (l->flags & ~(PERLIO_F_FASTGETS | PERLIO_F_UTF8)) |
3441 (PerlIOBase(PerlIONext(f))->
3442 flags & (PERLIO_F_FASTGETS | PERLIO_F_UTF8));
3443 return code;
5e2ab84b
NIS
3444}
3445
3446SSize_t
f62ce20a 3447PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
5e2ab84b 3448{
14a5cf38
JH
3449 SSize_t avail = PerlIO_get_cnt(f);
3450 SSize_t got = 0;
eb160463 3451 if ((SSize_t)count < avail)
14a5cf38
JH
3452 avail = count;
3453 if (avail > 0)
f62ce20a 3454 got = PerlIOBuf_read(aTHX_ f, vbuf, avail);
eb160463 3455 if (got >= 0 && got < (SSize_t)count) {
14a5cf38
JH
3456 SSize_t more =
3457 PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got);
3458 if (more >= 0 || got == 0)
3459 got += more;
3460 }
3461 return got;
5e2ab84b
NIS
3462}
3463
5e2ab84b 3464PerlIO_funcs PerlIO_pending = {
14a5cf38
JH
3465 "pending",
3466 sizeof(PerlIOBuf),
3467 PERLIO_K_BUFFERED,
3468 PerlIOPending_pushed,
44798d05 3469 PerlIOBuf_popped,
14a5cf38
JH
3470 NULL,
3471 NULL,
3472 PerlIOBase_fileno,
71200d45 3473 PerlIOBuf_dup,
14a5cf38
JH
3474 PerlIOPending_read,
3475 PerlIOBuf_unread,
3476 PerlIOBuf_write,
3477 PerlIOPending_seek,
3478 PerlIOBuf_tell,
3479 PerlIOPending_close,
3480 PerlIOPending_flush,
3481 PerlIOPending_fill,
3482 PerlIOBase_eof,
3483 PerlIOBase_error,
3484 PerlIOBase_clearerr,
3485 PerlIOBase_setlinebuf,
3486 PerlIOBuf_get_base,
3487 PerlIOBuf_bufsiz,
3488 PerlIOBuf_get_ptr,
3489 PerlIOBuf_get_cnt,
3490 PerlIOPending_set_ptrcnt,
5e2ab84b
NIS
3491};
3492
3493
3494
3495/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
3496/*
3497 * crlf - translation On read translate CR,LF to "\n" we do this by
3498 * overriding ptr/cnt entries to hand back a line at a time and keeping a
71200d45 3499 * record of which nl we "lied" about. On write translate "\n" to CR,LF
66ecd56b
NIS
3500 */
3501
14a5cf38 3502typedef struct {
22569500
NIS
3503 PerlIOBuf base; /* PerlIOBuf stuff */
3504 STDCHAR *nl; /* Position of crlf we "lied" about in the
14a5cf38 3505 * buffer */
99efab12
NIS
3506} PerlIOCrlf;
3507
f5b9d040 3508IV
f62ce20a 3509PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg)
f5b9d040 3510{
14a5cf38
JH
3511 IV code;
3512 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
f62ce20a 3513 code = PerlIOBuf_pushed(aTHX_ f, mode, arg);
5e2ab84b 3514#if 0
14a5cf38
JH
3515 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n",
3516 f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)",
3517 PerlIOBase(f)->flags);
5e2ab84b 3518#endif
14a5cf38 3519 return code;
f5b9d040
NIS
3520}
3521
3522
99efab12 3523SSize_t
f62ce20a 3524PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 3525{
14a5cf38
JH
3526 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3527 if (c->nl) {
3528 *(c->nl) = 0xd;
3529 c->nl = NULL;
3530 }
3531 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 3532 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
14a5cf38
JH
3533 else {
3534 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
3535 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3536 SSize_t unread = 0;
3537 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3538 PerlIO_flush(f);
3539 if (!b->buf)
3540 PerlIO_get_base(f);
3541 if (b->buf) {
3542 if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3543 b->end = b->ptr = b->buf + b->bufsiz;
3544 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3545 b->posn -= b->bufsiz;
3546 }
3547 while (count > 0 && b->ptr > b->buf) {
3548 int ch = *--buf;
3549 if (ch == '\n') {
3550 if (b->ptr - 2 >= b->buf) {
3551 *--(b->ptr) = 0xa;
3552 *--(b->ptr) = 0xd;
3553 unread++;
3554 count--;
3555 }
3556 else {
3557 buf++;
3558 break;
3559 }
3560 }
3561 else {
3562 *--(b->ptr) = ch;
3563 unread++;
3564 count--;
3565 }
3566 }
3567 }
3568 return unread;
3569 }
99efab12
NIS
3570}
3571
3572SSize_t
f62ce20a 3573PerlIOCrlf_get_cnt(pTHX_ PerlIO *f)
99efab12 3574{
14a5cf38
JH
3575 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3576 if (!b->buf)
3577 PerlIO_get_base(f);
3578 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3579 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
23b3c6af
NIS
3580 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) {
3581 STDCHAR *nl = (c->nl) ? c->nl : b->ptr;
14a5cf38
JH
3582 scan:
3583 while (nl < b->end && *nl != 0xd)
3584 nl++;
3585 if (nl < b->end && *nl == 0xd) {
3586 test:
3587 if (nl + 1 < b->end) {
3588 if (nl[1] == 0xa) {
3589 *nl = '\n';
3590 c->nl = nl;
3591 }
3592 else {
3593 /*
71200d45 3594 * Not CR,LF but just CR
14a5cf38
JH
3595 */
3596 nl++;
3597 goto scan;
3598 }
3599 }
3600 else {
3601 /*
71200d45 3602 * Blast - found CR as last char in buffer
14a5cf38 3603 */
e87a358a 3604
14a5cf38
JH
3605 if (b->ptr < nl) {
3606 /*
3607 * They may not care, defer work as long as
71200d45 3608 * possible
14a5cf38 3609 */
a0d1d361 3610 c->nl = nl;
14a5cf38
JH
3611 return (nl - b->ptr);
3612 }
3613 else {
3614 int code;
22569500 3615 b->ptr++; /* say we have read it as far as
14a5cf38 3616 * flush() is concerned */
22569500
NIS
3617 b->buf++; /* Leave space in front of buffer */
3618 b->bufsiz--; /* Buffer is thus smaller */
3619 code = PerlIO_fill(f); /* Fetch some more */
3620 b->bufsiz++; /* Restore size for next time */
3621 b->buf--; /* Point at space */
3622 b->ptr = nl = b->buf; /* Which is what we hand
14a5cf38 3623 * off */
22569500
NIS
3624 b->posn--; /* Buffer starts here */
3625 *nl = 0xd; /* Fill in the CR */
14a5cf38 3626 if (code == 0)
22569500 3627 goto test; /* fill() call worked */
14a5cf38 3628 /*
71200d45 3629 * CR at EOF - just fall through
14a5cf38 3630 */
a0d1d361 3631 /* Should we clear EOF though ??? */
14a5cf38
JH
3632 }
3633 }
3634 }
3635 }
3636 return (((c->nl) ? (c->nl + 1) : b->end) - b->ptr);
3637 }
3638 return 0;
99efab12
NIS
3639}
3640
3641void
f62ce20a 3642PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
14a5cf38
JH
3643{
3644 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3645 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
14a5cf38
JH
3646 if (!b->buf)
3647 PerlIO_get_base(f);
3648 if (!ptr) {
a0d1d361 3649 if (c->nl) {
14a5cf38 3650 ptr = c->nl + 1;
22569500 3651 if (ptr == b->end && *c->nl == 0xd) {
a0d1d361 3652 /* Defered CR at end of buffer case - we lied about count */
22569500
NIS
3653 ptr--;
3654 }
3655 }
14a5cf38
JH
3656 else {
3657 ptr = b->end;
14a5cf38
JH
3658 }
3659 ptr -= cnt;
3660 }
3661 else {
3b4bd3fd 3662#if 0
14a5cf38 3663 /*
71200d45 3664 * Test code - delete when it works ...
14a5cf38 3665 */
3b4bd3fd 3666 IV flags = PerlIOBase(f)->flags;
ba7abf9d 3667 STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end;
22569500 3668 if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) {
a0d1d361
NIS
3669 /* Defered CR at end of buffer case - we lied about count */
3670 chk--;
22569500 3671 }
14a5cf38
JH
3672 chk -= cnt;
3673
a0d1d361 3674 if (ptr != chk ) {
99ef548b 3675 Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08" UVxf
14a5cf38
JH
3676 " nl=%p e=%p for %d", ptr, chk, flags, c->nl,
3677 b->end, cnt);
3678 }
99ef548b 3679#endif
14a5cf38
JH
3680 }
3681 if (c->nl) {
3682 if (ptr > c->nl) {
3683 /*
71200d45 3684 * They have taken what we lied about
14a5cf38
JH
3685 */
3686 *(c->nl) = 0xd;
3687 c->nl = NULL;
3688 ptr++;
3689 }
3690 }
3691 b->ptr = ptr;
3692 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
99efab12
NIS
3693}
3694
3695SSize_t
f62ce20a 3696PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 3697{
14a5cf38 3698 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 3699 return PerlIOBuf_write(aTHX_ f, vbuf, count);
14a5cf38
JH
3700 else {
3701 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3702 const STDCHAR *buf = (const STDCHAR *) vbuf;
3703 const STDCHAR *ebuf = buf + count;
3704 if (!b->buf)
3705 PerlIO_get_base(f);
3706 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3707 return 0;
3708 while (buf < ebuf) {
3709 STDCHAR *eptr = b->buf + b->bufsiz;
3710 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
3711 while (buf < ebuf && b->ptr < eptr) {
3712 if (*buf == '\n') {
3713 if ((b->ptr + 2) > eptr) {
3714 /*
71200d45 3715 * Not room for both
14a5cf38
JH
3716 */
3717 PerlIO_flush(f);
3718 break;
3719 }
3720 else {
22569500
NIS
3721 *(b->ptr)++ = 0xd; /* CR */
3722 *(b->ptr)++ = 0xa; /* LF */
14a5cf38
JH
3723 buf++;
3724 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3725 PerlIO_flush(f);
3726 break;
3727 }
3728 }
3729 }
3730 else {
3731 int ch = *buf++;
3732 *(b->ptr)++ = ch;
3733 }
3734 if (b->ptr >= eptr) {
3735 PerlIO_flush(f);
3736 break;
3737 }
3738 }
3739 }
3740 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3741 PerlIO_flush(f);
3742 return (buf - (STDCHAR *) vbuf);
3743 }
99efab12
NIS
3744}
3745
3746IV
f62ce20a 3747PerlIOCrlf_flush(pTHX_ PerlIO *f)
99efab12 3748{
14a5cf38
JH
3749 PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3750 if (c->nl) {
3751 *(c->nl) = 0xd;
3752 c->nl = NULL;
3753 }
f62ce20a 3754 return PerlIOBuf_flush(aTHX_ f);
99efab12
NIS
3755}
3756
66ecd56b 3757PerlIO_funcs PerlIO_crlf = {
14a5cf38
JH
3758 "crlf",
3759 sizeof(PerlIOCrlf),
3760 PERLIO_K_BUFFERED | PERLIO_K_CANCRLF,
3761 PerlIOCrlf_pushed,
44798d05 3762 PerlIOBuf_popped, /* popped */
14a5cf38
JH
3763 PerlIOBuf_open,
3764 NULL,
3765 PerlIOBase_fileno,
71200d45 3766 PerlIOBuf_dup,
22569500 3767 PerlIOBuf_read, /* generic read works with ptr/cnt lies
14a5cf38 3768 * ... */
22569500
NIS
3769 PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */
3770 PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */
14a5cf38
JH
3771 PerlIOBuf_seek,
3772 PerlIOBuf_tell,
3773 PerlIOBuf_close,
3774 PerlIOCrlf_flush,
3775 PerlIOBuf_fill,
3776 PerlIOBase_eof,
3777 PerlIOBase_error,
3778 PerlIOBase_clearerr,
3779 PerlIOBase_setlinebuf,
3780 PerlIOBuf_get_base,
3781 PerlIOBuf_bufsiz,
3782 PerlIOBuf_get_ptr,
3783 PerlIOCrlf_get_cnt,
3784 PerlIOCrlf_set_ptrcnt,
66ecd56b
NIS
3785};
3786
06da4f11
NIS
3787#ifdef HAS_MMAP
3788/*--------------------------------------------------------------------------------------*/
14a5cf38 3789/*
71200d45 3790 * mmap as "buffer" layer
14a5cf38 3791 */
06da4f11 3792
14a5cf38 3793typedef struct {
22569500
NIS
3794 PerlIOBuf base; /* PerlIOBuf stuff */
3795 Mmap_t mptr; /* Mapped address */
3796 Size_t len; /* mapped length */
3797 STDCHAR *bbuf; /* malloced buffer if map fails */
06da4f11
NIS
3798} PerlIOMmap;
3799
c3d7c7c9
NIS
3800static size_t page_size = 0;
3801
06da4f11 3802IV
f62ce20a 3803PerlIOMmap_map(pTHX_ PerlIO *f)
06da4f11 3804{
14a5cf38
JH
3805 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3806 IV flags = PerlIOBase(f)->flags;
3807 IV code = 0;
3808 if (m->len)
3809 abort();
3810 if (flags & PERLIO_F_CANREAD) {
3811 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3812 int fd = PerlIO_fileno(f);
10eefe7f
CB
3813 Stat_t st;
3814 code = Fstat(fd, &st);
14a5cf38
JH
3815 if (code == 0 && S_ISREG(st.st_mode)) {
3816 SSize_t len = st.st_size - b->posn;
3817 if (len > 0) {
3818 Off_t posn;
3819 if (!page_size) {
68d873c6 3820#if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE))
14a5cf38
JH
3821 {
3822 SETERRNO(0, SS$_NORMAL);
68d873c6 3823# ifdef _SC_PAGESIZE
14a5cf38 3824 page_size = sysconf(_SC_PAGESIZE);
68d873c6 3825# else
14a5cf38 3826 page_size = sysconf(_SC_PAGE_SIZE);
14aaf8e8 3827# endif
14a5cf38
JH
3828 if ((long) page_size < 0) {
3829 if (errno) {
3830 SV *error = ERRSV;
3831 char *msg;
3832 STRLEN n_a;
3833 (void) SvUPGRADE(error, SVt_PV);
3834 msg = SvPVx(error, n_a);
3835 Perl_croak(aTHX_ "panic: sysconf: %s",
3836 msg);
3837 }
3838 else
3839 Perl_croak(aTHX_
3840 "panic: sysconf: pagesize unknown");
3841 }
3842 }
68d873c6
JH
3843#else
3844# ifdef HAS_GETPAGESIZE
14a5cf38 3845 page_size = getpagesize();
68d873c6
JH
3846# else
3847# if defined(I_SYS_PARAM) && defined(PAGESIZE)
22569500 3848 page_size = PAGESIZE; /* compiletime, bad */
68d873c6
JH
3849# endif
3850# endif
3851#endif
14a5cf38
JH
3852 if ((IV) page_size <= 0)
3853 Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
3854 (IV) page_size);
3855 }
3856 if (b->posn < 0) {
3857 /*
3858 * This is a hack - should never happen - open should
71200d45 3859 * have set it !
14a5cf38
JH
3860 */
3861 b->posn = PerlIO_tell(PerlIONext(f));
3862 }
3863 posn = (b->posn / page_size) * page_size;
3864 len = st.st_size - posn;
3865 m->mptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
3866 if (m->mptr && m->mptr != (Mmap_t) - 1) {
a5262162 3867#if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
14a5cf38 3868 madvise(m->mptr, len, MADV_SEQUENTIAL);
06da4f11 3869#endif
a5262162 3870#if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED)
14a5cf38 3871 madvise(m->mptr, len, MADV_WILLNEED);
a5262162 3872#endif
14a5cf38
JH
3873 PerlIOBase(f)->flags =
3874 (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
3875 b->end = ((STDCHAR *) m->mptr) + len;
3876 b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn);
3877 b->ptr = b->buf;
3878 m->len = len;
3879 }
3880 else {
3881 b->buf = NULL;
3882 }
3883 }
3884 else {
3885 PerlIOBase(f)->flags =
3886 flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
3887 b->buf = NULL;
3888 b->ptr = b->end = b->ptr;
3889 code = -1;
3890 }
3891 }
3892 }
3893 return code;
06da4f11
NIS
3894}
3895
3896IV
e87a358a 3897PerlIOMmap_unmap(pTHX_ PerlIO *f)
06da4f11 3898{
14a5cf38
JH
3899 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3900 PerlIOBuf *b = &m->base;
3901 IV code = 0;
3902 if (m->len) {
3903 if (b->buf) {
3904 code = munmap(m->mptr, m->len);
3905 b->buf = NULL;
3906 m->len = 0;
3907 m->mptr = NULL;
3908 if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0)
3909 code = -1;
3910 }
3911 b->ptr = b->end = b->buf;
3912 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3913 }
3914 return code;
06da4f11
NIS
3915}
3916
3917STDCHAR *
f62ce20a 3918PerlIOMmap_get_base(pTHX_ PerlIO *f)
06da4f11 3919{
14a5cf38
JH
3920 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3921 PerlIOBuf *b = &m->base;
3922 if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3923 /*
71200d45 3924 * Already have a readbuffer in progress
14a5cf38
JH
3925 */
3926 return b->buf;
3927 }
3928 if (b->buf) {
3929 /*
71200d45 3930 * We have a write buffer or flushed PerlIOBuf read buffer
14a5cf38 3931 */
22569500
NIS
3932 m->bbuf = b->buf; /* save it in case we need it again */
3933 b->buf = NULL; /* Clear to trigger below */
14a5cf38
JH
3934 }
3935 if (!b->buf) {
22569500 3936 PerlIOMmap_map(aTHX_ f); /* Try and map it */
14a5cf38
JH
3937 if (!b->buf) {
3938 /*
71200d45 3939 * Map did not work - recover PerlIOBuf buffer if we have one
14a5cf38
JH
3940 */
3941 b->buf = m->bbuf;
3942 }
3943 }
3944 b->ptr = b->end = b->buf;
3945 if (b->buf)
3946 return b->buf;
f62ce20a 3947 return PerlIOBuf_get_base(aTHX_ f);
06da4f11
NIS
3948}
3949
3950SSize_t
f62ce20a 3951PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 3952{
14a5cf38
JH
3953 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3954 PerlIOBuf *b = &m->base;
3955 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3956 PerlIO_flush(f);
3957 if (b->ptr && (b->ptr - count) >= b->buf
3958 && memEQ(b->ptr - count, vbuf, count)) {
3959 b->ptr -= count;
3960 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3961 return count;
3962 }
3963 if (m->len) {
3964 /*
71200d45 3965 * Loose the unwritable mapped buffer
14a5cf38
JH
3966 */
3967 PerlIO_flush(f);
3968 /*
71200d45 3969 * If flush took the "buffer" see if we have one from before
14a5cf38
JH
3970 */
3971 if (!b->buf && m->bbuf)
3972 b->buf = m->bbuf;
3973 if (!b->buf) {
f62ce20a 3974 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
3975 m->bbuf = b->buf;
3976 }
3977 }
f62ce20a 3978 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
06da4f11
NIS
3979}
3980
3981SSize_t
f62ce20a 3982PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 3983{
14a5cf38
JH
3984 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3985 PerlIOBuf *b = &m->base;
3986 if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
3987 /*
71200d45 3988 * No, or wrong sort of, buffer
14a5cf38
JH
3989 */
3990 if (m->len) {
e87a358a 3991 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
3992 return 0;
3993 }
3994 /*
71200d45 3995 * If unmap took the "buffer" see if we have one from before
14a5cf38
JH
3996 */
3997 if (!b->buf && m->bbuf)
3998 b->buf = m->bbuf;
3999 if (!b->buf) {
f62ce20a 4000 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
4001 m->bbuf = b->buf;
4002 }
06da4f11 4003 }
f62ce20a 4004 return PerlIOBuf_write(aTHX_ f, vbuf, count);
06da4f11
NIS
4005}
4006
4007IV
f62ce20a 4008PerlIOMmap_flush(pTHX_ PerlIO *f)
06da4f11 4009{
14a5cf38
JH
4010 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4011 PerlIOBuf *b = &m->base;
f62ce20a 4012 IV code = PerlIOBuf_flush(aTHX_ f);
14a5cf38 4013 /*
71200d45 4014 * Now we are "synced" at PerlIOBuf level
14a5cf38
JH
4015 */
4016 if (b->buf) {
4017 if (m->len) {
4018 /*
71200d45 4019 * Unmap the buffer
14a5cf38 4020 */
e87a358a 4021 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
4022 code = -1;
4023 }
4024 else {
4025 /*
4026 * We seem to have a PerlIOBuf buffer which was not mapped
71200d45 4027 * remember it in case we need one later
14a5cf38
JH
4028 */
4029 m->bbuf = b->buf;
4030 }
4031 }
4032 return code;
06da4f11
NIS
4033}
4034
4035IV
f62ce20a 4036PerlIOMmap_fill(pTHX_ PerlIO *f)
06da4f11 4037{
14a5cf38
JH
4038 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
4039 IV code = PerlIO_flush(f);
4040 if (code == 0 && !b->buf) {
f62ce20a 4041 code = PerlIOMmap_map(aTHX_ f);
14a5cf38
JH
4042 }
4043 if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
f62ce20a 4044 code = PerlIOBuf_fill(aTHX_ f);
14a5cf38
JH
4045 }
4046 return code;
06da4f11
NIS
4047}
4048
4049IV
f62ce20a 4050PerlIOMmap_close(pTHX_ PerlIO *f)
06da4f11 4051{
14a5cf38
JH
4052 PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
4053 PerlIOBuf *b = &m->base;
4054 IV code = PerlIO_flush(f);
4055 if (m->bbuf) {
4056 b->buf = m->bbuf;
4057 m->bbuf = NULL;
4058 b->ptr = b->end = b->buf;
4059 }
f62ce20a 4060 if (PerlIOBuf_close(aTHX_ f) != 0)
14a5cf38
JH
4061 code = -1;
4062 return code;
06da4f11
NIS
4063}
4064
71200d45 4065PerlIO *
ecdeb87c 4066PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 4067{
ecdeb87c 4068 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
4069}
4070
06da4f11
NIS
4071
4072PerlIO_funcs PerlIO_mmap = {
14a5cf38
JH
4073 "mmap",
4074 sizeof(PerlIOMmap),
4075 PERLIO_K_BUFFERED,
4076 PerlIOBuf_pushed,
44798d05 4077 PerlIOBuf_popped,
14a5cf38
JH
4078 PerlIOBuf_open,
4079 NULL,
4080 PerlIOBase_fileno,
71200d45 4081 PerlIOMmap_dup,
14a5cf38
JH
4082 PerlIOBuf_read,
4083 PerlIOMmap_unread,
4084 PerlIOMmap_write,
4085 PerlIOBuf_seek,
4086 PerlIOBuf_tell,
4087 PerlIOBuf_close,
4088 PerlIOMmap_flush,
4089 PerlIOMmap_fill,
4090 PerlIOBase_eof,
4091 PerlIOBase_error,
4092 PerlIOBase_clearerr,
4093 PerlIOBase_setlinebuf,
4094 PerlIOMmap_get_base,
4095 PerlIOBuf_bufsiz,
4096 PerlIOBuf_get_ptr,
4097 PerlIOBuf_get_cnt,
4098 PerlIOBuf_set_ptrcnt,
06da4f11
NIS
4099};
4100
22569500 4101#endif /* HAS_MMAP */
06da4f11 4102
9e353e3b 4103PerlIO *
e87a358a 4104Perl_PerlIO_stdin(pTHX)
9e353e3b 4105{
a1ea730d 4106 if (!PL_perlio) {
14a5cf38
JH
4107 PerlIO_stdstreams(aTHX);
4108 }
a1ea730d 4109 return &PL_perlio[1];
9e353e3b
NIS
4110}
4111
9e353e3b 4112PerlIO *
e87a358a 4113Perl_PerlIO_stdout(pTHX)
9e353e3b 4114{
a1ea730d 4115 if (!PL_perlio) {
14a5cf38
JH
4116 PerlIO_stdstreams(aTHX);
4117 }
a1ea730d 4118 return &PL_perlio[2];
9e353e3b
NIS
4119}
4120
9e353e3b 4121PerlIO *
e87a358a 4122Perl_PerlIO_stderr(pTHX)
9e353e3b 4123{
a1ea730d 4124 if (!PL_perlio) {
14a5cf38
JH
4125 PerlIO_stdstreams(aTHX);
4126 }
a1ea730d 4127 return &PL_perlio[3];
9e353e3b
NIS
4128}
4129
4130/*--------------------------------------------------------------------------------------*/
4131
9e353e3b
NIS
4132char *
4133PerlIO_getname(PerlIO *f, char *buf)
4134{
14a5cf38
JH
4135 dTHX;
4136 char *name = NULL;
a15cef0c 4137#ifdef VMS
14a5cf38
JH
4138 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
4139 if (stdio)
4140 name = fgetname(stdio, buf);
a15cef0c 4141#else
14a5cf38 4142 Perl_croak(aTHX_ "Don't know how to get file name");
a15cef0c 4143#endif
14a5cf38 4144 return name;
9e353e3b
NIS
4145}
4146
4147
4148/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
4149/*
4150 * Functions which can be called on any kind of PerlIO implemented in
71200d45 4151 * terms of above
14a5cf38 4152 */
9e353e3b 4153
e87a358a
NIS
4154#undef PerlIO_fdopen
4155PerlIO *
4156PerlIO_fdopen(int fd, const char *mode)
4157{
4158 dTHX;
4159 return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL);
4160}
4161
4162#undef PerlIO_open
4163PerlIO *
4164PerlIO_open(const char *path, const char *mode)
4165{
4166 dTHX;
4167 SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
4168 return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name);
4169}
4170
4171#undef Perlio_reopen
4172PerlIO *
4173PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
4174{
4175 dTHX;
4176 SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
4177 return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name);
4178}
4179
9e353e3b 4180#undef PerlIO_getc
6f9d8c32 4181int
9e353e3b 4182PerlIO_getc(PerlIO *f)
760ac839 4183{
e87a358a 4184 dTHX;
14a5cf38
JH
4185 STDCHAR buf[1];
4186 SSize_t count = PerlIO_read(f, buf, 1);
4187 if (count == 1) {
4188 return (unsigned char) buf[0];
4189 }
4190 return EOF;
313ca112
NIS
4191}
4192
4193#undef PerlIO_ungetc
4194int
4195PerlIO_ungetc(PerlIO *f, int ch)
4196{
e87a358a 4197 dTHX;
14a5cf38
JH
4198 if (ch != EOF) {
4199 STDCHAR buf = ch;
4200 if (PerlIO_unread(f, &buf, 1) == 1)
4201 return ch;
4202 }
4203 return EOF;
760ac839
LW
4204}
4205
9e353e3b
NIS
4206#undef PerlIO_putc
4207int
4208PerlIO_putc(PerlIO *f, int ch)
760ac839 4209{
e87a358a 4210 dTHX;
14a5cf38
JH
4211 STDCHAR buf = ch;
4212 return PerlIO_write(f, &buf, 1);
760ac839
LW
4213}
4214
9e353e3b 4215#undef PerlIO_puts
760ac839 4216int
9e353e3b 4217PerlIO_puts(PerlIO *f, const char *s)
760ac839 4218{
e87a358a 4219 dTHX;
14a5cf38
JH
4220 STRLEN len = strlen(s);
4221 return PerlIO_write(f, s, len);
760ac839
LW
4222}
4223
4224#undef PerlIO_rewind
4225void
c78749f2 4226PerlIO_rewind(PerlIO *f)
760ac839 4227{
e87a358a 4228 dTHX;
14a5cf38
JH
4229 PerlIO_seek(f, (Off_t) 0, SEEK_SET);
4230 PerlIO_clearerr(f);
6f9d8c32
NIS
4231}
4232
4233#undef PerlIO_vprintf
4234int
4235PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
4236{
14a5cf38
JH
4237 dTHX;
4238 SV *sv = newSVpvn("", 0);
4239 char *s;
4240 STRLEN len;
4241 SSize_t wrote;
2cc61e15 4242#ifdef NEED_VA_COPY
14a5cf38
JH
4243 va_list apc;
4244 Perl_va_copy(ap, apc);
4245 sv_vcatpvf(sv, fmt, &apc);
2cc61e15 4246#else
14a5cf38 4247 sv_vcatpvf(sv, fmt, &ap);
2cc61e15 4248#endif
14a5cf38
JH
4249 s = SvPV(sv, len);
4250 wrote = PerlIO_write(f, s, len);
4251 SvREFCNT_dec(sv);
4252 return wrote;
760ac839
LW
4253}
4254
4255#undef PerlIO_printf
6f9d8c32 4256int
14a5cf38 4257PerlIO_printf(PerlIO *f, const char *fmt, ...)
760ac839 4258{
14a5cf38
JH
4259 va_list ap;
4260 int result;
4261 va_start(ap, fmt);
4262 result = PerlIO_vprintf(f, fmt, ap);
4263 va_end(ap);
4264 return result;
760ac839
LW
4265}
4266
4267#undef PerlIO_stdoutf
6f9d8c32 4268int
14a5cf38 4269PerlIO_stdoutf(const char *fmt, ...)
760ac839 4270{
e87a358a 4271 dTHX;
14a5cf38
JH
4272 va_list ap;
4273 int result;
4274 va_start(ap, fmt);
4275 result = PerlIO_vprintf(PerlIO_stdout(), fmt, ap);
4276 va_end(ap);
4277 return result;
760ac839
LW
4278}
4279
4280#undef PerlIO_tmpfile
4281PerlIO *
c78749f2 4282PerlIO_tmpfile(void)
760ac839 4283{
14a5cf38 4284 /*
71200d45 4285 * I have no idea how portable mkstemp() is ...
14a5cf38 4286 */
83b075c3 4287#if defined(WIN32) || !defined(HAVE_MKSTEMP)
14a5cf38
JH
4288 dTHX;
4289 PerlIO *f = NULL;
4290 FILE *stdio = PerlSIO_tmpfile();
4291 if (stdio) {
4292 PerlIOStdio *s =
4293 PerlIOSelf(PerlIO_push
4294 (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
4295 "w+", Nullsv), PerlIOStdio);
4296 s->stdio = stdio;
4297 }
4298 return f;
83b075c3 4299#else
14a5cf38
JH
4300 dTHX;
4301 SV *sv = newSVpv("/tmp/PerlIO_XXXXXX", 0);
4302 int fd = mkstemp(SvPVX(sv));
4303 PerlIO *f = NULL;
4304 if (fd >= 0) {
4305 f = PerlIO_fdopen(fd, "w+");
4306 if (f) {
4307 PerlIOBase(f)->flags |= PERLIO_F_TEMP;
4308 }
4309 PerlLIO_unlink(SvPVX(sv));
4310 SvREFCNT_dec(sv);
4311 }
4312 return f;
83b075c3 4313#endif
760ac839
LW
4314}
4315
6f9d8c32
NIS
4316#undef HAS_FSETPOS
4317#undef HAS_FGETPOS
4318
22569500
NIS
4319#endif /* USE_SFIO */
4320#endif /* PERLIO_IS_STDIO */
760ac839 4321
9e353e3b 4322/*======================================================================================*/
14a5cf38 4323/*
71200d45
NIS
4324 * Now some functions in terms of above which may be needed even if we are
4325 * not in true PerlIO mode
9e353e3b
NIS
4326 */
4327
760ac839
LW
4328#ifndef HAS_FSETPOS
4329#undef PerlIO_setpos
4330int
766a733e 4331PerlIO_setpos(PerlIO *f, SV *pos)
760ac839 4332{
14a5cf38
JH
4333 dTHX;
4334 if (SvOK(pos)) {
4335 STRLEN len;
4336 Off_t *posn = (Off_t *) SvPV(pos, len);
4337 if (f && len == sizeof(Off_t))
4338 return PerlIO_seek(f, *posn, SEEK_SET);
4339 }
4340 SETERRNO(EINVAL, SS$_IVCHAN);
4341 return -1;
760ac839 4342}
c411622e 4343#else
c411622e 4344#undef PerlIO_setpos
4345int
766a733e 4346PerlIO_setpos(PerlIO *f, SV *pos)
c411622e 4347{
14a5cf38
JH
4348 dTHX;
4349 if (SvOK(pos)) {
4350 STRLEN len;
4351 Fpos_t *fpos = (Fpos_t *) SvPV(pos, len);
4352 if (f && len == sizeof(Fpos_t)) {
2d4389e4 4353#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 4354 return fsetpos64(f, fpos);
d9b3e12d 4355#else
14a5cf38 4356 return fsetpos(f, fpos);
d9b3e12d 4357#endif
14a5cf38 4358 }
766a733e 4359 }
14a5cf38
JH
4360 SETERRNO(EINVAL, SS$_IVCHAN);
4361 return -1;
c411622e 4362}
4363#endif
760ac839
LW
4364
4365#ifndef HAS_FGETPOS
4366#undef PerlIO_getpos
4367int
766a733e 4368PerlIO_getpos(PerlIO *f, SV *pos)
760ac839 4369{
14a5cf38
JH
4370 dTHX;
4371 Off_t posn = PerlIO_tell(f);
4372 sv_setpvn(pos, (char *) &posn, sizeof(posn));
4373 return (posn == (Off_t) - 1) ? -1 : 0;
760ac839 4374}
c411622e 4375#else
c411622e 4376#undef PerlIO_getpos
4377int
766a733e 4378PerlIO_getpos(PerlIO *f, SV *pos)
c411622e 4379{
14a5cf38
JH
4380 dTHX;
4381 Fpos_t fpos;
4382 int code;
2d4389e4 4383#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 4384 code = fgetpos64(f, &fpos);
d9b3e12d 4385#else
14a5cf38 4386 code = fgetpos(f, &fpos);
d9b3e12d 4387#endif
14a5cf38
JH
4388 sv_setpvn(pos, (char *) &fpos, sizeof(fpos));
4389 return code;
c411622e 4390}
4391#endif
760ac839
LW
4392
4393#if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
4394
4395int
c78749f2 4396vprintf(char *pat, char *args)
662a7e3f
CS
4397{
4398 _doprnt(pat, args, stdout);
22569500 4399 return 0; /* wrong, but perl doesn't use the return
14a5cf38 4400 * value */
662a7e3f
CS
4401}
4402
4403int
c78749f2 4404vfprintf(FILE *fd, char *pat, char *args)
760ac839
LW
4405{
4406 _doprnt(pat, args, fd);
22569500 4407 return 0; /* wrong, but perl doesn't use the return
14a5cf38 4408 * value */
760ac839
LW
4409}
4410
4411#endif
4412
4413#ifndef PerlIO_vsprintf
6f9d8c32 4414int
8ac85365 4415PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
760ac839 4416{
14a5cf38
JH
4417 int val = vsprintf(s, fmt, ap);
4418 if (n >= 0) {
4419 if (strlen(s) >= (STRLEN) n) {
4420 dTHX;
4421 (void) PerlIO_puts(Perl_error_log,
4422 "panic: sprintf overflow - memory corrupted!\n");
4423 my_exit(1);
4424 }
760ac839 4425 }
14a5cf38 4426 return val;
760ac839
LW
4427}
4428#endif
4429
4430#ifndef PerlIO_sprintf
6f9d8c32 4431int
14a5cf38 4432PerlIO_sprintf(char *s, int n, const char *fmt, ...)
760ac839 4433{
14a5cf38
JH
4434 va_list ap;
4435 int result;
4436 va_start(ap, fmt);
4437 result = PerlIO_vsprintf(s, n, fmt, ap);
4438 va_end(ap);
4439 return result;
760ac839
LW
4440}
4441#endif
7fcdafbd 4442
93a8090d
NIS
4443
4444
4445
4446