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