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