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