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