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