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