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