]>
Commit | Line | Data |
---|---|---|
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 | ||
34 | void | |
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 | ||
53 | void | |
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 | 67 | static _IO_size_t _IO_least_marker __P ((_IO_FILE *fp)); |
96aa2d94 | 68 | |
40a55d20 UD |
69 | static _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 | ||
83 | void | |
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 | ||
103 | void | |
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 | ||
121 | int | |
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 | ||
144 | void | |
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 | |
157 | int | |
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 | ||
175 | int | |
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 |
183 | static int save_for_backup __P ((_IO_FILE *fp)); |
184 | ||
185 | static int | |
186 | save_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 | ||
248 | int | |
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 | ||
273 | int | |
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 | ||
298 | void | |
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 | ||
315 | void | |
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 | ||
327 | int | |
40a55d20 UD |
328 | _IO_default_underflow (fp) |
329 | _IO_FILE *fp; | |
96aa2d94 RM |
330 | { |
331 | return EOF; | |
332 | } | |
333 | ||
334 | int | |
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 | 439 | int |
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 | ||
479 | int | |
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 | ||
490 | void | |
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 | ||
516 | int | |
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 | ||
526 | void | |
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 | ||
564 | int | |
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 | ||
586 | int | |
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 | 609 | void |
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 | |
620 | int | |
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 | ||
632 | unsigned | |
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 | 647 | int |
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 | |
659 | int | |
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 | ||
671 | void | |
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 |
680 | static void _IO_unbuffer_all __P ((void)); |
681 | ||
682 | static 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 | ||
691 | void | |
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 | ||
706 | void | |
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 | ||
724 | void | |
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 | ||
748 | int | |
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 | 757 | int |
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 | ||
771 | int | |
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 | ||
794 | void | |
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 | 824 | int |
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 | |
837 | int | |
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 | ||
894 | int | |
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 | |
929 | struct __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 | |
939 | weak_alias (_IO_cleanup, _cleanup) | |
940 | #endif | |
f65fd747 UD |
941 | |
942 | #ifdef text_set_element | |
943 | text_set_element(__libc_atexit, _cleanup); | |
944 | #endif |