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