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