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