2398cff684476052f7b9f4f0addf731362c01e87
[kopensolaris-gnu/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   if (fp->_lock != NULL)
617     _IO_lock_init (*fp->_lock);
618 #endif
619   fp->_mode = orientation;
620 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
621   if (orientation >= 0)
622     {
623       fp->_wide_data = wd;
624       fp->_wide_data->_IO_buf_base = NULL;
625       fp->_wide_data->_IO_buf_end = NULL;
626       fp->_wide_data->_IO_read_base = NULL;
627       fp->_wide_data->_IO_read_ptr = NULL;
628       fp->_wide_data->_IO_read_end = NULL;
629       fp->_wide_data->_IO_write_base = NULL;
630       fp->_wide_data->_IO_write_ptr = NULL;
631       fp->_wide_data->_IO_write_end = NULL;
632       fp->_wide_data->_IO_save_base = NULL;
633       fp->_wide_data->_IO_backup_base = NULL;
634       fp->_wide_data->_IO_save_end = NULL;
635
636       fp->_wide_data->_wide_vtable = jmp;
637     }
638 #endif
639 }
640
641 int
642 _IO_default_sync (fp)
643      _IO_FILE *fp;
644 {
645   return 0;
646 }
647
648 /* The way the C++ classes are mapped into the C functions in the
649    current implementation, this function can get called twice! */
650
651 void
652 _IO_default_finish (fp, dummy)
653      _IO_FILE *fp;
654      int dummy;
655 {
656   struct _IO_marker *mark;
657   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
658     {
659       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
660       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
661     }
662
663   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
664     mark->_sbuf = NULL;
665
666   if (fp->_IO_save_base)
667     {
668       free (fp->_IO_save_base);
669       fp->_IO_save_base = NULL;
670     }
671
672 #ifdef _IO_MTSAFE_IO
673   if (fp->_lock != NULL)
674     _IO_lock_fini (*fp->_lock);
675 #endif
676
677   _IO_un_link ((struct _IO_FILE_plus *) fp);
678 }
679
680 _IO_off64_t
681 _IO_default_seekoff (fp, offset, dir, mode)
682      _IO_FILE *fp;
683      _IO_off64_t offset;
684      int dir;
685      int mode;
686 {
687   return _IO_pos_BAD;
688 }
689
690 int
691 _IO_sputbackc (fp, c)
692      _IO_FILE *fp;
693      int c;
694 {
695   int result;
696
697   if (fp->_IO_read_ptr > fp->_IO_read_base
698       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
699     {
700       fp->_IO_read_ptr--;
701       result = (unsigned char) c;
702     }
703   else
704     result = _IO_PBACKFAIL (fp, c);
705
706   if (result != EOF)
707     fp->_flags &= ~_IO_EOF_SEEN;
708
709   return result;
710 }
711
712 int
713 _IO_sungetc (fp)
714      _IO_FILE *fp;
715 {
716   int result;
717
718   if (fp->_IO_read_ptr > fp->_IO_read_base)
719     {
720       fp->_IO_read_ptr--;
721       result = (unsigned char) *fp->_IO_read_ptr;
722     }
723   else
724     result = _IO_PBACKFAIL (fp, EOF);
725
726   if (result != EOF)
727     fp->_flags &= ~_IO_EOF_SEEN;
728
729   return result;
730 }
731
732 #if 0 /* Work in progress */
733 /* Seems not to be needed.  */
734 #if 0
735 void
736 _IO_set_column (fp, c)
737      _IO_FILE *fp;
738      int c;
739 {
740   if (c == -1)
741     fp->_column = -1;
742   else
743     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
744 }
745 #else
746 int
747 _IO_set_column (fp, i)
748      _IO_FILE *fp;
749      int i;
750 {
751   fp->_cur_column = i + 1;
752   return 0;
753 }
754 #endif
755 #endif
756
757
758 unsigned
759 _IO_adjust_column (start, line, count)
760      unsigned start;
761      const char *line;
762      int count;
763 {
764   const char *ptr = line + count;
765   while (ptr > line)
766     if (*--ptr == '\n')
767       return line + count - ptr - 1;
768   return start + count;
769 }
770
771 #if 0
772 /* Seems not to be needed. --drepper */
773 int
774 _IO_get_column (fp)
775      _IO_FILE *fp;
776 {
777   if (fp->_cur_column)
778     return _IO_adjust_column (fp->_cur_column - 1,
779                               fp->_IO_write_base,
780                               fp->_IO_write_ptr - fp->_IO_write_base);
781   return -1;
782 }
783 #endif
784
785
786 int
787 _IO_flush_all_lockp (int do_lock)
788 {
789   int result = 0;
790   struct _IO_FILE *fp;
791   int last_stamp;
792
793 #ifdef _IO_MTSAFE_IO
794   _IO_cleanup_region_start_noarg (flush_cleanup);
795   if (do_lock)
796     _IO_lock_lock (list_all_lock);
797 #endif
798
799   last_stamp = _IO_list_all_stamp;
800   fp = (_IO_FILE *) _IO_list_all;
801   while (fp != NULL)
802     {
803       run_fp = fp;
804       if (do_lock)
805         _IO_flockfile (fp);
806
807       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
808 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
809            || (fp->_vtable_offset == 0
810                && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
811                                     > fp->_wide_data->_IO_write_base))
812 #endif
813            )
814           && _IO_OVERFLOW (fp, EOF) == EOF)
815         result = EOF;
816
817       if (do_lock)
818         _IO_funlockfile (fp);
819       run_fp = NULL;
820
821       if (last_stamp != _IO_list_all_stamp)
822         {
823           /* Something was added to the list.  Start all over again.  */
824           fp = (_IO_FILE *) _IO_list_all;
825           last_stamp = _IO_list_all_stamp;
826         }
827       else
828         fp = fp->_chain;
829     }
830
831 #ifdef _IO_MTSAFE_IO
832   if (do_lock)
833     _IO_lock_unlock (list_all_lock);
834   _IO_cleanup_region_end (0);
835 #endif
836
837   return result;
838 }
839
840
841 int
842 _IO_flush_all ()
843 {
844   /* We want locking.  */
845   return _IO_flush_all_lockp (1);
846 }
847
848 void
849 _IO_flush_all_linebuffered ()
850 {
851   struct _IO_FILE *fp;
852   int last_stamp;
853
854 #ifdef _IO_MTSAFE_IO
855   _IO_cleanup_region_start_noarg (flush_cleanup);
856   _IO_lock_lock (list_all_lock);
857 #endif
858
859   last_stamp = _IO_list_all_stamp;
860   fp = (_IO_FILE *) _IO_list_all;
861   while (fp != NULL)
862     {
863       run_fp = fp;
864       _IO_flockfile (fp);
865
866       if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
867         _IO_OVERFLOW (fp, EOF);
868
869       _IO_funlockfile (fp);
870       run_fp = NULL;
871
872       if (last_stamp != _IO_list_all_stamp)
873         {
874           /* Something was added to the list.  Start all over again.  */
875           fp = (_IO_FILE *) _IO_list_all;
876           last_stamp = _IO_list_all_stamp;
877         }
878       else
879         fp = fp->_chain;
880     }
881
882 #ifdef _IO_MTSAFE_IO
883   _IO_lock_unlock (list_all_lock);
884   _IO_cleanup_region_end (0);
885 #endif
886 }
887 #ifdef _LIBC
888 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
889 #endif
890
891 static void _IO_unbuffer_write __P ((void));
892
893 static void
894 _IO_unbuffer_write ()
895 {
896   struct _IO_FILE *fp;
897   for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
898     {
899       if (! (fp->_flags & _IO_UNBUFFERED)
900           && (! (fp->_flags & _IO_NO_WRITES)
901               || (fp->_flags & _IO_IS_APPENDING))
902           /* Iff stream is un-orientated, it wasn't used. */
903           && fp->_mode != 0)
904         _IO_SETBUF (fp, NULL, 0);
905
906       /* Make sure that never again the wide char functions can be
907          used.  */
908       fp->_mode = -1;
909     }
910 }
911
912 int
913 _IO_cleanup ()
914 {
915   int result = _IO_flush_all ();
916
917   /* We currently don't have a reliable mechanism for making sure that
918      C++ static destructors are executed in the correct order.
919      So it is possible that other static destructors might want to
920      write to cout - and they're supposed to be able to do so.
921
922      The following will make the standard streambufs be unbuffered,
923      which forces any output from late destructors to be written out. */
924   _IO_unbuffer_write ();
925
926   return result;
927 }
928
929
930 void
931 _IO_init_marker (marker, fp)
932      struct _IO_marker *marker;
933      _IO_FILE *fp;
934 {
935   marker->_sbuf = fp;
936   if (_IO_in_put_mode (fp))
937     _IO_switch_to_get_mode (fp);
938   if (_IO_in_backup (fp))
939     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
940   else
941     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
942
943   /* Should perhaps sort the chain? */
944   marker->_next = fp->_markers;
945   fp->_markers = marker;
946 }
947
948 void
949 _IO_remove_marker (marker)
950      struct _IO_marker *marker;
951 {
952   /* Unlink from sb's chain. */
953   struct _IO_marker **ptr = &marker->_sbuf->_markers;
954   for (; ; ptr = &(*ptr)->_next)
955     {
956       if (*ptr == NULL)
957         break;
958       else if (*ptr == marker)
959         {
960           *ptr = marker->_next;
961           return;
962         }
963     }
964 #if 0
965     if _sbuf has a backup area that is no longer needed, should we delete
966     it now, or wait until the next underflow?
967 #endif
968 }
969
970 #define BAD_DELTA EOF
971
972 int
973 _IO_marker_difference (mark1, mark2)
974      struct _IO_marker *mark1;
975      struct _IO_marker *mark2;
976 {
977   return mark1->_pos - mark2->_pos;
978 }
979
980 /* Return difference between MARK and current position of MARK's stream. */
981 int
982 _IO_marker_delta (mark)
983      struct _IO_marker *mark;
984 {
985   int cur_pos;
986   if (mark->_sbuf == NULL)
987     return BAD_DELTA;
988   if (_IO_in_backup (mark->_sbuf))
989     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
990   else
991     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
992   return mark->_pos - cur_pos;
993 }
994
995 int
996 _IO_seekmark (fp, mark, delta)
997      _IO_FILE *fp;
998      struct _IO_marker *mark;
999      int delta;
1000 {
1001   if (mark->_sbuf != fp)
1002     return EOF;
1003  if (mark->_pos >= 0)
1004     {
1005       if (_IO_in_backup (fp))
1006         _IO_switch_to_main_get_area (fp);
1007       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
1008     }
1009   else
1010     {
1011       if (!_IO_in_backup (fp))
1012         _IO_switch_to_backup_area (fp);
1013       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
1014     }
1015   return 0;
1016 }
1017
1018 void
1019 _IO_unsave_markers (fp)
1020      _IO_FILE *fp;
1021 {
1022   struct _IO_marker *mark = fp->_markers;
1023   if (mark)
1024     {
1025 #ifdef TODO
1026       streampos offset = seekoff (0, ios::cur, ios::in);
1027       if (offset != EOF)
1028         {
1029           offset += eGptr () - Gbase ();
1030           for ( ; mark != NULL; mark = mark->_next)
1031             mark->set_streampos (mark->_pos + offset);
1032         }
1033     else
1034       {
1035         for ( ; mark != NULL; mark = mark->_next)
1036           mark->set_streampos (EOF);
1037       }
1038 #endif
1039       fp->_markers = 0;
1040     }
1041
1042   if (_IO_have_backup (fp))
1043     _IO_free_backup_area (fp);
1044 }
1045
1046 #if 0
1047 /* Seems not to be needed. --drepper */
1048 int
1049 _IO_nobackup_pbackfail (fp, c)
1050      _IO_FILE *fp;
1051      int c;
1052 {
1053   if (fp->_IO_read_ptr > fp->_IO_read_base)
1054         fp->_IO_read_ptr--;
1055   if (c != EOF && *fp->_IO_read_ptr != c)
1056       *fp->_IO_read_ptr = c;
1057   return (unsigned char) c;
1058 }
1059 #endif
1060
1061 int
1062 _IO_default_pbackfail (fp, c)
1063      _IO_FILE *fp;
1064      int c;
1065 {
1066   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
1067       && (unsigned char) fp->_IO_read_ptr[-1] == c)
1068     --fp->_IO_read_ptr;
1069   else
1070     {
1071       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
1072       if (!_IO_in_backup (fp))
1073         {
1074           /* We need to keep the invariant that the main get area
1075              logically follows the backup area.  */
1076           if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
1077             {
1078               if (save_for_backup (fp, fp->_IO_read_ptr))
1079                 return EOF;
1080             }
1081           else if (!_IO_have_backup (fp))
1082             {
1083               /* No backup buffer: allocate one. */
1084               /* Use nshort buffer, if unused? (probably not)  FIXME */
1085               int backup_size = 128;
1086               char *bbuf = (char *) malloc (backup_size);
1087               if (bbuf == NULL)
1088                 return EOF;
1089               fp->_IO_save_base = bbuf;
1090               fp->_IO_save_end = fp->_IO_save_base + backup_size;
1091               fp->_IO_backup_base = fp->_IO_save_end;
1092             }
1093           fp->_IO_read_base = fp->_IO_read_ptr;
1094           _IO_switch_to_backup_area (fp);
1095         }
1096       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
1097         {
1098           /* Increase size of existing backup buffer. */
1099           _IO_size_t new_size;
1100           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
1101           char *new_buf;
1102           new_size = 2 * old_size;
1103           new_buf = (char *) malloc (new_size);
1104           if (new_buf == NULL)
1105             return EOF;
1106           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1107                   old_size);
1108           free (fp->_IO_read_base);
1109           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1110                     new_buf + new_size);
1111           fp->_IO_backup_base = fp->_IO_read_ptr;
1112         }
1113
1114       *--fp->_IO_read_ptr = c;
1115     }
1116   return (unsigned char) c;
1117 }
1118
1119 _IO_off64_t
1120 _IO_default_seek (fp, offset, dir)
1121      _IO_FILE *fp;
1122      _IO_off64_t offset;
1123      int dir;
1124 {
1125   return _IO_pos_BAD;
1126 }
1127
1128 int
1129 _IO_default_stat (fp, st)
1130      _IO_FILE *fp;
1131      void* st;
1132 {
1133   return EOF;
1134 }
1135
1136 _IO_ssize_t
1137 _IO_default_read (fp, data, n)
1138      _IO_FILE* fp;
1139      void *data;
1140      _IO_ssize_t n;
1141 {
1142   return -1;
1143 }
1144
1145 _IO_ssize_t
1146 _IO_default_write (fp, data, n)
1147      _IO_FILE *fp;
1148      const void *data;
1149      _IO_ssize_t n;
1150 {
1151   return 0;
1152 }
1153
1154 int
1155 _IO_default_showmanyc (fp)
1156      _IO_FILE *fp;
1157 {
1158   return -1;
1159 }
1160
1161 void
1162 _IO_default_imbue (fp, locale)
1163      _IO_FILE *fp;
1164      void *locale;
1165 {
1166 }
1167
1168 _IO_ITER
1169 _IO_iter_begin()
1170 {
1171   return (_IO_ITER) _IO_list_all;
1172 }
1173
1174 _IO_ITER
1175 _IO_iter_end()
1176 {
1177   return NULL;
1178 }
1179
1180 _IO_ITER
1181 _IO_iter_next(iter)
1182     _IO_ITER iter;
1183 {
1184   return iter->_chain;
1185 }
1186
1187 _IO_FILE *
1188 _IO_iter_file(iter)
1189     _IO_ITER iter;
1190 {
1191   return iter;
1192 }
1193
1194 void
1195 _IO_list_lock()
1196 {
1197 #ifdef _IO_MTSAFE_IO
1198   _IO_lock_lock (list_all_lock);
1199 #endif
1200 }
1201
1202 void
1203 _IO_list_unlock()
1204 {
1205 #ifdef _IO_MTSAFE_IO
1206   _IO_lock_unlock (list_all_lock);
1207 #endif
1208 }
1209
1210 void
1211 _IO_list_resetlock()
1212 {
1213 #ifdef _IO_MTSAFE_IO
1214   _IO_lock_init (list_all_lock);
1215 #endif
1216 }
1217
1218
1219 #ifdef TODO
1220 #if defined(linux)
1221 #define IO_CLEANUP ;
1222 #endif
1223
1224 #ifdef IO_CLEANUP
1225   IO_CLEANUP
1226 #else
1227 struct __io_defs {
1228     __io_defs() { }
1229     ~__io_defs() { _IO_cleanup (); }
1230 };
1231 __io_defs io_defs__;
1232 #endif
1233
1234 #endif /* TODO */
1235
1236 #ifdef weak_alias
1237 weak_alias (_IO_cleanup, _cleanup)
1238 #endif
1239
1240 #ifdef text_set_element
1241 text_set_element(__libc_atexit, _cleanup);
1242 #endif