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