]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 1993-2019 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 | ||
9964a145 | 37 | static 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 |
41 | ssize_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 | 51 | libc_hidden_def (_IO_least_wmarker) |
d64b6ad0 UD |
52 | |
53 | /* Switch current get area from backup buffer to (start of) main get area. */ | |
54 | void | |
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 | 70 | libc_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. */ | |
74 | void | |
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 | 90 | libc_hidden_def (_IO_switch_to_wbackup_area) |
d64b6ad0 UD |
91 | |
92 | ||
93 | void | |
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 | 105 | libc_hidden_def (_IO_wsetb) |
d64b6ad0 UD |
106 | |
107 | ||
108 | wint_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 | 168 | libc_hidden_def (_IO_wdefault_pbackfail) |
d64b6ad0 UD |
169 | |
170 | ||
171 | void | |
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 | 197 | libc_hidden_def (_IO_wdefault_finish) |
d64b6ad0 UD |
198 | |
199 | ||
200 | wint_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 | 209 | libc_hidden_def (_IO_wdefault_uflow) |
d64b6ad0 UD |
210 | |
211 | ||
212 | wint_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 | 219 | libc_hidden_def (__woverflow) |
d64b6ad0 UD |
220 | |
221 | ||
222 | wint_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 | 250 | libc_hidden_def (__wuflow) |
d64b6ad0 UD |
251 | |
252 | wint_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 | 280 | libc_hidden_def (__wunderflow) |
d64b6ad0 UD |
281 | |
282 | ||
9964a145 ZW |
283 | size_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 | 323 | libc_hidden_def (_IO_wdefault_xsputn) |
d64b6ad0 UD |
324 | |
325 | ||
9964a145 ZW |
326 | size_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 | 362 | libc_hidden_def (_IO_wdefault_xsgetn) |
d64b6ad0 UD |
363 | |
364 | ||
365 | void | |
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 | 376 | libc_hidden_def (_IO_wdoallocbuf) |
d64b6ad0 UD |
377 | |
378 | ||
379 | int | |
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 | 390 | libc_hidden_def (_IO_wdefault_doallocate) |
d64b6ad0 UD |
391 | |
392 | ||
393 | int | |
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 | 415 | libc_hidden_def (_IO_switch_to_wget_mode) |
d64b6ad0 UD |
416 | |
417 | void | |
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 | 427 | libc_hidden_def (_IO_free_wbackup_area) |
d64b6ad0 | 428 | |
d64b6ad0 | 429 | static int |
9964a145 | 430 | save_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 | ||
494 | wint_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 | 513 | libc_hidden_def (_IO_sputbackwc) |
d64b6ad0 UD |
514 | |
515 | wint_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 | ||
535 | unsigned | |
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 | ||
545 | void | |
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. */ | |
565 | int | |
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 | ||
580 | int | |
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 | ||
601 | void | |
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 | } |