]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/wgenops.c
powerpc: Regenerate ULPs
[thirdparty/glibc.git] / libio / wgenops.c
CommitLineData
bfff8b1b 1/* Copyright (C) 1993-2017 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
PE
17 License along with the GNU C Library; if not, see
18 <http://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
319d719d
UD
37#ifndef _LIBC
38# define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
39#endif
40
d64b6ad0 41
79937577 42static int save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) __THROW
d64b6ad0
UD
43#ifdef _LIBC
44 internal_function
45#endif
46 ;
47
48/* Return minimum _pos markers
49 Assumes the current get area is the main get area. */
d64b6ad0 50_IO_ssize_t
9d46370c 51_IO_least_wmarker (_IO_FILE *fp, wchar_t *end_p)
d64b6ad0
UD
52{
53 _IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base;
54 struct _IO_marker *mark;
55 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
56 if (mark->_pos < least_so_far)
57 least_so_far = mark->_pos;
58 return least_so_far;
59}
d18ea0c5 60libc_hidden_def (_IO_least_wmarker)
d64b6ad0
UD
61
62/* Switch current get area from backup buffer to (start of) main get area. */
63void
9d46370c 64_IO_switch_to_main_wget_area (_IO_FILE *fp)
d64b6ad0
UD
65{
66 wchar_t *tmp;
67 fp->_flags &= ~_IO_IN_BACKUP;
68 /* Swap _IO_read_end and _IO_save_end. */
69 tmp = fp->_wide_data->_IO_read_end;
70 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
71 fp->_wide_data->_IO_save_end= tmp;
72 /* Swap _IO_read_base and _IO_save_base. */
73 tmp = fp->_wide_data->_IO_read_base;
74 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
75 fp->_wide_data->_IO_save_base = tmp;
76 /* Set _IO_read_ptr. */
77 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
78}
d18ea0c5 79libc_hidden_def (_IO_switch_to_main_wget_area)
d64b6ad0
UD
80
81
82/* Switch current get area from main get area to (end of) backup area. */
83void
9d46370c 84_IO_switch_to_wbackup_area (_IO_FILE *fp)
d64b6ad0
UD
85{
86 wchar_t *tmp;
87 fp->_flags |= _IO_IN_BACKUP;
88 /* Swap _IO_read_end and _IO_save_end. */
89 tmp = fp->_wide_data->_IO_read_end;
90 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
91 fp->_wide_data->_IO_save_end = tmp;
92 /* Swap _IO_read_base and _IO_save_base. */
93 tmp = fp->_wide_data->_IO_read_base;
94 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
95 fp->_wide_data->_IO_save_base = tmp;
96 /* Set _IO_read_ptr. */
97 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
98}
d18ea0c5 99libc_hidden_def (_IO_switch_to_wbackup_area)
d64b6ad0
UD
100
101
102void
9d46370c 103_IO_wsetb (_IO_FILE *f, wchar_t *b, wchar_t *eb, int a)
d64b6ad0 104{
1e88bd0f 105 if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF))
8a29509d 106 free (f->_wide_data->_IO_buf_base);
d64b6ad0
UD
107 f->_wide_data->_IO_buf_base = b;
108 f->_wide_data->_IO_buf_end = eb;
109 if (a)
1e88bd0f 110 f->_flags2 &= ~_IO_FLAGS2_USER_WBUF;
d64b6ad0 111 else
1e88bd0f 112 f->_flags2 |= _IO_FLAGS2_USER_WBUF;
d64b6ad0 113}
d18ea0c5 114libc_hidden_def (_IO_wsetb)
d64b6ad0
UD
115
116
117wint_t
9d46370c 118_IO_wdefault_pbackfail (_IO_FILE *fp, wint_t c)
d64b6ad0
UD
119{
120 if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
121 && !_IO_in_backup (fp)
122 && (wint_t) fp->_IO_read_ptr[-1] == c)
123 --fp->_IO_read_ptr;
124 else
125 {
126 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
127 if (!_IO_in_backup (fp))
128 {
129 /* We need to keep the invariant that the main get area
130 logically follows the backup area. */
131 if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
132 && _IO_have_wbackup (fp))
133 {
134 if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr))
135 return WEOF;
136 }
137 else if (!_IO_have_wbackup (fp))
138 {
139 /* No backup buffer: allocate one. */
140 /* Use nshort buffer, if unused? (probably not) FIXME */
141 int backup_size = 128;
142 wchar_t *bbuf = (wchar_t *) malloc (backup_size
143 * sizeof (wchar_t));
144 if (bbuf == NULL)
145 return WEOF;
146 fp->_wide_data->_IO_save_base = bbuf;
147 fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base
148 + backup_size);
149 fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end;
150 }
151 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr;
d18ea0c5 152 _IO_switch_to_wbackup_area (fp);
d64b6ad0
UD
153 }
154 else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base)
155 {
156 /* Increase size of existing backup buffer. */
157 _IO_size_t new_size;
158 _IO_size_t old_size = (fp->_wide_data->_IO_read_end
159 - fp->_wide_data->_IO_read_base);
160 wchar_t *new_buf;
161 new_size = 2 * old_size;
162 new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t));
163 if (new_buf == NULL)
164 return WEOF;
165 __wmemcpy (new_buf + (new_size - old_size),
166 fp->_wide_data->_IO_read_base, old_size);
167 free (fp->_wide_data->_IO_read_base);
168 _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size),
169 new_buf + new_size);
170 fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr;
171 }
172
173 *--fp->_wide_data->_IO_read_ptr = c;
174 }
175 return c;
176}
d18ea0c5 177libc_hidden_def (_IO_wdefault_pbackfail)
d64b6ad0
UD
178
179
180void
9d46370c 181_IO_wdefault_finish (_IO_FILE *fp, int dummy)
d64b6ad0
UD
182{
183 struct _IO_marker *mark;
1e88bd0f 184 if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
d64b6ad0 185 {
8a29509d 186 free (fp->_wide_data->_IO_buf_base);
d64b6ad0
UD
187 fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL;
188 }
189
190 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
191 mark->_sbuf = NULL;
192
193 if (fp->_IO_save_base)
194 {
195 free (fp->_wide_data->_IO_save_base);
196 fp->_IO_save_base = NULL;
197 }
198
199#ifdef _IO_MTSAFE_IO
c020d48c
UD
200 if (fp->_lock != NULL)
201 _IO_lock_fini (*fp->_lock);
d64b6ad0
UD
202#endif
203
d18ea0c5 204 _IO_un_link ((struct _IO_FILE_plus *) fp);
d64b6ad0 205}
d18ea0c5 206libc_hidden_def (_IO_wdefault_finish)
d64b6ad0
UD
207
208
209wint_t
9d46370c 210_IO_wdefault_uflow (_IO_FILE *fp)
d64b6ad0
UD
211{
212 wint_t wch;
213 wch = _IO_UNDERFLOW (fp);
214 if (wch == WEOF)
215 return WEOF;
216 return *fp->_wide_data->_IO_read_ptr++;
217}
d18ea0c5 218libc_hidden_def (_IO_wdefault_uflow)
d64b6ad0
UD
219
220
221wint_t
9d46370c 222__woverflow (_IO_FILE *f, wint_t wch)
d64b6ad0
UD
223{
224 if (f->_mode == 0)
225 _IO_fwide (f, 1);
226 return _IO_OVERFLOW (f, wch);
227}
37ba7d66 228libc_hidden_def (__woverflow)
d64b6ad0
UD
229
230
231wint_t
9d46370c 232__wuflow (_IO_FILE *fp)
d64b6ad0
UD
233{
234 if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
655c0697 235 return WEOF;
d64b6ad0
UD
236
237 if (fp->_mode == 0)
238 _IO_fwide (fp, 1);
239 if (_IO_in_put_mode (fp))
d18ea0c5 240 if (_IO_switch_to_wget_mode (fp) == EOF)
d64b6ad0
UD
241 return WEOF;
242 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
243 return *fp->_wide_data->_IO_read_ptr++;
244 if (_IO_in_backup (fp))
245 {
d18ea0c5 246 _IO_switch_to_main_wget_area (fp);
d64b6ad0
UD
247 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
248 return *fp->_wide_data->_IO_read_ptr++;
249 }
250 if (_IO_have_markers (fp))
251 {
252 if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
253 return WEOF;
254 }
255 else if (_IO_have_wbackup (fp))
d18ea0c5 256 _IO_free_wbackup_area (fp);
d64b6ad0
UD
257 return _IO_UFLOW (fp);
258}
a20d8dbe 259libc_hidden_def (__wuflow)
d64b6ad0
UD
260
261wint_t
9d46370c 262__wunderflow (_IO_FILE *fp)
d64b6ad0
UD
263{
264 if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
655c0697 265 return WEOF;
d64b6ad0 266
6f98fd7e
UD
267 if (fp->_mode == 0)
268 _IO_fwide (fp, 1);
d64b6ad0 269 if (_IO_in_put_mode (fp))
d18ea0c5 270 if (_IO_switch_to_wget_mode (fp) == EOF)
d64b6ad0
UD
271 return WEOF;
272 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
273 return *fp->_wide_data->_IO_read_ptr;
274 if (_IO_in_backup (fp))
275 {
d18ea0c5 276 _IO_switch_to_main_wget_area (fp);
d64b6ad0
UD
277 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
278 return *fp->_wide_data->_IO_read_ptr;
279 }
280 if (_IO_have_markers (fp))
281 {
282 if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
655c0697 283 return WEOF;
d64b6ad0
UD
284 }
285 else if (_IO_have_backup (fp))
d18ea0c5 286 _IO_free_wbackup_area (fp);
d64b6ad0
UD
287 return _IO_UNDERFLOW (fp);
288}
a20d8dbe 289libc_hidden_def (__wunderflow)
d64b6ad0
UD
290
291
292_IO_size_t
9d46370c 293_IO_wdefault_xsputn (_IO_FILE *f, const void *data, _IO_size_t n)
d64b6ad0
UD
294{
295 const wchar_t *s = (const wchar_t *) data;
296 _IO_size_t more = n;
297 if (more <= 0)
298 return 0;
299 for (;;)
300 {
301 /* Space available. */
302 _IO_ssize_t count = (f->_wide_data->_IO_write_end
303 - f->_wide_data->_IO_write_ptr);
304 if (count > 0)
305 {
306 if ((_IO_size_t) count > more)
307 count = more;
308 if (count > 20)
309 {
310#ifdef _LIBC
311 f->_wide_data->_IO_write_ptr =
312 __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
313#else
314 memcpy (f->_wide_data->_IO_write_ptr, s, count);
315 f->_wide_data->_IO_write_ptr += count;
316#endif
317 s += count;
318 }
319 else if (count <= 0)
320 count = 0;
321 else
322 {
323 wchar_t *p = f->_wide_data->_IO_write_ptr;
324 _IO_ssize_t i;
325 for (i = count; --i >= 0; )
326 *p++ = *s++;
327 f->_wide_data->_IO_write_ptr = p;
328 }
329 more -= count;
330 }
331 if (more == 0 || __woverflow (f, *s++) == WEOF)
332 break;
333 more--;
334 }
335 return n - more;
336}
d18ea0c5 337libc_hidden_def (_IO_wdefault_xsputn)
d64b6ad0
UD
338
339
340_IO_size_t
9d46370c 341_IO_wdefault_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n)
d64b6ad0
UD
342{
343 _IO_size_t more = n;
344 wchar_t *s = (wchar_t*) data;
345 for (;;)
346 {
347 /* Data available. */
348 _IO_ssize_t count = (fp->_wide_data->_IO_read_end
349 - fp->_wide_data->_IO_read_ptr);
350 if (count > 0)
351 {
352 if ((_IO_size_t) count > more)
353 count = more;
354 if (count > 20)
355 {
356#ifdef _LIBC
357 s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count);
358#else
359 memcpy (s, fp->_wide_data->_IO_read_ptr, count);
360 s += count;
361#endif
362 fp->_wide_data->_IO_read_ptr += count;
363 }
364 else if (count <= 0)
365 count = 0;
366 else
367 {
368 wchar_t *p = fp->_wide_data->_IO_read_ptr;
369 int i = (int) count;
370 while (--i >= 0)
371 *s++ = *p++;
372 fp->_wide_data->_IO_read_ptr = p;
373 }
374 more -= count;
375 }
376 if (more == 0 || __wunderflow (fp) == WEOF)
377 break;
378 }
379 return n - more;
380}
d18ea0c5 381libc_hidden_def (_IO_wdefault_xsgetn)
d64b6ad0
UD
382
383
384void
9d46370c 385_IO_wdoallocbuf (_IO_FILE *fp)
d64b6ad0
UD
386{
387 if (fp->_wide_data->_IO_buf_base)
388 return;
389 if (!(fp->_flags & _IO_UNBUFFERED))
1dc72e4f 390 if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF)
d64b6ad0 391 return;
d18ea0c5 392 _IO_wsetb (fp, fp->_wide_data->_shortbuf,
77fe0b9c 393 fp->_wide_data->_shortbuf + 1, 0);
d64b6ad0 394}
d18ea0c5 395libc_hidden_def (_IO_wdoallocbuf)
d64b6ad0
UD
396
397
398int
9d46370c 399_IO_wdefault_doallocate (_IO_FILE *fp)
d64b6ad0
UD
400{
401 wchar_t *buf;
402
8a29509d
PP
403 buf = malloc (_IO_BUFSIZ);
404 if (__glibc_unlikely (buf == NULL))
405 return EOF;
d18ea0c5 406 _IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1);
d64b6ad0
UD
407 return 1;
408}
d18ea0c5 409libc_hidden_def (_IO_wdefault_doallocate)
d64b6ad0
UD
410
411
412int
9d46370c 413_IO_switch_to_wget_mode (_IO_FILE *fp)
d64b6ad0
UD
414{
415 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
1dc72e4f 416 if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
d64b6ad0
UD
417 return EOF;
418 if (_IO_in_backup (fp))
419 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base;
420 else
421 {
422 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base;
423 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
424 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
425 }
426 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
427
428 fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
429 = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr;
430
431 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
432 return 0;
433}
d18ea0c5 434libc_hidden_def (_IO_switch_to_wget_mode)
d64b6ad0
UD
435
436void
9d46370c 437_IO_free_wbackup_area (_IO_FILE *fp)
d64b6ad0
UD
438{
439 if (_IO_in_backup (fp))
d18ea0c5 440 _IO_switch_to_main_wget_area (fp); /* Just in case. */
d64b6ad0
UD
441 free (fp->_wide_data->_IO_save_base);
442 fp->_wide_data->_IO_save_base = NULL;
443 fp->_wide_data->_IO_save_end = NULL;
444 fp->_wide_data->_IO_backup_base = NULL;
445}
d18ea0c5 446libc_hidden_def (_IO_free_wbackup_area)
d64b6ad0
UD
447
448#if 0
449int
9d46370c 450_IO_switch_to_wput_mode (_IO_FILE *fp)
d64b6ad0
UD
451{
452 fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr;
453 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
454 /* Following is wrong if line- or un-buffered? */
455 fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
456 ? fp->_wide_data->_IO_read_end
457 : fp->_wide_data->_IO_buf_end);
458
459 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
460 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end;
461
462 fp->_flags |= _IO_CURRENTLY_PUTTING;
463 return 0;
464}
465#endif
466
467
468static int
469#ifdef _LIBC
470internal_function
471#endif
80d9be81 472save_for_wbackup (_IO_FILE *fp, wchar_t *end_p)
d64b6ad0
UD
473{
474 /* Append [_IO_read_base..end_p] to backup area. */
d18ea0c5 475 _IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p);
d64b6ad0
UD
476 /* needed_size is how much space we need in the backup area. */
477 _IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base)
478 - least_mark);
479 /* FIXME: Dubious arithmetic if pointers are NULL */
480 _IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end
481 - fp->_wide_data->_IO_save_base);
482 _IO_size_t avail; /* Extra space available for future expansion. */
483 _IO_ssize_t delta;
484 struct _IO_marker *mark;
485 if (needed_size > current_Bsize)
486 {
487 wchar_t *new_buffer;
488 avail = 100;
489 new_buffer = (wchar_t *) malloc ((avail + needed_size)
490 * sizeof (wchar_t));
491 if (new_buffer == NULL)
492 return EOF; /* FIXME */
493 if (least_mark < 0)
494 {
495#ifdef _LIBC
496 __wmempcpy (__wmempcpy (new_buffer + avail,
497 fp->_wide_data->_IO_save_end + least_mark,
498 -least_mark),
499 fp->_wide_data->_IO_read_base,
500 end_p - fp->_wide_data->_IO_read_base);
501#else
502 memcpy (new_buffer + avail,
503 fp->_wide_data->_IO_save_end + least_mark,
504 -least_mark * sizeof (wchar_t));
505 memcpy (new_buffer + avail - least_mark,
506 fp->_wide_data->_IO_read_base,
507 (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
508#endif
509 }
510 else
511 {
512#ifdef _LIBC
513 __wmemcpy (new_buffer + avail,
514 fp->_wide_data->_IO_read_base + least_mark,
515 needed_size);
516#else
517 memcpy (new_buffer + avail,
518 fp->_wide_data->_IO_read_base + least_mark,
519 needed_size * sizeof (wchar_t));
520#endif
521 }
72e6cdfa 522 free (fp->_wide_data->_IO_save_base);
d64b6ad0
UD
523 fp->_wide_data->_IO_save_base = new_buffer;
524 fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size;
525 }
526 else
527 {
528 avail = current_Bsize - needed_size;
529 if (least_mark < 0)
530 {
531#ifdef _LIBC
532 __wmemmove (fp->_wide_data->_IO_save_base + avail,
533 fp->_wide_data->_IO_save_end + least_mark,
534 -least_mark);
535 __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
536 fp->_wide_data->_IO_read_base,
537 end_p - fp->_wide_data->_IO_read_base);
538#else
539 memmove (fp->_wide_data->_IO_save_base + avail,
540 fp->_wide_data->_IO_save_end + least_mark,
541 -least_mark * sizeof (wchar_t));
542 memcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
543 fp->_wide_data->_IO_read_base,
544 (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
545#endif
546 }
547 else if (needed_size > 0)
548#ifdef _LIBC
549 __wmemcpy (fp->_wide_data->_IO_save_base + avail,
550 fp->_wide_data->_IO_read_base + least_mark,
551 needed_size);
552#else
553 memcpy (fp->_wide_data->_IO_save_base + avail,
554 fp->_wide_data->_IO_read_base + least_mark,
555 needed_size * sizeof (wchar_t));
556#endif
557 }
558 fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail;
559 /* Adjust all the streammarkers. */
560 delta = end_p - fp->_wide_data->_IO_read_base;
561 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
562 mark->_pos -= delta;
563 return 0;
564}
565
566wint_t
9d46370c 567_IO_sputbackwc (_IO_FILE *fp, wint_t c)
d64b6ad0
UD
568{
569 wint_t result;
570
571 if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
572 && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c)
573 {
574 fp->_wide_data->_IO_read_ptr--;
575 result = c;
576 }
577 else
578 result = _IO_PBACKFAIL (fp, c);
579
1dc72e4f 580 if (result != WEOF)
d64b6ad0
UD
581 fp->_flags &= ~_IO_EOF_SEEN;
582
583 return result;
584}
d18ea0c5 585libc_hidden_def (_IO_sputbackwc)
d64b6ad0
UD
586
587wint_t
9d46370c 588_IO_sungetwc (_IO_FILE *fp)
d64b6ad0 589{
1dc72e4f 590 wint_t result;
d64b6ad0
UD
591
592 if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base)
593 {
594 fp->_wide_data->_IO_read_ptr--;
595 result = *fp->_wide_data->_IO_read_ptr;
596 }
597 else
598 result = _IO_PBACKFAIL (fp, EOF);
599
600 if (result != WEOF)
601 fp->_flags &= ~_IO_EOF_SEEN;
602
603 return result;
604}
605
606
607unsigned
9d46370c 608_IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count)
d64b6ad0
UD
609{
610 const wchar_t *ptr = line + count;
611 while (ptr > line)
612 if (*--ptr == L'\n')
613 return line + count - ptr - 1;
614 return start + count;
615}
616
617void
9d46370c 618_IO_init_wmarker (struct _IO_marker *marker, _IO_FILE *fp)
d64b6ad0
UD
619{
620 marker->_sbuf = fp;
621 if (_IO_in_put_mode (fp))
d18ea0c5 622 _IO_switch_to_wget_mode (fp);
d64b6ad0
UD
623 if (_IO_in_backup (fp))
624 marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
625 else
626 marker->_pos = (fp->_wide_data->_IO_read_ptr
627 - fp->_wide_data->_IO_read_base);
628
629 /* Should perhaps sort the chain? */
630 marker->_next = fp->_markers;
631 fp->_markers = marker;
632}
633
634#define BAD_DELTA EOF
635
636/* Return difference between MARK and current position of MARK's stream. */
637int
9d46370c 638_IO_wmarker_delta (struct _IO_marker *mark)
d64b6ad0
UD
639{
640 int cur_pos;
641 if (mark->_sbuf == NULL)
642 return BAD_DELTA;
643 if (_IO_in_backup (mark->_sbuf))
644 cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
645 - mark->_sbuf->_wide_data->_IO_read_end);
646 else
647 cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
648 - mark->_sbuf->_wide_data->_IO_read_base);
649 return mark->_pos - cur_pos;
650}
651
652int
9d46370c 653_IO_seekwmark (_IO_FILE *fp, struct _IO_marker *mark, int delta)
d64b6ad0
UD
654{
655 if (mark->_sbuf != fp)
656 return EOF;
657 if (mark->_pos >= 0)
658 {
659 if (_IO_in_backup (fp))
d18ea0c5 660 _IO_switch_to_main_wget_area (fp);
d64b6ad0
UD
661 fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
662 + mark->_pos);
663 }
664 else
665 {
666 if (!_IO_in_backup (fp))
d18ea0c5 667 _IO_switch_to_wbackup_area (fp);
d64b6ad0
UD
668 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos;
669 }
670 return 0;
671}
672
673void
9d46370c 674_IO_unsave_wmarkers (_IO_FILE *fp)
d64b6ad0
UD
675{
676 struct _IO_marker *mark = fp->_markers;
677 if (mark)
678 {
679#ifdef TODO
680 streampos offset = seekoff (0, ios::cur, ios::in);
681 if (offset != EOF)
682 {
683 offset += eGptr () - Gbase ();
684 for ( ; mark != NULL; mark = mark->_next)
685 mark->set_streampos (mark->_pos + offset);
686 }
687 else
688 {
689 for ( ; mark != NULL; mark = mark->_next)
690 mark->set_streampos (EOF);
691 }
692#endif
693 fp->_markers = 0;
694 }
695
696 if (_IO_have_backup (fp))
d18ea0c5 697 _IO_free_wbackup_area (fp);
d64b6ad0 698}