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