(_IO_no_init): Split in two. New function _IO_old_init.
[kopensolaris-gnu/glibc.git] / libio / genops.c
1 /* Copyright (C) 1993,1995,1997-2002, 2003 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_old_init (fp, flags)
606      _IO_FILE *fp;
607      int flags;
608 {
609   fp->_flags = _IO_MAGIC|flags;
610   fp->_flags2 = 0;
611   fp->_IO_buf_base = NULL;
612   fp->_IO_buf_end = NULL;
613   fp->_IO_read_base = NULL;
614   fp->_IO_read_ptr = NULL;
615   fp->_IO_read_end = NULL;
616   fp->_IO_write_base = NULL;
617   fp->_IO_write_ptr = NULL;
618   fp->_IO_write_end = NULL;
619   fp->_chain = NULL; /* Not necessary. */
620
621   fp->_IO_save_base = NULL;
622   fp->_IO_backup_base = NULL;
623   fp->_IO_save_end = NULL;
624   fp->_markers = NULL;
625   fp->_cur_column = 0;
626 #if _IO_JUMPS_OFFSET
627   fp->_vtable_offset = 0;
628 #endif
629 #ifdef _IO_MTSAFE_IO
630   if (fp->_lock != NULL)
631     _IO_lock_init (*fp->_lock);
632 #endif
633 }
634
635 void
636 _IO_no_init (fp, flags, orientation, wd, jmp)
637      _IO_FILE *fp;
638      int flags;
639      int orientation;
640      struct _IO_wide_data *wd;
641      struct _IO_jump_t *jmp;
642 {
643   _IO_old_init (fp, flags);
644   fp->_mode = orientation;
645 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
646   if (orientation >= 0)
647     {
648       fp->_wide_data = wd;
649       fp->_wide_data->_IO_buf_base = NULL;
650       fp->_wide_data->_IO_buf_end = NULL;
651       fp->_wide_data->_IO_read_base = NULL;
652       fp->_wide_data->_IO_read_ptr = NULL;
653       fp->_wide_data->_IO_read_end = NULL;
654       fp->_wide_data->_IO_write_base = NULL;
655       fp->_wide_data->_IO_write_ptr = NULL;
656       fp->_wide_data->_IO_write_end = NULL;
657       fp->_wide_data->_IO_save_base = NULL;
658       fp->_wide_data->_IO_backup_base = NULL;
659       fp->_wide_data->_IO_save_end = NULL;
660
661       fp->_wide_data->_wide_vtable = jmp;
662     }
663 #endif
664 }
665
666 int
667 _IO_default_sync (fp)
668      _IO_FILE *fp;
669 {
670   return 0;
671 }
672
673 /* The way the C++ classes are mapped into the C functions in the
674    current implementation, this function can get called twice! */
675
676 void
677 _IO_default_finish (fp, dummy)
678      _IO_FILE *fp;
679      int dummy;
680 {
681   struct _IO_marker *mark;
682   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
683     {
684       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
685       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
686     }
687
688   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
689     mark->_sbuf = NULL;
690
691   if (fp->_IO_save_base)
692     {
693       free (fp->_IO_save_base);
694       fp->_IO_save_base = NULL;
695     }
696
697 #ifdef _IO_MTSAFE_IO
698   if (fp->_lock != NULL)
699     _IO_lock_fini (*fp->_lock);
700 #endif
701
702   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
703 }
704 INTDEF(_IO_default_finish)
705
706 _IO_off64_t
707 _IO_default_seekoff (fp, offset, dir, mode)
708      _IO_FILE *fp;
709      _IO_off64_t offset;
710      int dir;
711      int mode;
712 {
713   return _IO_pos_BAD;
714 }
715
716 int
717 _IO_sputbackc (fp, c)
718      _IO_FILE *fp;
719      int c;
720 {
721   int result;
722
723   if (fp->_IO_read_ptr > fp->_IO_read_base
724       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
725     {
726       fp->_IO_read_ptr--;
727       result = (unsigned char) c;
728     }
729   else
730     result = _IO_PBACKFAIL (fp, c);
731
732   if (result != EOF)
733     fp->_flags &= ~_IO_EOF_SEEN;
734
735   return result;
736 }
737 INTDEF(_IO_sputbackc)
738
739 int
740 _IO_sungetc (fp)
741      _IO_FILE *fp;
742 {
743   int result;
744
745   if (fp->_IO_read_ptr > fp->_IO_read_base)
746     {
747       fp->_IO_read_ptr--;
748       result = (unsigned char) *fp->_IO_read_ptr;
749     }
750   else
751     result = _IO_PBACKFAIL (fp, EOF);
752
753   if (result != EOF)
754     fp->_flags &= ~_IO_EOF_SEEN;
755
756   return result;
757 }
758
759 #if 0 /* Work in progress */
760 /* Seems not to be needed.  */
761 #if 0
762 void
763 _IO_set_column (fp, c)
764      _IO_FILE *fp;
765      int c;
766 {
767   if (c == -1)
768     fp->_column = -1;
769   else
770     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
771 }
772 #else
773 int
774 _IO_set_column (fp, i)
775      _IO_FILE *fp;
776      int i;
777 {
778   fp->_cur_column = i + 1;
779   return 0;
780 }
781 #endif
782 #endif
783
784
785 unsigned
786 _IO_adjust_column (start, line, count)
787      unsigned start;
788      const char *line;
789      int count;
790 {
791   const char *ptr = line + count;
792   while (ptr > line)
793     if (*--ptr == '\n')
794       return line + count - ptr - 1;
795   return start + count;
796 }
797 INTDEF(_IO_adjust_column)
798
799 #if 0
800 /* Seems not to be needed. --drepper */
801 int
802 _IO_get_column (fp)
803      _IO_FILE *fp;
804 {
805   if (fp->_cur_column)
806     return _IO_adjust_column (fp->_cur_column - 1,
807                               fp->_IO_write_base,
808                               fp->_IO_write_ptr - fp->_IO_write_base);
809   return -1;
810 }
811 #endif
812
813
814 int
815 _IO_flush_all_lockp (int do_lock)
816 {
817   int result = 0;
818   struct _IO_FILE *fp;
819   int last_stamp;
820
821 #ifdef _IO_MTSAFE_IO
822   _IO_cleanup_region_start_noarg (flush_cleanup);
823   if (do_lock)
824     _IO_lock_lock (list_all_lock);
825 #endif
826
827   last_stamp = _IO_list_all_stamp;
828   fp = (_IO_FILE *) INTUSE(_IO_list_all);
829   while (fp != NULL)
830     {
831       run_fp = fp;
832       if (do_lock)
833         _IO_flockfile (fp);
834
835       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
836 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
837            || (fp->_vtable_offset == 0
838                && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
839                                     > fp->_wide_data->_IO_write_base))
840 #endif
841            )
842           && _IO_OVERFLOW (fp, EOF) == EOF)
843         result = EOF;
844
845       if (do_lock)
846         _IO_funlockfile (fp);
847       run_fp = NULL;
848
849       if (last_stamp != _IO_list_all_stamp)
850         {
851           /* Something was added to the list.  Start all over again.  */
852           fp = (_IO_FILE *) INTUSE(_IO_list_all);
853           last_stamp = _IO_list_all_stamp;
854         }
855       else
856         fp = fp->_chain;
857     }
858
859 #ifdef _IO_MTSAFE_IO
860   if (do_lock)
861     _IO_lock_unlock (list_all_lock);
862   _IO_cleanup_region_end (0);
863 #endif
864
865   return result;
866 }
867
868
869 int
870 _IO_flush_all ()
871 {
872   /* We want locking.  */
873   return _IO_flush_all_lockp (1);
874 }
875 INTDEF(_IO_flush_all)
876
877 void
878 _IO_flush_all_linebuffered ()
879 {
880   struct _IO_FILE *fp;
881   int last_stamp;
882
883 #ifdef _IO_MTSAFE_IO
884   _IO_cleanup_region_start_noarg (flush_cleanup);
885   _IO_lock_lock (list_all_lock);
886 #endif
887
888   last_stamp = _IO_list_all_stamp;
889   fp = (_IO_FILE *) INTUSE(_IO_list_all);
890   while (fp != NULL)
891     {
892       run_fp = fp;
893       _IO_flockfile (fp);
894
895       if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
896         _IO_OVERFLOW (fp, EOF);
897
898       _IO_funlockfile (fp);
899       run_fp = NULL;
900
901       if (last_stamp != _IO_list_all_stamp)
902         {
903           /* Something was added to the list.  Start all over again.  */
904           fp = (_IO_FILE *) INTUSE(_IO_list_all);
905           last_stamp = _IO_list_all_stamp;
906         }
907       else
908         fp = fp->_chain;
909     }
910
911 #ifdef _IO_MTSAFE_IO
912   _IO_lock_unlock (list_all_lock);
913   _IO_cleanup_region_end (0);
914 #endif
915 }
916 INTDEF(_IO_flush_all_linebuffered)
917 #ifdef _LIBC
918 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
919 #endif
920
921 static void _IO_unbuffer_write __P ((void));
922
923 static void
924 _IO_unbuffer_write ()
925 {
926   struct _IO_FILE *fp;
927   for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
928     {
929       if (! (fp->_flags & _IO_UNBUFFERED)
930           && (! (fp->_flags & _IO_NO_WRITES)
931               || (fp->_flags & _IO_IS_APPENDING))
932           /* Iff stream is un-orientated, it wasn't used. */
933           && fp->_mode != 0)
934         _IO_SETBUF (fp, NULL, 0);
935
936       /* Make sure that never again the wide char functions can be
937          used.  */
938       fp->_mode = -1;
939     }
940 }
941
942 int
943 _IO_cleanup ()
944 {
945   int result = INTUSE(_IO_flush_all) ();
946
947   /* We currently don't have a reliable mechanism for making sure that
948      C++ static destructors are executed in the correct order.
949      So it is possible that other static destructors might want to
950      write to cout - and they're supposed to be able to do so.
951
952      The following will make the standard streambufs be unbuffered,
953      which forces any output from late destructors to be written out. */
954   _IO_unbuffer_write ();
955
956   return result;
957 }
958
959
960 void
961 _IO_init_marker (marker, fp)
962      struct _IO_marker *marker;
963      _IO_FILE *fp;
964 {
965   marker->_sbuf = fp;
966   if (_IO_in_put_mode (fp))
967     INTUSE(_IO_switch_to_get_mode) (fp);
968   if (_IO_in_backup (fp))
969     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
970   else
971     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
972
973   /* Should perhaps sort the chain? */
974   marker->_next = fp->_markers;
975   fp->_markers = marker;
976 }
977
978 void
979 _IO_remove_marker (marker)
980      struct _IO_marker *marker;
981 {
982   /* Unlink from sb's chain. */
983   struct _IO_marker **ptr = &marker->_sbuf->_markers;
984   for (; ; ptr = &(*ptr)->_next)
985     {
986       if (*ptr == NULL)
987         break;
988       else if (*ptr == marker)
989         {
990           *ptr = marker->_next;
991           return;
992         }
993     }
994 #if 0
995     if _sbuf has a backup area that is no longer needed, should we delete
996     it now, or wait until the next underflow?
997 #endif
998 }
999
1000 #define BAD_DELTA EOF
1001
1002 int
1003 _IO_marker_difference (mark1, mark2)
1004      struct _IO_marker *mark1;
1005      struct _IO_marker *mark2;
1006 {
1007   return mark1->_pos - mark2->_pos;
1008 }
1009
1010 /* Return difference between MARK and current position of MARK's stream. */
1011 int
1012 _IO_marker_delta (mark)
1013      struct _IO_marker *mark;
1014 {
1015   int cur_pos;
1016   if (mark->_sbuf == NULL)
1017     return BAD_DELTA;
1018   if (_IO_in_backup (mark->_sbuf))
1019     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
1020   else
1021     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
1022   return mark->_pos - cur_pos;
1023 }
1024
1025 int
1026 _IO_seekmark (fp, mark, delta)
1027      _IO_FILE *fp;
1028      struct _IO_marker *mark;
1029      int delta;
1030 {
1031   if (mark->_sbuf != fp)
1032     return EOF;
1033  if (mark->_pos >= 0)
1034     {
1035       if (_IO_in_backup (fp))
1036         _IO_switch_to_main_get_area (fp);
1037       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
1038     }
1039   else
1040     {
1041       if (!_IO_in_backup (fp))
1042         _IO_switch_to_backup_area (fp);
1043       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
1044     }
1045   return 0;
1046 }
1047
1048 void
1049 _IO_unsave_markers (fp)
1050      _IO_FILE *fp;
1051 {
1052   struct _IO_marker *mark = fp->_markers;
1053   if (mark)
1054     {
1055 #ifdef TODO
1056       streampos offset = seekoff (0, ios::cur, ios::in);
1057       if (offset != EOF)
1058         {
1059           offset += eGptr () - Gbase ();
1060           for ( ; mark != NULL; mark = mark->_next)
1061             mark->set_streampos (mark->_pos + offset);
1062         }
1063     else
1064       {
1065         for ( ; mark != NULL; mark = mark->_next)
1066           mark->set_streampos (EOF);
1067       }
1068 #endif
1069       fp->_markers = 0;
1070     }
1071
1072   if (_IO_have_backup (fp))
1073     INTUSE(_IO_free_backup_area) (fp);
1074 }
1075 INTDEF(_IO_unsave_markers)
1076
1077 #if 0
1078 /* Seems not to be needed. --drepper */
1079 int
1080 _IO_nobackup_pbackfail (fp, c)
1081      _IO_FILE *fp;
1082      int c;
1083 {
1084   if (fp->_IO_read_ptr > fp->_IO_read_base)
1085         fp->_IO_read_ptr--;
1086   if (c != EOF && *fp->_IO_read_ptr != c)
1087       *fp->_IO_read_ptr = c;
1088   return (unsigned char) c;
1089 }
1090 #endif
1091
1092 int
1093 _IO_default_pbackfail (fp, c)
1094      _IO_FILE *fp;
1095      int c;
1096 {
1097   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
1098       && (unsigned char) fp->_IO_read_ptr[-1] == c)
1099     --fp->_IO_read_ptr;
1100   else
1101     {
1102       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
1103       if (!_IO_in_backup (fp))
1104         {
1105           /* We need to keep the invariant that the main get area
1106              logically follows the backup area.  */
1107           if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
1108             {
1109               if (save_for_backup (fp, fp->_IO_read_ptr))
1110                 return EOF;
1111             }
1112           else if (!_IO_have_backup (fp))
1113             {
1114               /* No backup buffer: allocate one. */
1115               /* Use nshort buffer, if unused? (probably not)  FIXME */
1116               int backup_size = 128;
1117               char *bbuf = (char *) malloc (backup_size);
1118               if (bbuf == NULL)
1119                 return EOF;
1120               fp->_IO_save_base = bbuf;
1121               fp->_IO_save_end = fp->_IO_save_base + backup_size;
1122               fp->_IO_backup_base = fp->_IO_save_end;
1123             }
1124           fp->_IO_read_base = fp->_IO_read_ptr;
1125           _IO_switch_to_backup_area (fp);
1126         }
1127       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
1128         {
1129           /* Increase size of existing backup buffer. */
1130           _IO_size_t new_size;
1131           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
1132           char *new_buf;
1133           new_size = 2 * old_size;
1134           new_buf = (char *) malloc (new_size);
1135           if (new_buf == NULL)
1136             return EOF;
1137           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1138                   old_size);
1139           free (fp->_IO_read_base);
1140           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1141                     new_buf + new_size);
1142           fp->_IO_backup_base = fp->_IO_read_ptr;
1143         }
1144
1145       *--fp->_IO_read_ptr = c;
1146     }
1147   return (unsigned char) c;
1148 }
1149 INTDEF(_IO_default_pbackfail)
1150
1151 _IO_off64_t
1152 _IO_default_seek (fp, offset, dir)
1153      _IO_FILE *fp;
1154      _IO_off64_t offset;
1155      int dir;
1156 {
1157   return _IO_pos_BAD;
1158 }
1159
1160 int
1161 _IO_default_stat (fp, st)
1162      _IO_FILE *fp;
1163      void* st;
1164 {
1165   return EOF;
1166 }
1167
1168 _IO_ssize_t
1169 _IO_default_read (fp, data, n)
1170      _IO_FILE* fp;
1171      void *data;
1172      _IO_ssize_t n;
1173 {
1174   return -1;
1175 }
1176
1177 _IO_ssize_t
1178 _IO_default_write (fp, data, n)
1179      _IO_FILE *fp;
1180      const void *data;
1181      _IO_ssize_t n;
1182 {
1183   return 0;
1184 }
1185
1186 int
1187 _IO_default_showmanyc (fp)
1188      _IO_FILE *fp;
1189 {
1190   return -1;
1191 }
1192
1193 void
1194 _IO_default_imbue (fp, locale)
1195      _IO_FILE *fp;
1196      void *locale;
1197 {
1198 }
1199
1200 _IO_ITER
1201 _IO_iter_begin()
1202 {
1203   return (_IO_ITER) INTUSE(_IO_list_all);
1204 }
1205 libc_hidden_def (_IO_iter_begin)
1206
1207 _IO_ITER
1208 _IO_iter_end()
1209 {
1210   return NULL;
1211 }
1212 libc_hidden_def (_IO_iter_end)
1213
1214 _IO_ITER
1215 _IO_iter_next(iter)
1216     _IO_ITER iter;
1217 {
1218   return iter->_chain;
1219 }
1220 libc_hidden_def (_IO_iter_next)
1221
1222 _IO_FILE *
1223 _IO_iter_file(iter)
1224     _IO_ITER iter;
1225 {
1226   return iter;
1227 }
1228 libc_hidden_def (_IO_iter_file)
1229
1230 void
1231 _IO_list_lock()
1232 {
1233 #ifdef _IO_MTSAFE_IO
1234   _IO_lock_lock (list_all_lock);
1235 #endif
1236 }
1237 libc_hidden_def (_IO_list_lock)
1238
1239 void
1240 _IO_list_unlock()
1241 {
1242 #ifdef _IO_MTSAFE_IO
1243   _IO_lock_unlock (list_all_lock);
1244 #endif
1245 }
1246 libc_hidden_def (_IO_list_unlock)
1247
1248 void
1249 _IO_list_resetlock()
1250 {
1251 #ifdef _IO_MTSAFE_IO
1252   _IO_lock_init (list_all_lock);
1253 #endif
1254 }
1255 libc_hidden_def (_IO_list_resetlock)
1256
1257
1258 #ifdef TODO
1259 #if defined(linux)
1260 #define IO_CLEANUP ;
1261 #endif
1262
1263 #ifdef IO_CLEANUP
1264   IO_CLEANUP
1265 #else
1266 struct __io_defs {
1267     __io_defs() { }
1268     ~__io_defs() { _IO_cleanup (); }
1269 };
1270 __io_defs io_defs__;
1271 #endif
1272
1273 #endif /* TODO */
1274
1275 #ifdef text_set_element
1276 text_set_element(__libc_atexit, _IO_cleanup);
1277 #endif