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