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