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