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