03c93e136eff25f6d324daf6e0459ea290b5958c
[p5sagit/p5-mst-13.2.git] / perlio.c
1 /*    perlio.c
2  *
3  *    Copyright (c) 1996-2000, Nick Ing-Simmons
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  */
9
10 #define VOIDUSED 1
11 #ifdef PERL_MICRO
12 #   include "uconfig.h"
13 #else
14 #   include "config.h"
15 #endif
16
17 #define PERLIO_NOT_STDIO 0
18 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
19 /* #define PerlIO FILE */
20 #endif
21 /*
22  * This file provides those parts of PerlIO abstraction
23  * which are not #defined in iperlsys.h.
24  * Which these are depends on various Configure #ifdef's
25  */
26
27 #include "EXTERN.h"
28 #define PERL_IN_PERLIO_C
29 #include "perl.h"
30
31 #if !defined(PERL_IMPLICIT_SYS)
32
33 #ifdef PERLIO_IS_STDIO
34
35 void
36 PerlIO_init(void)
37 {
38  /* Does nothing (yet) except force this file to be included
39     in perl binary. That allows this file to force inclusion
40     of other functions that may be required by loadable
41     extensions e.g. for FileHandle::tmpfile
42  */
43 }
44
45 #undef PerlIO_tmpfile
46 PerlIO *
47 PerlIO_tmpfile(void)
48 {
49  return tmpfile();
50 }
51
52 #else /* PERLIO_IS_STDIO */
53
54 #ifdef USE_SFIO
55
56 #undef HAS_FSETPOS
57 #undef HAS_FGETPOS
58
59 /* This section is just to make sure these functions
60    get pulled in from libsfio.a
61 */
62
63 #undef PerlIO_tmpfile
64 PerlIO *
65 PerlIO_tmpfile(void)
66 {
67  return sftmp(0);
68 }
69
70 void
71 PerlIO_init(void)
72 {
73  /* Force this file to be included  in perl binary. Which allows
74   *  this file to force inclusion  of other functions that may be
75   *  required by loadable  extensions e.g. for FileHandle::tmpfile
76   */
77
78  /* Hack
79   * sfio does its own 'autoflush' on stdout in common cases.
80   * Flush results in a lot of lseek()s to regular files and
81   * lot of small writes to pipes.
82   */
83  sfset(sfstdout,SF_SHARE,0);
84 }
85
86 #else /* USE_SFIO */
87 /*======================================================================================*/
88 /* Implement all the PerlIO interface ourselves.
89  */
90
91 /* We _MUST_ have <unistd.h> if we are using lseek() and may have large files */
92 #ifdef I_UNISTD
93 #include <unistd.h>
94 #endif
95 #include "XSUB.h"
96
97 #undef printf
98 void PerlIO_debug(char *fmt,...) __attribute__((format(printf,1,2)));
99
100 void
101 PerlIO_debug(char *fmt,...)
102 {
103  static int dbg = 0;
104  if (!dbg)
105   {
106    char *s = getenv("PERLIO_DEBUG");
107    if (s && *s)
108     dbg = open(s,O_WRONLY|O_CREAT|O_APPEND,0666);
109    else
110     dbg = -1;
111   }
112  if (dbg > 0)
113   {
114    dTHX;
115    va_list ap;
116    SV *sv = newSVpvn("",0);
117    char *s;
118    STRLEN len;
119    va_start(ap,fmt);
120    s = CopFILE(PL_curcop);
121    if (!s)
122     s = "(none)";
123    Perl_sv_catpvf(aTHX_ sv, "%s:%"IVdf" ", s, (IV)CopLINE(PL_curcop));
124    Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
125
126    s = SvPV(sv,len);
127    write(dbg,s,len);
128    va_end(ap);
129    SvREFCNT_dec(sv);
130   }
131 }
132
133 /*--------------------------------------------------------------------------------------*/
134
135 typedef struct
136 {
137  char *         name;
138  Size_t         size;
139  IV             kind;
140  IV             (*Fileno)(PerlIO *f);
141  PerlIO *       (*Fdopen)(int fd, const char *mode);
142  PerlIO *       (*Open)(const char *path, const char *mode);
143  int            (*Reopen)(const char *path, const char *mode, PerlIO *f);
144  /* Unix-like functions - cf sfio line disciplines */
145  SSize_t        (*Read)(PerlIO *f, void *vbuf, Size_t count);
146  SSize_t        (*Unread)(PerlIO *f, const void *vbuf, Size_t count);
147  SSize_t        (*Write)(PerlIO *f, const void *vbuf, Size_t count);
148  IV             (*Seek)(PerlIO *f, Off_t offset, int whence);
149  Off_t          (*Tell)(PerlIO *f);
150  IV             (*Close)(PerlIO *f);
151  /* Stdio-like buffered IO functions */
152  IV             (*Flush)(PerlIO *f);
153  IV             (*Eof)(PerlIO *f);
154  IV             (*Error)(PerlIO *f);
155  void           (*Clearerr)(PerlIO *f);
156  void           (*Setlinebuf)(PerlIO *f);
157  /* Perl's snooping functions */
158  STDCHAR *      (*Get_base)(PerlIO *f);
159  Size_t         (*Get_bufsiz)(PerlIO *f);
160  STDCHAR *      (*Get_ptr)(PerlIO *f);
161  SSize_t        (*Get_cnt)(PerlIO *f);
162  void           (*Set_ptrcnt)(PerlIO *f,STDCHAR *ptr,SSize_t cnt);
163 } PerlIO_funcs;
164
165
166 struct _PerlIO
167 {
168  PerlIOl *      next;       /* Lower layer */
169  PerlIO_funcs * tab;        /* Functions for this layer */
170  IV             flags;      /* Various flags for state */
171 };
172
173 /*--------------------------------------------------------------------------------------*/
174
175 /* Flag values */
176 #define PERLIO_F_EOF            0x00010000
177 #define PERLIO_F_CANWRITE       0x00020000
178 #define PERLIO_F_CANREAD        0x00040000
179 #define PERLIO_F_ERROR          0x00080000
180 #define PERLIO_F_TRUNCATE       0x00100000
181 #define PERLIO_F_APPEND         0x00200000
182 #define PERLIO_F_BINARY         0x00400000
183 #define PERLIO_F_UTF8           0x00800000
184 #define PERLIO_F_LINEBUF        0x01000000
185 #define PERLIO_F_WRBUF          0x02000000
186 #define PERLIO_F_RDBUF          0x04000000
187 #define PERLIO_F_TEMP           0x08000000
188 #define PERLIO_F_OPEN           0x10000000
189
190 #define PerlIOBase(f)      (*(f))
191 #define PerlIOSelf(f,type) ((type *)PerlIOBase(f))
192 #define PerlIONext(f)      (&(PerlIOBase(f)->next))
193
194 /*--------------------------------------------------------------------------------------*/
195 /* Inner level routines */
196
197 /* Table of pointers to the PerlIO structs (malloc'ed) */
198 PerlIO *_perlio      = NULL;
199 #define PERLIO_TABLE_SIZE 64
200
201 PerlIO *
202 PerlIO_allocate(void)
203 {
204  /* Find a free slot in the table, allocating new table as necessary */
205  PerlIO **last = &_perlio;
206  PerlIO *f;
207  while ((f = *last))
208   {
209    int i;
210    last = (PerlIO **)(f);
211    for (i=1; i < PERLIO_TABLE_SIZE; i++)
212     {
213      if (!*++f)
214       {
215        return f;
216       }
217     }
218   }
219  Newz('I',f,PERLIO_TABLE_SIZE,PerlIO);
220  if (!f)
221   return NULL;
222  *last = f;
223  return f+1;
224 }
225
226 void
227 PerlIO_cleantable(PerlIO **tablep)
228 {
229  PerlIO *table = *tablep;
230  if (table)
231   {
232    int i;
233    PerlIO_cleantable((PerlIO **) &(table[0]));
234    for (i=PERLIO_TABLE_SIZE-1; i > 0; i--)
235     {
236      PerlIO *f = table+i;
237      if (*f)
238       PerlIO_close(f);
239     }
240    Safefree(table);
241    *tablep = NULL;
242   }
243 }
244
245 void
246 PerlIO_cleanup(void)
247 {
248  PerlIO_cleantable(&_perlio);
249 }
250
251 void
252 PerlIO_pop(PerlIO *f)
253 {
254  PerlIOl *l = *f;
255  if (l)
256   {
257    *f = l->next;
258    Safefree(l);
259   }
260 }
261
262 #undef PerlIO_close
263 int
264 PerlIO_close(PerlIO *f)
265 {
266  int code = (*PerlIOBase(f)->tab->Close)(f);
267  while (*f)
268   {
269    PerlIO_pop(f);
270   }
271  return code;
272 }
273
274
275 /*--------------------------------------------------------------------------------------*/
276 /* Given the abstraction above the public API functions */
277
278 #undef PerlIO_fileno
279 int
280 PerlIO_fileno(PerlIO *f)
281 {
282  return (*PerlIOBase(f)->tab->Fileno)(f);
283 }
284
285
286 extern PerlIO_funcs PerlIO_unix;
287 extern PerlIO_funcs PerlIO_perlio;
288 extern PerlIO_funcs PerlIO_stdio;
289
290 XS(XS_perlio_import)
291 {
292  dXSARGS;
293  GV *gv = CvGV(cv);
294  char *s = GvNAME(gv);
295  STRLEN l = GvNAMELEN(gv);
296  PerlIO_debug("%.*s\n",(int) l,s);
297  XSRETURN_EMPTY;
298 }
299
300 XS(XS_perlio_unimport)
301 {
302  dXSARGS;
303  GV *gv = CvGV(cv);
304  char *s = GvNAME(gv);
305  STRLEN l = GvNAMELEN(gv);
306  PerlIO_debug("%.*s\n",(int) l,s);
307  XSRETURN_EMPTY;
308 }
309
310 HV *PerlIO_layer_hv;
311 AV *PerlIO_layer_av;
312
313 SV *
314 PerlIO_find_layer(char *name, STRLEN len)
315 {
316  dTHX;
317  SV **svp;
318  SV *sv;
319  if (len <= 0)
320   len = strlen(name);
321  svp  = hv_fetch(PerlIO_layer_hv,name,len,0);
322  if (svp && (sv = *svp) && SvROK(sv))
323   return *svp;
324  return NULL;
325 }
326
327 void
328 PerlIO_define_layer(PerlIO_funcs *tab)
329 {
330  dTHX;
331  HV *stash = gv_stashpv("perlio::Layer", TRUE);
332  SV *sv = sv_bless(newRV_noinc(newSViv((IV) tab)),stash);
333  hv_store(PerlIO_layer_hv,tab->name,strlen(tab->name),sv,0);
334 }
335
336 PerlIO_funcs *
337 PerlIO_default_layer(I32 n)
338 {
339  dTHX;
340  SV **svp;
341  SV *layer;
342  PerlIO_funcs *tab = &PerlIO_stdio;
343  int len;
344  if (!PerlIO_layer_hv)
345   {
346    char *s  = getenv("PERLIO");
347    newXS("perlio::import",XS_perlio_import,__FILE__);
348    newXS("perlio::unimport",XS_perlio_unimport,__FILE__);
349    PerlIO_layer_hv = get_hv("perlio::layers",GV_ADD|GV_ADDMULTI);
350    PerlIO_layer_av = get_av("perlio::layers",GV_ADD|GV_ADDMULTI);
351    PerlIO_define_layer(&PerlIO_unix);
352    PerlIO_define_layer(&PerlIO_unix);
353    PerlIO_define_layer(&PerlIO_perlio);
354    PerlIO_define_layer(&PerlIO_stdio);
355    av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_unix.name,0)));
356    if (s)
357     {
358      while (*s)
359       {
360        while (*s && isspace((unsigned char)*s))
361         s++;
362        if (*s)
363         {
364          char *e = s;
365          SV *layer;
366          while (*e && !isspace((unsigned char)*e))
367           e++;
368          layer = PerlIO_find_layer(s,e-s);
369          if (layer)
370           {
371            PerlIO_debug("Pushing %.*s\n",(e-s),s);
372            av_push(PerlIO_layer_av,SvREFCNT_inc(layer));
373           }
374          else
375           Perl_croak(aTHX_ "Unknown layer %.*s",(e-s),s);
376          s = e;
377         }
378       }
379     }
380   }
381  len  = av_len(PerlIO_layer_av);
382  if (len < 1)
383   {
384    if (PerlIO_stdio.Set_ptrcnt)
385     {
386      av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_stdio.name,0)));
387     }
388    else
389     {
390      av_push(PerlIO_layer_av,SvREFCNT_inc(PerlIO_find_layer(PerlIO_perlio.name,0)));
391     }
392    len  = av_len(PerlIO_layer_av);
393   }
394  if (n < 0)
395   n += len+1;
396  svp = av_fetch(PerlIO_layer_av,n,0);
397  if (svp && (layer = *svp) && SvROK(layer) && SvIOK((layer = SvRV(layer))))
398   {
399    tab = (PerlIO_funcs *) SvIV(layer);
400   }
401  /* PerlIO_debug("Layer %d is %s\n",n,tab->name); */
402  return tab;
403 }
404
405 #define PerlIO_default_top() PerlIO_default_layer(-1)
406 #define PerlIO_default_btm() PerlIO_default_layer(0)
407
408 void
409 PerlIO_stdstreams()
410 {
411  if (!_perlio)
412   {
413    PerlIO_allocate();
414    PerlIO_fdopen(0,"Ir");
415    PerlIO_fdopen(1,"Iw");
416    PerlIO_fdopen(2,"Iw");
417   }
418 }
419
420 #undef PerlIO_fdopen
421 PerlIO *
422 PerlIO_fdopen(int fd, const char *mode)
423 {
424  PerlIO_funcs *tab = PerlIO_default_top();
425  if (!_perlio)
426   PerlIO_stdstreams();
427  return (*tab->Fdopen)(fd,mode);
428 }
429
430 #undef PerlIO_open
431 PerlIO *
432 PerlIO_open(const char *path, const char *mode)
433 {
434  PerlIO_funcs *tab = PerlIO_default_top();
435  if (!_perlio)
436   PerlIO_stdstreams();
437  return (*tab->Open)(path,mode);
438 }
439
440 IV
441 PerlIOBase_init(PerlIO *f, const char *mode)
442 {
443  PerlIOl *l = PerlIOBase(f);
444  l->flags  &= ~(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|
445                 PERLIO_F_TRUNCATE|PERLIO_F_APPEND|PERLIO_F_BINARY);
446  if (mode)
447   {
448    switch (*mode++)
449     {
450      case 'r':
451       l->flags = PERLIO_F_CANREAD;
452       break;
453      case 'a':
454       l->flags = PERLIO_F_APPEND|PERLIO_F_CANWRITE;
455       break;
456      case 'w':
457       l->flags = PERLIO_F_TRUNCATE|PERLIO_F_CANWRITE;
458       break;
459      default:
460       errno = EINVAL;
461       return -1;
462     }
463    while (*mode)
464     {
465      switch (*mode++)
466       {
467        case '+':
468         l->flags |= PERLIO_F_CANREAD|PERLIO_F_CANWRITE;
469         break;
470        case 'b':
471         l->flags |= PERLIO_F_BINARY;
472         break;
473       default:
474        errno = EINVAL;
475        return -1;
476       }
477     }
478   }
479  else
480   {
481    if (l->next)
482     {
483      l->flags |= l->next->flags &
484                  (PERLIO_F_CANREAD|PERLIO_F_CANWRITE|
485                    PERLIO_F_TRUNCATE|PERLIO_F_APPEND|PERLIO_F_BINARY);
486     }
487   }
488  return 0;
489 }
490
491 #undef PerlIO_reopen
492 PerlIO *
493 PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
494 {
495  if (f)
496   {
497    PerlIO_flush(f);
498    if ((*PerlIOBase(f)->tab->Reopen)(path,mode,f) == 0)
499     {
500      PerlIOBase_init(f,mode);
501      return f;
502     }
503    return NULL;
504   }
505  else
506   return PerlIO_open(path,mode);
507 }
508
509 #undef PerlIO_read
510 SSize_t
511 PerlIO_read(PerlIO *f, void *vbuf, Size_t count)
512 {
513  return (*PerlIOBase(f)->tab->Read)(f,vbuf,count);
514 }
515
516 #undef PerlIO_ungetc
517 int
518 PerlIO_ungetc(PerlIO *f, int ch)
519 {
520  STDCHAR buf = ch;
521  if ((*PerlIOBase(f)->tab->Unread)(f,&buf,1) == 1)
522   return ch;
523  return -1;
524 }
525
526 #undef PerlIO_write
527 SSize_t
528 PerlIO_write(PerlIO *f, const void *vbuf, Size_t count)
529 {
530  return (*PerlIOBase(f)->tab->Write)(f,vbuf,count);
531 }
532
533 #undef PerlIO_seek
534 int
535 PerlIO_seek(PerlIO *f, Off_t offset, int whence)
536 {
537  return (*PerlIOBase(f)->tab->Seek)(f,offset,whence);
538 }
539
540 #undef PerlIO_tell
541 Off_t
542 PerlIO_tell(PerlIO *f)
543 {
544  return (*PerlIOBase(f)->tab->Tell)(f);
545 }
546
547 #undef PerlIO_flush
548 int
549 PerlIO_flush(PerlIO *f)
550 {
551  if (f)
552   {
553    return (*PerlIOBase(f)->tab->Flush)(f);
554   }
555  else
556   {
557    PerlIO **table = &_perlio;
558    int code = 0;
559    while ((f = *table))
560     {
561      int i;
562      table = (PerlIO **)(f++);
563      for (i=1; i < PERLIO_TABLE_SIZE; i++)
564       {
565        if (*f && PerlIO_flush(f) != 0)
566         code = -1;
567        f++;
568       }
569     }
570    return code;
571   }
572 }
573
574 #undef PerlIO_isutf8
575 int
576 PerlIO_isutf8(PerlIO *f)
577 {
578  return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
579 }
580
581 #undef PerlIO_eof
582 int
583 PerlIO_eof(PerlIO *f)
584 {
585  return (*PerlIOBase(f)->tab->Eof)(f);
586 }
587
588 #undef PerlIO_error
589 int
590 PerlIO_error(PerlIO *f)
591 {
592  return (*PerlIOBase(f)->tab->Error)(f);
593 }
594
595 #undef PerlIO_clearerr
596 void
597 PerlIO_clearerr(PerlIO *f)
598 {
599  (*PerlIOBase(f)->tab->Clearerr)(f);
600 }
601
602 #undef PerlIO_setlinebuf
603 void
604 PerlIO_setlinebuf(PerlIO *f)
605 {
606  (*PerlIOBase(f)->tab->Setlinebuf)(f);
607 }
608
609 #undef PerlIO_has_base
610 int
611 PerlIO_has_base(PerlIO *f)
612 {
613  if (f && *f)
614   {
615    return (PerlIOBase(f)->tab->Get_base != NULL);
616   }
617  return 0;
618 }
619
620 #undef PerlIO_fast_gets
621 int
622 PerlIO_fast_gets(PerlIO *f)
623 {
624  if (f && *f)
625   {
626    PerlIOl *l = PerlIOBase(f);
627    return (l->tab->Set_ptrcnt != NULL);
628   }
629  return 0;
630 }
631
632 #undef PerlIO_has_cntptr
633 int
634 PerlIO_has_cntptr(PerlIO *f)
635 {
636  if (f && *f)
637   {
638    PerlIO_funcs *tab = PerlIOBase(f)->tab;
639    return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
640   }
641  return 0;
642 }
643
644 #undef PerlIO_canset_cnt
645 int
646 PerlIO_canset_cnt(PerlIO *f)
647 {
648  if (f && *f)
649   {
650    PerlIOl *l = PerlIOBase(f);
651    return (l->tab->Set_ptrcnt != NULL);
652   }
653  return 0;
654 }
655
656 #undef PerlIO_get_base
657 STDCHAR *
658 PerlIO_get_base(PerlIO *f)
659 {
660  return (*PerlIOBase(f)->tab->Get_base)(f);
661 }
662
663 #undef PerlIO_get_bufsiz
664 int
665 PerlIO_get_bufsiz(PerlIO *f)
666 {
667  return (*PerlIOBase(f)->tab->Get_bufsiz)(f);
668 }
669
670 #undef PerlIO_get_ptr
671 STDCHAR *
672 PerlIO_get_ptr(PerlIO *f)
673 {
674  return (*PerlIOBase(f)->tab->Get_ptr)(f);
675 }
676
677 #undef PerlIO_get_cnt
678 int
679 PerlIO_get_cnt(PerlIO *f)
680 {
681  return (*PerlIOBase(f)->tab->Get_cnt)(f);
682 }
683
684 #undef PerlIO_set_cnt
685 void
686 PerlIO_set_cnt(PerlIO *f,int cnt)
687 {
688  (*PerlIOBase(f)->tab->Set_ptrcnt)(f,NULL,cnt);
689 }
690
691 #undef PerlIO_set_ptrcnt
692 void
693 PerlIO_set_ptrcnt(PerlIO *f, STDCHAR *ptr, int cnt)
694 {
695  (*PerlIOBase(f)->tab->Set_ptrcnt)(f,ptr,cnt);
696 }
697
698 /*--------------------------------------------------------------------------------------*/
699 /* "Methods" of the "base class" */
700
701 IV
702 PerlIOBase_fileno(PerlIO *f)
703 {
704  return PerlIO_fileno(PerlIONext(f));
705 }
706
707 PerlIO *
708 PerlIO_push(PerlIO *f,PerlIO_funcs *tab,const char *mode)
709 {
710  PerlIOl *l = NULL;
711  Newc('L',l,tab->size,char,PerlIOl);
712  if (l)
713   {
714    Zero(l,tab->size,char);
715    l->next = *f;
716    l->tab  = tab;
717    *f      = l;
718    PerlIOBase_init(f,mode);
719   }
720  return f;
721 }
722
723 SSize_t
724 PerlIOBase_unread(PerlIO *f, const void *vbuf, Size_t count)
725 {
726  Off_t old = PerlIO_tell(f);
727  if (PerlIO_seek(f,-((Off_t)count),SEEK_CUR) == 0)
728   {
729    Off_t new = PerlIO_tell(f);
730    return old - new;
731   }
732  return 0;
733 }
734
735 IV
736 PerlIOBase_sync(PerlIO *f)
737 {
738  return 0;
739 }
740
741 IV
742 PerlIOBase_close(PerlIO *f)
743 {
744  IV code = 0;
745  if (PerlIO_flush(f) != 0)
746   code = -1;
747  if (PerlIO_close(PerlIONext(f)) != 0)
748   code = -1;
749  PerlIOBase(f)->flags &= ~(PERLIO_F_CANREAD|PERLIO_F_CANWRITE|PERLIO_F_OPEN);
750  return code;
751 }
752
753 IV
754 PerlIOBase_eof(PerlIO *f)
755 {
756  if (f && *f)
757   {
758    return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
759   }
760  return 1;
761 }
762
763 IV
764 PerlIOBase_error(PerlIO *f)
765 {
766  if (f && *f)
767   {
768    return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
769   }
770  return 1;
771 }
772
773 void
774 PerlIOBase_clearerr(PerlIO *f)
775 {
776  if (f && *f)
777   {
778    PerlIOBase(f)->flags &= ~PERLIO_F_ERROR;
779   }
780 }
781
782 void
783 PerlIOBase_setlinebuf(PerlIO *f)
784 {
785
786 }
787
788
789
790 /*--------------------------------------------------------------------------------------*/
791 /* Bottom-most level for UNIX-like case */
792
793 typedef struct
794 {
795  struct _PerlIO base;       /* The generic part */
796  int            fd;         /* UNIX like file descriptor */
797  int            oflags;     /* open/fcntl flags */
798 } PerlIOUnix;
799
800 int
801 PerlIOUnix_oflags(const char *mode)
802 {
803  int oflags = -1;
804  switch(*mode)
805   {
806    case 'r':
807     oflags = O_RDONLY;
808     if (*++mode == '+')
809      {
810       oflags = O_RDWR;
811       mode++;
812      }
813     break;
814
815    case 'w':
816     oflags = O_CREAT|O_TRUNC;
817     if (*++mode == '+')
818      {
819       oflags |= O_RDWR;
820       mode++;
821      }
822     else
823      oflags |= O_WRONLY;
824     break;
825
826    case 'a':
827     oflags = O_CREAT|O_APPEND;
828     if (*++mode == '+')
829      {
830       oflags |= O_RDWR;
831       mode++;
832      }
833     else
834      oflags |= O_WRONLY;
835     break;
836   }
837  if (*mode || oflags == -1)
838   {
839    errno = EINVAL;
840    oflags = -1;
841   }
842  return oflags;
843 }
844
845 IV
846 PerlIOUnix_fileno(PerlIO *f)
847 {
848  return PerlIOSelf(f,PerlIOUnix)->fd;
849 }
850
851 PerlIO *
852 PerlIOUnix_fdopen(int fd,const char *mode)
853 {
854  PerlIO *f = NULL;
855  if (*mode == 'I')
856   mode++;
857  if (fd >= 0)
858   {
859    int oflags = PerlIOUnix_oflags(mode);
860    if (oflags != -1)
861     {
862      PerlIOUnix *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(),&PerlIO_unix,mode),PerlIOUnix);
863      s->fd     = fd;
864      s->oflags = oflags;
865      PerlIOBase(f)->flags |= PERLIO_F_OPEN;
866     }
867   }
868  return f;
869 }
870
871 PerlIO *
872 PerlIOUnix_open(const char *path,const char *mode)
873 {
874  PerlIO *f = NULL;
875  int oflags = PerlIOUnix_oflags(mode);
876  if (oflags != -1)
877   {
878    int fd = open(path,oflags,0666);
879    if (fd >= 0)
880     {
881      PerlIOUnix *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(),&PerlIO_unix,mode),PerlIOUnix);
882      s->fd     = fd;
883      s->oflags = oflags;
884      PerlIOBase(f)->flags |= PERLIO_F_OPEN;
885     }
886   }
887  return f;
888 }
889
890 int
891 PerlIOUnix_reopen(const char *path, const char *mode, PerlIO *f)
892 {
893  PerlIOUnix *s = PerlIOSelf(f,PerlIOUnix);
894  int oflags = PerlIOUnix_oflags(mode);
895  if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
896   (*PerlIOBase(f)->tab->Close)(f);
897  if (oflags != -1)
898   {
899    int fd = open(path,oflags,0666);
900    if (fd >= 0)
901     {
902      s->fd = fd;
903      s->oflags = oflags;
904      PerlIOBase(f)->flags |= PERLIO_F_OPEN;
905      return 0;
906     }
907   }
908  return -1;
909 }
910
911 SSize_t
912 PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count)
913 {
914  int fd = PerlIOSelf(f,PerlIOUnix)->fd;
915  while (1)
916   {
917    SSize_t len = read(fd,vbuf,count);
918    if (len >= 0 || errno != EINTR)
919     return len;
920   }
921 }
922
923 SSize_t
924 PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count)
925 {
926  int fd = PerlIOSelf(f,PerlIOUnix)->fd;
927  while (1)
928   {
929    SSize_t len = write(fd,vbuf,count);
930    if (len >= 0 || errno != EINTR)
931     return len;
932   }
933 }
934
935 IV
936 PerlIOUnix_seek(PerlIO *f, Off_t offset, int whence)
937 {
938  Off_t new = lseek(PerlIOSelf(f,PerlIOUnix)->fd,offset,whence);
939  return (new == (Off_t) -1) ? -1 : 0;
940 }
941
942 Off_t
943 PerlIOUnix_tell(PerlIO *f)
944 {
945  return lseek(PerlIOSelf(f,PerlIOUnix)->fd,0,SEEK_CUR);
946 }
947
948 IV
949 PerlIOUnix_close(PerlIO *f)
950 {
951  int fd = PerlIOSelf(f,PerlIOUnix)->fd;
952  int code = 0;
953  while (close(fd) != 0)
954   {
955    if (errno != EINTR)
956     {
957      code = -1;
958      break;
959     }
960   }
961  if (code == 0)
962   {
963    PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
964   }
965  return code;
966 }
967
968 PerlIO_funcs PerlIO_unix = {
969  "unix",
970  sizeof(PerlIOUnix),
971  0,
972  PerlIOUnix_fileno,
973  PerlIOUnix_fdopen,
974  PerlIOUnix_open,
975  PerlIOUnix_reopen,
976  PerlIOUnix_read,
977  PerlIOBase_unread,
978  PerlIOUnix_write,
979  PerlIOUnix_seek,
980  PerlIOUnix_tell,
981  PerlIOUnix_close,
982  PerlIOBase_sync,
983  PerlIOBase_eof,
984  PerlIOBase_error,
985  PerlIOBase_clearerr,
986  PerlIOBase_setlinebuf,
987  NULL, /* get_base */
988  NULL, /* get_bufsiz */
989  NULL, /* get_ptr */
990  NULL, /* get_cnt */
991  NULL, /* set_ptrcnt */
992 };
993
994 /*--------------------------------------------------------------------------------------*/
995 /* stdio as a layer */
996
997 typedef struct
998 {
999  struct _PerlIO base;
1000  FILE *         stdio;      /* The stream */
1001 } PerlIOStdio;
1002
1003 IV
1004 PerlIOStdio_fileno(PerlIO *f)
1005 {
1006  return fileno(PerlIOSelf(f,PerlIOStdio)->stdio);
1007 }
1008
1009
1010 PerlIO *
1011 PerlIOStdio_fdopen(int fd,const char *mode)
1012 {
1013  PerlIO *f = NULL;
1014  int init = 0;
1015  if (*mode == 'I')
1016   {
1017    init = 1;
1018    mode++;
1019   }
1020  if (fd >= 0)
1021   {
1022    FILE *stdio = NULL;
1023    if (init)
1024     {
1025      switch(fd)
1026       {
1027        case 0:
1028         stdio = stdin;
1029         break;
1030        case 1:
1031         stdio = stdout;
1032         break;
1033        case 2:
1034         stdio = stderr;
1035         break;
1036       }
1037     }
1038    else
1039     stdio = fdopen(fd,mode);
1040    if (stdio)
1041     {
1042      PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(),&PerlIO_stdio,mode),PerlIOStdio);
1043      s->stdio  = stdio;
1044     }
1045   }
1046  return f;
1047 }
1048
1049 #undef PerlIO_importFILE
1050 PerlIO *
1051 PerlIO_importFILE(FILE *stdio, int fl)
1052 {
1053  PerlIO *f = NULL;
1054  if (stdio)
1055   {
1056    PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(),&PerlIO_stdio,"r+"),PerlIOStdio);
1057    s->stdio  = stdio;
1058   }
1059  return f;
1060 }
1061
1062 PerlIO *
1063 PerlIOStdio_open(const char *path,const char *mode)
1064 {
1065  PerlIO *f = NULL;
1066  FILE *stdio = fopen(path,mode);
1067  if (stdio)
1068   {
1069    PerlIOStdio *s = PerlIOSelf(PerlIO_push(f = PerlIO_allocate(),&PerlIO_stdio,mode),PerlIOStdio);
1070    s->stdio  = stdio;
1071   }
1072  return f;
1073 }
1074
1075 int
1076 PerlIOStdio_reopen(const char *path, const char *mode, PerlIO *f)
1077 {
1078  PerlIOStdio *s = PerlIOSelf(f,PerlIOStdio);
1079  FILE *stdio = freopen(path,mode,s->stdio);
1080  if (!s->stdio)
1081   return -1;
1082  s->stdio = stdio;
1083  return 0;
1084 }
1085
1086 SSize_t
1087 PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count)
1088 {
1089  FILE *s = PerlIOSelf(f,PerlIOStdio)->stdio;
1090  SSize_t got = 0;
1091  if (count == 1)
1092   {
1093    STDCHAR *buf = (STDCHAR *) vbuf;
1094    /* Perl is expecting PerlIO_getc() to fill the buffer
1095     * Linux's stdio does not do that for fread()
1096     */
1097    int ch = fgetc(s);
1098    if (ch != EOF)
1099     {
1100      *buf = ch;
1101      got = 1;
1102     }
1103   }
1104  else
1105   got = fread(vbuf,1,count,s);
1106  return got;
1107 }
1108
1109 SSize_t
1110 PerlIOStdio_unread(PerlIO *f, const void *vbuf, Size_t count)
1111 {
1112  FILE *s = PerlIOSelf(f,PerlIOStdio)->stdio;
1113  STDCHAR *buf = ((STDCHAR *)vbuf)+count-1;
1114  SSize_t unread = 0;
1115  while (count > 0)
1116   {
1117    int ch = *buf-- & 0xff;
1118    if (ungetc(ch,s) != ch)
1119     break;
1120    unread++;
1121    count--;
1122   }
1123  return unread;
1124 }
1125
1126 SSize_t
1127 PerlIOStdio_write(PerlIO *f, const void *vbuf, Size_t count)
1128 {
1129  return fwrite(vbuf,1,count,PerlIOSelf(f,PerlIOStdio)->stdio);
1130 }
1131
1132 IV
1133 PerlIOStdio_seek(PerlIO *f, Off_t offset, int whence)
1134 {
1135  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1136  return fseek(stdio,offset,whence);
1137 }
1138
1139 Off_t
1140 PerlIOStdio_tell(PerlIO *f)
1141 {
1142  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1143  return ftell(stdio);
1144 }
1145
1146 IV
1147 PerlIOStdio_close(PerlIO *f)
1148 {
1149  return fclose(PerlIOSelf(f,PerlIOStdio)->stdio);
1150 }
1151
1152 IV
1153 PerlIOStdio_flush(PerlIO *f)
1154 {
1155  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1156  return fflush(stdio);
1157 }
1158
1159 IV
1160 PerlIOStdio_eof(PerlIO *f)
1161 {
1162  return feof(PerlIOSelf(f,PerlIOStdio)->stdio);
1163 }
1164
1165 IV
1166 PerlIOStdio_error(PerlIO *f)
1167 {
1168  return ferror(PerlIOSelf(f,PerlIOStdio)->stdio);
1169 }
1170
1171 void
1172 PerlIOStdio_clearerr(PerlIO *f)
1173 {
1174  clearerr(PerlIOSelf(f,PerlIOStdio)->stdio);
1175 }
1176
1177 void
1178 PerlIOStdio_setlinebuf(PerlIO *f)
1179 {
1180 #ifdef HAS_SETLINEBUF
1181  setlinebuf(PerlIOSelf(f,PerlIOStdio)->stdio);
1182 #else
1183  setvbuf(PerlIOSelf(f,PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
1184 #endif
1185 }
1186
1187 #ifdef FILE_base
1188 STDCHAR *
1189 PerlIOStdio_get_base(PerlIO *f)
1190 {
1191  FILE *stdio  = PerlIOSelf(f,PerlIOStdio)->stdio;
1192  return FILE_base(stdio);
1193 }
1194
1195 Size_t
1196 PerlIOStdio_get_bufsiz(PerlIO *f)
1197 {
1198  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1199  return FILE_bufsiz(stdio);
1200 }
1201 #endif
1202
1203 #ifdef USE_STDIO_PTR
1204 STDCHAR *
1205 PerlIOStdio_get_ptr(PerlIO *f)
1206 {
1207  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1208  return FILE_ptr(stdio);
1209 }
1210
1211 SSize_t
1212 PerlIOStdio_get_cnt(PerlIO *f)
1213 {
1214  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1215  return FILE_cnt(stdio);
1216 }
1217
1218 void
1219 PerlIOStdio_set_ptrcnt(PerlIO *f,STDCHAR *ptr,SSize_t cnt)
1220 {
1221  FILE *stdio = PerlIOSelf(f,PerlIOStdio)->stdio;
1222  if (ptr != NULL)
1223   {
1224 #ifdef STDIO_PTR_LVALUE
1225    FILE_ptr(stdio) = ptr;
1226 #ifdef STDIO_PTR_LVAL_SETS_CNT
1227    if (FILE_cnt(stdio) != (cnt))
1228     {
1229      dTHX;
1230      assert(FILE_cnt(stdio) == (cnt));
1231     }
1232 #endif
1233 #if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
1234    /* Setting ptr _does_ change cnt - we are done */
1235    return;
1236 #endif
1237 #else  /* STDIO_PTR_LVALUE */
1238    abort();
1239 #endif /* STDIO_PTR_LVALUE */
1240   }
1241 /* Now (or only) set cnt */
1242 #ifdef STDIO_CNT_LVALUE
1243  FILE_cnt(stdio) = cnt;
1244 #else  /* STDIO_CNT_LVALUE */
1245 #if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
1246  FILE_ptr(stdio) = FILE_ptr(stdio)+(FILE_cnt(stdio)-cnt);
1247 #else  /* STDIO_PTR_LVAL_SETS_CNT */
1248  abort();
1249 #endif /* STDIO_PTR_LVAL_SETS_CNT */
1250 #endif /* STDIO_CNT_LVALUE */
1251 }
1252
1253 #endif
1254
1255 PerlIO_funcs PerlIO_stdio = {
1256  "stdio",
1257  sizeof(PerlIOStdio),
1258  0,
1259  PerlIOStdio_fileno,
1260  PerlIOStdio_fdopen,
1261  PerlIOStdio_open,
1262  PerlIOStdio_reopen,
1263  PerlIOStdio_read,
1264  PerlIOStdio_unread,
1265  PerlIOStdio_write,
1266  PerlIOStdio_seek,
1267  PerlIOStdio_tell,
1268  PerlIOStdio_close,
1269  PerlIOStdio_flush,
1270  PerlIOStdio_eof,
1271  PerlIOStdio_error,
1272  PerlIOStdio_clearerr,
1273  PerlIOStdio_setlinebuf,
1274 #ifdef FILE_base
1275  PerlIOStdio_get_base,
1276  PerlIOStdio_get_bufsiz,
1277 #else
1278  NULL,
1279  NULL,
1280 #endif
1281 #ifdef USE_STDIO_PTR
1282  PerlIOStdio_get_ptr,
1283  PerlIOStdio_get_cnt,
1284 #if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
1285  PerlIOStdio_set_ptrcnt
1286 #else  /* STDIO_PTR_LVALUE */
1287  NULL
1288 #endif /* STDIO_PTR_LVALUE */
1289 #else  /* USE_STDIO_PTR */
1290  NULL,
1291  NULL,
1292  NULL
1293 #endif /* USE_STDIO_PTR */
1294 };
1295
1296 #undef PerlIO_exportFILE
1297 FILE *
1298 PerlIO_exportFILE(PerlIO *f, int fl)
1299 {
1300  PerlIO_flush(f);
1301  /* Should really push stdio discipline when we have them */
1302  return fdopen(PerlIO_fileno(f),"r+");
1303 }
1304
1305 #undef PerlIO_findFILE
1306 FILE *
1307 PerlIO_findFILE(PerlIO *f)
1308 {
1309  return PerlIO_exportFILE(f,0);
1310 }
1311
1312 #undef PerlIO_releaseFILE
1313 void
1314 PerlIO_releaseFILE(PerlIO *p, FILE *f)
1315 {
1316 }
1317
1318 /*--------------------------------------------------------------------------------------*/
1319 /* perlio buffer layer */
1320
1321 typedef struct
1322 {
1323  struct _PerlIO base;
1324  Off_t          posn;       /* Offset of buf into the file */
1325  STDCHAR *      buf;        /* Start of buffer */
1326  STDCHAR *      end;        /* End of valid part of buffer */
1327  STDCHAR *      ptr;        /* Current position in buffer */
1328  Size_t         bufsiz;     /* Size of buffer */
1329  IV             oneword;    /* Emergency buffer */
1330 } PerlIOBuf;
1331
1332
1333 PerlIO *
1334 PerlIOBuf_fdopen(int fd, const char *mode)
1335 {
1336  PerlIO_funcs *tab = PerlIO_default_btm();
1337  int init = 0;
1338  PerlIO *f;
1339  if (*mode == 'I')
1340   {
1341    init = 1;
1342    mode++;
1343   }
1344  f = (*tab->Fdopen)(fd,mode);
1345  if (f)
1346   {
1347    /* Initial stderr is unbuffered */
1348    if (!init || fd != 2)
1349     {
1350      PerlIOBuf *b = PerlIOSelf(PerlIO_push(f,&PerlIO_perlio,NULL),PerlIOBuf);
1351      b->posn = PerlIO_tell(PerlIONext(f));
1352     }
1353   }
1354  return f;
1355 }
1356
1357 PerlIO *
1358 PerlIOBuf_open(const char *path, const char *mode)
1359 {
1360  PerlIO_funcs *tab = PerlIO_default_btm();
1361  PerlIO *f = (*tab->Open)(path,mode);
1362  if (f)
1363   {
1364    PerlIOBuf *b = PerlIOSelf(PerlIO_push(f,&PerlIO_perlio,NULL),PerlIOBuf);
1365    b->posn = 0;
1366   }
1367  return f;
1368 }
1369
1370 int
1371 PerlIOBase_reopen(const char *path, const char *mode, PerlIO *f)
1372 {
1373  return (*PerlIOBase(f)->tab->Reopen)(path,mode,PerlIONext(f));
1374 }
1375
1376 void
1377 PerlIOBuf_alloc_buf(PerlIOBuf *b)
1378 {
1379  if (!b->bufsiz)
1380   b->bufsiz = 4096;
1381  New('B',b->buf,b->bufsiz,STDCHAR);
1382  if (!b->buf)
1383   {
1384    b->buf = (STDCHAR *)&b->oneword;
1385    b->bufsiz = sizeof(b->oneword);
1386   }
1387  b->ptr = b->buf;
1388  b->end = b->ptr;
1389 }
1390
1391 /* This "flush" is akin to sfio's sync in that it handles files in either
1392    read or write state
1393 */
1394 IV
1395 PerlIOBuf_flush(PerlIO *f)
1396 {
1397  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1398  int code = 0;
1399  if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
1400   {
1401    /* write() the buffer */
1402    STDCHAR *p = b->buf;
1403    int count;
1404    while (p < b->ptr)
1405     {
1406      count = PerlIO_write(PerlIONext(f),p,b->ptr - p);
1407      if (count > 0)
1408       {
1409        p += count;
1410       }
1411      else if (count < 0)
1412       {
1413        PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1414        code = -1;
1415        break;
1416       }
1417     }
1418    b->posn += (p - b->buf);
1419   }
1420  else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
1421   {
1422    /* Note position change */
1423    b->posn += (b->ptr - b->buf);
1424    if (b->ptr < b->end)
1425     {
1426      /* We did not consume all of it */
1427      if (PerlIO_seek(PerlIONext(f),b->posn,SEEK_SET) == 0)
1428       {
1429        b->posn = PerlIO_tell(PerlIONext(f));
1430       }
1431     }
1432   }
1433  b->ptr = b->end = b->buf;
1434  PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF|PERLIO_F_WRBUF);
1435  if (PerlIO_flush(PerlIONext(f)) != 0)
1436   code = -1;
1437  return code;
1438 }
1439
1440 SSize_t
1441 PerlIOBuf_read(PerlIO *f, void *vbuf, Size_t count)
1442 {
1443  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1444  STDCHAR *buf = (STDCHAR *) vbuf;
1445  if (f)
1446   {
1447    Size_t got = 0;
1448    if (!b->ptr)
1449     PerlIOBuf_alloc_buf(b);
1450    if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
1451     return 0;
1452    while (count > 0)
1453     {
1454      SSize_t avail = (b->end - b->ptr);
1455      if ((SSize_t) count < avail)
1456       avail = count;
1457      if (avail > 0)
1458       {
1459        Copy(b->ptr,buf,avail,char);
1460        got     += avail;
1461        b->ptr  += avail;
1462        count   -= avail;
1463        buf     += avail;
1464       }
1465      if (count && (b->ptr >= b->end))
1466       {
1467        PerlIO_flush(f);
1468        b->ptr = b->end = b->buf;
1469        avail = PerlIO_read(PerlIONext(f),b->ptr,b->bufsiz);
1470        if (avail <= 0)
1471         {
1472          if (avail == 0)
1473           PerlIOBase(f)->flags |= PERLIO_F_EOF;
1474          else
1475           PerlIOBase(f)->flags |= PERLIO_F_ERROR;
1476          break;
1477         }
1478        b->end      = b->buf+avail;
1479        PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
1480       }
1481     }
1482    return got;
1483   }
1484  return 0;
1485 }
1486
1487 SSize_t
1488 PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count)
1489 {
1490  const STDCHAR *buf = (const STDCHAR *) vbuf+count;
1491  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1492  SSize_t unread = 0;
1493  SSize_t avail;
1494  if (!b->buf)
1495   PerlIOBuf_alloc_buf(b);
1496  if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
1497   PerlIO_flush(f);
1498  if (b->buf)
1499   {
1500    if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
1501     {
1502      avail = (b->ptr - b->buf);
1503      if (avail > (SSize_t) count)
1504       avail = count;
1505      b->ptr -= avail;
1506     }
1507    else
1508     {
1509      avail = b->bufsiz;
1510      if (avail > (SSize_t) count)
1511       avail = count;
1512      b->end = b->ptr + avail;
1513     }
1514    if (avail > 0)
1515     {
1516      buf    -= avail;
1517      if (buf != b->ptr)
1518       {
1519        Copy(buf,b->ptr,avail,char);
1520       }
1521      count  -= avail;
1522      unread += avail;
1523      PerlIOBase(f)->flags &= ~ PERLIO_F_EOF;
1524     }
1525   }
1526  return unread;
1527 }
1528
1529 SSize_t
1530 PerlIOBuf_write(PerlIO *f, const void *vbuf, Size_t count)
1531 {
1532  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1533  const STDCHAR *buf = (const STDCHAR *) vbuf;
1534  Size_t written = 0;
1535  if (!b->buf)
1536   PerlIOBuf_alloc_buf(b);
1537  if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
1538   return 0;
1539  while (count > 0)
1540   {
1541    SSize_t avail = b->bufsiz - (b->ptr - b->buf);
1542    if ((SSize_t) count < avail)
1543     avail = count;
1544    PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
1545    if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF)
1546     {
1547      while (avail > 0)
1548       {
1549        int ch = *buf++;
1550        *(b->ptr)++ = ch;
1551        count--;
1552        avail--;
1553        written++;
1554        if (ch == '\n')
1555         {
1556          PerlIO_flush(f);
1557          break;
1558         }
1559       }
1560     }
1561    else
1562     {
1563      if (avail)
1564       {
1565        Copy(buf,b->ptr,avail,char);
1566        count   -= avail;
1567        buf     += avail;
1568        written += avail;
1569        b->ptr  += avail;
1570       }
1571     }
1572    if (b->ptr >= (b->buf + b->bufsiz))
1573     PerlIO_flush(f);
1574   }
1575  return written;
1576 }
1577
1578 IV
1579 PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence)
1580 {
1581  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1582  int code;
1583  code = PerlIO_flush(f);
1584  if (code == 0)
1585   {
1586    PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
1587    code = PerlIO_seek(PerlIONext(f),offset,whence);
1588    if (code == 0)
1589     {
1590      b->posn = PerlIO_tell(PerlIONext(f));
1591     }
1592   }
1593  return code;
1594 }
1595
1596 Off_t
1597 PerlIOBuf_tell(PerlIO *f)
1598 {
1599  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1600  Off_t posn = b->posn;
1601  if (b->buf)
1602   posn += (b->ptr - b->buf);
1603  return posn;
1604 }
1605
1606 IV
1607 PerlIOBuf_close(PerlIO *f)
1608 {
1609  IV code = PerlIOBase_close(f);
1610  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1611  if (b->buf && b->buf != (STDCHAR *) &b->oneword)
1612   {
1613    Safefree(b->buf);
1614   }
1615  b->buf = NULL;
1616  b->ptr = b->end = b->buf;
1617  PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF|PERLIO_F_WRBUF);
1618  return code;
1619 }
1620
1621 void
1622 PerlIOBuf_setlinebuf(PerlIO *f)
1623 {
1624  if (f)
1625   {
1626    PerlIOBase(f)->flags &= ~PERLIO_F_LINEBUF;
1627   }
1628 }
1629
1630 void
1631 PerlIOBuf_set_cnt(PerlIO *f, int cnt)
1632 {
1633  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1634  dTHX;
1635  if (!b->buf)
1636   PerlIOBuf_alloc_buf(b);
1637  b->ptr = b->end - cnt;
1638  assert(b->ptr >= b->buf);
1639 }
1640
1641 STDCHAR *
1642 PerlIOBuf_get_ptr(PerlIO *f)
1643 {
1644  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1645  if (!b->buf)
1646   PerlIOBuf_alloc_buf(b);
1647  return b->ptr;
1648 }
1649
1650 SSize_t
1651 PerlIOBuf_get_cnt(PerlIO *f)
1652 {
1653  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1654  if (!b->buf)
1655   PerlIOBuf_alloc_buf(b);
1656  if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
1657   return (b->end - b->ptr);
1658  return 0;
1659 }
1660
1661 STDCHAR *
1662 PerlIOBuf_get_base(PerlIO *f)
1663 {
1664  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1665  if (!b->buf)
1666   PerlIOBuf_alloc_buf(b);
1667  return b->buf;
1668 }
1669
1670 Size_t
1671 PerlIOBuf_bufsiz(PerlIO *f)
1672 {
1673  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1674  if (!b->buf)
1675   PerlIOBuf_alloc_buf(b);
1676  return (b->end - b->buf);
1677 }
1678
1679 void
1680 PerlIOBuf_set_ptrcnt(PerlIO *f, STDCHAR *ptr, SSize_t cnt)
1681 {
1682  PerlIOBuf *b = PerlIOSelf(f,PerlIOBuf);
1683  if (!b->buf)
1684   PerlIOBuf_alloc_buf(b);
1685  b->ptr = ptr;
1686  if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf)
1687   {
1688    dTHX;
1689    assert(PerlIO_get_cnt(f) == cnt);
1690    assert(b->ptr >= b->buf);
1691   }
1692  PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
1693 }
1694
1695 PerlIO_funcs PerlIO_perlio = {
1696  "perlio",
1697  sizeof(PerlIOBuf),
1698  0,
1699  PerlIOBase_fileno,
1700  PerlIOBuf_fdopen,
1701  PerlIOBuf_open,
1702  PerlIOBase_reopen,
1703  PerlIOBuf_read,
1704  PerlIOBuf_unread,
1705  PerlIOBuf_write,
1706  PerlIOBuf_seek,
1707  PerlIOBuf_tell,
1708  PerlIOBuf_close,
1709  PerlIOBuf_flush,
1710  PerlIOBase_eof,
1711  PerlIOBase_error,
1712  PerlIOBase_clearerr,
1713  PerlIOBuf_setlinebuf,
1714  PerlIOBuf_get_base,
1715  PerlIOBuf_bufsiz,
1716  PerlIOBuf_get_ptr,
1717  PerlIOBuf_get_cnt,
1718  PerlIOBuf_set_ptrcnt,
1719 };
1720
1721 void
1722 PerlIO_init(void)
1723 {
1724  if (!_perlio)
1725   {
1726    atexit(&PerlIO_cleanup);
1727   }
1728 }
1729
1730 #undef PerlIO_stdin
1731 PerlIO *
1732 PerlIO_stdin(void)
1733 {
1734  if (!_perlio)
1735   PerlIO_stdstreams();
1736  return &_perlio[1];
1737 }
1738
1739 #undef PerlIO_stdout
1740 PerlIO *
1741 PerlIO_stdout(void)
1742 {
1743  if (!_perlio)
1744   PerlIO_stdstreams();
1745  return &_perlio[2];
1746 }
1747
1748 #undef PerlIO_stderr
1749 PerlIO *
1750 PerlIO_stderr(void)
1751 {
1752  if (!_perlio)
1753   PerlIO_stdstreams();
1754  return &_perlio[3];
1755 }
1756
1757 /*--------------------------------------------------------------------------------------*/
1758
1759 #undef PerlIO_getname
1760 char *
1761 PerlIO_getname(PerlIO *f, char *buf)
1762 {
1763  dTHX;
1764  Perl_croak(aTHX_ "Don't know how to get file name");
1765  return NULL;
1766 }
1767
1768
1769 /*--------------------------------------------------------------------------------------*/
1770 /* Functions which can be called on any kind of PerlIO implemented
1771    in terms of above
1772 */
1773
1774 #undef PerlIO_getc
1775 int
1776 PerlIO_getc(PerlIO *f)
1777 {
1778  STDCHAR buf;
1779  int count = PerlIO_read(f,&buf,1);
1780  if (count == 1)
1781   return (unsigned char) buf;
1782  return -1;
1783 }
1784
1785 #undef PerlIO_putc
1786 int
1787 PerlIO_putc(PerlIO *f, int ch)
1788 {
1789  STDCHAR buf = ch;
1790  return PerlIO_write(f,&buf,1);
1791 }
1792
1793 #undef PerlIO_puts
1794 int
1795 PerlIO_puts(PerlIO *f, const char *s)
1796 {
1797  STRLEN len = strlen(s);
1798  return PerlIO_write(f,s,len);
1799 }
1800
1801 #undef PerlIO_rewind
1802 void
1803 PerlIO_rewind(PerlIO *f)
1804 {
1805  PerlIO_seek(f,(Off_t)0,SEEK_SET);
1806  PerlIO_clearerr(f);
1807 }
1808
1809 #undef PerlIO_vprintf
1810 int
1811 PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
1812 {
1813  dTHX;
1814  SV *sv = newSVpvn("",0);
1815  char *s;
1816  STRLEN len;
1817  sv_vcatpvf(sv, fmt, &ap);
1818  s = SvPV(sv,len);
1819  return PerlIO_write(f,s,len);
1820 }
1821
1822 #undef PerlIO_printf
1823 int
1824 PerlIO_printf(PerlIO *f,const char *fmt,...)
1825 {
1826  va_list ap;
1827  int result;
1828  va_start(ap,fmt);
1829  result = PerlIO_vprintf(f,fmt,ap);
1830  va_end(ap);
1831  return result;
1832 }
1833
1834 #undef PerlIO_stdoutf
1835 int
1836 PerlIO_stdoutf(const char *fmt,...)
1837 {
1838  va_list ap;
1839  int result;
1840  va_start(ap,fmt);
1841  result = PerlIO_vprintf(PerlIO_stdout(),fmt,ap);
1842  va_end(ap);
1843  return result;
1844 }
1845
1846 #undef PerlIO_tmpfile
1847 PerlIO *
1848 PerlIO_tmpfile(void)
1849 {
1850  dTHX;
1851  /* I have no idea how portable mkstemp() is ... */
1852  SV *sv = newSVpv("/tmp/PerlIO_XXXXXX",0);
1853  int fd = mkstemp(SvPVX(sv));
1854  PerlIO *f = NULL;
1855  if (fd >= 0)
1856   {
1857    f = PerlIO_fdopen(fd,"w+");
1858    if (f)
1859     {
1860      PerlIOBase(f)->flags |= PERLIO_F_TEMP;
1861     }
1862    unlink(SvPVX(sv));
1863    SvREFCNT_dec(sv);
1864   }
1865  return f;
1866 }
1867
1868 #undef HAS_FSETPOS
1869 #undef HAS_FGETPOS
1870
1871 #endif /* USE_SFIO */
1872 #endif /* PERLIO_IS_STDIO */
1873
1874 /*======================================================================================*/
1875 /* Now some functions in terms of above which may be needed even if
1876    we are not in true PerlIO mode
1877  */
1878
1879 #ifndef HAS_FSETPOS
1880 #undef PerlIO_setpos
1881 int
1882 PerlIO_setpos(PerlIO *f, const Fpos_t *pos)
1883 {
1884  return PerlIO_seek(f,*pos,0);
1885 }
1886 #else
1887 #ifndef PERLIO_IS_STDIO
1888 #undef PerlIO_setpos
1889 int
1890 PerlIO_setpos(PerlIO *f, const Fpos_t *pos)
1891 {
1892 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
1893  return fsetpos64(f, pos);
1894 #else
1895  return fsetpos(f, pos);
1896 #endif
1897 }
1898 #endif
1899 #endif
1900
1901 #ifndef HAS_FGETPOS
1902 #undef PerlIO_getpos
1903 int
1904 PerlIO_getpos(PerlIO *f, Fpos_t *pos)
1905 {
1906  *pos = PerlIO_tell(f);
1907  return 0;
1908 }
1909 #else
1910 #ifndef PERLIO_IS_STDIO
1911 #undef PerlIO_getpos
1912 int
1913 PerlIO_getpos(PerlIO *f, Fpos_t *pos)
1914 {
1915 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
1916  return fgetpos64(f, pos);
1917 #else
1918  return fgetpos(f, pos);
1919 #endif
1920 }
1921 #endif
1922 #endif
1923
1924 #if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
1925
1926 int
1927 vprintf(char *pat, char *args)
1928 {
1929     _doprnt(pat, args, stdout);
1930     return 0;           /* wrong, but perl doesn't use the return value */
1931 }
1932
1933 int
1934 vfprintf(FILE *fd, char *pat, char *args)
1935 {
1936     _doprnt(pat, args, fd);
1937     return 0;           /* wrong, but perl doesn't use the return value */
1938 }
1939
1940 #endif
1941
1942 #ifndef PerlIO_vsprintf
1943 int
1944 PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
1945 {
1946  int val = vsprintf(s, fmt, ap);
1947  if (n >= 0)
1948   {
1949    if (strlen(s) >= (STRLEN)n)
1950     {
1951      dTHX;
1952      PerlIO_puts(Perl_error_log,"panic: sprintf overflow - memory corrupted!\n");
1953      my_exit(1);
1954     }
1955   }
1956  return val;
1957 }
1958 #endif
1959
1960 #ifndef PerlIO_sprintf
1961 int
1962 PerlIO_sprintf(char *s, int n, const char *fmt,...)
1963 {
1964  va_list ap;
1965  int result;
1966  va_start(ap,fmt);
1967  result = PerlIO_vsprintf(s, n, fmt, ap);
1968  va_end(ap);
1969  return result;
1970 }
1971 #endif
1972
1973 #endif /* !PERL_IMPLICIT_SYS */
1974