Blame libio/wgenops.c

Packit Service 82fcde
/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Written by Ulrich Drepper <drepper@cygnus.com>.
Packit Service 82fcde
   Based on the single byte version by Per Bothner <bothner@cygnus.com>.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.
Packit Service 82fcde
Packit Service 82fcde
   As a special exception, if you link the code in this file with
Packit Service 82fcde
   files compiled with a GNU compiler to produce an executable,
Packit Service 82fcde
   that does not cause the resulting executable to be covered by
Packit Service 82fcde
   the GNU Lesser General Public License.  This exception does not
Packit Service 82fcde
   however invalidate any other reasons why the executable file
Packit Service 82fcde
   might be covered by the GNU Lesser General Public License.
Packit Service 82fcde
   This exception applies to code released by its copyright holders
Packit Service 82fcde
   in files containing the exception.  */
Packit Service 82fcde
Packit Service 82fcde
/* Generic or default I/O operations. */
Packit Service 82fcde
Packit Service 82fcde
#include "libioP.h"
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <wchar.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int save_for_wbackup (FILE *fp, wchar_t *end_p) __THROW;
Packit Service 82fcde
Packit Service 82fcde
/* Return minimum _pos markers
Packit Service 82fcde
   Assumes the current get area is the main get area. */
Packit Service 82fcde
ssize_t
Packit Service 82fcde
_IO_least_wmarker (FILE *fp, wchar_t *end_p)
Packit Service 82fcde
{
Packit Service 82fcde
  ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base;
Packit Service 82fcde
  struct _IO_marker *mark;
Packit Service 82fcde
  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
Packit Service 82fcde
    if (mark->_pos < least_so_far)
Packit Service 82fcde
      least_so_far = mark->_pos;
Packit Service 82fcde
  return least_so_far;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_least_wmarker)
Packit Service 82fcde
Packit Service 82fcde
/* Switch current get area from backup buffer to (start of) main get area. */
Packit Service 82fcde
void
Packit Service 82fcde
_IO_switch_to_main_wget_area (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  wchar_t *tmp;
Packit Service 82fcde
  fp->_flags &= ~_IO_IN_BACKUP;
Packit Service 82fcde
  /* Swap _IO_read_end and _IO_save_end. */
Packit Service 82fcde
  tmp = fp->_wide_data->_IO_read_end;
Packit Service 82fcde
  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
Packit Service 82fcde
  fp->_wide_data->_IO_save_end= tmp;
Packit Service 82fcde
  /* Swap _IO_read_base and _IO_save_base. */
Packit Service 82fcde
  tmp = fp->_wide_data->_IO_read_base;
Packit Service 82fcde
  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
Packit Service 82fcde
  fp->_wide_data->_IO_save_base = tmp;
Packit Service 82fcde
  /* Set _IO_read_ptr. */
Packit Service 82fcde
  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_switch_to_main_wget_area)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Switch current get area from main get area to (end of) backup area. */
Packit Service 82fcde
void
Packit Service 82fcde
_IO_switch_to_wbackup_area (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  wchar_t *tmp;
Packit Service 82fcde
  fp->_flags |= _IO_IN_BACKUP;
Packit Service 82fcde
  /* Swap _IO_read_end and _IO_save_end. */
Packit Service 82fcde
  tmp = fp->_wide_data->_IO_read_end;
Packit Service 82fcde
  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
Packit Service 82fcde
  fp->_wide_data->_IO_save_end = tmp;
Packit Service 82fcde
  /* Swap _IO_read_base and _IO_save_base. */
Packit Service 82fcde
  tmp = fp->_wide_data->_IO_read_base;
Packit Service 82fcde
  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
Packit Service 82fcde
  fp->_wide_data->_IO_save_base = tmp;
Packit Service 82fcde
  /* Set _IO_read_ptr.  */
Packit Service 82fcde
  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_switch_to_wbackup_area)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_wsetb (FILE *f, wchar_t *b, wchar_t *eb, int a)
Packit Service 82fcde
{
Packit Service 82fcde
  if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF))
Packit Service 82fcde
    free (f->_wide_data->_IO_buf_base);
Packit Service 82fcde
  f->_wide_data->_IO_buf_base = b;
Packit Service 82fcde
  f->_wide_data->_IO_buf_end = eb;
Packit Service 82fcde
  if (a)
Packit Service 82fcde
    f->_flags2 &= ~_IO_FLAGS2_USER_WBUF;
Packit Service 82fcde
  else
Packit Service 82fcde
    f->_flags2 |= _IO_FLAGS2_USER_WBUF;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wsetb)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
_IO_wdefault_pbackfail (FILE *fp, wint_t c)
Packit Service 82fcde
{
Packit Service 82fcde
  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
Packit Service 82fcde
      && !_IO_in_backup (fp)
Packit Service 82fcde
      && (wint_t) fp->_IO_read_ptr[-1] == c)
Packit Service 82fcde
    --fp->_IO_read_ptr;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
Packit Service 82fcde
      if (!_IO_in_backup (fp))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We need to keep the invariant that the main get area
Packit Service 82fcde
	     logically follows the backup area.  */
Packit Service 82fcde
	  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
Packit Service 82fcde
	      && _IO_have_wbackup (fp))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr))
Packit Service 82fcde
		return WEOF;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else if (!_IO_have_wbackup (fp))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* No backup buffer: allocate one. */
Packit Service 82fcde
	      /* Use nshort buffer, if unused? (probably not)  FIXME */
Packit Service 82fcde
	      int backup_size = 128;
Packit Service 82fcde
	      wchar_t *bbuf = (wchar_t *) malloc (backup_size
Packit Service 82fcde
						  * sizeof (wchar_t));
Packit Service 82fcde
	      if (bbuf == NULL)
Packit Service 82fcde
		return WEOF;
Packit Service 82fcde
	      fp->_wide_data->_IO_save_base = bbuf;
Packit Service 82fcde
	      fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base
Packit Service 82fcde
					      + backup_size);
Packit Service 82fcde
	      fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
	  _IO_switch_to_wbackup_area (fp);
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Increase size of existing backup buffer. */
Packit Service 82fcde
	  size_t new_size;
Packit Service 82fcde
	  size_t old_size = (fp->_wide_data->_IO_read_end
Packit Service 82fcde
                             - fp->_wide_data->_IO_read_base);
Packit Service 82fcde
	  wchar_t *new_buf;
Packit Service 82fcde
	  new_size = 2 * old_size;
Packit Service 82fcde
	  new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t));
Packit Service 82fcde
	  if (new_buf == NULL)
Packit Service 82fcde
	    return WEOF;
Packit Service 82fcde
	  __wmemcpy (new_buf + (new_size - old_size),
Packit Service 82fcde
		     fp->_wide_data->_IO_read_base, old_size);
Packit Service 82fcde
	  free (fp->_wide_data->_IO_read_base);
Packit Service 82fcde
	  _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size),
Packit Service 82fcde
		     new_buf + new_size);
Packit Service 82fcde
	  fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      *--fp->_wide_data->_IO_read_ptr = c;
Packit Service 82fcde
    }
Packit Service 82fcde
  return c;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_pbackfail)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_wdefault_finish (FILE *fp, int dummy)
Packit Service 82fcde
{
Packit Service 82fcde
  struct _IO_marker *mark;
Packit Service 82fcde
  if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
Packit Service 82fcde
    {
Packit Service 82fcde
      free (fp->_wide_data->_IO_buf_base);
Packit Service 82fcde
      fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
Packit Service 82fcde
    mark->_sbuf = NULL;
Packit Service 82fcde
Packit Service 82fcde
  if (fp->_IO_save_base)
Packit Service 82fcde
    {
Packit Service 82fcde
      free (fp->_wide_data->_IO_save_base);
Packit Service 82fcde
      fp->_IO_save_base = NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
#ifdef _IO_MTSAFE_IO
Packit Service 82fcde
  if (fp->_lock != NULL)
Packit Service 82fcde
    _IO_lock_fini (*fp->_lock);
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  _IO_un_link ((struct _IO_FILE_plus *) fp);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_finish)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
_IO_wdefault_uflow (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  wint_t wch;
Packit Service 82fcde
  wch = _IO_UNDERFLOW (fp);
Packit Service 82fcde
  if (wch == WEOF)
Packit Service 82fcde
    return WEOF;
Packit Service 82fcde
  return *fp->_wide_data->_IO_read_ptr++;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_uflow)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
__woverflow (FILE *f, wint_t wch)
Packit Service 82fcde
{
Packit Service 82fcde
  if (f->_mode == 0)
Packit Service 82fcde
    _IO_fwide (f, 1);
Packit Service 82fcde
  return _IO_OVERFLOW (f, wch);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__woverflow)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
__wuflow (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
Packit Service 82fcde
    return WEOF;
Packit Service 82fcde
Packit Service 82fcde
  if (fp->_mode == 0)
Packit Service 82fcde
    _IO_fwide (fp, 1);
Packit Service 82fcde
  if (_IO_in_put_mode (fp))
Packit Service 82fcde
    if (_IO_switch_to_wget_mode (fp) == EOF)
Packit Service 82fcde
      return WEOF;
Packit Service 82fcde
  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
Packit Service 82fcde
    return *fp->_wide_data->_IO_read_ptr++;
Packit Service 82fcde
  if (_IO_in_backup (fp))
Packit Service 82fcde
    {
Packit Service 82fcde
      _IO_switch_to_main_wget_area (fp);
Packit Service 82fcde
      if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
Packit Service 82fcde
	return *fp->_wide_data->_IO_read_ptr++;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (_IO_have_markers (fp))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
Packit Service 82fcde
	return WEOF;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (_IO_have_wbackup (fp))
Packit Service 82fcde
    _IO_free_wbackup_area (fp);
Packit Service 82fcde
  return _IO_UFLOW (fp);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__wuflow)
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
__wunderflow (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
Packit Service 82fcde
    return WEOF;
Packit Service 82fcde
Packit Service 82fcde
  if (fp->_mode == 0)
Packit Service 82fcde
    _IO_fwide (fp, 1);
Packit Service 82fcde
  if (_IO_in_put_mode (fp))
Packit Service 82fcde
    if (_IO_switch_to_wget_mode (fp) == EOF)
Packit Service 82fcde
      return WEOF;
Packit Service 82fcde
  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
Packit Service 82fcde
    return *fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
  if (_IO_in_backup (fp))
Packit Service 82fcde
    {
Packit Service 82fcde
      _IO_switch_to_main_wget_area (fp);
Packit Service 82fcde
      if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
Packit Service 82fcde
	return *fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (_IO_have_markers (fp))
Packit Service 82fcde
    {
Packit Service 82fcde
      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
Packit Service 82fcde
	return WEOF;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (_IO_have_backup (fp))
Packit Service 82fcde
    _IO_free_wbackup_area (fp);
Packit Service 82fcde
  return _IO_UNDERFLOW (fp);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__wunderflow)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
size_t
Packit Service 82fcde
_IO_wdefault_xsputn (FILE *f, const void *data, size_t n)
Packit Service 82fcde
{
Packit Service 82fcde
  const wchar_t *s = (const wchar_t *) data;
Packit Service 82fcde
  size_t more = n;
Packit Service 82fcde
  if (more <= 0)
Packit Service 82fcde
    return 0;
Packit Service 82fcde
  for (;;)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Space available. */
Packit Service 82fcde
      ssize_t count = (f->_wide_data->_IO_write_end
Packit Service 82fcde
                       - f->_wide_data->_IO_write_ptr);
Packit Service 82fcde
      if (count > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if ((size_t) count > more)
Packit Service 82fcde
	    count = more;
Packit Service 82fcde
	  if (count > 20)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      f->_wide_data->_IO_write_ptr =
Packit Service 82fcde
		__wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
Packit Service 82fcde
	      s += count;
Packit Service 82fcde
            }
Packit Service 82fcde
	  else if (count <= 0)
Packit Service 82fcde
	    count = 0;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      wchar_t *p = f->_wide_data->_IO_write_ptr;
Packit Service 82fcde
	      ssize_t i;
Packit Service 82fcde
	      for (i = count; --i >= 0; )
Packit Service 82fcde
		*p++ = *s++;
Packit Service 82fcde
	      f->_wide_data->_IO_write_ptr = p;
Packit Service 82fcde
            }
Packit Service 82fcde
	  more -= count;
Packit Service 82fcde
        }
Packit Service 82fcde
      if (more == 0 || __woverflow (f, *s++) == WEOF)
Packit Service 82fcde
	break;
Packit Service 82fcde
      more--;
Packit Service 82fcde
    }
Packit Service 82fcde
  return n - more;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_xsputn)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
size_t
Packit Service 82fcde
_IO_wdefault_xsgetn (FILE *fp, void *data, size_t n)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t more = n;
Packit Service 82fcde
  wchar_t *s = (wchar_t*) data;
Packit Service 82fcde
  for (;;)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Data available. */
Packit Service 82fcde
      ssize_t count = (fp->_wide_data->_IO_read_end
Packit Service 82fcde
                       - fp->_wide_data->_IO_read_ptr);
Packit Service 82fcde
      if (count > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if ((size_t) count > more)
Packit Service 82fcde
	    count = more;
Packit Service 82fcde
	  if (count > 20)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count);
Packit Service 82fcde
	      fp->_wide_data->_IO_read_ptr += count;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else if (count <= 0)
Packit Service 82fcde
	    count = 0;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      wchar_t *p = fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
	      int i = (int) count;
Packit Service 82fcde
	      while (--i >= 0)
Packit Service 82fcde
		*s++ = *p++;
Packit Service 82fcde
	      fp->_wide_data->_IO_read_ptr = p;
Packit Service 82fcde
            }
Packit Service 82fcde
            more -= count;
Packit Service 82fcde
        }
Packit Service 82fcde
      if (more == 0 || __wunderflow (fp) == WEOF)
Packit Service 82fcde
	break;
Packit Service 82fcde
    }
Packit Service 82fcde
  return n - more;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_xsgetn)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_wdoallocbuf (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  if (fp->_wide_data->_IO_buf_base)
Packit Service 82fcde
    return;
Packit Service 82fcde
  if (!(fp->_flags & _IO_UNBUFFERED))
Packit Service 82fcde
    if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF)
Packit Service 82fcde
      return;
Packit Service 82fcde
  _IO_wsetb (fp, fp->_wide_data->_shortbuf,
Packit Service 82fcde
		     fp->_wide_data->_shortbuf + 1, 0);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdoallocbuf)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
_IO_wdefault_doallocate (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  wchar_t *buf;
Packit Service 82fcde
Packit Service 82fcde
  buf = malloc (BUFSIZ);
Packit Service 82fcde
  if (__glibc_unlikely (buf == NULL))
Packit Service 82fcde
    return EOF;
Packit Service 82fcde
  _IO_wsetb (fp, buf, buf + BUFSIZ, 1);
Packit Service 82fcde
  return 1;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_wdefault_doallocate)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
_IO_switch_to_wget_mode (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
Packit Service 82fcde
    if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
Packit Service 82fcde
      return EOF;
Packit Service 82fcde
  if (_IO_in_backup (fp))
Packit Service 82fcde
    fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base;
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base;
Packit Service 82fcde
      if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
Packit Service 82fcde
	fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
Packit Service 82fcde
    }
Packit Service 82fcde
  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
Packit Service 82fcde
Packit Service 82fcde
  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
Packit Service 82fcde
    = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
Packit Service 82fcde
  fp->_flags &= ~_IO_CURRENTLY_PUTTING;
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_switch_to_wget_mode)
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_free_wbackup_area (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  if (_IO_in_backup (fp))
Packit Service 82fcde
    _IO_switch_to_main_wget_area (fp);  /* Just in case. */
Packit Service 82fcde
  free (fp->_wide_data->_IO_save_base);
Packit Service 82fcde
  fp->_wide_data->_IO_save_base = NULL;
Packit Service 82fcde
  fp->_wide_data->_IO_save_end = NULL;
Packit Service 82fcde
  fp->_wide_data->_IO_backup_base = NULL;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_free_wbackup_area)
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
save_for_wbackup (FILE *fp, wchar_t *end_p)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Append [_IO_read_base..end_p] to backup area. */
Packit Service 82fcde
  ssize_t least_mark = _IO_least_wmarker (fp, end_p);
Packit Service 82fcde
  /* needed_size is how much space we need in the backup area. */
Packit Service 82fcde
  size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base)
Packit Service 82fcde
                        - least_mark);
Packit Service 82fcde
  /* FIXME: Dubious arithmetic if pointers are NULL */
Packit Service 82fcde
  size_t current_Bsize = (fp->_wide_data->_IO_save_end
Packit Service 82fcde
                          - fp->_wide_data->_IO_save_base);
Packit Service 82fcde
  size_t avail; /* Extra space available for future expansion. */
Packit Service 82fcde
  ssize_t delta;
Packit Service 82fcde
  struct _IO_marker *mark;
Packit Service 82fcde
  if (needed_size > current_Bsize)
Packit Service 82fcde
    {
Packit Service 82fcde
      wchar_t *new_buffer;
Packit Service 82fcde
      avail = 100;
Packit Service 82fcde
      new_buffer = (wchar_t *) malloc ((avail + needed_size)
Packit Service 82fcde
				       * sizeof (wchar_t));
Packit Service 82fcde
      if (new_buffer == NULL)
Packit Service 82fcde
	return EOF;		/* FIXME */
Packit Service 82fcde
      if (least_mark < 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  __wmempcpy (__wmempcpy (new_buffer + avail,
Packit Service 82fcde
				  fp->_wide_data->_IO_save_end + least_mark,
Packit Service 82fcde
				  -least_mark),
Packit Service 82fcde
		      fp->_wide_data->_IO_read_base,
Packit Service 82fcde
		      end_p - fp->_wide_data->_IO_read_base);
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  __wmemcpy (new_buffer + avail,
Packit Service 82fcde
		     fp->_wide_data->_IO_read_base + least_mark,
Packit Service 82fcde
		     needed_size);
Packit Service 82fcde
	}
Packit Service 82fcde
      free (fp->_wide_data->_IO_save_base);
Packit Service 82fcde
      fp->_wide_data->_IO_save_base = new_buffer;
Packit Service 82fcde
      fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      avail = current_Bsize - needed_size;
Packit Service 82fcde
      if (least_mark < 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  __wmemmove (fp->_wide_data->_IO_save_base + avail,
Packit Service 82fcde
		      fp->_wide_data->_IO_save_end + least_mark,
Packit Service 82fcde
		      -least_mark);
Packit Service 82fcde
	  __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
Packit Service 82fcde
		     fp->_wide_data->_IO_read_base,
Packit Service 82fcde
		     end_p - fp->_wide_data->_IO_read_base);
Packit Service 82fcde
	}
Packit Service 82fcde
      else if (needed_size > 0)
Packit Service 82fcde
	__wmemcpy (fp->_wide_data->_IO_save_base + avail,
Packit Service 82fcde
		   fp->_wide_data->_IO_read_base + least_mark,
Packit Service 82fcde
		   needed_size);
Packit Service 82fcde
    }
Packit Service 82fcde
  fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail;
Packit Service 82fcde
  /* Adjust all the streammarkers. */
Packit Service 82fcde
  delta = end_p - fp->_wide_data->_IO_read_base;
Packit Service 82fcde
  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
Packit Service 82fcde
    mark->_pos -= delta;
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
_IO_sputbackwc (FILE *fp, wint_t c)
Packit Service 82fcde
{
Packit Service 82fcde
  wint_t result;
Packit Service 82fcde
Packit Service 82fcde
  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
Packit Service 82fcde
      && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c)
Packit Service 82fcde
    {
Packit Service 82fcde
      fp->_wide_data->_IO_read_ptr--;
Packit Service 82fcde
      result = c;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    result = _IO_PBACKFAIL (fp, c);
Packit Service 82fcde
Packit Service 82fcde
  if (result != WEOF)
Packit Service 82fcde
    fp->_flags &= ~_IO_EOF_SEEN;
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_IO_sputbackwc)
Packit Service 82fcde
Packit Service 82fcde
wint_t
Packit Service 82fcde
_IO_sungetwc (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  wint_t result;
Packit Service 82fcde
Packit Service 82fcde
  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base)
Packit Service 82fcde
    {
Packit Service 82fcde
      fp->_wide_data->_IO_read_ptr--;
Packit Service 82fcde
      result = *fp->_wide_data->_IO_read_ptr;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    result = _IO_PBACKFAIL (fp, EOF);
Packit Service 82fcde
Packit Service 82fcde
  if (result != WEOF)
Packit Service 82fcde
    fp->_flags &= ~_IO_EOF_SEEN;
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
unsigned
Packit Service 82fcde
_IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count)
Packit Service 82fcde
{
Packit Service 82fcde
  const wchar_t *ptr = line + count;
Packit Service 82fcde
  while (ptr > line)
Packit Service 82fcde
    if (*--ptr == L'\n')
Packit Service 82fcde
      return line + count - ptr - 1;
Packit Service 82fcde
  return start + count;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_init_wmarker (struct _IO_marker *marker, FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  marker->_sbuf = fp;
Packit Service 82fcde
  if (_IO_in_put_mode (fp))
Packit Service 82fcde
    _IO_switch_to_wget_mode (fp);
Packit Service 82fcde
  if (_IO_in_backup (fp))
Packit Service 82fcde
    marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
Packit Service 82fcde
  else
Packit Service 82fcde
    marker->_pos = (fp->_wide_data->_IO_read_ptr
Packit Service 82fcde
		    - fp->_wide_data->_IO_read_base);
Packit Service 82fcde
Packit Service 82fcde
  /* Should perhaps sort the chain? */
Packit Service 82fcde
  marker->_next = fp->_markers;
Packit Service 82fcde
  fp->_markers = marker;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define BAD_DELTA EOF
Packit Service 82fcde
Packit Service 82fcde
/* Return difference between MARK and current position of MARK's stream. */
Packit Service 82fcde
int
Packit Service 82fcde
_IO_wmarker_delta (struct _IO_marker *mark)
Packit Service 82fcde
{
Packit Service 82fcde
  int cur_pos;
Packit Service 82fcde
  if (mark->_sbuf == NULL)
Packit Service 82fcde
    return BAD_DELTA;
Packit Service 82fcde
  if (_IO_in_backup (mark->_sbuf))
Packit Service 82fcde
    cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
Packit Service 82fcde
	       - mark->_sbuf->_wide_data->_IO_read_end);
Packit Service 82fcde
  else
Packit Service 82fcde
    cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
Packit Service 82fcde
	       - mark->_sbuf->_wide_data->_IO_read_base);
Packit Service 82fcde
  return mark->_pos - cur_pos;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
_IO_seekwmark (FILE *fp, struct _IO_marker *mark, int delta)
Packit Service 82fcde
{
Packit Service 82fcde
  if (mark->_sbuf != fp)
Packit Service 82fcde
    return EOF;
Packit Service 82fcde
 if (mark->_pos >= 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (_IO_in_backup (fp))
Packit Service 82fcde
	_IO_switch_to_main_wget_area (fp);
Packit Service 82fcde
      fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
Packit Service 82fcde
				      + mark->_pos);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      if (!_IO_in_backup (fp))
Packit Service 82fcde
	_IO_switch_to_wbackup_area (fp);
Packit Service 82fcde
      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos;
Packit Service 82fcde
    }
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_IO_unsave_wmarkers (FILE *fp)
Packit Service 82fcde
{
Packit Service 82fcde
  struct _IO_marker *mark = fp->_markers;
Packit Service 82fcde
  if (mark)
Packit Service 82fcde
    {
Packit Service 82fcde
      fp->_markers = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (_IO_have_backup (fp))
Packit Service 82fcde
    _IO_free_wbackup_area (fp);
Packit Service 82fcde
}