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