]>
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 | ||
dfd2257a UD |
183 | static int save_for_backup __P ((_IO_FILE *fp)) |
184 | #ifdef _LIBC | |
185 | internal_function | |
186 | #endif | |
187 | ; | |
40a55d20 UD |
188 | |
189 | static int | |
dfd2257a UD |
190 | #ifdef _LIBC |
191 | internal_function | |
192 | #endif | |
40a55d20 UD |
193 | save_for_backup (fp) |
194 | _IO_FILE *fp; | |
96aa2d94 RM |
195 | { |
196 | /* Append [_IO_read_base.._IO_read_end] to backup area. */ | |
40a55d20 | 197 | int least_mark = _IO_least_marker (fp); |
96aa2d94 RM |
198 | /* needed_size is how much space we need in the backup area. */ |
199 | int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark; | |
200 | int current_Bsize = fp->_IO_save_end - fp->_IO_save_base; | |
201 | int avail; /* Extra space available for future expansion. */ | |
202 | int delta; | |
203 | struct _IO_marker *mark; | |
204 | if (needed_size > current_Bsize) | |
205 | { | |
206 | char *new_buffer; | |
207 | avail = 100; | |
40a55d20 | 208 | new_buffer = (char *) malloc (avail + needed_size); |
96aa2d94 RM |
209 | if (new_buffer == NULL) |
210 | return EOF; /* FIXME */ | |
211 | if (least_mark < 0) | |
212 | { | |
40a55d20 UD |
213 | memcpy (new_buffer + avail, |
214 | fp->_IO_save_end + least_mark, | |
215 | -least_mark); | |
216 | memcpy (new_buffer + avail - least_mark, | |
217 | fp->_IO_read_base, | |
218 | fp->_IO_read_end - fp->_IO_read_base); | |
96aa2d94 RM |
219 | } |
220 | else | |
40a55d20 UD |
221 | memcpy (new_buffer + avail, |
222 | fp->_IO_read_base + least_mark, | |
223 | needed_size); | |
96aa2d94 RM |
224 | if (fp->_IO_save_base) |
225 | free (fp->_IO_save_base); | |
226 | fp->_IO_save_base = new_buffer; | |
227 | fp->_IO_save_end = new_buffer + avail + needed_size; | |
228 | } | |
229 | else | |
230 | { | |
231 | avail = current_Bsize - needed_size; | |
232 | if (least_mark < 0) | |
233 | { | |
40a55d20 UD |
234 | memmove (fp->_IO_save_base + avail, |
235 | fp->_IO_save_end + least_mark, | |
236 | -least_mark); | |
237 | memcpy (fp->_IO_save_base + avail - least_mark, | |
238 | fp->_IO_read_base, | |
239 | fp->_IO_read_end - fp->_IO_read_base); | |
96aa2d94 RM |
240 | } |
241 | else if (needed_size > 0) | |
40a55d20 UD |
242 | memcpy (fp->_IO_save_base + avail, |
243 | fp->_IO_read_base + least_mark, | |
244 | needed_size); | |
96aa2d94 RM |
245 | } |
246 | /* FIXME: Dubious arithmetic if pointers are NULL */ | |
247 | fp->_IO_backup_base = fp->_IO_save_base + avail; | |
248 | /* Adjust all the streammarkers. */ | |
249 | delta = fp->_IO_read_end - fp->_IO_read_base; | |
250 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) | |
251 | mark->_pos -= delta; | |
252 | return 0; | |
253 | } | |
254 | ||
255 | int | |
40a55d20 UD |
256 | __underflow (fp) |
257 | _IO_FILE *fp; | |
96aa2d94 | 258 | { |
40a55d20 UD |
259 | if (_IO_in_put_mode (fp)) |
260 | if (_IO_switch_to_get_mode (fp) == EOF) | |
261 | return EOF; | |
96aa2d94 | 262 | if (fp->_IO_read_ptr < fp->_IO_read_end) |
40a55d20 UD |
263 | return *(unsigned char *) fp->_IO_read_ptr; |
264 | if (_IO_in_backup (fp)) | |
96aa2d94 | 265 | { |
40a55d20 | 266 | _IO_switch_to_main_get_area (fp); |
96aa2d94 RM |
267 | if (fp->_IO_read_ptr < fp->_IO_read_end) |
268 | return *fp->_IO_read_ptr; | |
269 | } | |
40a55d20 | 270 | if (_IO_have_markers (fp)) |
96aa2d94 RM |
271 | { |
272 | if (save_for_backup (fp)) | |
273 | return EOF; | |
274 | } | |
40a55d20 UD |
275 | else if (_IO_have_backup (fp)) |
276 | _IO_free_backup_area (fp); | |
96aa2d94 RM |
277 | return _IO_UNDERFLOW (fp); |
278 | } | |
279 | ||
280 | int | |
40a55d20 UD |
281 | __uflow (fp) |
282 | _IO_FILE *fp; | |
96aa2d94 | 283 | { |
40a55d20 UD |
284 | if (_IO_in_put_mode (fp)) |
285 | if (_IO_switch_to_get_mode (fp) == EOF) | |
286 | return EOF; | |
96aa2d94 | 287 | if (fp->_IO_read_ptr < fp->_IO_read_end) |
40a55d20 UD |
288 | return *(unsigned char *) fp->_IO_read_ptr++; |
289 | if (_IO_in_backup (fp)) | |
96aa2d94 | 290 | { |
40a55d20 | 291 | _IO_switch_to_main_get_area (fp); |
96aa2d94 RM |
292 | if (fp->_IO_read_ptr < fp->_IO_read_end) |
293 | return *fp->_IO_read_ptr++; | |
294 | } | |
40a55d20 | 295 | if (_IO_have_markers (fp)) |
96aa2d94 RM |
296 | { |
297 | if (save_for_backup (fp)) | |
298 | return EOF; | |
299 | } | |
40a55d20 UD |
300 | else if (_IO_have_backup (fp)) |
301 | _IO_free_backup_area (fp); | |
96aa2d94 RM |
302 | return _IO_UFLOW (fp); |
303 | } | |
304 | ||
305 | void | |
40a55d20 UD |
306 | _IO_setb (f, b, eb, a) |
307 | _IO_FILE *f; | |
308 | char *b; | |
309 | char *eb; | |
310 | int a; | |
96aa2d94 RM |
311 | { |
312 | if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF)) | |
40a55d20 | 313 | FREE_BUF (f->_IO_buf_base, _IO_blen (f)); |
96aa2d94 RM |
314 | f->_IO_buf_base = b; |
315 | f->_IO_buf_end = eb; | |
316 | if (a) | |
317 | f->_flags &= ~_IO_USER_BUF; | |
318 | else | |
319 | f->_flags |= _IO_USER_BUF; | |
320 | } | |
321 | ||
322 | void | |
40a55d20 UD |
323 | _IO_doallocbuf (fp) |
324 | _IO_FILE *fp; | |
96aa2d94 RM |
325 | { |
326 | if (fp->_IO_buf_base) | |
327 | return; | |
328 | if (!(fp->_flags & _IO_UNBUFFERED)) | |
329 | if (_IO_DOALLOCATE (fp) != EOF) | |
330 | return; | |
40a55d20 | 331 | _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0); |
96aa2d94 RM |
332 | } |
333 | ||
334 | int | |
40a55d20 UD |
335 | _IO_default_underflow (fp) |
336 | _IO_FILE *fp; | |
96aa2d94 RM |
337 | { |
338 | return EOF; | |
339 | } | |
340 | ||
341 | int | |
40a55d20 UD |
342 | _IO_default_uflow (fp) |
343 | _IO_FILE *fp; | |
96aa2d94 RM |
344 | { |
345 | int ch = _IO_UNDERFLOW (fp); | |
346 | if (ch == EOF) | |
347 | return EOF; | |
40a55d20 | 348 | return *(unsigned char *) fp->_IO_read_ptr++; |
96aa2d94 RM |
349 | } |
350 | ||
351 | _IO_size_t | |
40a55d20 UD |
352 | _IO_default_xsputn (f, data, n) |
353 | _IO_FILE *f; | |
354 | const void *data; | |
355 | _IO_size_t n; | |
96aa2d94 | 356 | { |
40a55d20 UD |
357 | const char *s = (char *) data; |
358 | _IO_size_t more = n; | |
96aa2d94 RM |
359 | if (more <= 0) |
360 | return 0; | |
361 | for (;;) | |
362 | { | |
40a55d20 UD |
363 | /* Space available. */ |
364 | _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr; | |
96aa2d94 RM |
365 | if (count > 0) |
366 | { | |
a68b0d31 | 367 | if ((_IO_size_t) count > more) |
96aa2d94 RM |
368 | count = more; |
369 | if (count > 20) | |
370 | { | |
40a55d20 | 371 | memcpy (f->_IO_write_ptr, s, count); |
96aa2d94 RM |
372 | s += count; |
373 | f->_IO_write_ptr += count; | |
374 | } | |
375 | else if (count <= 0) | |
376 | count = 0; | |
377 | else | |
378 | { | |
40a55d20 UD |
379 | char *p = f->_IO_write_ptr; |
380 | _IO_ssize_t i; | |
381 | for (i = count; --i >= 0; ) | |
382 | *p++ = *s++; | |
96aa2d94 RM |
383 | f->_IO_write_ptr = p; |
384 | } | |
385 | more -= count; | |
386 | } | |
40a55d20 | 387 | if (more == 0 || __overflow (f, (unsigned char) *s++) == EOF) |
96aa2d94 RM |
388 | break; |
389 | more--; | |
390 | } | |
391 | return n - more; | |
392 | } | |
393 | ||
394 | _IO_size_t | |
40a55d20 UD |
395 | _IO_sgetn (fp, data, n) |
396 | _IO_FILE *fp; | |
397 | void *data; | |
398 | _IO_size_t n; | |
96aa2d94 RM |
399 | { |
400 | /* FIXME handle putback buffer here! */ | |
401 | return _IO_XSGETN (fp, data, n); | |
402 | } | |
403 | ||
404 | _IO_size_t | |
40a55d20 UD |
405 | _IO_default_xsgetn (fp, data, n) |
406 | _IO_FILE *fp; | |
407 | void *data; | |
408 | _IO_size_t n; | |
96aa2d94 | 409 | { |
40a55d20 UD |
410 | _IO_size_t more = n; |
411 | char *s = (char*) data; | |
96aa2d94 RM |
412 | for (;;) |
413 | { | |
40a55d20 UD |
414 | /* Data available. */ |
415 | _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; | |
96aa2d94 RM |
416 | if (count > 0) |
417 | { | |
a68b0d31 | 418 | if ((_IO_size_t) count > more) |
96aa2d94 RM |
419 | count = more; |
420 | if (count > 20) | |
421 | { | |
40a55d20 | 422 | memcpy (s, fp->_IO_read_ptr, count); |
96aa2d94 RM |
423 | s += count; |
424 | fp->_IO_read_ptr += count; | |
425 | } | |
426 | else if (count <= 0) | |
427 | count = 0; | |
428 | else | |
429 | { | |
40a55d20 UD |
430 | char *p = fp->_IO_read_ptr; |
431 | int i = (int) count; | |
432 | while (--i >= 0) | |
433 | *s++ = *p++; | |
96aa2d94 RM |
434 | fp->_IO_read_ptr = p; |
435 | } | |
436 | more -= count; | |
437 | } | |
40a55d20 | 438 | if (more == 0 || __underflow (fp) == EOF) |
96aa2d94 RM |
439 | break; |
440 | } | |
441 | return n - more; | |
442 | } | |
443 | ||
40a55d20 UD |
444 | #if 0 |
445 | /* Seems not to be needed. --drepper */ | |
96aa2d94 | 446 | int |
40a55d20 UD |
447 | _IO_sync (fp) |
448 | _IO_FILE *fp; | |
96aa2d94 RM |
449 | { |
450 | return 0; | |
451 | } | |
40a55d20 | 452 | #endif |
96aa2d94 | 453 | |
40a55d20 UD |
454 | _IO_FILE * |
455 | _IO_default_setbuf (fp, p, len) | |
456 | _IO_FILE *fp; | |
457 | char *p; | |
458 | _IO_ssize_t len; | |
96aa2d94 RM |
459 | { |
460 | if (_IO_SYNC (fp) == EOF) | |
461 | return NULL; | |
462 | if (p == NULL || len == 0) | |
463 | { | |
464 | fp->_flags |= _IO_UNBUFFERED; | |
40a55d20 | 465 | _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0); |
96aa2d94 RM |
466 | } |
467 | else | |
468 | { | |
469 | fp->_flags &= ~_IO_UNBUFFERED; | |
40a55d20 | 470 | _IO_setb (fp, p, p+len, 0); |
96aa2d94 RM |
471 | } |
472 | fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0; | |
473 | fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0; | |
474 | return fp; | |
475 | } | |
476 | ||
dfd2257a | 477 | _IO_fpos64_t |
40a55d20 UD |
478 | _IO_default_seekpos (fp, pos, mode) |
479 | _IO_FILE *fp; | |
dfd2257a | 480 | _IO_fpos64_t pos; |
40a55d20 | 481 | int mode; |
96aa2d94 | 482 | { |
40a55d20 | 483 | return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode); |
96aa2d94 RM |
484 | } |
485 | ||
486 | int | |
40a55d20 UD |
487 | _IO_default_doallocate (fp) |
488 | _IO_FILE *fp; | |
96aa2d94 | 489 | { |
f8b87ef0 UD |
490 | char *buf; |
491 | ||
40a55d20 UD |
492 | ALLOC_BUF (buf, _IO_BUFSIZ, EOF); |
493 | _IO_setb (fp, buf, buf+_IO_BUFSIZ, 1); | |
96aa2d94 RM |
494 | return 1; |
495 | } | |
496 | ||
497 | void | |
40a55d20 UD |
498 | _IO_init (fp, flags) |
499 | _IO_FILE *fp; | |
500 | int flags; | |
96aa2d94 RM |
501 | { |
502 | fp->_flags = _IO_MAGIC|flags; | |
503 | fp->_IO_buf_base = NULL; | |
504 | fp->_IO_buf_end = NULL; | |
505 | fp->_IO_read_base = NULL; | |
506 | fp->_IO_read_ptr = NULL; | |
507 | fp->_IO_read_end = NULL; | |
508 | fp->_IO_write_base = NULL; | |
509 | fp->_IO_write_ptr = NULL; | |
510 | fp->_IO_write_end = NULL; | |
511 | fp->_chain = NULL; /* Not necessary. */ | |
512 | ||
513 | fp->_IO_save_base = NULL; | |
514 | fp->_IO_backup_base = NULL; | |
515 | fp->_IO_save_end = NULL; | |
516 | fp->_markers = NULL; | |
517 | fp->_cur_column = 0; | |
7c713e28 | 518 | #ifdef _IO_MTSAFE_IO |
df4ef2ab | 519 | _IO_lock_init (*fp->_lock); |
7c713e28 | 520 | #endif |
96aa2d94 RM |
521 | } |
522 | ||
523 | int | |
40a55d20 UD |
524 | _IO_default_sync (fp) |
525 | _IO_FILE *fp; | |
96aa2d94 RM |
526 | { |
527 | return 0; | |
528 | } | |
529 | ||
530 | /* The way the C++ classes are mapped into the C functions in the | |
531 | current implementation, this function can get called twice! */ | |
532 | ||
533 | void | |
40a55d20 UD |
534 | _IO_default_finish (fp, dummy) |
535 | _IO_FILE *fp; | |
536 | int dummy; | |
96aa2d94 RM |
537 | { |
538 | struct _IO_marker *mark; | |
539 | if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) | |
540 | { | |
40a55d20 | 541 | FREE_BUF (fp->_IO_buf_base, _IO_blen (fp)); |
96aa2d94 RM |
542 | fp->_IO_buf_base = fp->_IO_buf_end = NULL; |
543 | } | |
544 | ||
545 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) | |
546 | mark->_sbuf = NULL; | |
547 | ||
548 | if (fp->_IO_save_base) | |
549 | { | |
550 | free (fp->_IO_save_base); | |
551 | fp->_IO_save_base = NULL; | |
552 | } | |
553 | ||
7c713e28 | 554 | #ifdef _IO_MTSAFE_IO |
68dbb3a6 | 555 | _IO_lock_fini (*fp->_lock); |
7c713e28 | 556 | #endif |
adfa2078 | 557 | |
40a55d20 | 558 | _IO_un_link (fp); |
96aa2d94 RM |
559 | } |
560 | ||
dfd2257a | 561 | _IO_fpos64_t |
40a55d20 UD |
562 | _IO_default_seekoff (fp, offset, dir, mode) |
563 | _IO_FILE *fp; | |
dfd2257a | 564 | _IO_off64_t offset; |
40a55d20 UD |
565 | int dir; |
566 | int mode; | |
96aa2d94 RM |
567 | { |
568 | return _IO_pos_BAD; | |
569 | } | |
570 | ||
571 | int | |
40a55d20 UD |
572 | _IO_sputbackc (fp, c) |
573 | _IO_FILE *fp; | |
574 | int c; | |
96aa2d94 | 575 | { |
19bc17a9 | 576 | int result; |
adfa2078 | 577 | |
96aa2d94 RM |
578 | if (fp->_IO_read_ptr > fp->_IO_read_base |
579 | && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c) | |
580 | { | |
581 | fp->_IO_read_ptr--; | |
40a55d20 | 582 | result = (unsigned char) c; |
96aa2d94 | 583 | } |
19bc17a9 RM |
584 | else |
585 | result = _IO_PBACKFAIL (fp, c); | |
586 | ||
587 | if (result != EOF) | |
588 | fp->_flags &= ~_IO_EOF_SEEN; | |
589 | ||
590 | return result; | |
96aa2d94 RM |
591 | } |
592 | ||
593 | int | |
40a55d20 UD |
594 | _IO_sungetc (fp) |
595 | _IO_FILE *fp; | |
96aa2d94 | 596 | { |
19bc17a9 | 597 | int result; |
adfa2078 | 598 | |
96aa2d94 RM |
599 | if (fp->_IO_read_ptr > fp->_IO_read_base) |
600 | { | |
601 | fp->_IO_read_ptr--; | |
40a55d20 | 602 | result = (unsigned char) *fp->_IO_read_ptr; |
96aa2d94 RM |
603 | } |
604 | else | |
19bc17a9 RM |
605 | result = _IO_PBACKFAIL (fp, EOF); |
606 | ||
607 | if (result != EOF) | |
608 | fp->_flags &= ~_IO_EOF_SEEN; | |
609 | ||
610 | return result; | |
96aa2d94 RM |
611 | } |
612 | ||
613 | #if 0 /* Work in progress */ | |
40a55d20 UD |
614 | /* Seems not to be needed. */ |
615 | #if 0 | |
96aa2d94 | 616 | void |
40a55d20 UD |
617 | _IO_set_column (fp, c) |
618 | _IO_FILE *fp; | |
619 | int c; | |
96aa2d94 RM |
620 | { |
621 | if (c == -1) | |
622 | fp->_column = -1; | |
623 | else | |
624 | fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base); | |
625 | } | |
626 | #else | |
627 | int | |
40a55d20 UD |
628 | _IO_set_column (fp, i) |
629 | _IO_FILE *fp; | |
630 | int i; | |
96aa2d94 | 631 | { |
40a55d20 | 632 | fp->_cur_column = i + 1; |
96aa2d94 RM |
633 | return 0; |
634 | } | |
635 | #endif | |
40a55d20 | 636 | #endif |
96aa2d94 RM |
637 | |
638 | ||
639 | unsigned | |
40a55d20 UD |
640 | _IO_adjust_column (start, line, count) |
641 | unsigned start; | |
642 | const char *line; | |
643 | int count; | |
96aa2d94 | 644 | { |
40a55d20 | 645 | const char *ptr = line + count; |
96aa2d94 RM |
646 | while (ptr > line) |
647 | if (*--ptr == '\n') | |
648 | return line + count - ptr - 1; | |
649 | return start + count; | |
650 | } | |
651 | ||
40a55d20 UD |
652 | #if 0 |
653 | /* Seems not to be needed. --drepper */ | |
96aa2d94 | 654 | int |
40a55d20 UD |
655 | _IO_get_column (fp) |
656 | _IO_FILE *fp; | |
96aa2d94 | 657 | { |
adfa2078 | 658 | if (fp->_cur_column) |
40a55d20 | 659 | return _IO_adjust_column (fp->_cur_column - 1, |
96aa2d94 RM |
660 | fp->_IO_write_base, |
661 | fp->_IO_write_ptr - fp->_IO_write_base); | |
662 | return -1; | |
663 | } | |
40a55d20 | 664 | #endif |
96aa2d94 RM |
665 | |
666 | int | |
40a55d20 | 667 | _IO_flush_all () |
96aa2d94 RM |
668 | { |
669 | int result = 0; | |
670 | _IO_FILE *fp; | |
671 | for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) | |
672 | if (fp->_IO_write_ptr > fp->_IO_write_base | |
673 | && _IO_OVERFLOW (fp, EOF) == EOF) | |
674 | result = EOF; | |
675 | return result; | |
676 | } | |
677 | ||
678 | void | |
40a55d20 | 679 | _IO_flush_all_linebuffered () |
96aa2d94 RM |
680 | { |
681 | _IO_FILE *fp; | |
682 | for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) | |
63551311 | 683 | if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF) |
96aa2d94 RM |
684 | _IO_OVERFLOW (fp, EOF); |
685 | } | |
686 | ||
40a55d20 UD |
687 | static void _IO_unbuffer_all __P ((void)); |
688 | ||
689 | static void | |
690 | _IO_unbuffer_all () | |
96aa2d94 RM |
691 | { |
692 | _IO_FILE *fp; | |
693 | for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) | |
694 | if (! (fp->_flags & _IO_UNBUFFERED)) | |
695 | _IO_SETBUF (fp, NULL, 0); | |
696 | } | |
697 | ||
698 | void | |
40a55d20 | 699 | _IO_cleanup () |
96aa2d94 RM |
700 | { |
701 | _IO_flush_all (); | |
702 | ||
703 | /* We currently don't have a reliable mechanism for making sure that | |
704 | C++ static destructors are executed in the correct order. | |
6d52618b | 705 | So it is possible that other static destructors might want to |
96aa2d94 RM |
706 | write to cout - and they're supposed to be able to do so. |
707 | ||
adfa2078 | 708 | The following will make the standard streambufs be unbuffered, |
96aa2d94 RM |
709 | which forces any output from late destructors to be written out. */ |
710 | _IO_unbuffer_all (); | |
711 | } | |
712 | ||
f2ea0f5b UD |
713 | _IO_FILE *_IO_list_all = &_IO_stderr_.plus.file; |
714 | ||
96aa2d94 | 715 | void |
40a55d20 UD |
716 | _IO_init_marker (marker, fp) |
717 | struct _IO_marker *marker; | |
718 | _IO_FILE *fp; | |
96aa2d94 RM |
719 | { |
720 | marker->_sbuf = fp; | |
40a55d20 UD |
721 | if (_IO_in_put_mode (fp)) |
722 | _IO_switch_to_get_mode (fp); | |
723 | if (_IO_in_backup (fp)) | |
96aa2d94 RM |
724 | marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end; |
725 | else | |
726 | marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base; | |
adfa2078 | 727 | |
96aa2d94 RM |
728 | /* Should perhaps sort the chain? */ |
729 | marker->_next = fp->_markers; | |
730 | fp->_markers = marker; | |
731 | } | |
732 | ||
733 | void | |
40a55d20 UD |
734 | _IO_remove_marker (marker) |
735 | struct _IO_marker *marker; | |
96aa2d94 RM |
736 | { |
737 | /* Unlink from sb's chain. */ | |
40a55d20 | 738 | struct _IO_marker **ptr = &marker->_sbuf->_markers; |
96aa2d94 RM |
739 | for (; ; ptr = &(*ptr)->_next) |
740 | { | |
741 | if (*ptr == NULL) | |
742 | break; | |
743 | else if (*ptr == marker) | |
744 | { | |
745 | *ptr = marker->_next; | |
746 | return; | |
747 | } | |
748 | } | |
749 | #if 0 | |
750 | if _sbuf has a backup area that is no longer needed, should we delete | |
751 | it now, or wait until the next underflow? | |
752 | #endif | |
753 | } | |
754 | ||
755 | #define BAD_DELTA EOF | |
756 | ||
757 | int | |
40a55d20 UD |
758 | _IO_marker_difference (mark1, mark2) |
759 | struct _IO_marker *mark1; | |
760 | struct _IO_marker *mark2; | |
96aa2d94 RM |
761 | { |
762 | return mark1->_pos - mark2->_pos; | |
763 | } | |
764 | ||
6d52618b | 765 | /* Return difference between MARK and current position of MARK's stream. */ |
96aa2d94 | 766 | int |
40a55d20 UD |
767 | _IO_marker_delta (mark) |
768 | struct _IO_marker *mark; | |
96aa2d94 RM |
769 | { |
770 | int cur_pos; | |
771 | if (mark->_sbuf == NULL) | |
772 | return BAD_DELTA; | |
40a55d20 | 773 | if (_IO_in_backup (mark->_sbuf)) |
96aa2d94 RM |
774 | cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end; |
775 | else | |
776 | cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base; | |
777 | return mark->_pos - cur_pos; | |
778 | } | |
779 | ||
780 | int | |
40a55d20 UD |
781 | _IO_seekmark (fp, mark, delta) |
782 | _IO_FILE *fp; | |
783 | struct _IO_marker *mark; | |
784 | int delta; | |
96aa2d94 RM |
785 | { |
786 | if (mark->_sbuf != fp) | |
787 | return EOF; | |
788 | if (mark->_pos >= 0) | |
789 | { | |
40a55d20 UD |
790 | if (_IO_in_backup (fp)) |
791 | _IO_switch_to_main_get_area (fp); | |
96aa2d94 RM |
792 | fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos; |
793 | } | |
794 | else | |
795 | { | |
40a55d20 UD |
796 | if (!_IO_in_backup (fp)) |
797 | _IO_switch_to_backup_area (fp); | |
96aa2d94 RM |
798 | fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos; |
799 | } | |
800 | return 0; | |
801 | } | |
802 | ||
803 | void | |
40a55d20 UD |
804 | _IO_unsave_markers (fp) |
805 | _IO_FILE *fp; | |
96aa2d94 | 806 | { |
40a55d20 | 807 | struct _IO_marker *mark = fp->_markers; |
96aa2d94 RM |
808 | if (mark) |
809 | { | |
810 | #ifdef TODO | |
40a55d20 | 811 | streampos offset = seekoff (0, ios::cur, ios::in); |
96aa2d94 RM |
812 | if (offset != EOF) |
813 | { | |
40a55d20 | 814 | offset += eGptr () - Gbase (); |
96aa2d94 | 815 | for ( ; mark != NULL; mark = mark->_next) |
40a55d20 | 816 | mark->set_streampos (mark->_pos + offset); |
96aa2d94 RM |
817 | } |
818 | else | |
819 | { | |
820 | for ( ; mark != NULL; mark = mark->_next) | |
40a55d20 | 821 | mark->set_streampos (EOF); |
96aa2d94 RM |
822 | } |
823 | #endif | |
824 | fp->_markers = 0; | |
825 | } | |
826 | ||
40a55d20 UD |
827 | if (_IO_have_backup (fp)) |
828 | _IO_free_backup_area (fp); | |
96aa2d94 RM |
829 | } |
830 | ||
40a55d20 UD |
831 | #if 0 |
832 | /* Seems not to be needed. --drepper */ | |
96aa2d94 | 833 | int |
40a55d20 UD |
834 | _IO_nobackup_pbackfail (fp, c) |
835 | _IO_FILE *fp; | |
836 | int c; | |
96aa2d94 RM |
837 | { |
838 | if (fp->_IO_read_ptr > fp->_IO_read_base) | |
839 | fp->_IO_read_ptr--; | |
840 | if (c != EOF && *fp->_IO_read_ptr != c) | |
841 | *fp->_IO_read_ptr = c; | |
40a55d20 | 842 | return (unsigned char) c; |
96aa2d94 | 843 | } |
40a55d20 | 844 | #endif |
96aa2d94 RM |
845 | |
846 | int | |
40a55d20 UD |
847 | _IO_default_pbackfail (fp, c) |
848 | _IO_FILE *fp; | |
849 | int c; | |
96aa2d94 RM |
850 | { |
851 | if (fp->_IO_read_ptr <= fp->_IO_read_base) | |
40a55d20 UD |
852 | { |
853 | /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ | |
854 | if (_IO_have_backup (fp) && !_IO_in_backup (fp)) | |
855 | _IO_switch_to_backup_area (fp); | |
856 | ||
857 | if (!_IO_have_backup (fp)) | |
858 | { | |
859 | /* No backup buffer: allocate one. */ | |
860 | /* Use nshort buffer, if unused? (probably not) FIXME */ | |
861 | int backup_size = 128; | |
862 | char *bbuf = (char *) malloc (backup_size); | |
863 | if (bbuf == NULL) | |
864 | return EOF; | |
865 | fp->_IO_save_base = bbuf; | |
866 | fp->_IO_save_end = fp->_IO_save_base + backup_size; | |
867 | fp->_IO_backup_base = fp->_IO_save_end; | |
868 | _IO_switch_to_backup_area (fp); | |
869 | } | |
870 | else if (fp->_IO_read_ptr <= fp->_IO_read_base) | |
871 | { | |
872 | /* Increase size of existing backup buffer. */ | |
873 | _IO_size_t new_size; | |
874 | _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base; | |
875 | char *new_buf; | |
876 | new_size = 2 * old_size; | |
877 | new_buf = (char *) malloc (new_size); | |
878 | if (new_buf == NULL) | |
879 | return EOF; | |
880 | memcpy (new_buf + (new_size - old_size), fp->_IO_read_base, | |
881 | old_size); | |
882 | free (fp->_IO_read_base); | |
883 | _IO_setg (fp, new_buf, new_buf + (new_size - old_size), | |
884 | new_buf + new_size); | |
885 | fp->_IO_backup_base = fp->_IO_read_ptr; | |
886 | } | |
887 | } | |
888 | --fp->_IO_read_ptr; | |
96aa2d94 RM |
889 | if (c != EOF && *fp->_IO_read_ptr != c) |
890 | *fp->_IO_read_ptr = c; | |
40a55d20 | 891 | return (unsigned char) *fp->_IO_read_ptr; |
96aa2d94 RM |
892 | } |
893 | ||
dfd2257a | 894 | _IO_fpos64_t |
40a55d20 UD |
895 | _IO_default_seek (fp, offset, dir) |
896 | _IO_FILE *fp; | |
dfd2257a | 897 | _IO_off64_t offset; |
40a55d20 | 898 | int dir; |
96aa2d94 RM |
899 | { |
900 | return _IO_pos_BAD; | |
901 | } | |
902 | ||
903 | int | |
40a55d20 UD |
904 | _IO_default_stat (fp, st) |
905 | _IO_FILE *fp; | |
906 | void* st; | |
96aa2d94 RM |
907 | { |
908 | return EOF; | |
909 | } | |
910 | ||
911 | _IO_ssize_t | |
40a55d20 UD |
912 | _IO_default_read (fp, data, n) |
913 | _IO_FILE* fp; | |
914 | void *data; | |
915 | _IO_ssize_t n; | |
96aa2d94 RM |
916 | { |
917 | return -1; | |
918 | } | |
919 | ||
920 | _IO_ssize_t | |
40a55d20 UD |
921 | _IO_default_write (fp, data, n) |
922 | _IO_FILE *fp; | |
923 | const void *data; | |
924 | _IO_ssize_t n; | |
96aa2d94 RM |
925 | { |
926 | return 0; | |
927 | } | |
928 | ||
dfd2257a UD |
929 | int |
930 | _IO_default_showmanyc (fp) | |
931 | _IO_FILE *fp; | |
932 | { | |
933 | return -1; | |
934 | } | |
935 | ||
936 | void | |
937 | _IO_default_imbue (fp, locale) | |
938 | _IO_FILE *fp; | |
939 | void *locale; | |
940 | { | |
941 | } | |
942 | ||
96aa2d94 RM |
943 | |
944 | #ifdef TODO | |
945 | #if defined(linux) | |
946 | #define IO_CLEANUP ; | |
947 | #endif | |
948 | ||
949 | #ifdef IO_CLEANUP | |
950 | IO_CLEANUP | |
951 | #else | |
952 | struct __io_defs { | |
953 | __io_defs() { } | |
40a55d20 | 954 | ~__io_defs() { _IO_cleanup (); } |
adfa2078 | 955 | }; |
96aa2d94 RM |
956 | __io_defs io_defs__; |
957 | #endif | |
958 | ||
959 | #endif /* TODO */ | |
adfa2078 UD |
960 | |
961 | #ifdef weak_alias | |
962 | weak_alias (_IO_cleanup, _cleanup) | |
963 | #endif | |
f65fd747 UD |
964 | |
965 | #ifdef text_set_element | |
966 | text_set_element(__libc_atexit, _cleanup); | |
967 | #endif |