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