xref: /haiku/src/system/libroot/posix/glibc/libio/genops.c (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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
36 static _IO_lock_t list_all_lock = _IO_lock_initializer;
37 #endif
38 
39 /* Used to signal modifications to the list of FILE decriptors.  */
40 static int _IO_list_all_stamp;
41 
42 
43 static _IO_FILE *run_fp;
44 
45 #if 0
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 #endif
56 
57 
58 void
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 }
89 INTDEF(_IO_un_link)
90 
91 void
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 }
115 INTDEF(_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 
136 void
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 
156 void
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 
174 int
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 }
196 INTDEF(_IO_switch_to_get_mode)
197 
198 void
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 }
209 INTDEF(_IO_free_backup_area)
210 
211 #if 0
212 int
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 
231 int
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 }
240 libc_hidden_def(__overflow)
241 
242 
243 static int save_for_backup __P ((_IO_FILE *fp, char *end_p))
244 #ifdef _LIBC
245      internal_function
246 #endif
247      ;
248 
249 static int
250 #ifdef _LIBC
251 internal_function
252 #endif
253 save_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 
325 int
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 }
356 libc_hidden_def(__underflow)
357 
358 
359 int
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 }
391 libc_hidden_def(__uflow)
392 
393 
394 void
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 }
410 INTDEF(_IO_setb)
411 
412 void
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 }
423 INTDEF(_IO_doallocbuf)
424 
425 int
426 _IO_default_underflow (fp)
427      _IO_FILE *fp;
428 {
429   return EOF;
430 }
431 
432 int
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 }
441 INTDEF(_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 }
489 INTDEF(_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 }
500 INTDEF(_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 }
545 INTDEF(_IO_default_xsgetn)
546 
547 #if 0
548 /* Seems not to be needed. --drepper */
549 int
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 
589 int
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 }
599 INTDEF(_IO_default_doallocate)
600 
601 void
602 _IO_init (fp, flags)
603      _IO_FILE *fp;
604      int flags;
605 {
606   _IO_no_init (fp, flags, -1, NULL, NULL);
607 }
608 INTDEF(_IO_init)
609 
610 void
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 
664 int
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 
674 void
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 }
703 INTDEF(_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 
715 int
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 }
736 INTDEF(_IO_sputbackc)
737 
738 int
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
761 void
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
772 int
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 
784 unsigned
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 }
796 INTDEF(_IO_adjust_column)
797 
798 #if 0
799 /* Seems not to be needed. --drepper */
800 int
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 
813 int
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 
868 int
869 _IO_flush_all ()
870 {
871   /* We want locking.  */
872   return _IO_flush_all_lockp (1);
873 }
874 INTDEF(_IO_flush_all)
875 
876 void
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 }
915 INTDEF(_IO_flush_all_linebuffered)
916 #ifdef _LIBC
917 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
918 #endif
919 
920 static void _IO_unbuffer_write __P ((void));
921 
922 static 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 
941 int
942 _IO_cleanup ()
943 {
944   int result = INTUSE(_IO_flush_all) ();
945 
946   /* We currently don't have a reliable mechanism for making sure that
947      C++ static destructors are executed in the correct order.
948      So it is possible that other static destructors might want to
949      write to cout - and they're supposed to be able to do so.
950 
951      The following will make the standard streambufs be unbuffered,
952      which forces any output from late destructors to be written out. */
953   _IO_unbuffer_write ();
954 
955   return result;
956 }
957 
958 
959 void
960 _IO_init_marker (marker, fp)
961      struct _IO_marker *marker;
962      _IO_FILE *fp;
963 {
964   marker->_sbuf = fp;
965   if (_IO_in_put_mode (fp))
966     INTUSE(_IO_switch_to_get_mode) (fp);
967   if (_IO_in_backup (fp))
968     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
969   else
970     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
971 
972   /* Should perhaps sort the chain? */
973   marker->_next = fp->_markers;
974   fp->_markers = marker;
975 }
976 
977 void
978 _IO_remove_marker (marker)
979      struct _IO_marker *marker;
980 {
981   /* Unlink from sb's chain. */
982   struct _IO_marker **ptr = &marker->_sbuf->_markers;
983   for (; ; ptr = &(*ptr)->_next)
984     {
985       if (*ptr == NULL)
986 	break;
987       else if (*ptr == marker)
988 	{
989 	  *ptr = marker->_next;
990 	  return;
991 	}
992     }
993 #if 0
994     if _sbuf has a backup area that is no longer needed, should we delete
995     it now, or wait until the next underflow?
996 #endif
997 }
998 
999 #define BAD_DELTA EOF
1000 
1001 int
1002 _IO_marker_difference (mark1, mark2)
1003      struct _IO_marker *mark1;
1004      struct _IO_marker *mark2;
1005 {
1006   return mark1->_pos - mark2->_pos;
1007 }
1008 
1009 /* Return difference between MARK and current position of MARK's stream. */
1010 int
1011 _IO_marker_delta (mark)
1012      struct _IO_marker *mark;
1013 {
1014   int cur_pos;
1015   if (mark->_sbuf == NULL)
1016     return BAD_DELTA;
1017   if (_IO_in_backup (mark->_sbuf))
1018     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
1019   else
1020     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
1021   return mark->_pos - cur_pos;
1022 }
1023 
1024 int
1025 _IO_seekmark (fp, mark, delta)
1026      _IO_FILE *fp;
1027      struct _IO_marker *mark;
1028      int delta;
1029 {
1030   if (mark->_sbuf != fp)
1031     return EOF;
1032  if (mark->_pos >= 0)
1033     {
1034       if (_IO_in_backup (fp))
1035 	_IO_switch_to_main_get_area (fp);
1036       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
1037     }
1038   else
1039     {
1040       if (!_IO_in_backup (fp))
1041 	_IO_switch_to_backup_area (fp);
1042       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
1043     }
1044   return 0;
1045 }
1046 
1047 void
1048 _IO_unsave_markers (fp)
1049      _IO_FILE *fp;
1050 {
1051   struct _IO_marker *mark = fp->_markers;
1052   if (mark)
1053     {
1054 #ifdef TODO
1055       streampos offset = seekoff (0, ios::cur, ios::in);
1056       if (offset != EOF)
1057 	{
1058 	  offset += eGptr () - Gbase ();
1059 	  for ( ; mark != NULL; mark = mark->_next)
1060 	    mark->set_streampos (mark->_pos + offset);
1061 	}
1062     else
1063       {
1064 	for ( ; mark != NULL; mark = mark->_next)
1065 	  mark->set_streampos (EOF);
1066       }
1067 #endif
1068       fp->_markers = 0;
1069     }
1070 
1071   if (_IO_have_backup (fp))
1072     INTUSE(_IO_free_backup_area) (fp);
1073 }
1074 INTDEF(_IO_unsave_markers)
1075 
1076 #if 0
1077 /* Seems not to be needed. --drepper */
1078 int
1079 _IO_nobackup_pbackfail (fp, c)
1080      _IO_FILE *fp;
1081      int c;
1082 {
1083   if (fp->_IO_read_ptr > fp->_IO_read_base)
1084 	fp->_IO_read_ptr--;
1085   if (c != EOF && *fp->_IO_read_ptr != c)
1086       *fp->_IO_read_ptr = c;
1087   return (unsigned char) c;
1088 }
1089 #endif
1090 
1091 int
1092 _IO_default_pbackfail (fp, c)
1093      _IO_FILE *fp;
1094      int c;
1095 {
1096   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
1097       && (unsigned char) fp->_IO_read_ptr[-1] == c)
1098     --fp->_IO_read_ptr;
1099   else
1100     {
1101       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
1102       if (!_IO_in_backup (fp))
1103 	{
1104 	  /* We need to keep the invariant that the main get area
1105 	     logically follows the backup area.  */
1106 	  if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
1107 	    {
1108 	      if (save_for_backup (fp, fp->_IO_read_ptr))
1109 		return EOF;
1110 	    }
1111 	  else if (!_IO_have_backup (fp))
1112 	    {
1113 	      /* No backup buffer: allocate one. */
1114 	      /* Use nshort buffer, if unused? (probably not)  FIXME */
1115 	      int backup_size = 128;
1116 	      char *bbuf = (char *) malloc (backup_size);
1117 	      if (bbuf == NULL)
1118 		return EOF;
1119 	      fp->_IO_save_base = bbuf;
1120 	      fp->_IO_save_end = fp->_IO_save_base + backup_size;
1121 	      fp->_IO_backup_base = fp->_IO_save_end;
1122 	    }
1123 	  fp->_IO_read_base = fp->_IO_read_ptr;
1124 	  _IO_switch_to_backup_area (fp);
1125 	}
1126       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
1127 	{
1128 	  /* Increase size of existing backup buffer. */
1129 	  _IO_size_t new_size;
1130 	  _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
1131 	  char *new_buf;
1132 	  new_size = 2 * old_size;
1133 	  new_buf = (char *) malloc (new_size);
1134 	  if (new_buf == NULL)
1135 	    return EOF;
1136 	  memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1137 		  old_size);
1138 	  free (fp->_IO_read_base);
1139 	  _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1140 		    new_buf + new_size);
1141 	  fp->_IO_backup_base = fp->_IO_read_ptr;
1142 	}
1143 
1144       *--fp->_IO_read_ptr = c;
1145     }
1146   return (unsigned char) c;
1147 }
1148 INTDEF(_IO_default_pbackfail)
1149 
1150 _IO_off64_t
1151 _IO_default_seek (fp, offset, dir)
1152      _IO_FILE *fp;
1153      _IO_off64_t offset;
1154      int dir;
1155 {
1156   return _IO_pos_BAD;
1157 }
1158 
1159 int
1160 _IO_default_stat (fp, st)
1161      _IO_FILE *fp;
1162      void* st;
1163 {
1164   return EOF;
1165 }
1166 
1167 _IO_ssize_t
1168 _IO_default_read (fp, data, n)
1169      _IO_FILE* fp;
1170      void *data;
1171      _IO_ssize_t n;
1172 {
1173   return -1;
1174 }
1175 
1176 _IO_ssize_t
1177 _IO_default_write (fp, data, n)
1178      _IO_FILE *fp;
1179      const void *data;
1180      _IO_ssize_t n;
1181 {
1182   return 0;
1183 }
1184 
1185 int
1186 _IO_default_showmanyc (fp)
1187      _IO_FILE *fp;
1188 {
1189   return -1;
1190 }
1191 
1192 void
1193 _IO_default_imbue (fp, locale)
1194      _IO_FILE *fp;
1195      void *locale;
1196 {
1197 }
1198 
1199 _IO_ITER
1200 _IO_iter_begin()
1201 {
1202   return (_IO_ITER) INTUSE(_IO_list_all);
1203 }
1204 libc_hidden_def (_IO_iter_begin)
1205 
1206 _IO_ITER
1207 _IO_iter_end()
1208 {
1209   return NULL;
1210 }
1211 libc_hidden_def (_IO_iter_end)
1212 
1213 _IO_ITER
1214 _IO_iter_next(iter)
1215     _IO_ITER iter;
1216 {
1217   return iter->_chain;
1218 }
1219 libc_hidden_def (_IO_iter_next)
1220 
1221 _IO_FILE *
1222 _IO_iter_file(iter)
1223     _IO_ITER iter;
1224 {
1225   return iter;
1226 }
1227 libc_hidden_def (_IO_iter_file)
1228 
1229 void
1230 _IO_list_lock()
1231 {
1232 #ifdef _IO_MTSAFE_IO
1233   _IO_lock_lock (list_all_lock);
1234 #endif
1235 }
1236 libc_hidden_def (_IO_list_lock)
1237 
1238 void
1239 _IO_list_unlock()
1240 {
1241 #ifdef _IO_MTSAFE_IO
1242   _IO_lock_unlock (list_all_lock);
1243 #endif
1244 }
1245 libc_hidden_def (_IO_list_unlock)
1246 
1247 void
1248 _IO_list_resetlock()
1249 {
1250 #ifdef _IO_MTSAFE_IO
1251   _IO_lock_init (list_all_lock);
1252 #endif
1253 }
1254 libc_hidden_def (_IO_list_resetlock)
1255 
1256 
1257 #ifdef TODO
1258 #if defined(linux)
1259 #define IO_CLEANUP ;
1260 #endif
1261 
1262 #ifdef IO_CLEANUP
1263   IO_CLEANUP
1264 #else
1265 struct __io_defs {
1266     __io_defs() { }
1267     ~__io_defs() { _IO_cleanup (); }
1268 };
1269 __io_defs io_defs__;
1270 #endif
1271 
1272 #endif /* TODO */
1273 
1274 #ifdef text_set_element
1275 text_set_element(__libc_atexit, _IO_cleanup);
1276 #endif
1277