Sat Nov 18 16:46:01 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu>
[kopensolaris-gnu/glibc.git] / libio / genops.c
1 /* 
2 Copyright (C) 1993, 1995 Free Software Foundation
3
4 This file is part of the GNU IO Library.  This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING.  If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
24
25 /* Generic or default I/O operations. */
26
27 #include "libioP.h"
28 #ifdef __STDC__
29 #include <stdlib.h>
30 #endif
31 #include <string.h>
32
33 void
34 DEFUN(_IO_un_link, (fp),
35       _IO_FILE *fp)
36 {
37   if (fp->_flags & _IO_LINKED) {
38     _IO_FILE **f;
39     for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain) {
40       if (*f == fp) {
41         *f = fp->_chain;
42         break;
43       }
44     }
45     fp->_flags &= ~_IO_LINKED;
46   }
47 }
48
49 void
50 DEFUN(_IO_link_in, (fp),
51       _IO_FILE *fp)
52 {
53     if ((fp->_flags & _IO_LINKED) == 0) {
54         fp->_flags |= _IO_LINKED;
55         fp->_chain = _IO_list_all;
56         _IO_list_all = fp;
57     }
58 }
59
60 /* Return minimum _pos markers
61    Assumes the current get area is the main get area. */
62
63 _IO_size_t
64 DEFUN(_IO_least_marker, (fp),
65       register _IO_FILE *fp)
66 {
67   _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base;
68   register struct _IO_marker *mark;
69   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
70     if (mark->_pos < least_so_far)
71       least_so_far = mark->_pos;
72   return least_so_far;
73 }
74
75 /* Switch current get area from backup buffer to (start of) main get area. */
76
77 void
78 DEFUN(_IO_switch_to_main_get_area, (fp),
79       _IO_FILE *fp)
80 {
81   char *tmp;
82   fp->_flags &= ~_IO_IN_BACKUP;
83   /* Swap _IO_read_end and _IO_save_end. */
84   tmp = fp->_IO_read_end; fp->_IO_read_end= fp->_IO_save_end; fp->_IO_save_end= tmp;
85   /* Swap _IO_read_base and _IO_save_base. */
86   tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp;
87   fp->_IO_read_ptr = fp->_IO_read_base;
88 }
89
90 /* Switch current get area from main get area to (end of) backup area. */
91
92 void
93 DEFUN(_IO_switch_to_backup_area, (fp),
94      register _IO_FILE *fp)
95 {
96   char *tmp;
97   fp->_flags |= _IO_IN_BACKUP;
98   /* Swap _IO_read_end and _IO_save_end. */
99   tmp = fp->_IO_read_end; fp->_IO_read_end = fp->_IO_save_end; fp->_IO_save_end = tmp;
100   /* Swap _gbase and _IO_save_base. */
101   tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp;
102   fp->_IO_read_ptr = fp->_IO_read_end;
103 }
104
105 int
106 DEFUN(_IO_switch_to_get_mode, (fp),
107      register _IO_FILE *fp)
108 {
109   if (fp->_IO_write_ptr > fp->_IO_write_base)
110     if (_IO_OVERFLOW (fp, EOF) == EOF)
111       return EOF;
112   if (_IO_in_backup(fp))
113     fp->_IO_read_base = fp->_IO_backup_base;
114   else
115     {
116       fp->_IO_read_base = fp->_IO_buf_base;
117       if (fp->_IO_write_ptr > fp->_IO_read_end)
118         fp->_IO_read_end = fp->_IO_write_ptr;
119     }
120   fp->_IO_read_ptr = fp->_IO_write_ptr;
121
122   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
123
124   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
125   return 0;
126 }
127
128 void
129 DEFUN(_IO_free_backup_area, (fp),
130      register _IO_FILE *fp)
131 {
132   if (_IO_in_backup (fp))
133     _IO_switch_to_main_get_area(fp);  /* Just in case. */
134   free (fp->_IO_save_base);
135   fp->_IO_save_base = NULL;
136   fp->_IO_save_end = NULL;
137   fp->_IO_backup_base = NULL;
138 }
139
140 #if 0
141 int
142 DEFUN(_IO_switch_to_put_mode, (fp),
143       register _IO_FILE *fp)
144 {
145   fp->_IO_write_base = fp->_IO_read_ptr;
146   fp->_IO_write_ptr = fp->_IO_read_ptr;
147   /* Following is wrong if line- or un-buffered? */
148   fp->_IO_write_end = fp->_flags & _IO_IN_BACKUP ? fp->_IO_read_end : fp->_IO_buf_end;
149
150   fp->_IO_read_ptr = fp->_IO_read_end;
151   fp->_IO_read_base = fp->_IO_read_end;
152
153   fp->_flags |= _IO_CURRENTLY_PUTTING;
154   return 0;
155 }
156 #endif
157
158 int
159 DEFUN(__overflow, (f, ch),
160       _IO_FILE *f AND int ch)
161 {
162   return _IO_OVERFLOW (f, ch);
163 }
164
165 static int
166 DEFUN(save_for_backup, (fp),
167       _IO_FILE *fp)
168 {
169   /* Append [_IO_read_base.._IO_read_end] to backup area. */
170   int least_mark = _IO_least_marker(fp);
171   /* needed_size is how much space we need in the backup area. */
172   int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark;
173   int current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
174   int avail; /* Extra space available for future expansion. */
175   int delta;
176   struct _IO_marker *mark;
177   if (needed_size > current_Bsize)
178     {
179       char *new_buffer;
180       avail = 100;
181       new_buffer = (char*)malloc(avail+needed_size);
182       if (new_buffer == NULL)
183         return EOF;             /* FIXME */
184       if (least_mark < 0)
185         {
186           memcpy(new_buffer + avail,
187                  fp->_IO_save_end + least_mark,
188                  -least_mark);
189           memcpy(new_buffer +avail - least_mark,
190                  fp->_IO_read_base,
191                  fp->_IO_read_end - fp->_IO_read_base);
192         }
193       else
194         memcpy(new_buffer + avail,
195                fp->_IO_read_base + least_mark,
196                needed_size);
197       if (fp->_IO_save_base)
198         free (fp->_IO_save_base);
199       fp->_IO_save_base = new_buffer;
200       fp->_IO_save_end = new_buffer + avail + needed_size;
201     }
202   else
203     {
204       avail = current_Bsize - needed_size;
205       if (least_mark < 0)
206         {
207           memmove(fp->_IO_save_base + avail,
208                   fp->_IO_save_end + least_mark,
209                   -least_mark);
210           memcpy(fp->_IO_save_base + avail - least_mark,
211                  fp->_IO_read_base,
212                  fp->_IO_read_end - fp->_IO_read_base);
213         }
214       else if (needed_size > 0)
215         memcpy(fp->_IO_save_base + avail,
216                fp->_IO_read_base + least_mark,
217                needed_size);
218     }
219   /* FIXME: Dubious arithmetic if pointers are NULL */
220   fp->_IO_backup_base = fp->_IO_save_base + avail;
221   /* Adjust all the streammarkers. */
222   delta = fp->_IO_read_end - fp->_IO_read_base;
223   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
224     mark->_pos -= delta;
225   return 0;
226 }
227
228 int
229 DEFUN(__underflow, (fp),
230       _IO_FILE *fp)
231 {
232   if (_IO_in_put_mode(fp))
233     if (_IO_switch_to_get_mode(fp) == EOF) return EOF;
234   if (fp->_IO_read_ptr < fp->_IO_read_end)
235     return *(unsigned char*)fp->_IO_read_ptr;
236   if (_IO_in_backup(fp))
237     {
238       _IO_switch_to_main_get_area(fp);
239       if (fp->_IO_read_ptr < fp->_IO_read_end)
240         return *fp->_IO_read_ptr;
241     }
242   if (_IO_have_markers(fp))
243     {
244       if (save_for_backup (fp))
245         return EOF;
246     }
247   else if (_IO_have_backup(fp))
248     _IO_free_backup_area(fp);
249   return _IO_UNDERFLOW (fp);
250 }
251
252 int
253 DEFUN(__uflow, (fp),
254      _IO_FILE *fp)
255 {
256   if (_IO_in_put_mode(fp))
257     if (_IO_switch_to_get_mode(fp) == EOF) return EOF;
258   if (fp->_IO_read_ptr < fp->_IO_read_end)
259     return *(unsigned char*)fp->_IO_read_ptr++;
260   if (_IO_in_backup(fp))
261     {
262       _IO_switch_to_main_get_area(fp);
263       if (fp->_IO_read_ptr < fp->_IO_read_end)
264         return *fp->_IO_read_ptr++;
265     }
266   if (_IO_have_markers(fp))
267     {
268       if (save_for_backup (fp))
269         return EOF;
270     }
271   else if (_IO_have_backup(fp))
272     _IO_free_backup_area(fp);
273   return _IO_UFLOW (fp);
274 }
275
276 void
277 DEFUN(_IO_setb, (f, b, eb, a),
278       _IO_FILE *f AND char *b AND char *eb AND int a)
279 {
280   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
281     FREE_BUF(f->_IO_buf_base);
282   f->_IO_buf_base = b;
283   f->_IO_buf_end = eb;
284   if (a)
285     f->_flags &= ~_IO_USER_BUF;
286   else
287     f->_flags |= _IO_USER_BUF;
288 }
289
290 void
291 DEFUN(_IO_doallocbuf, (fp),
292       register _IO_FILE *fp)
293 {
294   if (fp->_IO_buf_base)
295     return;
296   if (!(fp->_flags & _IO_UNBUFFERED))
297     if (_IO_DOALLOCATE (fp) != EOF)
298       return;
299   _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0);
300 }
301
302 int
303 DEFUN(_IO_default_underflow, (fp),
304       _IO_FILE *fp)
305 {
306   return EOF;
307 }
308
309 int
310 DEFUN(_IO_default_uflow, (fp),
311       _IO_FILE *fp)
312 {
313   int ch = _IO_UNDERFLOW (fp);
314   if (ch == EOF)
315     return EOF;
316   return *(unsigned char*)fp->_IO_read_ptr++;
317 }
318
319 _IO_size_t
320 DEFUN(_IO_default_xsputn, (f, data, n),
321       register _IO_FILE *f AND const void *data AND _IO_size_t n)
322 {
323   register const char *s = (char*) data;
324   register _IO_size_t more = n;
325   if (more <= 0)
326     return 0;
327   for (;;)
328     {
329       _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
330       if (count > 0)
331         {
332           if (count > more)
333             count = more;
334           if (count > 20)
335             {
336               memcpy(f->_IO_write_ptr, s, count);
337               s += count;
338               f->_IO_write_ptr += count;
339             }
340           else if (count <= 0)
341             count = 0;
342           else
343             {
344               register char *p = f->_IO_write_ptr;
345               register _IO_ssize_t i;
346               for (i = count; --i >= 0; ) *p++ = *s++;
347               f->_IO_write_ptr = p;
348             }
349           more -= count;
350         }
351       if (more == 0 || __overflow(f, (unsigned char)*s++) == EOF)
352         break;
353       more--;
354     }
355   return n - more;
356 }
357
358 _IO_size_t
359 DEFUN(_IO_sgetn, (fp, data, n),
360       _IO_FILE *fp AND void *data AND _IO_size_t n)
361 {
362   /* FIXME handle putback buffer here! */
363   return _IO_XSGETN (fp, data, n);
364 }
365
366 _IO_size_t
367 DEFUN(_IO_default_xsgetn, (fp, data, n),
368       _IO_FILE *fp AND void *data AND _IO_size_t n)
369 {
370   register _IO_size_t more = n;
371   register char *s = (char*) data;
372   for (;;)
373     {
374       _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */
375       if (count > 0)
376         {
377           if (count > more)
378             count = more;
379           if (count > 20)
380             {
381               memcpy(s, fp->_IO_read_ptr, count);
382               s += count;
383               fp->_IO_read_ptr += count;
384             }
385           else if (count <= 0)
386             count = 0;
387           else
388             {
389               register char *p = fp->_IO_read_ptr;
390               register int i = (int)count;
391               while (--i >= 0) *s++ = *p++;
392               fp->_IO_read_ptr = p;
393             }
394             more -= count;
395         }
396       if (more == 0 || __underflow(fp) == EOF)
397         break;
398     }
399   return n - more;
400 }
401
402 int
403 DEFUN(_IO_sync, (fp),
404       register _IO_FILE *fp)
405 {
406   return 0;
407 }
408
409 _IO_FILE*
410 DEFUN(_IO_default_setbuf, (fp, p, len),
411       register _IO_FILE *fp AND char* p AND _IO_ssize_t len)
412 {
413     if (_IO_SYNC (fp) == EOF)
414         return NULL;
415     if (p == NULL || len == 0)
416       {
417         fp->_flags |= _IO_UNBUFFERED;
418         _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0);
419       }
420     else
421       {
422         fp->_flags &= ~_IO_UNBUFFERED;
423         _IO_setb(fp, p, p+len, 0);
424       }
425     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
426     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
427     return fp;
428 }
429
430 _IO_pos_t
431 DEFUN(_IO_default_seekpos, (fp, pos, mode),
432       _IO_FILE *fp AND _IO_pos_t pos AND int mode)
433 {
434   return _IO_SEEKOFF (fp, _IO_pos_as_off(pos), 0, mode);
435 }
436
437 int
438 DEFUN(_IO_default_doallocate, (fp),
439       _IO_FILE *fp)
440 {
441   char *buf = ALLOC_BUF(_IO_BUFSIZ);
442   if (buf == NULL)
443     return EOF;
444   _IO_setb(fp, buf, buf+_IO_BUFSIZ, 1);
445   return 1;
446 }
447
448 void
449 DEFUN(_IO_init, (fp, flags),
450       register _IO_FILE *fp AND int flags)
451 {
452   fp->_flags = _IO_MAGIC|flags;
453   fp->_IO_buf_base = NULL;
454   fp->_IO_buf_end = NULL;
455   fp->_IO_read_base = NULL;
456   fp->_IO_read_ptr = NULL;
457   fp->_IO_read_end = NULL;
458   fp->_IO_write_base = NULL;
459   fp->_IO_write_ptr = NULL;
460   fp->_IO_write_end = NULL;
461   fp->_chain = NULL; /* Not necessary. */
462
463   fp->_IO_save_base = NULL;
464   fp->_IO_backup_base = NULL;
465   fp->_IO_save_end = NULL;
466   fp->_markers = NULL;
467   fp->_cur_column = 0;
468 }
469
470 int
471 DEFUN(_IO_default_sync, (fp),
472       _IO_FILE *fp)
473 {
474   return 0;
475 }
476
477 /* The way the C++ classes are mapped into the C functions in the
478    current implementation, this function can get called twice! */
479
480 void
481 DEFUN(_IO_default_finish, (fp),
482       _IO_FILE *fp)
483 {
484   struct _IO_marker *mark;
485   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
486     {
487       FREE_BUF(fp->_IO_buf_base);
488       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
489     }
490
491   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
492     mark->_sbuf = NULL;
493
494   if (fp->_IO_save_base)
495     {
496       free (fp->_IO_save_base);
497       fp->_IO_save_base = NULL;
498     }
499
500   _IO_un_link(fp);
501 }
502
503 _IO_pos_t
504 DEFUN(_IO_default_seekoff, (fp, offset, dir, mode),
505       register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode)
506 {
507     return _IO_pos_BAD;
508 }
509
510 int
511 DEFUN(_IO_sputbackc, (fp, c),
512       register _IO_FILE *fp AND int c)
513 {
514   if (fp->_IO_read_ptr > fp->_IO_read_base
515       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
516     {
517       fp->_IO_read_ptr--;
518       return (unsigned char)c;
519     }
520   return _IO_PBACKFAIL (fp, c);
521 }
522
523 int
524 DEFUN(_IO_sungetc, (fp),
525       register _IO_FILE *fp)
526 {
527   if (fp->_IO_read_ptr > fp->_IO_read_base)
528     {
529       fp->_IO_read_ptr--;
530       return (unsigned char)*fp->_IO_read_ptr;
531     }
532   else
533     return _IO_PBACKFAIL (fp, EOF);
534 }
535
536 #if 0 /* Work in progress */
537 void
538 DEFUN(_IO_set_column, (fp, c),
539       register _IO_FILE *fp AND int c)
540 {
541   if (c == -1)
542     fp->_column = -1;
543   else
544     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
545 }
546 #else
547 int
548 DEFUN(_IO_set_column, (fp, i),
549       register _IO_FILE *fp AND int i)
550 {
551   fp->_cur_column = i+1;
552   return 0;
553 }
554 #endif
555
556
557 unsigned
558 DEFUN(_IO_adjust_column, (start, line, count),
559       unsigned start AND const char *line AND int count)
560 {
561   register const char *ptr = line + count;
562   while (ptr > line)
563     if (*--ptr == '\n')
564       return line + count - ptr - 1;
565   return start + count;
566 }
567
568 int
569 DEFUN(_IO_get_column, (fp),
570       register _IO_FILE *fp)
571 {
572   if (fp->_cur_column) 
573     return _IO_adjust_column(fp->_cur_column - 1,
574                               fp->_IO_write_base,
575                               fp->_IO_write_ptr - fp->_IO_write_base);
576   return -1;
577 }
578
579 int
580 DEFUN_VOID(_IO_flush_all)
581 {
582   int result = 0;
583   _IO_FILE *fp;
584   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
585     if (fp->_IO_write_ptr > fp->_IO_write_base
586         && _IO_OVERFLOW (fp, EOF) == EOF)
587       result = EOF;
588   return result;
589 }
590
591 void
592 DEFUN_VOID(_IO_flush_all_linebuffered)
593 {
594   _IO_FILE *fp;
595   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
596     if (fp->_flags & _IO_LINE_BUF)
597       _IO_OVERFLOW (fp, EOF);
598 }
599
600 void
601 DEFUN_VOID(_IO_unbuffer_all)
602 {
603   _IO_FILE *fp;
604   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
605     if (! (fp->_flags & _IO_UNBUFFERED))
606       _IO_SETBUF (fp, NULL, 0);
607 }
608
609 void
610 DEFUN_VOID(_IO_cleanup)
611 {
612   _IO_flush_all ();
613
614   /* We currently don't have a reliable mechanism for making sure that
615      C++ static destructors are executed in the correct order.
616      So it is possible that other static destructord might want to
617      write to cout - and they're supposed to be able to do so.
618
619      The following will make the standard streambufs be unbuffered, 
620      which forces any output from late destructors to be written out. */
621   _IO_unbuffer_all ();
622 }
623
624 void
625 DEFUN(_IO_init_marker, (marker, fp),
626       struct _IO_marker *marker AND _IO_FILE *fp)
627 {
628   marker->_sbuf = fp;
629   if (_IO_in_put_mode(fp))
630     _IO_switch_to_get_mode(fp);
631   if (_IO_in_backup(fp))
632     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
633   else
634     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
635   
636   /* Should perhaps sort the chain? */
637   marker->_next = fp->_markers;
638   fp->_markers = marker;
639 }
640
641 void
642 DEFUN(_IO_remove_marker, (marker),
643       register struct _IO_marker *marker)
644 {
645   /* Unlink from sb's chain. */
646   register struct _IO_marker **ptr = &marker->_sbuf->_markers;
647   for (; ; ptr = &(*ptr)->_next)
648     {
649       if (*ptr == NULL)
650         break;
651       else if (*ptr == marker)
652         {
653           *ptr = marker->_next;
654           return;
655         }
656     }
657 #if 0
658     if _sbuf has a backup area that is no longer needed, should we delete
659     it now, or wait until the next underflow?
660 #endif
661 }
662
663 #define BAD_DELTA EOF
664
665 int
666 DEFUN(_IO_marker_difference, (mark1, mark2),
667       struct _IO_marker *mark1 AND struct _IO_marker *mark2)
668 {
669   return mark1->_pos - mark2->_pos;
670 }
671
672 /* Return difference between MARK and current posistion of MARK's stream. */
673 int
674 DEFUN(_IO_marker_delta, (mark),
675       struct _IO_marker *mark)
676 {
677   int cur_pos;
678   if (mark->_sbuf == NULL)
679     return BAD_DELTA;
680   if (_IO_in_backup(mark->_sbuf))
681     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
682   else
683     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
684   return mark->_pos - cur_pos;
685 }
686
687 int
688 DEFUN(_IO_seekmark, (fp, mark, delta),
689       _IO_FILE *fp AND struct _IO_marker *mark AND int delta)
690 {
691   if (mark->_sbuf != fp)
692     return EOF;
693  if (mark->_pos >= 0)
694     {
695       if (_IO_in_backup(fp))
696         _IO_switch_to_main_get_area(fp);
697       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
698     }
699   else
700     {
701       if (!_IO_in_backup(fp))
702         _IO_switch_to_backup_area(fp);
703       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
704     }
705   return 0;
706 }
707
708 void
709 DEFUN(_IO_unsave_markers, (fp),
710      register _IO_FILE *fp)
711 {
712   register struct _IO_marker *mark = fp->_markers;
713   if (mark)
714     {
715 #ifdef TODO
716       streampos offset = seekoff(0, ios::cur, ios::in);
717       if (offset != EOF)
718         {
719           offset += eGptr() - Gbase();
720           for ( ; mark != NULL; mark = mark->_next)
721             mark->set_streampos(mark->_pos + offset);
722         }
723     else
724       {
725         for ( ; mark != NULL; mark = mark->_next)
726           mark->set_streampos(EOF);
727       }
728 #endif
729       fp->_markers = 0;
730     }
731
732   if (_IO_have_backup(fp))
733     _IO_free_backup_area(fp);
734 }
735
736 int
737 DEFUN(_IO_nobackup_pbackfail, (fp, c),
738      register _IO_FILE *fp AND int c)
739 {
740   if (fp->_IO_read_ptr > fp->_IO_read_base)
741         fp->_IO_read_ptr--;
742   if (c != EOF && *fp->_IO_read_ptr != c)
743       *fp->_IO_read_ptr = c;
744   return (unsigned char)c;
745 }
746
747 int
748 DEFUN(_IO_default_pbackfail, (fp, c),
749       register _IO_FILE *fp AND int c)
750 {
751   if (fp->_IO_read_ptr <= fp->_IO_read_base)
752       {
753         /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
754         if (_IO_have_backup(fp) && !_IO_in_backup(fp))
755           _IO_switch_to_backup_area(fp);
756         
757         if (!_IO_have_backup(fp))
758           {
759             /* No backup buffer: allocate one. */
760             /* Use nshort buffer, if unused? (probably not)  FIXME */
761             int backup_size = 128;
762             char *bbuf = (char*)malloc(backup_size);
763             if (bbuf == NULL)
764               return EOF;
765             fp->_IO_save_base = bbuf;
766             fp->_IO_save_end = fp->_IO_save_base + backup_size;
767             fp->_IO_backup_base = fp->_IO_save_end;
768             _IO_switch_to_backup_area(fp);
769           }
770         else if (fp->_IO_read_ptr <= fp->_IO_read_base)
771           {
772             /* Increase size of existing backup buffer. */
773             _IO_size_t new_size;
774             _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
775             char *new_buf;
776             new_size = 2 * old_size;
777             new_buf = (char*)malloc(new_size);
778             if (new_buf == NULL)
779               return EOF;
780             memcpy(new_buf+(new_size-old_size), fp->_IO_read_base, old_size);
781             free (fp->_IO_read_base);
782             _IO_setg(fp,
783                      new_buf, new_buf+(new_size-old_size), new_buf+new_size);
784             fp->_IO_backup_base = fp->_IO_read_ptr;
785           }
786       }
787   fp->_IO_read_ptr--;
788   if (c != EOF && *fp->_IO_read_ptr != c)
789     *fp->_IO_read_ptr = c;
790   return (unsigned char)*fp->_IO_read_ptr;
791 }
792
793 _IO_pos_t
794 DEFUN(_IO_default_seek, (fp, offset, dir),
795       _IO_FILE *fp AND _IO_off_t offset AND int dir)
796 {
797   return _IO_pos_BAD;
798 }
799
800 int
801 DEFUN(_IO_default_stat, (fp, st),
802       _IO_FILE *fp AND void* st)
803 {
804   return EOF;
805 }
806
807 _IO_ssize_t
808 DEFUN(_IO_default_read, (fp, data, n),
809       register _IO_FILE* fp AND void* data AND _IO_ssize_t n)
810 {
811   return -1;
812 }
813
814 _IO_ssize_t
815 DEFUN(_IO_default_write, (fp, data, n),
816       register _IO_FILE* fp AND const void* data AND _IO_ssize_t n)
817 {
818   return 0;
819 }
820
821
822 #ifdef TODO
823 #if defined(linux)
824 #define IO_CLEANUP ;
825 #endif
826
827 #ifdef IO_CLEANUP
828   IO_CLEANUP
829 #else
830 struct __io_defs {
831     __io_defs() { }
832     ~__io_defs() { _IO_cleanup(); }
833 };   
834 __io_defs io_defs__;
835 #endif
836
837 #endif /* TODO */