7005fdbd96114f6e1fe5479231e83e0fd2e30d88
[kopensolaris-gnu/glibc.git] / 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       if (fp->_IO_save_base)
304         free (fp->_IO_save_base);
305       fp->_IO_save_base = new_buffer;
306       fp->_IO_save_end = new_buffer + avail + needed_size;
307     }
308   else
309     {
310       avail = current_Bsize - needed_size;
311       if (least_mark < 0)
312         {
313           memmove (fp->_IO_save_base + avail,
314                    fp->_IO_save_end + least_mark,
315                    -least_mark);
316           memcpy (fp->_IO_save_base + avail - least_mark,
317                   fp->_IO_read_base,
318                   end_p - fp->_IO_read_base);
319         }
320       else if (needed_size > 0)
321         memcpy (fp->_IO_save_base + avail,
322                 fp->_IO_read_base + least_mark,
323                 needed_size);
324     }
325   fp->_IO_backup_base = fp->_IO_save_base + avail;
326   /* Adjust all the streammarkers. */
327   delta = end_p - fp->_IO_read_base;
328   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
329     mark->_pos -= delta;
330   return 0;
331 }
332
333 int
334 __underflow (fp)
335      _IO_FILE *fp;
336 {
337 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
338   if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
339     return EOF;
340 #endif
341
342   if (fp->_mode == 0)
343     _IO_fwide (fp, -1);
344   if (_IO_in_put_mode (fp))
345     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
346       return EOF;
347   if (fp->_IO_read_ptr < fp->_IO_read_end)
348     return *(unsigned char *) fp->_IO_read_ptr;
349   if (_IO_in_backup (fp))
350     {
351       _IO_switch_to_main_get_area (fp);
352       if (fp->_IO_read_ptr < fp->_IO_read_end)
353         return *(unsigned char *) fp->_IO_read_ptr;
354     }
355   if (_IO_have_markers (fp))
356     {
357       if (save_for_backup (fp, fp->_IO_read_end))
358         return EOF;
359     }
360   else if (_IO_have_backup (fp))
361     INTUSE(_IO_free_backup_area) (fp);
362   return _IO_UNDERFLOW (fp);
363 }
364 libc_hidden_def (__underflow)
365
366 int
367 __uflow (fp)
368      _IO_FILE *fp;
369 {
370 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
371   if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
372     return EOF;
373 #endif
374
375   if (fp->_mode == 0)
376     _IO_fwide (fp, -1);
377   if (_IO_in_put_mode (fp))
378     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
379       return EOF;
380   if (fp->_IO_read_ptr < fp->_IO_read_end)
381     return *(unsigned char *) fp->_IO_read_ptr++;
382   if (_IO_in_backup (fp))
383     {
384       _IO_switch_to_main_get_area (fp);
385       if (fp->_IO_read_ptr < fp->_IO_read_end)
386         return *(unsigned char *) fp->_IO_read_ptr++;
387     }
388   if (_IO_have_markers (fp))
389     {
390       if (save_for_backup (fp, fp->_IO_read_end))
391         return EOF;
392     }
393   else if (_IO_have_backup (fp))
394     INTUSE(_IO_free_backup_area) (fp);
395   return _IO_UFLOW (fp);
396 }
397 libc_hidden_def (__uflow)
398
399 void
400 _IO_setb (f, b, eb, a)
401      _IO_FILE *f;
402      char *b;
403      char *eb;
404      int a;
405 {
406   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
407     FREE_BUF (f->_IO_buf_base, _IO_blen (f));
408   f->_IO_buf_base = b;
409   f->_IO_buf_end = eb;
410   if (a)
411     f->_flags &= ~_IO_USER_BUF;
412   else
413     f->_flags |= _IO_USER_BUF;
414 }
415 INTDEF(_IO_setb)
416
417 void
418 _IO_doallocbuf (fp)
419      _IO_FILE *fp;
420 {
421   if (fp->_IO_buf_base)
422     return;
423   if (!(fp->_flags & _IO_UNBUFFERED) || fp->_mode > 0)
424     if (_IO_DOALLOCATE (fp) != EOF)
425       return;
426   INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
427 }
428 INTDEF(_IO_doallocbuf)
429
430 int
431 _IO_default_underflow (fp)
432      _IO_FILE *fp;
433 {
434   return EOF;
435 }
436
437 int
438 _IO_default_uflow (fp)
439      _IO_FILE *fp;
440 {
441   int ch = _IO_UNDERFLOW (fp);
442   if (ch == EOF)
443     return EOF;
444   return *(unsigned char *) fp->_IO_read_ptr++;
445 }
446 INTDEF(_IO_default_uflow)
447
448 _IO_size_t
449 _IO_default_xsputn (f, data, n)
450      _IO_FILE *f;
451      const void *data;
452      _IO_size_t n;
453 {
454   const char *s = (char *) data;
455   _IO_size_t more = n;
456   if (more <= 0)
457     return 0;
458   for (;;)
459     {
460       /* Space available. */
461       if (f->_IO_write_ptr < f->_IO_write_end)
462         {
463           _IO_size_t count = f->_IO_write_end - f->_IO_write_ptr;
464           if (count > more)
465             count = more;
466           if (count > 20)
467             {
468 #ifdef _LIBC
469               f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
470 #else
471               memcpy (f->_IO_write_ptr, s, count);
472               f->_IO_write_ptr += count;
473 #endif
474               s += count;
475             }
476           else if (count)
477             {
478               char *p = f->_IO_write_ptr;
479               _IO_ssize_t i;
480               for (i = count; --i >= 0; )
481                 *p++ = *s++;
482               f->_IO_write_ptr = p;
483             }
484           more -= count;
485         }
486       if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF)
487         break;
488       more--;
489     }
490   return n - more;
491 }
492 INTDEF(_IO_default_xsputn)
493
494 _IO_size_t
495 _IO_sgetn (fp, data, n)
496      _IO_FILE *fp;
497      void *data;
498      _IO_size_t n;
499 {
500   /* FIXME handle putback buffer here! */
501   return _IO_XSGETN (fp, data, n);
502 }
503 INTDEF(_IO_sgetn)
504
505 _IO_size_t
506 _IO_default_xsgetn (fp, data, n)
507      _IO_FILE *fp;
508      void *data;
509      _IO_size_t n;
510 {
511   _IO_size_t more = n;
512   char *s = (char*) data;
513   for (;;)
514     {
515       /* Data available. */
516       if (fp->_IO_read_ptr < fp->_IO_read_end)
517         {
518           _IO_size_t count = fp->_IO_read_end - fp->_IO_read_ptr;
519           if (count > more)
520             count = more;
521           if (count > 20)
522             {
523 #ifdef _LIBC
524               s = __mempcpy (s, fp->_IO_read_ptr, count);
525 #else
526               memcpy (s, fp->_IO_read_ptr, count);
527               s += count;
528 #endif
529               fp->_IO_read_ptr += count;
530             }
531           else if (count)
532             {
533               char *p = fp->_IO_read_ptr;
534               int i = (int) count;
535               while (--i >= 0)
536                 *s++ = *p++;
537               fp->_IO_read_ptr = p;
538             }
539             more -= count;
540         }
541       if (more == 0 || __underflow (fp) == EOF)
542         break;
543     }
544   return n - more;
545 }
546 INTDEF(_IO_default_xsgetn)
547
548 #if 0
549 /* Seems not to be needed. --drepper */
550 int
551 _IO_sync (fp)
552      _IO_FILE *fp;
553 {
554   return 0;
555 }
556 #endif
557
558 _IO_FILE *
559 _IO_default_setbuf (fp, p, len)
560      _IO_FILE *fp;
561      char *p;
562      _IO_ssize_t len;
563 {
564     if (_IO_SYNC (fp) == EOF)
565         return NULL;
566     if (p == NULL || len == 0)
567       {
568         fp->_flags |= _IO_UNBUFFERED;
569         INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
570       }
571     else
572       {
573         fp->_flags &= ~_IO_UNBUFFERED;
574         INTUSE(_IO_setb) (fp, p, p+len, 0);
575       }
576     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
577     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
578     return fp;
579 }
580
581 _IO_off64_t
582 _IO_default_seekpos (fp, pos, mode)
583      _IO_FILE *fp;
584      _IO_off64_t pos;
585      int mode;
586 {
587   return _IO_SEEKOFF (fp, pos, 0, mode);
588 }
589
590 int
591 _IO_default_doallocate (fp)
592      _IO_FILE *fp;
593 {
594   char *buf;
595
596   ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
597   INTUSE(_IO_setb) (fp, buf, buf+_IO_BUFSIZ, 1);
598   return 1;
599 }
600 INTDEF(_IO_default_doallocate)
601
602 void
603 _IO_init (fp, flags)
604      _IO_FILE *fp;
605      int flags;
606 {
607   _IO_no_init (fp, flags, -1, NULL, NULL);
608 }
609 INTDEF(_IO_init)
610
611 void
612 _IO_old_init (fp, flags)
613      _IO_FILE *fp;
614      int flags;
615 {
616   fp->_flags = _IO_MAGIC|flags;
617   fp->_flags2 = 0;
618   fp->_IO_buf_base = NULL;
619   fp->_IO_buf_end = NULL;
620   fp->_IO_read_base = NULL;
621   fp->_IO_read_ptr = NULL;
622   fp->_IO_read_end = NULL;
623   fp->_IO_write_base = NULL;
624   fp->_IO_write_ptr = NULL;
625   fp->_IO_write_end = NULL;
626   fp->_chain = NULL; /* Not necessary. */
627
628   fp->_IO_save_base = NULL;
629   fp->_IO_backup_base = NULL;
630   fp->_IO_save_end = NULL;
631   fp->_markers = NULL;
632   fp->_cur_column = 0;
633 #if _IO_JUMPS_OFFSET
634   fp->_vtable_offset = 0;
635 #endif
636 #ifdef _IO_MTSAFE_IO
637   if (fp->_lock != NULL)
638     _IO_lock_init (*fp->_lock);
639 #endif
640 }
641
642 void
643 _IO_no_init (fp, flags, orientation, wd, jmp)
644      _IO_FILE *fp;
645      int flags;
646      int orientation;
647      struct _IO_wide_data *wd;
648      const struct _IO_jump_t *jmp;
649 {
650   _IO_old_init (fp, flags);
651   fp->_mode = orientation;
652 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
653   if (orientation >= 0)
654     {
655       fp->_wide_data = wd;
656       fp->_wide_data->_IO_buf_base = NULL;
657       fp->_wide_data->_IO_buf_end = NULL;
658       fp->_wide_data->_IO_read_base = NULL;
659       fp->_wide_data->_IO_read_ptr = NULL;
660       fp->_wide_data->_IO_read_end = NULL;
661       fp->_wide_data->_IO_write_base = NULL;
662       fp->_wide_data->_IO_write_ptr = NULL;
663       fp->_wide_data->_IO_write_end = NULL;
664       fp->_wide_data->_IO_save_base = NULL;
665       fp->_wide_data->_IO_backup_base = NULL;
666       fp->_wide_data->_IO_save_end = NULL;
667
668       fp->_wide_data->_wide_vtable = jmp;
669     }
670 #endif
671   fp->_freeres_list = NULL;
672 }
673
674 int
675 _IO_default_sync (fp)
676      _IO_FILE *fp;
677 {
678   return 0;
679 }
680
681 /* The way the C++ classes are mapped into the C functions in the
682    current implementation, this function can get called twice! */
683
684 void
685 _IO_default_finish (fp, dummy)
686      _IO_FILE *fp;
687      int dummy;
688 {
689   struct _IO_marker *mark;
690   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
691     {
692       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
693       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
694     }
695
696   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
697     mark->_sbuf = NULL;
698
699   if (fp->_IO_save_base)
700     {
701       free (fp->_IO_save_base);
702       fp->_IO_save_base = NULL;
703     }
704
705   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
706
707 #ifdef _IO_MTSAFE_IO
708   if (fp->_lock != NULL)
709     _IO_lock_fini (*fp->_lock);
710 #endif
711 }
712 INTDEF(_IO_default_finish)
713
714 _IO_off64_t
715 _IO_default_seekoff (fp, offset, dir, mode)
716      _IO_FILE *fp;
717      _IO_off64_t offset;
718      int dir;
719      int mode;
720 {
721   return _IO_pos_BAD;
722 }
723
724 int
725 _IO_sputbackc (fp, c)
726      _IO_FILE *fp;
727      int c;
728 {
729   int result;
730
731   if (fp->_IO_read_ptr > fp->_IO_read_base
732       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
733     {
734       fp->_IO_read_ptr--;
735       result = (unsigned char) c;
736     }
737   else
738     result = _IO_PBACKFAIL (fp, c);
739
740   if (result != EOF)
741     fp->_flags &= ~_IO_EOF_SEEN;
742
743   return result;
744 }
745 INTDEF(_IO_sputbackc)
746
747 int
748 _IO_sungetc (fp)
749      _IO_FILE *fp;
750 {
751   int result;
752
753   if (fp->_IO_read_ptr > fp->_IO_read_base)
754     {
755       fp->_IO_read_ptr--;
756       result = (unsigned char) *fp->_IO_read_ptr;
757     }
758   else
759     result = _IO_PBACKFAIL (fp, EOF);
760
761   if (result != EOF)
762     fp->_flags &= ~_IO_EOF_SEEN;
763
764   return result;
765 }
766
767 #if 0 /* Work in progress */
768 /* Seems not to be needed.  */
769 #if 0
770 void
771 _IO_set_column (fp, c)
772      _IO_FILE *fp;
773      int c;
774 {
775   if (c == -1)
776     fp->_column = -1;
777   else
778     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
779 }
780 #else
781 int
782 _IO_set_column (fp, i)
783      _IO_FILE *fp;
784      int i;
785 {
786   fp->_cur_column = i + 1;
787   return 0;
788 }
789 #endif
790 #endif
791
792
793 unsigned
794 _IO_adjust_column (start, line, count)
795      unsigned start;
796      const char *line;
797      int count;
798 {
799   const char *ptr = line + count;
800   while (ptr > line)
801     if (*--ptr == '\n')
802       return line + count - ptr - 1;
803   return start + count;
804 }
805 INTDEF(_IO_adjust_column)
806
807 #if 0
808 /* Seems not to be needed. --drepper */
809 int
810 _IO_get_column (fp)
811      _IO_FILE *fp;
812 {
813   if (fp->_cur_column)
814     return _IO_adjust_column (fp->_cur_column - 1,
815                               fp->_IO_write_base,
816                               fp->_IO_write_ptr - fp->_IO_write_base);
817   return -1;
818 }
819 #endif
820
821
822 int
823 _IO_flush_all_lockp (int do_lock)
824 {
825   int result = 0;
826   struct _IO_FILE *fp;
827   int last_stamp;
828
829 #ifdef _IO_MTSAFE_IO
830   _IO_cleanup_region_start_noarg (flush_cleanup);
831   if (do_lock)
832     _IO_lock_lock (list_all_lock);
833 #endif
834
835   last_stamp = _IO_list_all_stamp;
836   fp = (_IO_FILE *) INTUSE(_IO_list_all);
837   while (fp != NULL)
838     {
839       run_fp = fp;
840       if (do_lock)
841         _IO_flockfile (fp);
842
843       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
844 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
845            || (_IO_vtable_offset (fp) == 0
846                && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
847                                     > fp->_wide_data->_IO_write_base))
848 #endif
849            )
850           && _IO_OVERFLOW (fp, EOF) == EOF)
851         result = EOF;
852
853       if (do_lock)
854         _IO_funlockfile (fp);
855       run_fp = NULL;
856
857       if (last_stamp != _IO_list_all_stamp)
858         {
859           /* Something was added to the list.  Start all over again.  */
860           fp = (_IO_FILE *) INTUSE(_IO_list_all);
861           last_stamp = _IO_list_all_stamp;
862         }
863       else
864         fp = fp->_chain;
865     }
866
867 #ifdef _IO_MTSAFE_IO
868   if (do_lock)
869     _IO_lock_unlock (list_all_lock);
870   _IO_cleanup_region_end (0);
871 #endif
872
873   return result;
874 }
875
876
877 int
878 _IO_flush_all ()
879 {
880   /* We want locking.  */
881   return _IO_flush_all_lockp (1);
882 }
883 INTDEF(_IO_flush_all)
884
885 void
886 _IO_flush_all_linebuffered ()
887 {
888   struct _IO_FILE *fp;
889   int last_stamp;
890
891 #ifdef _IO_MTSAFE_IO
892   _IO_cleanup_region_start_noarg (flush_cleanup);
893   _IO_lock_lock (list_all_lock);
894 #endif
895
896   last_stamp = _IO_list_all_stamp;
897   fp = (_IO_FILE *) INTUSE(_IO_list_all);
898   while (fp != NULL)
899     {
900       run_fp = fp;
901       _IO_flockfile (fp);
902
903       if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
904         _IO_OVERFLOW (fp, EOF);
905
906       _IO_funlockfile (fp);
907       run_fp = NULL;
908
909       if (last_stamp != _IO_list_all_stamp)
910         {
911           /* Something was added to the list.  Start all over again.  */
912           fp = (_IO_FILE *) INTUSE(_IO_list_all);
913           last_stamp = _IO_list_all_stamp;
914         }
915       else
916         fp = fp->_chain;
917     }
918
919 #ifdef _IO_MTSAFE_IO
920   _IO_lock_unlock (list_all_lock);
921   _IO_cleanup_region_end (0);
922 #endif
923 }
924 INTDEF(_IO_flush_all_linebuffered)
925 #ifdef _LIBC
926 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
927 #endif
928
929
930 /* The following is a bit tricky.  In general, we want to unbuffer the
931    streams so that all output which follows is seen.  If we are not
932    looking for memory leaks it does not make much sense to free the
933    actual buffer because this will happen anyway once the program
934    terminated.  If we do want to look for memory leaks we have to free
935    the buffers.  Whether something is freed is determined by the
936    function sin the libc_freeres section.  Those are called as part of
937    the atexit routine, just like _IO_cleanup.  The problem is we do
938    not know whether the freeres code is called first or _IO_cleanup.
939    if the former is the case, we set the DEALLOC_BUFFER variable to
940    true and _IO_unbuffer_write will take care of the rest.  If
941    _IO_unbuffer_write is called first we add the streams to a list
942    which the freeres function later can walk through.  */
943 static void _IO_unbuffer_write (void);
944
945 static bool dealloc_buffers;
946 static _IO_FILE *freeres_list;
947
948 static void
949 _IO_unbuffer_write (void)
950 {
951   struct _IO_FILE *fp;
952   for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
953     {
954       if (! (fp->_flags & _IO_UNBUFFERED)
955           && (! (fp->_flags & _IO_NO_WRITES)
956               || (fp->_flags & _IO_IS_APPENDING))
957           /* Iff stream is un-orientated, it wasn't used. */
958           && fp->_mode != 0)
959         {
960           int cnt;
961 #define MAXTRIES 2
962           for (cnt = 0; cnt < MAXTRIES; ++cnt)
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
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           if (cnt < MAXTRIES)
983             _IO_lock_unlock (*fp->_lock);
984         }
985
986       /* Make sure that never again the wide char functions can be
987          used.  */
988       fp->_mode = -1;
989     }
990 }
991
992
993 libc_freeres_fn (buffer_free)
994 {
995   dealloc_buffers = true;
996
997   while (freeres_list != NULL)
998     {
999       FREE_BUF (freeres_list->_freeres_buf, freeres_list->_freeres_size);
1000
1001       freeres_list = freeres_list->_freeres_list;
1002     }
1003 }
1004
1005
1006 int
1007 _IO_cleanup ()
1008 {
1009   /* We do *not* want locking.  Some threads might use streams but
1010      that is their problem, we flush them underneath them.  */
1011   int result = _IO_flush_all_lockp (0);
1012
1013   /* We currently don't have a reliable mechanism for making sure that
1014      C++ static destructors are executed in the correct order.
1015      So it is possible that other static destructors might want to
1016      write to cout - and they're supposed to be able to do so.
1017
1018      The following will make the standard streambufs be unbuffered,
1019      which forces any output from late destructors to be written out. */
1020   _IO_unbuffer_write ();
1021
1022   return result;
1023 }
1024
1025
1026 void
1027 _IO_init_marker (marker, fp)
1028      struct _IO_marker *marker;
1029      _IO_FILE *fp;
1030 {
1031   marker->_sbuf = fp;
1032   if (_IO_in_put_mode (fp))
1033     INTUSE(_IO_switch_to_get_mode) (fp);
1034   if (_IO_in_backup (fp))
1035     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
1036   else
1037     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
1038
1039   /* Should perhaps sort the chain? */
1040   marker->_next = fp->_markers;
1041   fp->_markers = marker;
1042 }
1043
1044 void
1045 _IO_remove_marker (marker)
1046      struct _IO_marker *marker;
1047 {
1048   /* Unlink from sb's chain. */
1049   struct _IO_marker **ptr = &marker->_sbuf->_markers;
1050   for (; ; ptr = &(*ptr)->_next)
1051     {
1052       if (*ptr == NULL)
1053         break;
1054       else if (*ptr == marker)
1055         {
1056           *ptr = marker->_next;
1057           return;
1058         }
1059     }
1060 #if 0
1061     if _sbuf has a backup area that is no longer needed, should we delete
1062     it now, or wait until the next underflow?
1063 #endif
1064 }
1065
1066 #define BAD_DELTA EOF
1067
1068 int
1069 _IO_marker_difference (mark1, mark2)
1070      struct _IO_marker *mark1;
1071      struct _IO_marker *mark2;
1072 {
1073   return mark1->_pos - mark2->_pos;
1074 }
1075
1076 /* Return difference between MARK and current position of MARK's stream. */
1077 int
1078 _IO_marker_delta (mark)
1079      struct _IO_marker *mark;
1080 {
1081   int cur_pos;
1082   if (mark->_sbuf == NULL)
1083     return BAD_DELTA;
1084   if (_IO_in_backup (mark->_sbuf))
1085     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
1086   else
1087     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
1088   return mark->_pos - cur_pos;
1089 }
1090
1091 int
1092 _IO_seekmark (fp, mark, delta)
1093      _IO_FILE *fp;
1094      struct _IO_marker *mark;
1095      int delta;
1096 {
1097   if (mark->_sbuf != fp)
1098     return EOF;
1099  if (mark->_pos >= 0)
1100     {
1101       if (_IO_in_backup (fp))
1102         _IO_switch_to_main_get_area (fp);
1103       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
1104     }
1105   else
1106     {
1107       if (!_IO_in_backup (fp))
1108         _IO_switch_to_backup_area (fp);
1109       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
1110     }
1111   return 0;
1112 }
1113
1114 void
1115 _IO_unsave_markers (fp)
1116      _IO_FILE *fp;
1117 {
1118   struct _IO_marker *mark = fp->_markers;
1119   if (mark)
1120     {
1121 #ifdef TODO
1122       streampos offset = seekoff (0, ios::cur, ios::in);
1123       if (offset != EOF)
1124         {
1125           offset += eGptr () - Gbase ();
1126           for ( ; mark != NULL; mark = mark->_next)
1127             mark->set_streampos (mark->_pos + offset);
1128         }
1129     else
1130       {
1131         for ( ; mark != NULL; mark = mark->_next)
1132           mark->set_streampos (EOF);
1133       }
1134 #endif
1135       fp->_markers = 0;
1136     }
1137
1138   if (_IO_have_backup (fp))
1139     INTUSE(_IO_free_backup_area) (fp);
1140 }
1141 INTDEF(_IO_unsave_markers)
1142
1143 #if 0
1144 /* Seems not to be needed. --drepper */
1145 int
1146 _IO_nobackup_pbackfail (fp, c)
1147      _IO_FILE *fp;
1148      int c;
1149 {
1150   if (fp->_IO_read_ptr > fp->_IO_read_base)
1151         fp->_IO_read_ptr--;
1152   if (c != EOF && *fp->_IO_read_ptr != c)
1153       *fp->_IO_read_ptr = c;
1154   return (unsigned char) c;
1155 }
1156 #endif
1157
1158 int
1159 _IO_default_pbackfail (fp, c)
1160      _IO_FILE *fp;
1161      int c;
1162 {
1163   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
1164       && (unsigned char) fp->_IO_read_ptr[-1] == c)
1165     --fp->_IO_read_ptr;
1166   else
1167     {
1168       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
1169       if (!_IO_in_backup (fp))
1170         {
1171           /* We need to keep the invariant that the main get area
1172              logically follows the backup area.  */
1173           if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
1174             {
1175               if (save_for_backup (fp, fp->_IO_read_ptr))
1176                 return EOF;
1177             }
1178           else if (!_IO_have_backup (fp))
1179             {
1180               /* No backup buffer: allocate one. */
1181               /* Use nshort buffer, if unused? (probably not)  FIXME */
1182               int backup_size = 128;
1183               char *bbuf = (char *) malloc (backup_size);
1184               if (bbuf == NULL)
1185                 return EOF;
1186               fp->_IO_save_base = bbuf;
1187               fp->_IO_save_end = fp->_IO_save_base + backup_size;
1188               fp->_IO_backup_base = fp->_IO_save_end;
1189             }
1190           fp->_IO_read_base = fp->_IO_read_ptr;
1191           _IO_switch_to_backup_area (fp);
1192         }
1193       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
1194         {
1195           /* Increase size of existing backup buffer. */
1196           _IO_size_t new_size;
1197           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
1198           char *new_buf;
1199           new_size = 2 * old_size;
1200           new_buf = (char *) malloc (new_size);
1201           if (new_buf == NULL)
1202             return EOF;
1203           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1204                   old_size);
1205           free (fp->_IO_read_base);
1206           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1207                     new_buf + new_size);
1208           fp->_IO_backup_base = fp->_IO_read_ptr;
1209         }
1210
1211       *--fp->_IO_read_ptr = c;
1212     }
1213   return (unsigned char) c;
1214 }
1215 INTDEF(_IO_default_pbackfail)
1216
1217 _IO_off64_t
1218 _IO_default_seek (fp, offset, dir)
1219      _IO_FILE *fp;
1220      _IO_off64_t offset;
1221      int dir;
1222 {
1223   return _IO_pos_BAD;
1224 }
1225
1226 int
1227 _IO_default_stat (fp, st)
1228      _IO_FILE *fp;
1229      void* st;
1230 {
1231   return EOF;
1232 }
1233
1234 _IO_ssize_t
1235 _IO_default_read (fp, data, n)
1236      _IO_FILE* fp;
1237      void *data;
1238      _IO_ssize_t n;
1239 {
1240   return -1;
1241 }
1242
1243 _IO_ssize_t
1244 _IO_default_write (fp, data, n)
1245      _IO_FILE *fp;
1246      const void *data;
1247      _IO_ssize_t n;
1248 {
1249   return 0;
1250 }
1251
1252 int
1253 _IO_default_showmanyc (fp)
1254      _IO_FILE *fp;
1255 {
1256   return -1;
1257 }
1258
1259 void
1260 _IO_default_imbue (fp, locale)
1261      _IO_FILE *fp;
1262      void *locale;
1263 {
1264 }
1265
1266 _IO_ITER
1267 _IO_iter_begin()
1268 {
1269   return (_IO_ITER) INTUSE(_IO_list_all);
1270 }
1271 libc_hidden_def (_IO_iter_begin)
1272
1273 _IO_ITER
1274 _IO_iter_end()
1275 {
1276   return NULL;
1277 }
1278 libc_hidden_def (_IO_iter_end)
1279
1280 _IO_ITER
1281 _IO_iter_next(iter)
1282     _IO_ITER iter;
1283 {
1284   return iter->_chain;
1285 }
1286 libc_hidden_def (_IO_iter_next)
1287
1288 _IO_FILE *
1289 _IO_iter_file(iter)
1290     _IO_ITER iter;
1291 {
1292   return iter;
1293 }
1294 libc_hidden_def (_IO_iter_file)
1295
1296 void
1297 _IO_list_lock()
1298 {
1299 #ifdef _IO_MTSAFE_IO
1300   _IO_lock_lock (list_all_lock);
1301 #endif
1302 }
1303 libc_hidden_def (_IO_list_lock)
1304
1305 void
1306 _IO_list_unlock()
1307 {
1308 #ifdef _IO_MTSAFE_IO
1309   _IO_lock_unlock (list_all_lock);
1310 #endif
1311 }
1312 libc_hidden_def (_IO_list_unlock)
1313
1314 void
1315 _IO_list_resetlock()
1316 {
1317 #ifdef _IO_MTSAFE_IO
1318   _IO_lock_init (list_all_lock);
1319 #endif
1320 }
1321 libc_hidden_def (_IO_list_resetlock)
1322
1323
1324 #ifdef TODO
1325 #if defined(linux)
1326 #define IO_CLEANUP ;
1327 #endif
1328
1329 #ifdef IO_CLEANUP
1330   IO_CLEANUP
1331 #else
1332 struct __io_defs {
1333     __io_defs() { }
1334     ~__io_defs() { _IO_cleanup (); }
1335 };
1336 __io_defs io_defs__;
1337 #endif
1338
1339 #endif /* TODO */
1340
1341 #ifdef text_set_element
1342 text_set_element(__libc_atexit, _IO_cleanup);
1343 #endif