(_IO_no_init): Initialize _flags2 field.
[kopensolaris-gnu/glibc.git] / libio / genops.c
1 /* Copyright (C) 1993,1995,1997-2001,2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.
18
19    As a special exception, if you link the code in this file with
20    files compiled with a GNU compiler to produce an executable,
21    that does not cause the resulting executable to be covered by
22    the GNU Lesser General Public License.  This exception does not
23    however invalidate any other reasons why the executable file
24    might be covered by the GNU Lesser General Public License.
25    This exception applies to code released by its copyright holders
26    in files containing the exception.  */
27
28 /* Generic or default I/O operations. */
29
30 #include "libioP.h"
31 #ifdef __STDC__
32 #include <stdlib.h>
33 #endif
34 #include <string.h>
35
36 #ifdef _IO_MTSAFE_IO
37 static _IO_lock_t list_all_lock = _IO_lock_initializer;
38 #endif
39
40 /* Used to signal modifications to the list of FILE decriptors.  */
41 static int _IO_list_all_stamp;
42
43
44 static _IO_FILE *run_fp;
45
46 static void
47 flush_cleanup (void *not_used)
48 {
49   if (run_fp != NULL)
50     _IO_funlockfile (run_fp);
51 #ifdef _IO_MTSAFE_IO
52   _IO_lock_unlock (list_all_lock);
53 #endif
54 }
55
56 void
57 _IO_un_link (fp)
58      struct _IO_FILE_plus *fp;
59 {
60   if (fp->file._flags & _IO_LINKED)
61     {
62       struct _IO_FILE_plus **f;
63 #ifdef _IO_MTSAFE_IO
64       _IO_cleanup_region_start_noarg (flush_cleanup);
65       _IO_lock_lock (list_all_lock);
66       run_fp = (_IO_FILE *) fp;
67       _IO_flockfile ((_IO_FILE *) fp);
68 #endif
69       for (f = &INTUSE(_IO_list_all); *f;
70            f = (struct _IO_FILE_plus **) &(*f)->file._chain)
71         {
72           if (*f == fp)
73             {
74               *f = (struct _IO_FILE_plus *) fp->file._chain;
75               ++_IO_list_all_stamp;
76               break;
77             }
78         }
79       fp->file._flags &= ~_IO_LINKED;
80 #ifdef _IO_MTSAFE_IO
81       _IO_funlockfile ((_IO_FILE *) fp);
82       run_fp = NULL;
83       _IO_lock_unlock (list_all_lock);
84       _IO_cleanup_region_end (0);
85 #endif
86     }
87 }
88 INTDEF(_IO_un_link)
89
90 void
91 _IO_link_in (fp)
92      struct _IO_FILE_plus *fp;
93 {
94   if ((fp->file._flags & _IO_LINKED) == 0)
95     {
96       fp->file._flags |= _IO_LINKED;
97 #ifdef _IO_MTSAFE_IO
98       _IO_cleanup_region_start_noarg (flush_cleanup);
99       _IO_lock_lock (list_all_lock);
100       run_fp = (_IO_FILE *) fp;
101       _IO_flockfile ((_IO_FILE *) fp);
102 #endif
103       fp->file._chain = (_IO_FILE *) INTUSE(_IO_list_all);
104       INTUSE(_IO_list_all) = fp;
105       ++_IO_list_all_stamp;
106 #ifdef _IO_MTSAFE_IO
107       _IO_funlockfile ((_IO_FILE *) fp);
108       run_fp = NULL;
109       _IO_lock_unlock (list_all_lock);
110       _IO_cleanup_region_end (0);
111 #endif
112     }
113 }
114 INTDEF(_IO_link_in)
115
116 /* Return minimum _pos markers
117    Assumes the current get area is the main get area. */
118 _IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p));
119
120 _IO_ssize_t
121 _IO_least_marker (fp, end_p)
122      _IO_FILE *fp;
123      char *end_p;
124 {
125   _IO_ssize_t least_so_far = end_p - fp->_IO_read_base;
126   struct _IO_marker *mark;
127   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
128     if (mark->_pos < least_so_far)
129       least_so_far = mark->_pos;
130   return least_so_far;
131 }
132
133 /* Switch current get area from backup buffer to (start of) main get area. */
134
135 void
136 _IO_switch_to_main_get_area (fp)
137      _IO_FILE *fp;
138 {
139   char *tmp;
140   fp->_flags &= ~_IO_IN_BACKUP;
141   /* Swap _IO_read_end and _IO_save_end. */
142   tmp = fp->_IO_read_end;
143   fp->_IO_read_end = fp->_IO_save_end;
144   fp->_IO_save_end= tmp;
145   /* Swap _IO_read_base and _IO_save_base. */
146   tmp = fp->_IO_read_base;
147   fp->_IO_read_base = fp->_IO_save_base;
148   fp->_IO_save_base = tmp;
149   /* Set _IO_read_ptr. */
150   fp->_IO_read_ptr = fp->_IO_read_base;
151 }
152
153 /* Switch current get area from main get area to (end of) backup area. */
154
155 void
156 _IO_switch_to_backup_area (fp)
157      _IO_FILE *fp;
158 {
159   char *tmp;
160   fp->_flags |= _IO_IN_BACKUP;
161   /* Swap _IO_read_end and _IO_save_end. */
162   tmp = fp->_IO_read_end;
163   fp->_IO_read_end = fp->_IO_save_end;
164   fp->_IO_save_end = tmp;
165   /* Swap _IO_read_base and _IO_save_base. */
166   tmp = fp->_IO_read_base;
167   fp->_IO_read_base = fp->_IO_save_base;
168   fp->_IO_save_base = tmp;
169   /* Set _IO_read_ptr.  */
170   fp->_IO_read_ptr = fp->_IO_read_end;
171 }
172
173 int
174 _IO_switch_to_get_mode (fp)
175      _IO_FILE *fp;
176 {
177   if (fp->_IO_write_ptr > fp->_IO_write_base)
178     if (_IO_OVERFLOW (fp, EOF) == EOF)
179       return EOF;
180   if (_IO_in_backup (fp))
181     fp->_IO_read_base = fp->_IO_backup_base;
182   else
183     {
184       fp->_IO_read_base = fp->_IO_buf_base;
185       if (fp->_IO_write_ptr > fp->_IO_read_end)
186         fp->_IO_read_end = fp->_IO_write_ptr;
187     }
188   fp->_IO_read_ptr = fp->_IO_write_ptr;
189
190   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
191
192   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
193   return 0;
194 }
195 INTDEF(_IO_switch_to_get_mode)
196
197 void
198 _IO_free_backup_area (fp)
199      _IO_FILE *fp;
200 {
201   if (_IO_in_backup (fp))
202     _IO_switch_to_main_get_area (fp);  /* Just in case. */
203   free (fp->_IO_save_base);
204   fp->_IO_save_base = NULL;
205   fp->_IO_save_end = NULL;
206   fp->_IO_backup_base = NULL;
207 }
208 INTDEF(_IO_free_backup_area)
209
210 #if 0
211 int
212 _IO_switch_to_put_mode (fp)
213      _IO_FILE *fp;
214 {
215   fp->_IO_write_base = fp->_IO_read_ptr;
216   fp->_IO_write_ptr = fp->_IO_read_ptr;
217   /* Following is wrong if line- or un-buffered? */
218   fp->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
219                        ? fp->_IO_read_end : fp->_IO_buf_end);
220
221   fp->_IO_read_ptr = fp->_IO_read_end;
222   fp->_IO_read_base = fp->_IO_read_end;
223
224   fp->_flags |= _IO_CURRENTLY_PUTTING;
225   return 0;
226 }
227 #endif
228
229 int
230 __overflow (f, ch)
231      _IO_FILE *f;
232      int ch;
233 {
234   /* This is a single-byte stream.  */
235   if (f->_mode == 0)
236     _IO_fwide (f, -1);
237   return _IO_OVERFLOW (f, ch);
238 }
239 libc_hidden_def (__overflow)
240
241 static int save_for_backup __P ((_IO_FILE *fp, char *end_p))
242 #ifdef _LIBC
243      internal_function
244 #endif
245      ;
246
247 static int
248 #ifdef _LIBC
249 internal_function
250 #endif
251 save_for_backup (fp, end_p)
252      _IO_FILE *fp;
253      char *end_p;
254 {
255   /* Append [_IO_read_base..end_p] to backup area. */
256   _IO_ssize_t least_mark = _IO_least_marker (fp, end_p);
257   /* needed_size is how much space we need in the backup area. */
258   _IO_size_t needed_size = (end_p - fp->_IO_read_base) - least_mark;
259   /* FIXME: Dubious arithmetic if pointers are NULL */
260   _IO_size_t current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
261   _IO_size_t avail; /* Extra space available for future expansion. */
262   _IO_ssize_t delta;
263   struct _IO_marker *mark;
264   if (needed_size > current_Bsize)
265     {
266       char *new_buffer;
267       avail = 100;
268       new_buffer = (char *) malloc (avail + needed_size);
269       if (new_buffer == NULL)
270         return EOF;             /* FIXME */
271       if (least_mark < 0)
272         {
273 #ifdef _LIBC
274           __mempcpy (__mempcpy (new_buffer + avail,
275                                 fp->_IO_save_end + least_mark,
276                                 -least_mark),
277                      fp->_IO_read_base,
278                      end_p - fp->_IO_read_base);
279 #else
280           memcpy (new_buffer + avail,
281                   fp->_IO_save_end + least_mark,
282                   -least_mark);
283           memcpy (new_buffer + avail - least_mark,
284                   fp->_IO_read_base,
285                   end_p - fp->_IO_read_base);
286 #endif
287         }
288       else
289         memcpy (new_buffer + avail,
290                 fp->_IO_read_base + least_mark,
291                 needed_size);
292       if (fp->_IO_save_base)
293         free (fp->_IO_save_base);
294       fp->_IO_save_base = new_buffer;
295       fp->_IO_save_end = new_buffer + avail + needed_size;
296     }
297   else
298     {
299       avail = current_Bsize - needed_size;
300       if (least_mark < 0)
301         {
302           memmove (fp->_IO_save_base + avail,
303                    fp->_IO_save_end + least_mark,
304                    -least_mark);
305           memcpy (fp->_IO_save_base + avail - least_mark,
306                   fp->_IO_read_base,
307                   end_p - fp->_IO_read_base);
308         }
309       else if (needed_size > 0)
310         memcpy (fp->_IO_save_base + avail,
311                 fp->_IO_read_base + least_mark,
312                 needed_size);
313     }
314   fp->_IO_backup_base = fp->_IO_save_base + avail;
315   /* Adjust all the streammarkers. */
316   delta = end_p - fp->_IO_read_base;
317   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
318     mark->_pos -= delta;
319   return 0;
320 }
321
322 int
323 __underflow (fp)
324      _IO_FILE *fp;
325 {
326 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
327   if (fp->_vtable_offset == 0 && _IO_fwide (fp, -1) != -1)
328     return EOF;
329 #endif
330
331   if (fp->_mode == 0)
332     _IO_fwide (fp, -1);
333   if (_IO_in_put_mode (fp))
334     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
335       return EOF;
336   if (fp->_IO_read_ptr < fp->_IO_read_end)
337     return *(unsigned char *) fp->_IO_read_ptr;
338   if (_IO_in_backup (fp))
339     {
340       _IO_switch_to_main_get_area (fp);
341       if (fp->_IO_read_ptr < fp->_IO_read_end)
342         return *(unsigned char *) fp->_IO_read_ptr;
343     }
344   if (_IO_have_markers (fp))
345     {
346       if (save_for_backup (fp, fp->_IO_read_end))
347         return EOF;
348     }
349   else if (_IO_have_backup (fp))
350     INTUSE(_IO_free_backup_area) (fp);
351   return _IO_UNDERFLOW (fp);
352 }
353 libc_hidden_def (__underflow)
354
355 int
356 __uflow (fp)
357      _IO_FILE *fp;
358 {
359 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
360   if (fp->_vtable_offset == 0 && _IO_fwide (fp, -1) != -1)
361     return EOF;
362 #endif
363
364   if (fp->_mode == 0)
365     _IO_fwide (fp, -11);
366   if (_IO_in_put_mode (fp))
367     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
368       return EOF;
369   if (fp->_IO_read_ptr < fp->_IO_read_end)
370     return *(unsigned char *) fp->_IO_read_ptr++;
371   if (_IO_in_backup (fp))
372     {
373       _IO_switch_to_main_get_area (fp);
374       if (fp->_IO_read_ptr < fp->_IO_read_end)
375         return *(unsigned char *) fp->_IO_read_ptr++;
376     }
377   if (_IO_have_markers (fp))
378     {
379       if (save_for_backup (fp, fp->_IO_read_end))
380         return EOF;
381     }
382   else if (_IO_have_backup (fp))
383     INTUSE(_IO_free_backup_area) (fp);
384   return _IO_UFLOW (fp);
385 }
386 libc_hidden_def (__uflow)
387
388 void
389 _IO_setb (f, b, eb, a)
390      _IO_FILE *f;
391      char *b;
392      char *eb;
393      int a;
394 {
395   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
396     FREE_BUF (f->_IO_buf_base, _IO_blen (f));
397   f->_IO_buf_base = b;
398   f->_IO_buf_end = eb;
399   if (a)
400     f->_flags &= ~_IO_USER_BUF;
401   else
402     f->_flags |= _IO_USER_BUF;
403 }
404 INTDEF(_IO_setb)
405
406 void
407 _IO_doallocbuf (fp)
408      _IO_FILE *fp;
409 {
410   if (fp->_IO_buf_base)
411     return;
412   if (!(fp->_flags & _IO_UNBUFFERED) || fp->_mode > 0)
413     if (_IO_DOALLOCATE (fp) != EOF)
414       return;
415   INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
416 }
417 INTDEF(_IO_doallocbuf)
418
419 int
420 _IO_default_underflow (fp)
421      _IO_FILE *fp;
422 {
423   return EOF;
424 }
425
426 int
427 _IO_default_uflow (fp)
428      _IO_FILE *fp;
429 {
430   int ch = _IO_UNDERFLOW (fp);
431   if (ch == EOF)
432     return EOF;
433   return *(unsigned char *) fp->_IO_read_ptr++;
434 }
435 INTDEF(_IO_default_uflow)
436
437 _IO_size_t
438 _IO_default_xsputn (f, data, n)
439      _IO_FILE *f;
440      const void *data;
441      _IO_size_t n;
442 {
443   const char *s = (char *) data;
444   _IO_size_t more = n;
445   if (more <= 0)
446     return 0;
447   for (;;)
448     {
449       /* Space available. */
450       _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr;
451       if (count > 0)
452         {
453           if ((_IO_size_t) count > more)
454             count = more;
455           if (count > 20)
456             {
457 #ifdef _LIBC
458               f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
459 #else
460               memcpy (f->_IO_write_ptr, s, count);
461               f->_IO_write_ptr += count;
462 #endif
463               s += count;
464             }
465           else if (count <= 0)
466             count = 0;
467           else
468             {
469               char *p = f->_IO_write_ptr;
470               _IO_ssize_t i;
471               for (i = count; --i >= 0; )
472                 *p++ = *s++;
473               f->_IO_write_ptr = p;
474             }
475           more -= count;
476         }
477       if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF)
478         break;
479       more--;
480     }
481   return n - more;
482 }
483 INTDEF(_IO_default_xsputn)
484
485 _IO_size_t
486 _IO_sgetn (fp, data, n)
487      _IO_FILE *fp;
488      void *data;
489      _IO_size_t n;
490 {
491   /* FIXME handle putback buffer here! */
492   return _IO_XSGETN (fp, data, n);
493 }
494 INTDEF(_IO_sgetn)
495
496 _IO_size_t
497 _IO_default_xsgetn (fp, data, n)
498      _IO_FILE *fp;
499      void *data;
500      _IO_size_t n;
501 {
502   _IO_size_t more = n;
503   char *s = (char*) data;
504   for (;;)
505     {
506       /* Data available. */
507       _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr;
508       if (count > 0)
509         {
510           if ((_IO_size_t) count > more)
511             count = more;
512           if (count > 20)
513             {
514 #ifdef _LIBC
515               s = __mempcpy (s, fp->_IO_read_ptr, count);
516 #else
517               memcpy (s, fp->_IO_read_ptr, count);
518               s += count;
519 #endif
520               fp->_IO_read_ptr += count;
521             }
522           else if (count <= 0)
523             count = 0;
524           else
525             {
526               char *p = fp->_IO_read_ptr;
527               int i = (int) count;
528               while (--i >= 0)
529                 *s++ = *p++;
530               fp->_IO_read_ptr = p;
531             }
532             more -= count;
533         }
534       if (more == 0 || __underflow (fp) == EOF)
535         break;
536     }
537   return n - more;
538 }
539 INTDEF(_IO_default_xsgetn)
540
541 #if 0
542 /* Seems not to be needed. --drepper */
543 int
544 _IO_sync (fp)
545      _IO_FILE *fp;
546 {
547   return 0;
548 }
549 #endif
550
551 _IO_FILE *
552 _IO_default_setbuf (fp, p, len)
553      _IO_FILE *fp;
554      char *p;
555      _IO_ssize_t len;
556 {
557     if (_IO_SYNC (fp) == EOF)
558         return NULL;
559     if (p == NULL || len == 0)
560       {
561         fp->_flags |= _IO_UNBUFFERED;
562         INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
563       }
564     else
565       {
566         fp->_flags &= ~_IO_UNBUFFERED;
567         INTUSE(_IO_setb) (fp, p, p+len, 0);
568       }
569     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
570     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
571     return fp;
572 }
573
574 _IO_off64_t
575 _IO_default_seekpos (fp, pos, mode)
576      _IO_FILE *fp;
577      _IO_off64_t pos;
578      int mode;
579 {
580   return _IO_SEEKOFF (fp, pos, 0, mode);
581 }
582
583 int
584 _IO_default_doallocate (fp)
585      _IO_FILE *fp;
586 {
587   char *buf;
588
589   ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
590   INTUSE(_IO_setb) (fp, buf, buf+_IO_BUFSIZ, 1);
591   return 1;
592 }
593 INTDEF(_IO_default_doallocate)
594
595 void
596 _IO_init (fp, flags)
597      _IO_FILE *fp;
598      int flags;
599 {
600   _IO_no_init (fp, flags, -1, NULL, NULL);
601 }
602 INTDEF(_IO_init)
603
604 void
605 _IO_no_init (fp, flags, orientation, wd, jmp)
606      _IO_FILE *fp;
607      int flags;
608      int orientation;
609      struct _IO_wide_data *wd;
610      struct _IO_jump_t *jmp;
611 {
612   fp->_flags = _IO_MAGIC|flags;
613   fp->_flags2 = 0;
614   fp->_IO_buf_base = NULL;
615   fp->_IO_buf_end = NULL;
616   fp->_IO_read_base = NULL;
617   fp->_IO_read_ptr = NULL;
618   fp->_IO_read_end = NULL;
619   fp->_IO_write_base = NULL;
620   fp->_IO_write_ptr = NULL;
621   fp->_IO_write_end = NULL;
622   fp->_chain = NULL; /* Not necessary. */
623
624   fp->_IO_save_base = NULL;
625   fp->_IO_backup_base = NULL;
626   fp->_IO_save_end = NULL;
627   fp->_markers = NULL;
628   fp->_cur_column = 0;
629 #if _IO_JUMPS_OFFSET
630   fp->_vtable_offset = 0;
631 #endif
632 #ifdef _IO_MTSAFE_IO
633   if (fp->_lock != NULL)
634     _IO_lock_init (*fp->_lock);
635 #endif
636   fp->_mode = orientation;
637 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
638   if (orientation >= 0)
639     {
640       fp->_wide_data = wd;
641       fp->_wide_data->_IO_buf_base = NULL;
642       fp->_wide_data->_IO_buf_end = NULL;
643       fp->_wide_data->_IO_read_base = NULL;
644       fp->_wide_data->_IO_read_ptr = NULL;
645       fp->_wide_data->_IO_read_end = NULL;
646       fp->_wide_data->_IO_write_base = NULL;
647       fp->_wide_data->_IO_write_ptr = NULL;
648       fp->_wide_data->_IO_write_end = NULL;
649       fp->_wide_data->_IO_save_base = NULL;
650       fp->_wide_data->_IO_backup_base = NULL;
651       fp->_wide_data->_IO_save_end = NULL;
652
653       fp->_wide_data->_wide_vtable = jmp;
654     }
655 #endif
656 }
657
658 int
659 _IO_default_sync (fp)
660      _IO_FILE *fp;
661 {
662   return 0;
663 }
664
665 /* The way the C++ classes are mapped into the C functions in the
666    current implementation, this function can get called twice! */
667
668 void
669 _IO_default_finish (fp, dummy)
670      _IO_FILE *fp;
671      int dummy;
672 {
673   struct _IO_marker *mark;
674   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
675     {
676       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
677       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
678     }
679
680   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
681     mark->_sbuf = NULL;
682
683   if (fp->_IO_save_base)
684     {
685       free (fp->_IO_save_base);
686       fp->_IO_save_base = NULL;
687     }
688
689 #ifdef _IO_MTSAFE_IO
690   if (fp->_lock != NULL)
691     _IO_lock_fini (*fp->_lock);
692 #endif
693
694   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
695 }
696 INTDEF(_IO_default_finish)
697
698 _IO_off64_t
699 _IO_default_seekoff (fp, offset, dir, mode)
700      _IO_FILE *fp;
701      _IO_off64_t offset;
702      int dir;
703      int mode;
704 {
705   return _IO_pos_BAD;
706 }
707
708 int
709 _IO_sputbackc (fp, c)
710      _IO_FILE *fp;
711      int c;
712 {
713   int result;
714
715   if (fp->_IO_read_ptr > fp->_IO_read_base
716       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
717     {
718       fp->_IO_read_ptr--;
719       result = (unsigned char) c;
720     }
721   else
722     result = _IO_PBACKFAIL (fp, c);
723
724   if (result != EOF)
725     fp->_flags &= ~_IO_EOF_SEEN;
726
727   return result;
728 }
729 INTDEF(_IO_sputbackc)
730
731 int
732 _IO_sungetc (fp)
733      _IO_FILE *fp;
734 {
735   int result;
736
737   if (fp->_IO_read_ptr > fp->_IO_read_base)
738     {
739       fp->_IO_read_ptr--;
740       result = (unsigned char) *fp->_IO_read_ptr;
741     }
742   else
743     result = _IO_PBACKFAIL (fp, EOF);
744
745   if (result != EOF)
746     fp->_flags &= ~_IO_EOF_SEEN;
747
748   return result;
749 }
750
751 #if 0 /* Work in progress */
752 /* Seems not to be needed.  */
753 #if 0
754 void
755 _IO_set_column (fp, c)
756      _IO_FILE *fp;
757      int c;
758 {
759   if (c == -1)
760     fp->_column = -1;
761   else
762     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
763 }
764 #else
765 int
766 _IO_set_column (fp, i)
767      _IO_FILE *fp;
768      int i;
769 {
770   fp->_cur_column = i + 1;
771   return 0;
772 }
773 #endif
774 #endif
775
776
777 unsigned
778 _IO_adjust_column (start, line, count)
779      unsigned start;
780      const char *line;
781      int count;
782 {
783   const char *ptr = line + count;
784   while (ptr > line)
785     if (*--ptr == '\n')
786       return line + count - ptr - 1;
787   return start + count;
788 }
789 INTDEF(_IO_adjust_column)
790
791 #if 0
792 /* Seems not to be needed. --drepper */
793 int
794 _IO_get_column (fp)
795      _IO_FILE *fp;
796 {
797   if (fp->_cur_column)
798     return _IO_adjust_column (fp->_cur_column - 1,
799                               fp->_IO_write_base,
800                               fp->_IO_write_ptr - fp->_IO_write_base);
801   return -1;
802 }
803 #endif
804
805
806 int
807 _IO_flush_all_lockp (int do_lock)
808 {
809   int result = 0;
810   struct _IO_FILE *fp;
811   int last_stamp;
812
813 #ifdef _IO_MTSAFE_IO
814   _IO_cleanup_region_start_noarg (flush_cleanup);
815   if (do_lock)
816     _IO_lock_lock (list_all_lock);
817 #endif
818
819   last_stamp = _IO_list_all_stamp;
820   fp = (_IO_FILE *) INTUSE(_IO_list_all);
821   while (fp != NULL)
822     {
823       run_fp = fp;
824       if (do_lock)
825         _IO_flockfile (fp);
826
827       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
828 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
829            || (fp->_vtable_offset == 0
830                && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
831                                     > fp->_wide_data->_IO_write_base))
832 #endif
833            )
834           && _IO_OVERFLOW (fp, EOF) == EOF)
835         result = EOF;
836
837       if (do_lock)
838         _IO_funlockfile (fp);
839       run_fp = NULL;
840
841       if (last_stamp != _IO_list_all_stamp)
842         {
843           /* Something was added to the list.  Start all over again.  */
844           fp = (_IO_FILE *) INTUSE(_IO_list_all);
845           last_stamp = _IO_list_all_stamp;
846         }
847       else
848         fp = fp->_chain;
849     }
850
851 #ifdef _IO_MTSAFE_IO
852   if (do_lock)
853     _IO_lock_unlock (list_all_lock);
854   _IO_cleanup_region_end (0);
855 #endif
856
857   return result;
858 }
859
860
861 int
862 _IO_flush_all ()
863 {
864   /* We want locking.  */
865   return _IO_flush_all_lockp (1);
866 }
867 INTDEF(_IO_flush_all)
868
869 void
870 _IO_flush_all_linebuffered ()
871 {
872   struct _IO_FILE *fp;
873   int last_stamp;
874
875 #ifdef _IO_MTSAFE_IO
876   _IO_cleanup_region_start_noarg (flush_cleanup);
877   _IO_lock_lock (list_all_lock);
878 #endif
879
880   last_stamp = _IO_list_all_stamp;
881   fp = (_IO_FILE *) INTUSE(_IO_list_all);
882   while (fp != NULL)
883     {
884       run_fp = fp;
885       _IO_flockfile (fp);
886
887       if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
888         _IO_OVERFLOW (fp, EOF);
889
890       _IO_funlockfile (fp);
891       run_fp = NULL;
892
893       if (last_stamp != _IO_list_all_stamp)
894         {
895           /* Something was added to the list.  Start all over again.  */
896           fp = (_IO_FILE *) INTUSE(_IO_list_all);
897           last_stamp = _IO_list_all_stamp;
898         }
899       else
900         fp = fp->_chain;
901     }
902
903 #ifdef _IO_MTSAFE_IO
904   _IO_lock_unlock (list_all_lock);
905   _IO_cleanup_region_end (0);
906 #endif
907 }
908 INTDEF(_IO_flush_all_linebuffered)
909 #ifdef _LIBC
910 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
911 #endif
912
913 static void _IO_unbuffer_write __P ((void));
914
915 static void
916 _IO_unbuffer_write ()
917 {
918   struct _IO_FILE *fp;
919   for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
920     {
921       if (! (fp->_flags & _IO_UNBUFFERED)
922           && (! (fp->_flags & _IO_NO_WRITES)
923               || (fp->_flags & _IO_IS_APPENDING))
924           /* Iff stream is un-orientated, it wasn't used. */
925           && fp->_mode != 0)
926         _IO_SETBUF (fp, NULL, 0);
927
928       /* Make sure that never again the wide char functions can be
929          used.  */
930       fp->_mode = -1;
931     }
932 }
933
934 int
935 _IO_cleanup ()
936 {
937   int result = INTUSE(_IO_flush_all) ();
938
939   /* We currently don't have a reliable mechanism for making sure that
940      C++ static destructors are executed in the correct order.
941      So it is possible that other static destructors might want to
942      write to cout - and they're supposed to be able to do so.
943
944      The following will make the standard streambufs be unbuffered,
945      which forces any output from late destructors to be written out. */
946   _IO_unbuffer_write ();
947
948   return result;
949 }
950
951
952 void
953 _IO_init_marker (marker, fp)
954      struct _IO_marker *marker;
955      _IO_FILE *fp;
956 {
957   marker->_sbuf = fp;
958   if (_IO_in_put_mode (fp))
959     INTUSE(_IO_switch_to_get_mode) (fp);
960   if (_IO_in_backup (fp))
961     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
962   else
963     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
964
965   /* Should perhaps sort the chain? */
966   marker->_next = fp->_markers;
967   fp->_markers = marker;
968 }
969
970 void
971 _IO_remove_marker (marker)
972      struct _IO_marker *marker;
973 {
974   /* Unlink from sb's chain. */
975   struct _IO_marker **ptr = &marker->_sbuf->_markers;
976   for (; ; ptr = &(*ptr)->_next)
977     {
978       if (*ptr == NULL)
979         break;
980       else if (*ptr == marker)
981         {
982           *ptr = marker->_next;
983           return;
984         }
985     }
986 #if 0
987     if _sbuf has a backup area that is no longer needed, should we delete
988     it now, or wait until the next underflow?
989 #endif
990 }
991
992 #define BAD_DELTA EOF
993
994 int
995 _IO_marker_difference (mark1, mark2)
996      struct _IO_marker *mark1;
997      struct _IO_marker *mark2;
998 {
999   return mark1->_pos - mark2->_pos;
1000 }
1001
1002 /* Return difference between MARK and current position of MARK's stream. */
1003 int
1004 _IO_marker_delta (mark)
1005      struct _IO_marker *mark;
1006 {
1007   int cur_pos;
1008   if (mark->_sbuf == NULL)
1009     return BAD_DELTA;
1010   if (_IO_in_backup (mark->_sbuf))
1011     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
1012   else
1013     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
1014   return mark->_pos - cur_pos;
1015 }
1016
1017 int
1018 _IO_seekmark (fp, mark, delta)
1019      _IO_FILE *fp;
1020      struct _IO_marker *mark;
1021      int delta;
1022 {
1023   if (mark->_sbuf != fp)
1024     return EOF;
1025  if (mark->_pos >= 0)
1026     {
1027       if (_IO_in_backup (fp))
1028         _IO_switch_to_main_get_area (fp);
1029       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
1030     }
1031   else
1032     {
1033       if (!_IO_in_backup (fp))
1034         _IO_switch_to_backup_area (fp);
1035       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
1036     }
1037   return 0;
1038 }
1039
1040 void
1041 _IO_unsave_markers (fp)
1042      _IO_FILE *fp;
1043 {
1044   struct _IO_marker *mark = fp->_markers;
1045   if (mark)
1046     {
1047 #ifdef TODO
1048       streampos offset = seekoff (0, ios::cur, ios::in);
1049       if (offset != EOF)
1050         {
1051           offset += eGptr () - Gbase ();
1052           for ( ; mark != NULL; mark = mark->_next)
1053             mark->set_streampos (mark->_pos + offset);
1054         }
1055     else
1056       {
1057         for ( ; mark != NULL; mark = mark->_next)
1058           mark->set_streampos (EOF);
1059       }
1060 #endif
1061       fp->_markers = 0;
1062     }
1063
1064   if (_IO_have_backup (fp))
1065     INTUSE(_IO_free_backup_area) (fp);
1066 }
1067 INTDEF(_IO_unsave_markers)
1068
1069 #if 0
1070 /* Seems not to be needed. --drepper */
1071 int
1072 _IO_nobackup_pbackfail (fp, c)
1073      _IO_FILE *fp;
1074      int c;
1075 {
1076   if (fp->_IO_read_ptr > fp->_IO_read_base)
1077         fp->_IO_read_ptr--;
1078   if (c != EOF && *fp->_IO_read_ptr != c)
1079       *fp->_IO_read_ptr = c;
1080   return (unsigned char) c;
1081 }
1082 #endif
1083
1084 int
1085 _IO_default_pbackfail (fp, c)
1086      _IO_FILE *fp;
1087      int c;
1088 {
1089   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
1090       && (unsigned char) fp->_IO_read_ptr[-1] == c)
1091     --fp->_IO_read_ptr;
1092   else
1093     {
1094       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
1095       if (!_IO_in_backup (fp))
1096         {
1097           /* We need to keep the invariant that the main get area
1098              logically follows the backup area.  */
1099           if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
1100             {
1101               if (save_for_backup (fp, fp->_IO_read_ptr))
1102                 return EOF;
1103             }
1104           else if (!_IO_have_backup (fp))
1105             {
1106               /* No backup buffer: allocate one. */
1107               /* Use nshort buffer, if unused? (probably not)  FIXME */
1108               int backup_size = 128;
1109               char *bbuf = (char *) malloc (backup_size);
1110               if (bbuf == NULL)
1111                 return EOF;
1112               fp->_IO_save_base = bbuf;
1113               fp->_IO_save_end = fp->_IO_save_base + backup_size;
1114               fp->_IO_backup_base = fp->_IO_save_end;
1115             }
1116           fp->_IO_read_base = fp->_IO_read_ptr;
1117           _IO_switch_to_backup_area (fp);
1118         }
1119       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
1120         {
1121           /* Increase size of existing backup buffer. */
1122           _IO_size_t new_size;
1123           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
1124           char *new_buf;
1125           new_size = 2 * old_size;
1126           new_buf = (char *) malloc (new_size);
1127           if (new_buf == NULL)
1128             return EOF;
1129           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1130                   old_size);
1131           free (fp->_IO_read_base);
1132           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1133                     new_buf + new_size);
1134           fp->_IO_backup_base = fp->_IO_read_ptr;
1135         }
1136
1137       *--fp->_IO_read_ptr = c;
1138     }
1139   return (unsigned char) c;
1140 }
1141 INTDEF(_IO_default_pbackfail)
1142
1143 _IO_off64_t
1144 _IO_default_seek (fp, offset, dir)
1145      _IO_FILE *fp;
1146      _IO_off64_t offset;
1147      int dir;
1148 {
1149   return _IO_pos_BAD;
1150 }
1151
1152 int
1153 _IO_default_stat (fp, st)
1154      _IO_FILE *fp;
1155      void* st;
1156 {
1157   return EOF;
1158 }
1159
1160 _IO_ssize_t
1161 _IO_default_read (fp, data, n)
1162      _IO_FILE* fp;
1163      void *data;
1164      _IO_ssize_t n;
1165 {
1166   return -1;
1167 }
1168
1169 _IO_ssize_t
1170 _IO_default_write (fp, data, n)
1171      _IO_FILE *fp;
1172      const void *data;
1173      _IO_ssize_t n;
1174 {
1175   return 0;
1176 }
1177
1178 int
1179 _IO_default_showmanyc (fp)
1180      _IO_FILE *fp;
1181 {
1182   return -1;
1183 }
1184
1185 void
1186 _IO_default_imbue (fp, locale)
1187      _IO_FILE *fp;
1188      void *locale;
1189 {
1190 }
1191
1192 _IO_ITER
1193 _IO_iter_begin()
1194 {
1195   return (_IO_ITER) INTUSE(_IO_list_all);
1196 }
1197
1198 _IO_ITER
1199 _IO_iter_end()
1200 {
1201   return NULL;
1202 }
1203
1204 _IO_ITER
1205 _IO_iter_next(iter)
1206     _IO_ITER iter;
1207 {
1208   return iter->_chain;
1209 }
1210
1211 _IO_FILE *
1212 _IO_iter_file(iter)
1213     _IO_ITER iter;
1214 {
1215   return iter;
1216 }
1217
1218 void
1219 _IO_list_lock()
1220 {
1221 #ifdef _IO_MTSAFE_IO
1222   _IO_lock_lock (list_all_lock);
1223 #endif
1224 }
1225
1226 void
1227 _IO_list_unlock()
1228 {
1229 #ifdef _IO_MTSAFE_IO
1230   _IO_lock_unlock (list_all_lock);
1231 #endif
1232 }
1233
1234 void
1235 _IO_list_resetlock()
1236 {
1237 #ifdef _IO_MTSAFE_IO
1238   _IO_lock_init (list_all_lock);
1239 #endif
1240 }
1241
1242
1243 #ifdef TODO
1244 #if defined(linux)
1245 #define IO_CLEANUP ;
1246 #endif
1247
1248 #ifdef IO_CLEANUP
1249   IO_CLEANUP
1250 #else
1251 struct __io_defs {
1252     __io_defs() { }
1253     ~__io_defs() { _IO_cleanup (); }
1254 };
1255 __io_defs io_defs__;
1256 #endif
1257
1258 #endif /* TODO */
1259
1260 #ifdef weak_alias
1261 weak_alias (_IO_cleanup, _cleanup)
1262 #endif
1263
1264 #ifdef text_set_element
1265 text_set_element(__libc_atexit, _cleanup);
1266 #endif