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