(_IO_default_seekpos): Change to use _IO_fpos64_t.
[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 void
714 _IO_init_marker (marker, fp)
715      struct _IO_marker *marker;
716      _IO_FILE *fp;
717 {
718   marker->_sbuf = fp;
719   if (_IO_in_put_mode (fp))
720     _IO_switch_to_get_mode (fp);
721   if (_IO_in_backup (fp))
722     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
723   else
724     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
725
726   /* Should perhaps sort the chain? */
727   marker->_next = fp->_markers;
728   fp->_markers = marker;
729 }
730
731 void
732 _IO_remove_marker (marker)
733      struct _IO_marker *marker;
734 {
735   /* Unlink from sb's chain. */
736   struct _IO_marker **ptr = &marker->_sbuf->_markers;
737   for (; ; ptr = &(*ptr)->_next)
738     {
739       if (*ptr == NULL)
740         break;
741       else if (*ptr == marker)
742         {
743           *ptr = marker->_next;
744           return;
745         }
746     }
747 #if 0
748     if _sbuf has a backup area that is no longer needed, should we delete
749     it now, or wait until the next underflow?
750 #endif
751 }
752
753 #define BAD_DELTA EOF
754
755 int
756 _IO_marker_difference (mark1, mark2)
757      struct _IO_marker *mark1;
758      struct _IO_marker *mark2;
759 {
760   return mark1->_pos - mark2->_pos;
761 }
762
763 /* Return difference between MARK and current position of MARK's stream. */
764 int
765 _IO_marker_delta (mark)
766      struct _IO_marker *mark;
767 {
768   int cur_pos;
769   if (mark->_sbuf == NULL)
770     return BAD_DELTA;
771   if (_IO_in_backup (mark->_sbuf))
772     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
773   else
774     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
775   return mark->_pos - cur_pos;
776 }
777
778 int
779 _IO_seekmark (fp, mark, delta)
780      _IO_FILE *fp;
781      struct _IO_marker *mark;
782      int delta;
783 {
784   if (mark->_sbuf != fp)
785     return EOF;
786  if (mark->_pos >= 0)
787     {
788       if (_IO_in_backup (fp))
789         _IO_switch_to_main_get_area (fp);
790       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
791     }
792   else
793     {
794       if (!_IO_in_backup (fp))
795         _IO_switch_to_backup_area (fp);
796       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
797     }
798   return 0;
799 }
800
801 void
802 _IO_unsave_markers (fp)
803      _IO_FILE *fp;
804 {
805   struct _IO_marker *mark = fp->_markers;
806   if (mark)
807     {
808 #ifdef TODO
809       streampos offset = seekoff (0, ios::cur, ios::in);
810       if (offset != EOF)
811         {
812           offset += eGptr () - Gbase ();
813           for ( ; mark != NULL; mark = mark->_next)
814             mark->set_streampos (mark->_pos + offset);
815         }
816     else
817       {
818         for ( ; mark != NULL; mark = mark->_next)
819           mark->set_streampos (EOF);
820       }
821 #endif
822       fp->_markers = 0;
823     }
824
825   if (_IO_have_backup (fp))
826     _IO_free_backup_area (fp);
827 }
828
829 #if 0
830 /* Seems not to be needed. --drepper */
831 int
832 _IO_nobackup_pbackfail (fp, c)
833      _IO_FILE *fp;
834      int c;
835 {
836   if (fp->_IO_read_ptr > fp->_IO_read_base)
837         fp->_IO_read_ptr--;
838   if (c != EOF && *fp->_IO_read_ptr != c)
839       *fp->_IO_read_ptr = c;
840   return (unsigned char) c;
841 }
842 #endif
843
844 int
845 _IO_default_pbackfail (fp, c)
846      _IO_FILE *fp;
847      int c;
848 {
849   if (fp->_IO_read_ptr <= fp->_IO_read_base)
850     {
851       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
852       if (_IO_have_backup (fp) && !_IO_in_backup (fp))
853         _IO_switch_to_backup_area (fp);
854
855       if (!_IO_have_backup (fp))
856         {
857           /* No backup buffer: allocate one. */
858           /* Use nshort buffer, if unused? (probably not)  FIXME */
859           int backup_size = 128;
860           char *bbuf = (char *) malloc (backup_size);
861           if (bbuf == NULL)
862             return EOF;
863           fp->_IO_save_base = bbuf;
864           fp->_IO_save_end = fp->_IO_save_base + backup_size;
865           fp->_IO_backup_base = fp->_IO_save_end;
866           _IO_switch_to_backup_area (fp);
867         }
868       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
869         {
870           /* Increase size of existing backup buffer. */
871           _IO_size_t new_size;
872           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
873           char *new_buf;
874           new_size = 2 * old_size;
875           new_buf = (char *) malloc (new_size);
876           if (new_buf == NULL)
877             return EOF;
878           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
879                   old_size);
880           free (fp->_IO_read_base);
881           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
882                     new_buf + new_size);
883           fp->_IO_backup_base = fp->_IO_read_ptr;
884         }
885     }
886   --fp->_IO_read_ptr;
887   if (c != EOF && *fp->_IO_read_ptr != c)
888     *fp->_IO_read_ptr = c;
889   return (unsigned char) *fp->_IO_read_ptr;
890 }
891
892 _IO_fpos64_t
893 _IO_default_seek (fp, offset, dir)
894      _IO_FILE *fp;
895      _IO_off64_t offset;
896      int dir;
897 {
898   return _IO_pos_BAD;
899 }
900
901 int
902 _IO_default_stat (fp, st)
903      _IO_FILE *fp;
904      void* st;
905 {
906   return EOF;
907 }
908
909 _IO_ssize_t
910 _IO_default_read (fp, data, n)
911      _IO_FILE* fp;
912      void *data;
913      _IO_ssize_t n;
914 {
915   return -1;
916 }
917
918 _IO_ssize_t
919 _IO_default_write (fp, data, n)
920      _IO_FILE *fp;
921      const void *data;
922      _IO_ssize_t n;
923 {
924   return 0;
925 }
926
927 int
928 _IO_default_showmanyc (fp)
929      _IO_FILE *fp;
930 {
931   return -1;
932 }
933
934 void
935 _IO_default_imbue (fp, locale)
936      _IO_FILE *fp;
937      void *locale;
938 {
939 }
940
941
942 #ifdef TODO
943 #if defined(linux)
944 #define IO_CLEANUP ;
945 #endif
946
947 #ifdef IO_CLEANUP
948   IO_CLEANUP
949 #else
950 struct __io_defs {
951     __io_defs() { }
952     ~__io_defs() { _IO_cleanup (); }
953 };
954 __io_defs io_defs__;
955 #endif
956
957 #endif /* TODO */
958
959 #ifdef weak_alias
960 weak_alias (_IO_cleanup, _cleanup)
961 #endif
962
963 #ifdef text_set_element
964 text_set_element(__libc_atexit, _cleanup);
965 #endif