1 | /* Copyright (C) 1993-2017 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | Written by Ulrich Drepper <drepper@cygnus.com>. |
4 | Based on the single byte version by Per Bothner <bothner@cygnus.com>. |
5 | |
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. |
10 | |
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 |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. |
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. */ |
28 | |
29 | /* Generic or default I/O operations. */ |
30 | |
31 | #include "libioP.h" |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | #include <wchar.h> |
35 | |
36 | |
37 | #ifndef _LIBC |
38 | # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n) |
39 | #endif |
40 | |
41 | |
42 | static int save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) __THROW |
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. */ |
50 | _IO_ssize_t |
51 | _IO_least_wmarker (_IO_FILE *fp, wchar_t *end_p) |
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 | } |
60 | libc_hidden_def (_IO_least_wmarker) |
61 | |
62 | /* Switch current get area from backup buffer to (start of) main get area. */ |
63 | void |
64 | _IO_switch_to_main_wget_area (_IO_FILE *fp) |
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 | } |
79 | libc_hidden_def (_IO_switch_to_main_wget_area) |
80 | |
81 | |
82 | /* Switch current get area from main get area to (end of) backup area. */ |
83 | void |
84 | _IO_switch_to_wbackup_area (_IO_FILE *fp) |
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 | } |
99 | libc_hidden_def (_IO_switch_to_wbackup_area) |
100 | |
101 | |
102 | void |
103 | _IO_wsetb (_IO_FILE *f, wchar_t *b, wchar_t *eb, int a) |
104 | { |
105 | if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF)) |
106 | free (f->_wide_data->_IO_buf_base); |
107 | f->_wide_data->_IO_buf_base = b; |
108 | f->_wide_data->_IO_buf_end = eb; |
109 | if (a) |
110 | f->_flags2 &= ~_IO_FLAGS2_USER_WBUF; |
111 | else |
112 | f->_flags2 |= _IO_FLAGS2_USER_WBUF; |
113 | } |
114 | libc_hidden_def (_IO_wsetb) |
115 | |
116 | |
117 | wint_t |
118 | _IO_wdefault_pbackfail (_IO_FILE *fp, wint_t c) |
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; |
152 | _IO_switch_to_wbackup_area (fp); |
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 | } |
177 | libc_hidden_def (_IO_wdefault_pbackfail) |
178 | |
179 | |
180 | void |
181 | _IO_wdefault_finish (_IO_FILE *fp, int dummy) |
182 | { |
183 | struct _IO_marker *mark; |
184 | if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) |
185 | { |
186 | free (fp->_wide_data->_IO_buf_base); |
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 |
200 | if (fp->_lock != NULL) |
201 | _IO_lock_fini (*fp->_lock); |
202 | #endif |
203 | |
204 | _IO_un_link ((struct _IO_FILE_plus *) fp); |
205 | } |
206 | libc_hidden_def (_IO_wdefault_finish) |
207 | |
208 | |
209 | wint_t |
210 | _IO_wdefault_uflow (_IO_FILE *fp) |
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 | } |
218 | libc_hidden_def (_IO_wdefault_uflow) |
219 | |
220 | |
221 | wint_t |
222 | __woverflow (_IO_FILE *f, wint_t wch) |
223 | { |
224 | if (f->_mode == 0) |
225 | _IO_fwide (f, 1); |
226 | return _IO_OVERFLOW (f, wch); |
227 | } |
228 | libc_hidden_def (__woverflow) |
229 | |
230 | |
231 | wint_t |
232 | __wuflow (_IO_FILE *fp) |
233 | { |
234 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
235 | return WEOF; |
236 | |
237 | if (fp->_mode == 0) |
238 | _IO_fwide (fp, 1); |
239 | if (_IO_in_put_mode (fp)) |
240 | if (_IO_switch_to_wget_mode (fp) == EOF) |
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 | { |
246 | _IO_switch_to_main_wget_area (fp); |
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)) |
256 | _IO_free_wbackup_area (fp); |
257 | return _IO_UFLOW (fp); |
258 | } |
259 | libc_hidden_def (__wuflow) |
260 | |
261 | wint_t |
262 | __wunderflow (_IO_FILE *fp) |
263 | { |
264 | if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) |
265 | return WEOF; |
266 | |
267 | if (fp->_mode == 0) |
268 | _IO_fwide (fp, 1); |
269 | if (_IO_in_put_mode (fp)) |
270 | if (_IO_switch_to_wget_mode (fp) == EOF) |
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 | { |
276 | _IO_switch_to_main_wget_area (fp); |
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)) |
283 | return WEOF; |
284 | } |
285 | else if (_IO_have_backup (fp)) |
286 | _IO_free_wbackup_area (fp); |
287 | return _IO_UNDERFLOW (fp); |
288 | } |
289 | libc_hidden_def (__wunderflow) |
290 | |
291 | |
292 | _IO_size_t |
293 | _IO_wdefault_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) |
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 | } |
337 | libc_hidden_def (_IO_wdefault_xsputn) |
338 | |
339 | |
340 | _IO_size_t |
341 | _IO_wdefault_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) |
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 | } |
381 | libc_hidden_def (_IO_wdefault_xsgetn) |
382 | |
383 | |
384 | void |
385 | _IO_wdoallocbuf (_IO_FILE *fp) |
386 | { |
387 | if (fp->_wide_data->_IO_buf_base) |
388 | return; |
389 | if (!(fp->_flags & _IO_UNBUFFERED)) |
390 | if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF) |
391 | return; |
392 | _IO_wsetb (fp, fp->_wide_data->_shortbuf, |
393 | fp->_wide_data->_shortbuf + 1, 0); |
394 | } |
395 | libc_hidden_def (_IO_wdoallocbuf) |
396 | |
397 | |
398 | int |
399 | _IO_wdefault_doallocate (_IO_FILE *fp) |
400 | { |
401 | wchar_t *buf; |
402 | |
403 | buf = malloc (_IO_BUFSIZ); |
404 | if (__glibc_unlikely (buf == NULL)) |
405 | return EOF; |
406 | _IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1); |
407 | return 1; |
408 | } |
409 | libc_hidden_def (_IO_wdefault_doallocate) |
410 | |
411 | |
412 | int |
413 | _IO_switch_to_wget_mode (_IO_FILE *fp) |
414 | { |
415 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) |
416 | if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF) |
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 | } |
434 | libc_hidden_def (_IO_switch_to_wget_mode) |
435 | |
436 | void |
437 | _IO_free_wbackup_area (_IO_FILE *fp) |
438 | { |
439 | if (_IO_in_backup (fp)) |
440 | _IO_switch_to_main_wget_area (fp); /* Just in case. */ |
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 | } |
446 | libc_hidden_def (_IO_free_wbackup_area) |
447 | |
448 | #if 0 |
449 | int |
450 | _IO_switch_to_wput_mode (_IO_FILE *fp) |
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 | |
468 | static int |
469 | #ifdef _LIBC |
470 | internal_function |
471 | #endif |
472 | save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) |
473 | { |
474 | /* Append [_IO_read_base..end_p] to backup area. */ |
475 | _IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p); |
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 | } |
522 | free (fp->_wide_data->_IO_save_base); |
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 | |
566 | wint_t |
567 | _IO_sputbackwc (_IO_FILE *fp, wint_t c) |
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 | |
580 | if (result != WEOF) |
581 | fp->_flags &= ~_IO_EOF_SEEN; |
582 | |
583 | return result; |
584 | } |
585 | libc_hidden_def (_IO_sputbackwc) |
586 | |
587 | wint_t |
588 | _IO_sungetwc (_IO_FILE *fp) |
589 | { |
590 | wint_t result; |
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 | |
607 | unsigned |
608 | _IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count) |
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 | |
617 | void |
618 | _IO_init_wmarker (struct _IO_marker *marker, _IO_FILE *fp) |
619 | { |
620 | marker->_sbuf = fp; |
621 | if (_IO_in_put_mode (fp)) |
622 | _IO_switch_to_wget_mode (fp); |
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. */ |
637 | int |
638 | _IO_wmarker_delta (struct _IO_marker *mark) |
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 | |
652 | int |
653 | _IO_seekwmark (_IO_FILE *fp, struct _IO_marker *mark, int delta) |
654 | { |
655 | if (mark->_sbuf != fp) |
656 | return EOF; |
657 | if (mark->_pos >= 0) |
658 | { |
659 | if (_IO_in_backup (fp)) |
660 | _IO_switch_to_main_wget_area (fp); |
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)) |
667 | _IO_switch_to_wbackup_area (fp); |
668 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos; |
669 | } |
670 | return 0; |
671 | } |
672 | |
673 | void |
674 | _IO_unsave_wmarkers (_IO_FILE *fp) |
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)) |
697 | _IO_free_wbackup_area (fp); |
698 | } |
699 | |