]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/genops.c
Update.
[thirdparty/glibc.git] / libio / genops.c
CommitLineData
40a55d20
UD
1/* Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU IO Library.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at
7 your option) any later version.
8
9 This library is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this library; see the file COPYING. If not, write to
16 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
17 MA 02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does
21 not cause the resulting executable to be covered by the GNU General
22 Public License. This exception does not however invalidate any
23 other reasons why the executable file might be covered by the GNU
24 General Public License. */
96aa2d94
RM
25
26/* Generic or default I/O operations. */
27
28#include "libioP.h"
29#ifdef __STDC__
30#include <stdlib.h>
31#endif
32#include <string.h>
33
34void
40a55d20
UD
35_IO_un_link (fp)
36 _IO_FILE *fp;
37{
38 if (fp->_flags & _IO_LINKED)
39 {
40 _IO_FILE **f;
41 for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain)
42 {
43 if (*f == fp)
44 {
45 *f = fp->_chain;
46 break;
47 }
48 }
49 fp->_flags &= ~_IO_LINKED;
96aa2d94 50 }
96aa2d94
RM
51}
52
53void
40a55d20
UD
54_IO_link_in (fp)
55 _IO_FILE *fp;
96aa2d94 56{
40a55d20
UD
57 if ((fp->_flags & _IO_LINKED) == 0)
58 {
96aa2d94
RM
59 fp->_flags |= _IO_LINKED;
60 fp->_chain = _IO_list_all;
61 _IO_list_all = fp;
40a55d20 62 }
96aa2d94
RM
63}
64
65/* Return minimum _pos markers
66 Assumes the current get area is the main get area. */
40a55d20 67static _IO_size_t _IO_least_marker __P ((_IO_FILE *fp));
96aa2d94 68
40a55d20
UD
69static _IO_size_t
70_IO_least_marker (fp)
71 _IO_FILE *fp;
96aa2d94
RM
72{
73 _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base;
40a55d20 74 struct _IO_marker *mark;
96aa2d94
RM
75 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
76 if (mark->_pos < least_so_far)
77 least_so_far = mark->_pos;
78 return least_so_far;
79}
80
81/* Switch current get area from backup buffer to (start of) main get area. */
82
83void
40a55d20
UD
84_IO_switch_to_main_get_area (fp)
85 _IO_FILE *fp;
96aa2d94
RM
86{
87 char *tmp;
88 fp->_flags &= ~_IO_IN_BACKUP;
89 /* Swap _IO_read_end and _IO_save_end. */
40a55d20
UD
90 tmp = fp->_IO_read_end;
91 fp->_IO_read_end = fp->_IO_save_end;
92 fp->_IO_save_end= tmp;
96aa2d94 93 /* Swap _IO_read_base and _IO_save_base. */
40a55d20
UD
94 tmp = fp->_IO_read_base;
95 fp->_IO_read_base = fp->_IO_save_base;
96 fp->_IO_save_base = tmp;
97
96aa2d94
RM
98 fp->_IO_read_ptr = fp->_IO_read_base;
99}
100
101/* Switch current get area from main get area to (end of) backup area. */
102
103void
40a55d20
UD
104_IO_switch_to_backup_area (fp)
105 _IO_FILE *fp;
96aa2d94
RM
106{
107 char *tmp;
108 fp->_flags |= _IO_IN_BACKUP;
109 /* Swap _IO_read_end and _IO_save_end. */
40a55d20
UD
110 tmp = fp->_IO_read_end;
111 fp->_IO_read_end = fp->_IO_save_end;
112 fp->_IO_save_end = tmp;
96aa2d94 113 /* Swap _gbase and _IO_save_base. */
40a55d20
UD
114 tmp = fp->_IO_read_base;
115 fp->_IO_read_base = fp->_IO_save_base;
116 fp->_IO_save_base = tmp;
117
96aa2d94
RM
118 fp->_IO_read_ptr = fp->_IO_read_end;
119}
120
121int
40a55d20
UD
122_IO_switch_to_get_mode (fp)
123 _IO_FILE *fp;
96aa2d94
RM
124{
125 if (fp->_IO_write_ptr > fp->_IO_write_base)
126 if (_IO_OVERFLOW (fp, EOF) == EOF)
127 return EOF;
40a55d20 128 if (_IO_in_backup (fp))
96aa2d94
RM
129 fp->_IO_read_base = fp->_IO_backup_base;
130 else
131 {
132 fp->_IO_read_base = fp->_IO_buf_base;
133 if (fp->_IO_write_ptr > fp->_IO_read_end)
134 fp->_IO_read_end = fp->_IO_write_ptr;
135 }
136 fp->_IO_read_ptr = fp->_IO_write_ptr;
137
138 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
139
140 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
141 return 0;
142}
143
144void
40a55d20
UD
145_IO_free_backup_area (fp)
146 _IO_FILE *fp;
96aa2d94
RM
147{
148 if (_IO_in_backup (fp))
40a55d20 149 _IO_switch_to_main_get_area (fp); /* Just in case. */
96aa2d94
RM
150 free (fp->_IO_save_base);
151 fp->_IO_save_base = NULL;
152 fp->_IO_save_end = NULL;
153 fp->_IO_backup_base = NULL;
154}
155
156#if 0
157int
40a55d20
UD
158_IO_switch_to_put_mode (fp)
159 _IO_FILE *fp;
96aa2d94
RM
160{
161 fp->_IO_write_base = fp->_IO_read_ptr;
162 fp->_IO_write_ptr = fp->_IO_read_ptr;
163 /* Following is wrong if line- or un-buffered? */
40a55d20
UD
164 fp->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
165 ? fp->_IO_read_end : fp->_IO_buf_end);
96aa2d94
RM
166
167 fp->_IO_read_ptr = fp->_IO_read_end;
168 fp->_IO_read_base = fp->_IO_read_end;
169
170 fp->_flags |= _IO_CURRENTLY_PUTTING;
171 return 0;
172}
173#endif
174
175int
40a55d20
UD
176__overflow (f, ch)
177 _IO_FILE *f;
178 int ch;
96aa2d94
RM
179{
180 return _IO_OVERFLOW (f, ch);
181}
182
40a55d20
UD
183static int save_for_backup __P ((_IO_FILE *fp));
184
185 static int
186save_for_backup (fp)
187 _IO_FILE *fp;
96aa2d94
RM
188{
189 /* Append [_IO_read_base.._IO_read_end] to backup area. */
40a55d20 190 int least_mark = _IO_least_marker (fp);
96aa2d94
RM
191 /* needed_size is how much space we need in the backup area. */
192 int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark;
193 int current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
194 int avail; /* Extra space available for future expansion. */
195 int delta;
196 struct _IO_marker *mark;
197 if (needed_size > current_Bsize)
198 {
199 char *new_buffer;
200 avail = 100;
40a55d20 201 new_buffer = (char *) malloc (avail + needed_size);
96aa2d94
RM
202 if (new_buffer == NULL)
203 return EOF; /* FIXME */
204 if (least_mark < 0)
205 {
40a55d20
UD
206 memcpy (new_buffer + avail,
207 fp->_IO_save_end + least_mark,
208 -least_mark);
209 memcpy (new_buffer + avail - least_mark,
210 fp->_IO_read_base,
211 fp->_IO_read_end - fp->_IO_read_base);
96aa2d94
RM
212 }
213 else
40a55d20
UD
214 memcpy (new_buffer + avail,
215 fp->_IO_read_base + least_mark,
216 needed_size);
96aa2d94
RM
217 if (fp->_IO_save_base)
218 free (fp->_IO_save_base);
219 fp->_IO_save_base = new_buffer;
220 fp->_IO_save_end = new_buffer + avail + needed_size;
221 }
222 else
223 {
224 avail = current_Bsize - needed_size;
225 if (least_mark < 0)
226 {
40a55d20
UD
227 memmove (fp->_IO_save_base + avail,
228 fp->_IO_save_end + least_mark,
229 -least_mark);
230 memcpy (fp->_IO_save_base + avail - least_mark,
231 fp->_IO_read_base,
232 fp->_IO_read_end - fp->_IO_read_base);
96aa2d94
RM
233 }
234 else if (needed_size > 0)
40a55d20
UD
235 memcpy (fp->_IO_save_base + avail,
236 fp->_IO_read_base + least_mark,
237 needed_size);
96aa2d94
RM
238 }
239 /* FIXME: Dubious arithmetic if pointers are NULL */
240 fp->_IO_backup_base = fp->_IO_save_base + avail;
241 /* Adjust all the streammarkers. */
242 delta = fp->_IO_read_end - fp->_IO_read_base;
243 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
244 mark->_pos -= delta;
245 return 0;
246}
247
248int
40a55d20
UD
249__underflow (fp)
250 _IO_FILE *fp;
96aa2d94 251{
40a55d20
UD
252 if (_IO_in_put_mode (fp))
253 if (_IO_switch_to_get_mode (fp) == EOF)
254 return EOF;
96aa2d94 255 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20
UD
256 return *(unsigned char *) fp->_IO_read_ptr;
257 if (_IO_in_backup (fp))
96aa2d94 258 {
40a55d20 259 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
260 if (fp->_IO_read_ptr < fp->_IO_read_end)
261 return *fp->_IO_read_ptr;
262 }
40a55d20 263 if (_IO_have_markers (fp))
96aa2d94
RM
264 {
265 if (save_for_backup (fp))
266 return EOF;
267 }
40a55d20
UD
268 else if (_IO_have_backup (fp))
269 _IO_free_backup_area (fp);
96aa2d94
RM
270 return _IO_UNDERFLOW (fp);
271}
272
273int
40a55d20
UD
274__uflow (fp)
275 _IO_FILE *fp;
96aa2d94 276{
40a55d20
UD
277 if (_IO_in_put_mode (fp))
278 if (_IO_switch_to_get_mode (fp) == EOF)
279 return EOF;
96aa2d94 280 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20
UD
281 return *(unsigned char *) fp->_IO_read_ptr++;
282 if (_IO_in_backup (fp))
96aa2d94 283 {
40a55d20 284 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
285 if (fp->_IO_read_ptr < fp->_IO_read_end)
286 return *fp->_IO_read_ptr++;
287 }
40a55d20 288 if (_IO_have_markers (fp))
96aa2d94
RM
289 {
290 if (save_for_backup (fp))
291 return EOF;
292 }
40a55d20
UD
293 else if (_IO_have_backup (fp))
294 _IO_free_backup_area (fp);
96aa2d94
RM
295 return _IO_UFLOW (fp);
296}
297
298void
40a55d20
UD
299_IO_setb (f, b, eb, a)
300 _IO_FILE *f;
301 char *b;
302 char *eb;
303 int a;
96aa2d94
RM
304{
305 if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
40a55d20 306 FREE_BUF (f->_IO_buf_base, _IO_blen (f));
96aa2d94
RM
307 f->_IO_buf_base = b;
308 f->_IO_buf_end = eb;
309 if (a)
310 f->_flags &= ~_IO_USER_BUF;
311 else
312 f->_flags |= _IO_USER_BUF;
313}
314
315void
40a55d20
UD
316_IO_doallocbuf (fp)
317 _IO_FILE *fp;
96aa2d94
RM
318{
319 if (fp->_IO_buf_base)
320 return;
321 if (!(fp->_flags & _IO_UNBUFFERED))
322 if (_IO_DOALLOCATE (fp) != EOF)
323 return;
40a55d20 324 _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
96aa2d94
RM
325}
326
327int
40a55d20
UD
328_IO_default_underflow (fp)
329 _IO_FILE *fp;
96aa2d94
RM
330{
331 return EOF;
332}
333
334int
40a55d20
UD
335_IO_default_uflow (fp)
336 _IO_FILE *fp;
96aa2d94
RM
337{
338 int ch = _IO_UNDERFLOW (fp);
339 if (ch == EOF)
340 return EOF;
40a55d20 341 return *(unsigned char *) fp->_IO_read_ptr++;
96aa2d94
RM
342}
343
344_IO_size_t
40a55d20
UD
345_IO_default_xsputn (f, data, n)
346 _IO_FILE *f;
347 const void *data;
348 _IO_size_t n;
96aa2d94 349{
40a55d20
UD
350 const char *s = (char *) data;
351 _IO_size_t more = n;
96aa2d94
RM
352 if (more <= 0)
353 return 0;
354 for (;;)
355 {
40a55d20
UD
356 /* Space available. */
357 _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr;
96aa2d94
RM
358 if (count > 0)
359 {
a68b0d31 360 if ((_IO_size_t) count > more)
96aa2d94
RM
361 count = more;
362 if (count > 20)
363 {
40a55d20 364 memcpy (f->_IO_write_ptr, s, count);
96aa2d94
RM
365 s += count;
366 f->_IO_write_ptr += count;
367 }
368 else if (count <= 0)
369 count = 0;
370 else
371 {
40a55d20
UD
372 char *p = f->_IO_write_ptr;
373 _IO_ssize_t i;
374 for (i = count; --i >= 0; )
375 *p++ = *s++;
96aa2d94
RM
376 f->_IO_write_ptr = p;
377 }
378 more -= count;
379 }
40a55d20 380 if (more == 0 || __overflow (f, (unsigned char) *s++) == EOF)
96aa2d94
RM
381 break;
382 more--;
383 }
384 return n - more;
385}
386
387_IO_size_t
40a55d20
UD
388_IO_sgetn (fp, data, n)
389 _IO_FILE *fp;
390 void *data;
391 _IO_size_t n;
96aa2d94
RM
392{
393 /* FIXME handle putback buffer here! */
394 return _IO_XSGETN (fp, data, n);
395}
396
397_IO_size_t
40a55d20
UD
398_IO_default_xsgetn (fp, data, n)
399 _IO_FILE *fp;
400 void *data;
401 _IO_size_t n;
96aa2d94 402{
40a55d20
UD
403 _IO_size_t more = n;
404 char *s = (char*) data;
96aa2d94
RM
405 for (;;)
406 {
40a55d20
UD
407 /* Data available. */
408 _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr;
96aa2d94
RM
409 if (count > 0)
410 {
a68b0d31 411 if ((_IO_size_t) count > more)
96aa2d94
RM
412 count = more;
413 if (count > 20)
414 {
40a55d20 415 memcpy (s, fp->_IO_read_ptr, count);
96aa2d94
RM
416 s += count;
417 fp->_IO_read_ptr += count;
418 }
419 else if (count <= 0)
420 count = 0;
421 else
422 {
40a55d20
UD
423 char *p = fp->_IO_read_ptr;
424 int i = (int) count;
425 while (--i >= 0)
426 *s++ = *p++;
96aa2d94
RM
427 fp->_IO_read_ptr = p;
428 }
429 more -= count;
430 }
40a55d20 431 if (more == 0 || __underflow (fp) == EOF)
96aa2d94
RM
432 break;
433 }
434 return n - more;
435}
436
40a55d20
UD
437#if 0
438/* Seems not to be needed. --drepper */
96aa2d94 439int
40a55d20
UD
440_IO_sync (fp)
441 _IO_FILE *fp;
96aa2d94
RM
442{
443 return 0;
444}
40a55d20 445#endif
96aa2d94 446
40a55d20
UD
447_IO_FILE *
448_IO_default_setbuf (fp, p, len)
449 _IO_FILE *fp;
450 char *p;
451 _IO_ssize_t len;
96aa2d94
RM
452{
453 if (_IO_SYNC (fp) == EOF)
454 return NULL;
455 if (p == NULL || len == 0)
456 {
457 fp->_flags |= _IO_UNBUFFERED;
40a55d20 458 _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
96aa2d94
RM
459 }
460 else
461 {
462 fp->_flags &= ~_IO_UNBUFFERED;
40a55d20 463 _IO_setb (fp, p, p+len, 0);
96aa2d94
RM
464 }
465 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
466 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
467 return fp;
468}
469
470_IO_pos_t
40a55d20
UD
471_IO_default_seekpos (fp, pos, mode)
472 _IO_FILE *fp;
473 _IO_pos_t pos;
474 int mode;
96aa2d94 475{
40a55d20 476 return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode);
96aa2d94
RM
477}
478
479int
40a55d20
UD
480_IO_default_doallocate (fp)
481 _IO_FILE *fp;
96aa2d94 482{
f8b87ef0
UD
483 char *buf;
484
40a55d20
UD
485 ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
486 _IO_setb (fp, buf, buf+_IO_BUFSIZ, 1);
96aa2d94
RM
487 return 1;
488}
489
490void
40a55d20
UD
491_IO_init (fp, flags)
492 _IO_FILE *fp;
493 int flags;
96aa2d94
RM
494{
495 fp->_flags = _IO_MAGIC|flags;
496 fp->_IO_buf_base = NULL;
497 fp->_IO_buf_end = NULL;
498 fp->_IO_read_base = NULL;
499 fp->_IO_read_ptr = NULL;
500 fp->_IO_read_end = NULL;
501 fp->_IO_write_base = NULL;
502 fp->_IO_write_ptr = NULL;
503 fp->_IO_write_end = NULL;
504 fp->_chain = NULL; /* Not necessary. */
505
506 fp->_IO_save_base = NULL;
507 fp->_IO_backup_base = NULL;
508 fp->_IO_save_end = NULL;
509 fp->_markers = NULL;
510 fp->_cur_column = 0;
7c713e28 511#ifdef _IO_MTSAFE_IO
df4ef2ab 512 _IO_lock_init (*fp->_lock);
7c713e28 513#endif
96aa2d94
RM
514}
515
516int
40a55d20
UD
517_IO_default_sync (fp)
518 _IO_FILE *fp;
96aa2d94
RM
519{
520 return 0;
521}
522
523/* The way the C++ classes are mapped into the C functions in the
524 current implementation, this function can get called twice! */
525
526void
40a55d20
UD
527_IO_default_finish (fp, dummy)
528 _IO_FILE *fp;
529 int dummy;
96aa2d94
RM
530{
531 struct _IO_marker *mark;
532 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
533 {
40a55d20 534 FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
96aa2d94
RM
535 fp->_IO_buf_base = fp->_IO_buf_end = NULL;
536 }
537
538 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
539 mark->_sbuf = NULL;
540
541 if (fp->_IO_save_base)
542 {
543 free (fp->_IO_save_base);
544 fp->_IO_save_base = NULL;
545 }
546
7c713e28 547#ifdef _IO_MTSAFE_IO
68dbb3a6 548 _IO_lock_fini (*fp->_lock);
7c713e28 549#endif
adfa2078 550
40a55d20 551 _IO_un_link (fp);
96aa2d94
RM
552}
553
554_IO_pos_t
40a55d20
UD
555_IO_default_seekoff (fp, offset, dir, mode)
556 _IO_FILE *fp;
557 _IO_off_t offset;
558 int dir;
559 int mode;
96aa2d94
RM
560{
561 return _IO_pos_BAD;
562}
563
564int
40a55d20
UD
565_IO_sputbackc (fp, c)
566 _IO_FILE *fp;
567 int c;
96aa2d94 568{
19bc17a9 569 int result;
adfa2078 570
96aa2d94
RM
571 if (fp->_IO_read_ptr > fp->_IO_read_base
572 && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
573 {
574 fp->_IO_read_ptr--;
40a55d20 575 result = (unsigned char) c;
96aa2d94 576 }
19bc17a9
RM
577 else
578 result = _IO_PBACKFAIL (fp, c);
579
580 if (result != EOF)
581 fp->_flags &= ~_IO_EOF_SEEN;
582
583 return result;
96aa2d94
RM
584}
585
586int
40a55d20
UD
587_IO_sungetc (fp)
588 _IO_FILE *fp;
96aa2d94 589{
19bc17a9 590 int result;
adfa2078 591
96aa2d94
RM
592 if (fp->_IO_read_ptr > fp->_IO_read_base)
593 {
594 fp->_IO_read_ptr--;
40a55d20 595 result = (unsigned char) *fp->_IO_read_ptr;
96aa2d94
RM
596 }
597 else
19bc17a9
RM
598 result = _IO_PBACKFAIL (fp, EOF);
599
600 if (result != EOF)
601 fp->_flags &= ~_IO_EOF_SEEN;
602
603 return result;
96aa2d94
RM
604}
605
606#if 0 /* Work in progress */
40a55d20
UD
607/* Seems not to be needed. */
608#if 0
96aa2d94 609void
40a55d20
UD
610_IO_set_column (fp, c)
611 _IO_FILE *fp;
612 int c;
96aa2d94
RM
613{
614 if (c == -1)
615 fp->_column = -1;
616 else
617 fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
618}
619#else
620int
40a55d20
UD
621_IO_set_column (fp, i)
622 _IO_FILE *fp;
623 int i;
96aa2d94 624{
40a55d20 625 fp->_cur_column = i + 1;
96aa2d94
RM
626 return 0;
627}
628#endif
40a55d20 629#endif
96aa2d94
RM
630
631
632unsigned
40a55d20
UD
633_IO_adjust_column (start, line, count)
634 unsigned start;
635 const char *line;
636 int count;
96aa2d94 637{
40a55d20 638 const char *ptr = line + count;
96aa2d94
RM
639 while (ptr > line)
640 if (*--ptr == '\n')
641 return line + count - ptr - 1;
642 return start + count;
643}
644
40a55d20
UD
645#if 0
646/* Seems not to be needed. --drepper */
96aa2d94 647int
40a55d20
UD
648_IO_get_column (fp)
649 _IO_FILE *fp;
96aa2d94 650{
adfa2078 651 if (fp->_cur_column)
40a55d20 652 return _IO_adjust_column (fp->_cur_column - 1,
96aa2d94
RM
653 fp->_IO_write_base,
654 fp->_IO_write_ptr - fp->_IO_write_base);
655 return -1;
656}
40a55d20 657#endif
96aa2d94
RM
658
659int
40a55d20 660_IO_flush_all ()
96aa2d94
RM
661{
662 int result = 0;
663 _IO_FILE *fp;
664 for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
665 if (fp->_IO_write_ptr > fp->_IO_write_base
666 && _IO_OVERFLOW (fp, EOF) == EOF)
667 result = EOF;
668 return result;
669}
670
671void
40a55d20 672_IO_flush_all_linebuffered ()
96aa2d94
RM
673{
674 _IO_FILE *fp;
675 for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
63551311 676 if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
96aa2d94
RM
677 _IO_OVERFLOW (fp, EOF);
678}
679
40a55d20
UD
680static void _IO_unbuffer_all __P ((void));
681
682static void
683_IO_unbuffer_all ()
96aa2d94
RM
684{
685 _IO_FILE *fp;
686 for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
687 if (! (fp->_flags & _IO_UNBUFFERED))
688 _IO_SETBUF (fp, NULL, 0);
689}
690
691void
40a55d20 692_IO_cleanup ()
96aa2d94
RM
693{
694 _IO_flush_all ();
695
696 /* We currently don't have a reliable mechanism for making sure that
697 C++ static destructors are executed in the correct order.
6d52618b 698 So it is possible that other static destructors might want to
96aa2d94
RM
699 write to cout - and they're supposed to be able to do so.
700
adfa2078 701 The following will make the standard streambufs be unbuffered,
96aa2d94
RM
702 which forces any output from late destructors to be written out. */
703 _IO_unbuffer_all ();
704}
705
706void
40a55d20
UD
707_IO_init_marker (marker, fp)
708 struct _IO_marker *marker;
709 _IO_FILE *fp;
96aa2d94
RM
710{
711 marker->_sbuf = fp;
40a55d20
UD
712 if (_IO_in_put_mode (fp))
713 _IO_switch_to_get_mode (fp);
714 if (_IO_in_backup (fp))
96aa2d94
RM
715 marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
716 else
717 marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
adfa2078 718
96aa2d94
RM
719 /* Should perhaps sort the chain? */
720 marker->_next = fp->_markers;
721 fp->_markers = marker;
722}
723
724void
40a55d20
UD
725_IO_remove_marker (marker)
726 struct _IO_marker *marker;
96aa2d94
RM
727{
728 /* Unlink from sb's chain. */
40a55d20 729 struct _IO_marker **ptr = &marker->_sbuf->_markers;
96aa2d94
RM
730 for (; ; ptr = &(*ptr)->_next)
731 {
732 if (*ptr == NULL)
733 break;
734 else if (*ptr == marker)
735 {
736 *ptr = marker->_next;
737 return;
738 }
739 }
740#if 0
741 if _sbuf has a backup area that is no longer needed, should we delete
742 it now, or wait until the next underflow?
743#endif
744}
745
746#define BAD_DELTA EOF
747
748int
40a55d20
UD
749_IO_marker_difference (mark1, mark2)
750 struct _IO_marker *mark1;
751 struct _IO_marker *mark2;
96aa2d94
RM
752{
753 return mark1->_pos - mark2->_pos;
754}
755
6d52618b 756/* Return difference between MARK and current position of MARK's stream. */
96aa2d94 757int
40a55d20
UD
758_IO_marker_delta (mark)
759 struct _IO_marker *mark;
96aa2d94
RM
760{
761 int cur_pos;
762 if (mark->_sbuf == NULL)
763 return BAD_DELTA;
40a55d20 764 if (_IO_in_backup (mark->_sbuf))
96aa2d94
RM
765 cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
766 else
767 cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
768 return mark->_pos - cur_pos;
769}
770
771int
40a55d20
UD
772_IO_seekmark (fp, mark, delta)
773 _IO_FILE *fp;
774 struct _IO_marker *mark;
775 int delta;
96aa2d94
RM
776{
777 if (mark->_sbuf != fp)
778 return EOF;
779 if (mark->_pos >= 0)
780 {
40a55d20
UD
781 if (_IO_in_backup (fp))
782 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
783 fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
784 }
785 else
786 {
40a55d20
UD
787 if (!_IO_in_backup (fp))
788 _IO_switch_to_backup_area (fp);
96aa2d94
RM
789 fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
790 }
791 return 0;
792}
793
794void
40a55d20
UD
795_IO_unsave_markers (fp)
796 _IO_FILE *fp;
96aa2d94 797{
40a55d20 798 struct _IO_marker *mark = fp->_markers;
96aa2d94
RM
799 if (mark)
800 {
801#ifdef TODO
40a55d20 802 streampos offset = seekoff (0, ios::cur, ios::in);
96aa2d94
RM
803 if (offset != EOF)
804 {
40a55d20 805 offset += eGptr () - Gbase ();
96aa2d94 806 for ( ; mark != NULL; mark = mark->_next)
40a55d20 807 mark->set_streampos (mark->_pos + offset);
96aa2d94
RM
808 }
809 else
810 {
811 for ( ; mark != NULL; mark = mark->_next)
40a55d20 812 mark->set_streampos (EOF);
96aa2d94
RM
813 }
814#endif
815 fp->_markers = 0;
816 }
817
40a55d20
UD
818 if (_IO_have_backup (fp))
819 _IO_free_backup_area (fp);
96aa2d94
RM
820}
821
40a55d20
UD
822#if 0
823/* Seems not to be needed. --drepper */
96aa2d94 824int
40a55d20
UD
825_IO_nobackup_pbackfail (fp, c)
826 _IO_FILE *fp;
827 int c;
96aa2d94
RM
828{
829 if (fp->_IO_read_ptr > fp->_IO_read_base)
830 fp->_IO_read_ptr--;
831 if (c != EOF && *fp->_IO_read_ptr != c)
832 *fp->_IO_read_ptr = c;
40a55d20 833 return (unsigned char) c;
96aa2d94 834}
40a55d20 835#endif
96aa2d94
RM
836
837int
40a55d20
UD
838_IO_default_pbackfail (fp, c)
839 _IO_FILE *fp;
840 int c;
96aa2d94
RM
841{
842 if (fp->_IO_read_ptr <= fp->_IO_read_base)
40a55d20
UD
843 {
844 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
845 if (_IO_have_backup (fp) && !_IO_in_backup (fp))
846 _IO_switch_to_backup_area (fp);
847
848 if (!_IO_have_backup (fp))
849 {
850 /* No backup buffer: allocate one. */
851 /* Use nshort buffer, if unused? (probably not) FIXME */
852 int backup_size = 128;
853 char *bbuf = (char *) malloc (backup_size);
854 if (bbuf == NULL)
855 return EOF;
856 fp->_IO_save_base = bbuf;
857 fp->_IO_save_end = fp->_IO_save_base + backup_size;
858 fp->_IO_backup_base = fp->_IO_save_end;
859 _IO_switch_to_backup_area (fp);
860 }
861 else if (fp->_IO_read_ptr <= fp->_IO_read_base)
862 {
863 /* Increase size of existing backup buffer. */
864 _IO_size_t new_size;
865 _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
866 char *new_buf;
867 new_size = 2 * old_size;
868 new_buf = (char *) malloc (new_size);
869 if (new_buf == NULL)
870 return EOF;
871 memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
872 old_size);
873 free (fp->_IO_read_base);
874 _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
875 new_buf + new_size);
876 fp->_IO_backup_base = fp->_IO_read_ptr;
877 }
878 }
879 --fp->_IO_read_ptr;
96aa2d94
RM
880 if (c != EOF && *fp->_IO_read_ptr != c)
881 *fp->_IO_read_ptr = c;
40a55d20 882 return (unsigned char) *fp->_IO_read_ptr;
96aa2d94
RM
883}
884
885_IO_pos_t
40a55d20
UD
886_IO_default_seek (fp, offset, dir)
887 _IO_FILE *fp;
888 _IO_off_t offset;
889 int dir;
96aa2d94
RM
890{
891 return _IO_pos_BAD;
892}
893
894int
40a55d20
UD
895_IO_default_stat (fp, st)
896 _IO_FILE *fp;
897 void* st;
96aa2d94
RM
898{
899 return EOF;
900}
901
902_IO_ssize_t
40a55d20
UD
903_IO_default_read (fp, data, n)
904 _IO_FILE* fp;
905 void *data;
906 _IO_ssize_t n;
96aa2d94
RM
907{
908 return -1;
909}
910
911_IO_ssize_t
40a55d20
UD
912_IO_default_write (fp, data, n)
913 _IO_FILE *fp;
914 const void *data;
915 _IO_ssize_t n;
96aa2d94
RM
916{
917 return 0;
918}
919
920
921#ifdef TODO
922#if defined(linux)
923#define IO_CLEANUP ;
924#endif
925
926#ifdef IO_CLEANUP
927 IO_CLEANUP
928#else
929struct __io_defs {
930 __io_defs() { }
40a55d20 931 ~__io_defs() { _IO_cleanup (); }
adfa2078 932};
96aa2d94
RM
933__io_defs io_defs__;
934#endif
935
936#endif /* TODO */
adfa2078
UD
937
938#ifdef weak_alias
939weak_alias (_IO_cleanup, _cleanup)
940#endif
f65fd747
UD
941
942#ifdef text_set_element
943text_set_element(__libc_atexit, _cleanup);
944#endif