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