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