1 | /* Copyright (C) 1993-2023 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. |
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. */ |
26 | |
27 | /* Generic or default I/O operations. */ |
28 | |
29 | #include "libioP.h" |
30 | #include <stdlib.h> |
31 | #include <string.h> |
32 | #include <wchar.h> |
33 | |
34 | |
35 | static int save_for_wbackup (FILE *fp, wchar_t *end_p) __THROW; |
36 | |
37 | /* Return minimum _pos markers |
38 | Assumes the current get area is the main get area. */ |
39 | ssize_t |
40 | _IO_least_wmarker (FILE *fp, wchar_t *end_p) |
41 | { |
42 | ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base; |
43 | struct _IO_marker *mark; |
44 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
45 | if (mark->_pos < least_so_far) |
46 | least_so_far = mark->_pos; |
47 | return least_so_far; |
48 | } |
49 | libc_hidden_def (_IO_least_wmarker) |
50 | |
51 | /* Switch current get area from backup buffer to (start of) main get area. */ |
52 | void |
53 | _IO_switch_to_main_wget_area (FILE *fp) |
54 | { |
55 | wchar_t *tmp; |
56 | fp->_flags &= ~_IO_IN_BACKUP; |
57 | /* Swap _IO_read_end and _IO_save_end. */ |
58 | tmp = fp->_wide_data->_IO_read_end; |
59 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; |
60 | fp->_wide_data->_IO_save_end= tmp; |
61 | /* Swap _IO_read_base and _IO_save_base. */ |
62 | tmp = fp->_wide_data->_IO_read_base; |
63 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; |
64 | fp->_wide_data->_IO_save_base = tmp; |
65 | /* Set _IO_read_ptr. */ |
66 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base; |
67 | } |
68 | libc_hidden_def (_IO_switch_to_main_wget_area) |
69 | |
70 | |
71 | /* Switch current get area from main get area to (end of) backup area. */ |
72 | void |
73 | _IO_switch_to_wbackup_area (FILE *fp) |
74 | { |
75 | wchar_t *tmp; |
76 | fp->_flags |= _IO_IN_BACKUP; |
77 | /* Swap _IO_read_end and _IO_save_end. */ |
78 | tmp = fp->_wide_data->_IO_read_end; |
79 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; |
80 | fp->_wide_data->_IO_save_end = tmp; |
81 | /* Swap _IO_read_base and _IO_save_base. */ |
82 | tmp = fp->_wide_data->_IO_read_base; |
83 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; |
84 | fp->_wide_data->_IO_save_base = tmp; |
85 | /* Set _IO_read_ptr. */ |
86 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; |
87 | } |
88 | libc_hidden_def (_IO_switch_to_wbackup_area) |
89 | |
90 | |
91 | void |
92 | _IO_wsetb (FILE *f, wchar_t *b, wchar_t *eb, int a) |
93 | { |
94 | if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF)) |
95 | free (f->_wide_data->_IO_buf_base); |
96 | f->_wide_data->_IO_buf_base = b; |
97 | f->_wide_data->_IO_buf_end = eb; |
98 | if (a) |
99 | f->_flags2 &= ~_IO_FLAGS2_USER_WBUF; |
100 | else |
101 | f->_flags2 |= _IO_FLAGS2_USER_WBUF; |
102 | } |
103 | libc_hidden_def (_IO_wsetb) |
104 | |
105 | |
106 | wint_t |
107 | _IO_wdefault_pbackfail (FILE *fp, wint_t c) |
108 | { |
109 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
110 | && !_IO_in_backup (fp) |
111 | && (wint_t) fp->_IO_read_ptr[-1] == c) |
112 | --fp->_IO_read_ptr; |
113 | else |
114 | { |
115 | /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ |
116 | if (!_IO_in_backup (fp)) |
117 | { |
118 | /* We need to keep the invariant that the main get area |
119 | logically follows the backup area. */ |
120 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
121 | && _IO_have_wbackup (fp)) |
122 | { |
123 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr)) |
124 | return WEOF; |
125 | } |
126 | else if (!_IO_have_wbackup (fp)) |
127 | { |
128 | /* No backup buffer: allocate one. */ |
129 | /* Use nshort buffer, if unused? (probably not) FIXME */ |
130 | int backup_size = 128; |
131 | wchar_t *bbuf = (wchar_t *) malloc (backup_size |
132 | * sizeof (wchar_t)); |
133 | if (bbuf == NULL) |
134 | return WEOF; |
135 | fp->_wide_data->_IO_save_base = bbuf; |
136 | fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base |
137 | + backup_size); |
138 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end; |
139 | } |
140 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr; |
141 | _IO_switch_to_wbackup_area (fp); |
142 | } |
143 | else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base) |
144 | { |
145 | /* Increase size of existing backup buffer. */ |
146 | size_t new_size; |
147 | size_t old_size = (fp->_wide_data->_IO_read_end |
148 | - fp->_wide_data->_IO_read_base); |
149 | wchar_t *new_buf; |
150 | new_size = 2 * old_size; |
151 | new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t)); |
152 | if (new_buf == NULL) |
153 | return WEOF; |
154 | __wmemcpy (new_buf + (new_size - old_size), |
155 | fp->_wide_data->_IO_read_base, old_size); |
156 | free (fp->_wide_data->_IO_read_base); |
157 | _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size), |
158 | new_buf + new_size); |
159 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr; |
160 | } |
161 | |
162 | *--fp->_wide_data->_IO_read_ptr = c; |
163 | } |
164 | return c; |
165 | } |
166 | libc_hidden_def (_IO_wdefault_pbackfail) |
167 | |
168 | |
169 | void |
170 | _IO_wdefault_finish (FILE *fp, int dummy) |
171 | { |
172 | struct _IO_marker *mark; |
173 | if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) |
174 | { |
175 | free (fp->_wide_data->_IO_buf_base); |
176 | fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL; |
177 | } |
178 | |
179 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
180 | mark->_sbuf = NULL; |
181 | |
182 | if (fp->_IO_save_base) |
183 | { |
184 | free (fp->_wide_data->_IO_save_base); |
185 | fp->_IO_save_base = NULL; |
186 | } |
187 | |
188 | #ifdef _IO_MTSAFE_IO |
189 | if (fp->_lock != NULL) |
190 | _IO_lock_fini (*fp->_lock); |
191 | #endif |
192 | |
193 | _IO_un_link ((struct _IO_FILE_plus *) fp); |
194 | } |
195 | libc_hidden_def (_IO_wdefault_finish) |
196 | |
197 | |
198 | wint_t |
199 | _IO_wdefault_uflow (FILE *fp) |
200 | { |
201 | wint_t wch; |
202 | wch = _IO_UNDERFLOW (fp); |
203 | if (wch == WEOF) |
204 | return WEOF; |
205 | return *fp->_wide_data->_IO_read_ptr++; |
206 | } |
207 | libc_hidden_def (_IO_wdefault_uflow) |
208 | |
209 | |
210 | wint_t |
211 | __woverflow (FILE *f, wint_t wch) |
212 | { |
213 | if (f->_mode == 0) |
214 | _IO_fwide (f, 1); |
215 | return _IO_OVERFLOW (f, wch); |
216 | } |
217 | libc_hidden_def (__woverflow) |
218 | |
219 | |
220 | wint_t |
221 | __wuflow (FILE *fp) |
222 | { |
223 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
224 | return WEOF; |
225 | |
226 | if (fp->_mode == 0) |
227 | _IO_fwide (fp, 1); |
228 | if (_IO_in_put_mode (fp)) |
229 | if (_IO_switch_to_wget_mode (fp) == EOF) |
230 | return WEOF; |
231 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
232 | return *fp->_wide_data->_IO_read_ptr++; |
233 | if (_IO_in_backup (fp)) |
234 | { |
235 | _IO_switch_to_main_wget_area (fp); |
236 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
237 | return *fp->_wide_data->_IO_read_ptr++; |
238 | } |
239 | if (_IO_have_markers (fp)) |
240 | { |
241 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) |
242 | return WEOF; |
243 | } |
244 | else if (_IO_have_wbackup (fp)) |
245 | _IO_free_wbackup_area (fp); |
246 | return _IO_UFLOW (fp); |
247 | } |
248 | libc_hidden_def (__wuflow) |
249 | |
250 | wint_t |
251 | __wunderflow (FILE *fp) |
252 | { |
253 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
254 | return WEOF; |
255 | |
256 | if (fp->_mode == 0) |
257 | _IO_fwide (fp, 1); |
258 | if (_IO_in_put_mode (fp)) |
259 | if (_IO_switch_to_wget_mode (fp) == EOF) |
260 | return WEOF; |
261 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
262 | return *fp->_wide_data->_IO_read_ptr; |
263 | if (_IO_in_backup (fp)) |
264 | { |
265 | _IO_switch_to_main_wget_area (fp); |
266 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) |
267 | return *fp->_wide_data->_IO_read_ptr; |
268 | } |
269 | if (_IO_have_markers (fp)) |
270 | { |
271 | if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) |
272 | return WEOF; |
273 | } |
274 | else if (_IO_have_backup (fp)) |
275 | _IO_free_wbackup_area (fp); |
276 | return _IO_UNDERFLOW (fp); |
277 | } |
278 | libc_hidden_def (__wunderflow) |
279 | |
280 | |
281 | size_t |
282 | _IO_wdefault_xsputn (FILE *f, const void *data, size_t n) |
283 | { |
284 | const wchar_t *s = (const wchar_t *) data; |
285 | size_t more = n; |
286 | if (more <= 0) |
287 | return 0; |
288 | for (;;) |
289 | { |
290 | /* Space available. */ |
291 | ssize_t count = (f->_wide_data->_IO_write_end |
292 | - f->_wide_data->_IO_write_ptr); |
293 | if (count > 0) |
294 | { |
295 | if ((size_t) count > more) |
296 | count = more; |
297 | if (count > 20) |
298 | { |
299 | f->_wide_data->_IO_write_ptr = |
300 | __wmempcpy (f->_wide_data->_IO_write_ptr, s, count); |
301 | s += count; |
302 | } |
303 | else if (count <= 0) |
304 | count = 0; |
305 | else |
306 | { |
307 | wchar_t *p = f->_wide_data->_IO_write_ptr; |
308 | ssize_t i; |
309 | for (i = count; --i >= 0; ) |
310 | *p++ = *s++; |
311 | f->_wide_data->_IO_write_ptr = p; |
312 | } |
313 | more -= count; |
314 | } |
315 | if (more == 0 || __woverflow (f, *s++) == WEOF) |
316 | break; |
317 | more--; |
318 | } |
319 | return n - more; |
320 | } |
321 | libc_hidden_def (_IO_wdefault_xsputn) |
322 | |
323 | |
324 | size_t |
325 | _IO_wdefault_xsgetn (FILE *fp, void *data, size_t n) |
326 | { |
327 | size_t more = n; |
328 | wchar_t *s = (wchar_t*) data; |
329 | for (;;) |
330 | { |
331 | /* Data available. */ |
332 | ssize_t count = (fp->_wide_data->_IO_read_end |
333 | - fp->_wide_data->_IO_read_ptr); |
334 | if (count > 0) |
335 | { |
336 | if ((size_t) count > more) |
337 | count = more; |
338 | if (count > 20) |
339 | { |
340 | s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count); |
341 | fp->_wide_data->_IO_read_ptr += count; |
342 | } |
343 | else if (count <= 0) |
344 | count = 0; |
345 | else |
346 | { |
347 | wchar_t *p = fp->_wide_data->_IO_read_ptr; |
348 | int i = (int) count; |
349 | while (--i >= 0) |
350 | *s++ = *p++; |
351 | fp->_wide_data->_IO_read_ptr = p; |
352 | } |
353 | more -= count; |
354 | } |
355 | if (more == 0 || __wunderflow (fp) == WEOF) |
356 | break; |
357 | } |
358 | return n - more; |
359 | } |
360 | libc_hidden_def (_IO_wdefault_xsgetn) |
361 | |
362 | |
363 | void |
364 | _IO_wdoallocbuf (FILE *fp) |
365 | { |
366 | if (fp->_wide_data->_IO_buf_base) |
367 | return; |
368 | if (!(fp->_flags & _IO_UNBUFFERED)) |
369 | if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF) |
370 | return; |
371 | _IO_wsetb (fp, fp->_wide_data->_shortbuf, |
372 | fp->_wide_data->_shortbuf + 1, 0); |
373 | } |
374 | libc_hidden_def (_IO_wdoallocbuf) |
375 | |
376 | |
377 | int |
378 | _IO_wdefault_doallocate (FILE *fp) |
379 | { |
380 | wchar_t *buf = (wchar_t *)malloc (BUFSIZ); |
381 | if (__glibc_unlikely (buf == NULL)) |
382 | return EOF; |
383 | |
384 | _IO_wsetb (fp, buf, buf + BUFSIZ / sizeof *buf, 1); |
385 | return 1; |
386 | } |
387 | libc_hidden_def (_IO_wdefault_doallocate) |
388 | |
389 | |
390 | int |
391 | _IO_switch_to_wget_mode (FILE *fp) |
392 | { |
393 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) |
394 | if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF) |
395 | return EOF; |
396 | if (_IO_in_backup (fp)) |
397 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base; |
398 | else |
399 | { |
400 | fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base; |
401 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) |
402 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; |
403 | } |
404 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; |
405 | |
406 | fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr |
407 | = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr; |
408 | |
409 | fp->_flags &= ~_IO_CURRENTLY_PUTTING; |
410 | return 0; |
411 | } |
412 | libc_hidden_def (_IO_switch_to_wget_mode) |
413 | |
414 | void |
415 | _IO_free_wbackup_area (FILE *fp) |
416 | { |
417 | if (_IO_in_backup (fp)) |
418 | _IO_switch_to_main_wget_area (fp); /* Just in case. */ |
419 | free (fp->_wide_data->_IO_save_base); |
420 | fp->_wide_data->_IO_save_base = NULL; |
421 | fp->_wide_data->_IO_save_end = NULL; |
422 | fp->_wide_data->_IO_backup_base = NULL; |
423 | } |
424 | libc_hidden_def (_IO_free_wbackup_area) |
425 | |
426 | static int |
427 | save_for_wbackup (FILE *fp, wchar_t *end_p) |
428 | { |
429 | /* Append [_IO_read_base..end_p] to backup area. */ |
430 | ssize_t least_mark = _IO_least_wmarker (fp, end_p); |
431 | /* needed_size is how much space we need in the backup area. */ |
432 | size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base) |
433 | - least_mark); |
434 | /* FIXME: Dubious arithmetic if pointers are NULL */ |
435 | size_t current_Bsize = (fp->_wide_data->_IO_save_end |
436 | - fp->_wide_data->_IO_save_base); |
437 | size_t avail; /* Extra space available for future expansion. */ |
438 | ssize_t delta; |
439 | struct _IO_marker *mark; |
440 | if (needed_size > current_Bsize) |
441 | { |
442 | wchar_t *new_buffer; |
443 | avail = 100; |
444 | new_buffer = (wchar_t *) malloc ((avail + needed_size) |
445 | * sizeof (wchar_t)); |
446 | if (new_buffer == NULL) |
447 | return EOF; /* FIXME */ |
448 | if (least_mark < 0) |
449 | { |
450 | __wmempcpy (__wmempcpy (new_buffer + avail, |
451 | fp->_wide_data->_IO_save_end + least_mark, |
452 | -least_mark), |
453 | fp->_wide_data->_IO_read_base, |
454 | end_p - fp->_wide_data->_IO_read_base); |
455 | } |
456 | else |
457 | { |
458 | __wmemcpy (new_buffer + avail, |
459 | fp->_wide_data->_IO_read_base + least_mark, |
460 | needed_size); |
461 | } |
462 | free (fp->_wide_data->_IO_save_base); |
463 | fp->_wide_data->_IO_save_base = new_buffer; |
464 | fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size; |
465 | } |
466 | else |
467 | { |
468 | avail = current_Bsize - needed_size; |
469 | if (least_mark < 0) |
470 | { |
471 | __wmemmove (fp->_wide_data->_IO_save_base + avail, |
472 | fp->_wide_data->_IO_save_end + least_mark, |
473 | -least_mark); |
474 | __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark, |
475 | fp->_wide_data->_IO_read_base, |
476 | end_p - fp->_wide_data->_IO_read_base); |
477 | } |
478 | else if (needed_size > 0) |
479 | __wmemcpy (fp->_wide_data->_IO_save_base + avail, |
480 | fp->_wide_data->_IO_read_base + least_mark, |
481 | needed_size); |
482 | } |
483 | fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail; |
484 | /* Adjust all the streammarkers. */ |
485 | delta = end_p - fp->_wide_data->_IO_read_base; |
486 | for (mark = fp->_markers; mark != NULL; mark = mark->_next) |
487 | mark->_pos -= delta; |
488 | return 0; |
489 | } |
490 | |
491 | wint_t |
492 | _IO_sputbackwc (FILE *fp, wint_t c) |
493 | { |
494 | wint_t result; |
495 | |
496 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base |
497 | && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c) |
498 | { |
499 | fp->_wide_data->_IO_read_ptr--; |
500 | result = c; |
501 | } |
502 | else |
503 | result = _IO_PBACKFAIL (fp, c); |
504 | |
505 | if (result != WEOF) |
506 | fp->_flags &= ~_IO_EOF_SEEN; |
507 | |
508 | return result; |
509 | } |
510 | libc_hidden_def (_IO_sputbackwc) |
511 | |
512 | wint_t |
513 | _IO_sungetwc (FILE *fp) |
514 | { |
515 | wint_t result; |
516 | |
517 | if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base) |
518 | { |
519 | fp->_wide_data->_IO_read_ptr--; |
520 | result = *fp->_wide_data->_IO_read_ptr; |
521 | } |
522 | else |
523 | result = _IO_PBACKFAIL (fp, EOF); |
524 | |
525 | if (result != WEOF) |
526 | fp->_flags &= ~_IO_EOF_SEEN; |
527 | |
528 | return result; |
529 | } |
530 | |
531 | |
532 | unsigned |
533 | _IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count) |
534 | { |
535 | const wchar_t *ptr = line + count; |
536 | while (ptr > line) |
537 | if (*--ptr == L'\n') |
538 | return line + count - ptr - 1; |
539 | return start + count; |
540 | } |
541 | |
542 | void |
543 | _IO_init_wmarker (struct _IO_marker *marker, FILE *fp) |
544 | { |
545 | marker->_sbuf = fp; |
546 | if (_IO_in_put_mode (fp)) |
547 | _IO_switch_to_wget_mode (fp); |
548 | if (_IO_in_backup (fp)) |
549 | marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; |
550 | else |
551 | marker->_pos = (fp->_wide_data->_IO_read_ptr |
552 | - fp->_wide_data->_IO_read_base); |
553 | |
554 | /* Should perhaps sort the chain? */ |
555 | marker->_next = fp->_markers; |
556 | fp->_markers = marker; |
557 | } |
558 | |
559 | #define BAD_DELTA EOF |
560 | |
561 | /* Return difference between MARK and current position of MARK's stream. */ |
562 | int |
563 | _IO_wmarker_delta (struct _IO_marker *mark) |
564 | { |
565 | int cur_pos; |
566 | if (mark->_sbuf == NULL) |
567 | return BAD_DELTA; |
568 | if (_IO_in_backup (mark->_sbuf)) |
569 | cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr |
570 | - mark->_sbuf->_wide_data->_IO_read_end); |
571 | else |
572 | cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr |
573 | - mark->_sbuf->_wide_data->_IO_read_base); |
574 | return mark->_pos - cur_pos; |
575 | } |
576 | |
577 | int |
578 | _IO_seekwmark (FILE *fp, struct _IO_marker *mark, int delta) |
579 | { |
580 | if (mark->_sbuf != fp) |
581 | return EOF; |
582 | if (mark->_pos >= 0) |
583 | { |
584 | if (_IO_in_backup (fp)) |
585 | _IO_switch_to_main_wget_area (fp); |
586 | fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base |
587 | + mark->_pos); |
588 | } |
589 | else |
590 | { |
591 | if (!_IO_in_backup (fp)) |
592 | _IO_switch_to_wbackup_area (fp); |
593 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos; |
594 | } |
595 | return 0; |
596 | } |
597 | |
598 | void |
599 | _IO_unsave_wmarkers (FILE *fp) |
600 | { |
601 | struct _IO_marker *mark = fp->_markers; |
602 | if (mark) |
603 | { |
604 | fp->_markers = 0; |
605 | } |
606 | |
607 | if (_IO_have_backup (fp)) |
608 | _IO_free_wbackup_area (fp); |
609 | } |
610 | |