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