(_IO_init): Set _vtable_offset to 0.
[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 #ifdef _LIBC
214           __mempcpy (__mempcpy (new_buffer + avail,
215                                 fp->_IO_save_end + least_mark,
216                                 -least_mark),
217                      fp->_IO_read_base,
218                      fp->_IO_read_end - fp->_IO_read_base);
219 #else
220           memcpy (new_buffer + avail,
221                   fp->_IO_save_end + least_mark,
222                   -least_mark);
223           memcpy (new_buffer + avail - least_mark,
224                   fp->_IO_read_base,
225                   fp->_IO_read_end - fp->_IO_read_base);
226 #endif
227         }
228       else
229         memcpy (new_buffer + avail,
230                 fp->_IO_read_base + least_mark,
231                 needed_size);
232       if (fp->_IO_save_base)
233         free (fp->_IO_save_base);
234       fp->_IO_save_base = new_buffer;
235       fp->_IO_save_end = new_buffer + avail + needed_size;
236     }
237   else
238     {
239       avail = current_Bsize - needed_size;
240       if (least_mark < 0)
241         {
242           memmove (fp->_IO_save_base + avail,
243                    fp->_IO_save_end + least_mark,
244                    -least_mark);
245           memcpy (fp->_IO_save_base + avail - least_mark,
246                   fp->_IO_read_base,
247                   fp->_IO_read_end - fp->_IO_read_base);
248         }
249       else if (needed_size > 0)
250         memcpy (fp->_IO_save_base + avail,
251                 fp->_IO_read_base + least_mark,
252                 needed_size);
253     }
254   /* FIXME: Dubious arithmetic if pointers are NULL */
255   fp->_IO_backup_base = fp->_IO_save_base + avail;
256   /* Adjust all the streammarkers. */
257   delta = fp->_IO_read_end - fp->_IO_read_base;
258   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
259     mark->_pos -= delta;
260   return 0;
261 }
262
263 int
264 __underflow (fp)
265      _IO_FILE *fp;
266 {
267   if (_IO_in_put_mode (fp))
268     if (_IO_switch_to_get_mode (fp) == EOF)
269       return EOF;
270   if (fp->_IO_read_ptr < fp->_IO_read_end)
271     return *(unsigned char *) fp->_IO_read_ptr;
272   if (_IO_in_backup (fp))
273     {
274       _IO_switch_to_main_get_area (fp);
275       if (fp->_IO_read_ptr < fp->_IO_read_end)
276         return *fp->_IO_read_ptr;
277     }
278   if (_IO_have_markers (fp))
279     {
280       if (save_for_backup (fp))
281         return EOF;
282     }
283   else if (_IO_have_backup (fp))
284     _IO_free_backup_area (fp);
285   return _IO_UNDERFLOW (fp);
286 }
287
288 int
289 __uflow (fp)
290      _IO_FILE *fp;
291 {
292   if (_IO_in_put_mode (fp))
293     if (_IO_switch_to_get_mode (fp) == EOF)
294       return EOF;
295   if (fp->_IO_read_ptr < fp->_IO_read_end)
296     return *(unsigned char *) fp->_IO_read_ptr++;
297   if (_IO_in_backup (fp))
298     {
299       _IO_switch_to_main_get_area (fp);
300       if (fp->_IO_read_ptr < fp->_IO_read_end)
301         return *fp->_IO_read_ptr++;
302     }
303   if (_IO_have_markers (fp))
304     {
305       if (save_for_backup (fp))
306         return EOF;
307     }
308   else if (_IO_have_backup (fp))
309     _IO_free_backup_area (fp);
310   return _IO_UFLOW (fp);
311 }
312
313 void
314 _IO_setb (f, b, eb, a)
315      _IO_FILE *f;
316       char *b;
317      char *eb;
318      int a;
319 {
320   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
321     FREE_BUF (f->_IO_buf_base, _IO_blen (f));
322   f->_IO_buf_base = b;
323   f->_IO_buf_end = eb;
324   if (a)
325     f->_flags &= ~_IO_USER_BUF;
326   else
327     f->_flags |= _IO_USER_BUF;
328 }
329
330 void
331 _IO_doallocbuf (fp)
332      _IO_FILE *fp;
333 {
334   if (fp->_IO_buf_base)
335     return;
336   if (!(fp->_flags & _IO_UNBUFFERED))
337     if (_IO_DOALLOCATE (fp) != EOF)
338       return;
339   _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
340 }
341
342 int
343 _IO_default_underflow (fp)
344      _IO_FILE *fp;
345 {
346   return EOF;
347 }
348
349 int
350 _IO_default_uflow (fp)
351      _IO_FILE *fp;
352 {
353   int ch = _IO_UNDERFLOW (fp);
354   if (ch == EOF)
355     return EOF;
356   return *(unsigned char *) fp->_IO_read_ptr++;
357 }
358
359 _IO_size_t
360 _IO_default_xsputn (f, data, n)
361      _IO_FILE *f;
362      const void *data;
363      _IO_size_t n;
364 {
365   const char *s = (char *) data;
366   _IO_size_t more = n;
367   if (more <= 0)
368     return 0;
369   for (;;)
370     {
371       /* Space available. */
372       _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr;
373       if (count > 0)
374         {
375           if ((_IO_size_t) count > more)
376             count = more;
377           if (count > 20)
378             {
379 #ifdef _LIBC
380               f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
381 #else
382               memcpy (f->_IO_write_ptr, s, count);
383               f->_IO_write_ptr += count;
384 #endif
385               s += count;
386             }
387           else if (count <= 0)
388             count = 0;
389           else
390             {
391               char *p = f->_IO_write_ptr;
392               _IO_ssize_t i;
393               for (i = count; --i >= 0; )
394                 *p++ = *s++;
395               f->_IO_write_ptr = p;
396             }
397           more -= count;
398         }
399       if (more == 0 || __overflow (f, (unsigned char) *s++) == EOF)
400         break;
401       more--;
402     }
403   return n - more;
404 }
405
406 _IO_size_t
407 _IO_sgetn (fp, data, n)
408      _IO_FILE *fp;
409      void *data;
410      _IO_size_t n;
411 {
412   /* FIXME handle putback buffer here! */
413   return _IO_XSGETN (fp, data, n);
414 }
415
416 _IO_size_t
417 _IO_default_xsgetn (fp, data, n)
418      _IO_FILE *fp;
419      void *data;
420      _IO_size_t n;
421 {
422   _IO_size_t more = n;
423   char *s = (char*) data;
424   for (;;)
425     {
426       /* Data available. */
427       _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr;
428       if (count > 0)
429         {
430           if ((_IO_size_t) count > more)
431             count = more;
432           if (count > 20)
433             {
434 #ifdef _LIBC
435               s = __mempcpy (s, fp->_IO_read_ptr, count);
436 #else
437               memcpy (s, fp->_IO_read_ptr, count);
438               s += count;
439 #endif
440               fp->_IO_read_ptr += count;
441             }
442           else if (count <= 0)
443             count = 0;
444           else
445             {
446               char *p = fp->_IO_read_ptr;
447               int i = (int) count;
448               while (--i >= 0)
449                 *s++ = *p++;
450               fp->_IO_read_ptr = p;
451             }
452             more -= count;
453         }
454       if (more == 0 || __underflow (fp) == EOF)
455         break;
456     }
457   return n - more;
458 }
459
460 #if 0
461 /* Seems not to be needed. --drepper */
462 int
463 _IO_sync (fp)
464      _IO_FILE *fp;
465 {
466   return 0;
467 }
468 #endif
469
470 _IO_FILE *
471 _IO_default_setbuf (fp, p, len)
472      _IO_FILE *fp;
473      char *p;
474      _IO_ssize_t len;
475 {
476     if (_IO_SYNC (fp) == EOF)
477         return NULL;
478     if (p == NULL || len == 0)
479       {
480         fp->_flags |= _IO_UNBUFFERED;
481         _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
482       }
483     else
484       {
485         fp->_flags &= ~_IO_UNBUFFERED;
486         _IO_setb (fp, p, p+len, 0);
487       }
488     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
489     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
490     return fp;
491 }
492
493 _IO_fpos64_t
494 _IO_default_seekpos (fp, pos, mode)
495      _IO_FILE *fp;
496      _IO_fpos64_t pos;
497      int mode;
498 {
499   return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode);
500 }
501
502 int
503 _IO_default_doallocate (fp)
504      _IO_FILE *fp;
505 {
506   char *buf;
507
508   ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
509   _IO_setb (fp, buf, buf+_IO_BUFSIZ, 1);
510   return 1;
511 }
512
513 void
514 _IO_init (fp, flags)
515      _IO_FILE *fp;
516      int flags;
517 {
518   fp->_flags = _IO_MAGIC|flags;
519   fp->_IO_buf_base = NULL;
520   fp->_IO_buf_end = NULL;
521   fp->_IO_read_base = NULL;
522   fp->_IO_read_ptr = NULL;
523   fp->_IO_read_end = NULL;
524   fp->_IO_write_base = NULL;
525   fp->_IO_write_ptr = NULL;
526   fp->_IO_write_end = NULL;
527   fp->_chain = NULL; /* Not necessary. */
528
529   fp->_IO_save_base = NULL;
530   fp->_IO_backup_base = NULL;
531   fp->_IO_save_end = NULL;
532   fp->_markers = NULL;
533   fp->_cur_column = 0;
534 #if _IO_JUMPS_OFFSET
535   fp->_vtable_offset = 0;
536 #endif
537 #ifdef _IO_MTSAFE_IO
538   _IO_lock_init (*fp->_lock);
539 #endif
540 }
541
542 int
543 _IO_default_sync (fp)
544      _IO_FILE *fp;
545 {
546   return 0;
547 }
548
549 /* The way the C++ classes are mapped into the C functions in the
550    current implementation, this function can get called twice! */
551
552 void
553 _IO_default_finish (fp, dummy)
554      _IO_FILE *fp;
555      int dummy;
556 {
557   struct _IO_marker *mark;
558   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
559     {
560       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
561       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
562     }
563
564   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
565     mark->_sbuf = NULL;
566
567   if (fp->_IO_save_base)
568     {
569       free (fp->_IO_save_base);
570       fp->_IO_save_base = NULL;
571     }
572
573 #ifdef _IO_MTSAFE_IO
574   _IO_lock_fini (*fp->_lock);
575 #endif
576
577   _IO_un_link (fp);
578 }
579
580 _IO_fpos64_t
581 _IO_default_seekoff (fp, offset, dir, mode)
582      _IO_FILE *fp;
583      _IO_off64_t offset;
584      int dir;
585      int mode;
586 {
587     return _IO_pos_BAD;
588 }
589
590 int
591 _IO_sputbackc (fp, c)
592      _IO_FILE *fp;
593      int c;
594 {
595   int result;
596
597   if (fp->_IO_read_ptr > fp->_IO_read_base
598       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
599     {
600       fp->_IO_read_ptr--;
601       result = (unsigned char) c;
602     }
603   else
604     result = _IO_PBACKFAIL (fp, c);
605
606   if (result != EOF)
607     fp->_flags &= ~_IO_EOF_SEEN;
608
609   return result;
610 }
611
612 int
613 _IO_sungetc (fp)
614      _IO_FILE *fp;
615 {
616   int result;
617
618   if (fp->_IO_read_ptr > fp->_IO_read_base)
619     {
620       fp->_IO_read_ptr--;
621       result = (unsigned char) *fp->_IO_read_ptr;
622     }
623   else
624     result = _IO_PBACKFAIL (fp, EOF);
625
626   if (result != EOF)
627     fp->_flags &= ~_IO_EOF_SEEN;
628
629   return result;
630 }
631
632 #if 0 /* Work in progress */
633 /* Seems not to be needed.  */
634 #if 0
635 void
636 _IO_set_column (fp, c)
637      _IO_FILE *fp;
638      int c;
639 {
640   if (c == -1)
641     fp->_column = -1;
642   else
643     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
644 }
645 #else
646 int
647 _IO_set_column (fp, i)
648      _IO_FILE *fp;
649      int i;
650 {
651   fp->_cur_column = i + 1;
652   return 0;
653 }
654 #endif
655 #endif
656
657
658 unsigned
659 _IO_adjust_column (start, line, count)
660      unsigned start;
661      const char *line;
662      int count;
663 {
664   const char *ptr = line + count;
665   while (ptr > line)
666     if (*--ptr == '\n')
667       return line + count - ptr - 1;
668   return start + count;
669 }
670
671 #if 0
672 /* Seems not to be needed. --drepper */
673 int
674 _IO_get_column (fp)
675      _IO_FILE *fp;
676 {
677   if (fp->_cur_column)
678     return _IO_adjust_column (fp->_cur_column - 1,
679                               fp->_IO_write_base,
680                               fp->_IO_write_ptr - fp->_IO_write_base);
681   return -1;
682 }
683 #endif
684
685 int
686 _IO_flush_all ()
687 {
688   int result = 0;
689   _IO_FILE *fp;
690   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
691     if (fp->_IO_write_ptr > fp->_IO_write_base
692         && _IO_OVERFLOW (fp, EOF) == EOF)
693       result = EOF;
694   return result;
695 }
696
697 void
698 _IO_flush_all_linebuffered ()
699 {
700   _IO_FILE *fp;
701   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
702     if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
703       _IO_OVERFLOW (fp, EOF);
704 }
705
706 static void _IO_unbuffer_all __P ((void));
707
708 static void
709 _IO_unbuffer_all ()
710 {
711   _IO_FILE *fp;
712   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
713     if (! (fp->_flags & _IO_UNBUFFERED))
714       _IO_SETBUF (fp, NULL, 0);
715 }
716
717 void
718 _IO_cleanup ()
719 {
720   _IO_flush_all ();
721
722   /* We currently don't have a reliable mechanism for making sure that
723      C++ static destructors are executed in the correct order.
724      So it is possible that other static destructors might want to
725      write to cout - and they're supposed to be able to do so.
726
727      The following will make the standard streambufs be unbuffered,
728      which forces any output from late destructors to be written out. */
729   _IO_unbuffer_all ();
730 }
731
732
733 void
734 _IO_init_marker (marker, fp)
735      struct _IO_marker *marker;
736      _IO_FILE *fp;
737 {
738   marker->_sbuf = fp;
739   if (_IO_in_put_mode (fp))
740     _IO_switch_to_get_mode (fp);
741   if (_IO_in_backup (fp))
742     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
743   else
744     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
745
746   /* Should perhaps sort the chain? */
747   marker->_next = fp->_markers;
748   fp->_markers = marker;
749 }
750
751 void
752 _IO_remove_marker (marker)
753      struct _IO_marker *marker;
754 {
755   /* Unlink from sb's chain. */
756   struct _IO_marker **ptr = &marker->_sbuf->_markers;
757   for (; ; ptr = &(*ptr)->_next)
758     {
759       if (*ptr == NULL)
760         break;
761       else if (*ptr == marker)
762         {
763           *ptr = marker->_next;
764           return;
765         }
766     }
767 #if 0
768     if _sbuf has a backup area that is no longer needed, should we delete
769     it now, or wait until the next underflow?
770 #endif
771 }
772
773 #define BAD_DELTA EOF
774
775 int
776 _IO_marker_difference (mark1, mark2)
777      struct _IO_marker *mark1;
778      struct _IO_marker *mark2;
779 {
780   return mark1->_pos - mark2->_pos;
781 }
782
783 /* Return difference between MARK and current position of MARK's stream. */
784 int
785 _IO_marker_delta (mark)
786      struct _IO_marker *mark;
787 {
788   int cur_pos;
789   if (mark->_sbuf == NULL)
790     return BAD_DELTA;
791   if (_IO_in_backup (mark->_sbuf))
792     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
793   else
794     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
795   return mark->_pos - cur_pos;
796 }
797
798 int
799 _IO_seekmark (fp, mark, delta)
800      _IO_FILE *fp;
801      struct _IO_marker *mark;
802      int delta;
803 {
804   if (mark->_sbuf != fp)
805     return EOF;
806  if (mark->_pos >= 0)
807     {
808       if (_IO_in_backup (fp))
809         _IO_switch_to_main_get_area (fp);
810       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
811     }
812   else
813     {
814       if (!_IO_in_backup (fp))
815         _IO_switch_to_backup_area (fp);
816       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
817     }
818   return 0;
819 }
820
821 void
822 _IO_unsave_markers (fp)
823      _IO_FILE *fp;
824 {
825   struct _IO_marker *mark = fp->_markers;
826   if (mark)
827     {
828 #ifdef TODO
829       streampos offset = seekoff (0, ios::cur, ios::in);
830       if (offset != EOF)
831         {
832           offset += eGptr () - Gbase ();
833           for ( ; mark != NULL; mark = mark->_next)
834             mark->set_streampos (mark->_pos + offset);
835         }
836     else
837       {
838         for ( ; mark != NULL; mark = mark->_next)
839           mark->set_streampos (EOF);
840       }
841 #endif
842       fp->_markers = 0;
843     }
844
845   if (_IO_have_backup (fp))
846     _IO_free_backup_area (fp);
847 }
848
849 #if 0
850 /* Seems not to be needed. --drepper */
851 int
852 _IO_nobackup_pbackfail (fp, c)
853      _IO_FILE *fp;
854      int c;
855 {
856   if (fp->_IO_read_ptr > fp->_IO_read_base)
857         fp->_IO_read_ptr--;
858   if (c != EOF && *fp->_IO_read_ptr != c)
859       *fp->_IO_read_ptr = c;
860   return (unsigned char) c;
861 }
862 #endif
863
864 int
865 _IO_default_pbackfail (fp, c)
866      _IO_FILE *fp;
867      int c;
868 {
869   if (fp->_IO_read_ptr <= fp->_IO_read_base)
870     {
871       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
872       if (_IO_have_backup (fp) && !_IO_in_backup (fp))
873         _IO_switch_to_backup_area (fp);
874
875       if (!_IO_have_backup (fp))
876         {
877           /* No backup buffer: allocate one. */
878           /* Use nshort buffer, if unused? (probably not)  FIXME */
879           int backup_size = 128;
880           char *bbuf = (char *) malloc (backup_size);
881           if (bbuf == NULL)
882             return EOF;
883           fp->_IO_save_base = bbuf;
884           fp->_IO_save_end = fp->_IO_save_base + backup_size;
885           fp->_IO_backup_base = fp->_IO_save_end;
886           _IO_switch_to_backup_area (fp);
887         }
888       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
889         {
890           /* Increase size of existing backup buffer. */
891           _IO_size_t new_size;
892           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
893           char *new_buf;
894           new_size = 2 * old_size;
895           new_buf = (char *) malloc (new_size);
896           if (new_buf == NULL)
897             return EOF;
898           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
899                   old_size);
900           free (fp->_IO_read_base);
901           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
902                     new_buf + new_size);
903           fp->_IO_backup_base = fp->_IO_read_ptr;
904         }
905     }
906   --fp->_IO_read_ptr;
907   if (c != EOF && *fp->_IO_read_ptr != c)
908     *fp->_IO_read_ptr = c;
909   return (unsigned char) *fp->_IO_read_ptr;
910 }
911
912 _IO_fpos64_t
913 _IO_default_seek (fp, offset, dir)
914      _IO_FILE *fp;
915      _IO_off64_t offset;
916      int dir;
917 {
918   return _IO_pos_BAD;
919 }
920
921 int
922 _IO_default_stat (fp, st)
923      _IO_FILE *fp;
924      void* st;
925 {
926   return EOF;
927 }
928
929 _IO_ssize_t
930 _IO_default_read (fp, data, n)
931      _IO_FILE* fp;
932      void *data;
933      _IO_ssize_t n;
934 {
935   return -1;
936 }
937
938 _IO_ssize_t
939 _IO_default_write (fp, data, n)
940      _IO_FILE *fp;
941      const void *data;
942      _IO_ssize_t n;
943 {
944   return 0;
945 }
946
947 int
948 _IO_default_showmanyc (fp)
949      _IO_FILE *fp;
950 {
951   return -1;
952 }
953
954 void
955 _IO_default_imbue (fp, locale)
956      _IO_FILE *fp;
957      void *locale;
958 {
959 }
960
961
962 #ifdef TODO
963 #if defined(linux)
964 #define IO_CLEANUP ;
965 #endif
966
967 #ifdef IO_CLEANUP
968   IO_CLEANUP
969 #else
970 struct __io_defs {
971     __io_defs() { }
972     ~__io_defs() { _IO_cleanup (); }
973 };
974 __io_defs io_defs__;
975 #endif
976
977 #endif /* TODO */
978
979 #ifdef weak_alias
980 weak_alias (_IO_cleanup, _cleanup)
981 #endif
982
983 #ifdef text_set_element
984 text_set_element(__libc_atexit, _cleanup);
985 #endif