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