about summary refs log tree commit diff
path: root/libio
diff options
context:
space:
mode:
Diffstat (limited to 'libio')
-rw-r--r--libio/Makefile9
-rw-r--r--libio/Versions27
-rw-r--r--libio/fileops.c60
-rw-r--r--libio/fputwc.c45
-rw-r--r--libio/fputwc_u.c40
-rw-r--r--libio/ftello.c14
-rw-r--r--libio/ftello64.c13
-rw-r--r--libio/fwprintf.c36
-rw-r--r--libio/fwscanf.c35
-rw-r--r--libio/genops.c53
-rw-r--r--libio/getwc.c50
-rw-r--r--libio/getwc_u.c39
-rw-r--r--libio/getwchar.c42
-rw-r--r--libio/getwchar_u.c35
-rw-r--r--libio/iofdopen.c5
-rw-r--r--libio/iofgetpos.c16
-rw-r--r--libio/iofgetpos64.c20
-rw-r--r--libio/iofgetws.c63
-rw-r--r--libio/iofgetws_u.c59
-rw-r--r--libio/iofopen.c3
-rw-r--r--libio/iofopen64.c3
-rw-r--r--libio/iofopncook.c6
-rw-r--r--libio/iofputs.c9
-rw-r--r--libio/iofputs_u.c8
-rw-r--r--libio/iofputws.c45
-rw-r--r--libio/iofputws_u.c42
-rw-r--r--libio/iofsetpos.c18
-rw-r--r--libio/iofsetpos64.c18
-rw-r--r--libio/ioftell.c14
-rw-r--r--libio/iofwide.c365
-rw-r--r--libio/iofwrite.c7
-rw-r--r--libio/iofwrite_u.c17
-rw-r--r--libio/iogetwline.c120
-rw-r--r--libio/iolibio.h4
-rw-r--r--libio/iopopen.c28
-rw-r--r--libio/ioputs.c11
-rw-r--r--libio/ioseekoff.c28
-rw-r--r--libio/ioseekpos.c8
-rw-r--r--libio/iosetbuffer.c5
-rw-r--r--libio/iosetvbuf.c6
-rw-r--r--libio/ioungetwc.c44
-rw-r--r--libio/iovdprintf.c5
-rw-r--r--libio/iovsprintf.c4
-rw-r--r--libio/iovsscanf.c4
-rw-r--r--libio/iovswscanf.c48
-rw-r--r--libio/iowpadn.c76
-rw-r--r--libio/libio.h114
-rw-r--r--libio/libioP.h157
-rw-r--r--libio/memstream.c85
-rw-r--r--libio/obprintf.c8
-rw-r--r--libio/oldfileops.c10
-rw-r--r--libio/oldiofgetpos.c61
-rw-r--r--libio/oldiofgetpos64.c66
-rw-r--r--libio/oldiofsetpos.c59
-rw-r--r--libio/oldiofsetpos64.c64
-rw-r--r--libio/oldstdfiles.c7
-rw-r--r--libio/putwc.c35
-rw-r--r--libio/putwc_u.c29
-rw-r--r--libio/putwchar.c34
-rw-r--r--libio/putwchar_u.c28
-rw-r--r--libio/stdfiles.c12
-rw-r--r--libio/strops.c10
-rw-r--r--libio/swprintf.c38
-rw-r--r--libio/swscanf.c37
-rw-r--r--libio/tst_swprintf.c42
-rw-r--r--libio/tst_swscanf.c38
-rw-r--r--libio/tst_wprintf.c10
-rw-r--r--libio/tst_wscanf.c28
-rw-r--r--libio/tst_wscanf.input1
-rw-r--r--libio/vasprintf.c4
-rw-r--r--libio/vsnprintf.c4
-rw-r--r--libio/vswprintf.c144
-rw-r--r--libio/vwprintf.c31
-rw-r--r--libio/vwscanf.c35
-rw-r--r--libio/wfiledoalloc.c105
-rw-r--r--libio/wfileops.c716
-rw-r--r--libio/wgenops.c747
-rw-r--r--libio/wprintf.c35
-rw-r--r--libio/wscanf.c36
-rw-r--r--libio/wstrops.c330
80 files changed, 4568 insertions, 199 deletions
diff --git a/libio/Makefile b/libio/Makefile
index 948556e15c..6fcde40814 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -25,11 +25,16 @@ headers	:= stdio.h libio.h _G_config.h bits/stdio.h
 
 routines	:=							      \
 	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
-	iofopncook iofputs iofread iofsetpos ioftell			      \
+	iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc	      \
 	iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs	      \
 	ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc	      \
 	iovsprintf iovsscanf						      \
 	iofgetpos64 iofopen64 iofsetpos64				      \
+	oldiofgetpos oldiofgetpos64 oldiofsetpos oldiofsetpos64		      \
+	fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
+	iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u	      \
+	putchar putchar_u swprintf vwprintf wprintf wscanf fwscanf vwscanf    \
+	vswprintf iovswscanf swscanf wgenops wstrops wfileops iofwide	      \
 									      \
 	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
 	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
@@ -38,6 +43,8 @@ routines	:=							      \
 									      \
 	libc_fatal
 
+tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf
+
 all: # Make this the default target; it will be defined in Rules.
 
 include ../Makeconfig
diff --git a/libio/Versions b/libio/Versions
index 61b767a2d3..c7a5f668a1 100644
--- a/libio/Versions
+++ b/libio/Versions
@@ -100,4 +100,31 @@ libc {
     # p*
     pclose; popen;
   }
+  GLIBC_2.2 {
+    # functions used in libstdc++
+    _IO_fgetpos; _IO_fgetpos64; _IO_fsetpos; _IO_fsetpos64;
+
+    # f*
+    fgetpos; fgetpos64; fgetwc; fgetwc_unlocked; fgetws; fgetws_unlocked;
+    fputwc; fputwc_unlocked; fputws; fputws_unlocked; fsetpos; fsetpos64;
+    fwide; fwprintf; fwscanf;
+
+    # g*
+    getwc; getwc_unlocked; getwchar; getwchar_unlocked;
+
+    # p*
+    putwc; putwc_unlocked; putwchar; putwchar_unlocked;
+
+    # s*
+    swprintf; swscanf;
+
+    # u*
+    ungetwc;
+
+    # v*
+    vfwprintf; vswprintf; vwprintf; vfwscanf; vswscanf; vwscanf;
+
+    # w*
+    wprintf; wscanf;
+  }
 }
diff --git a/libio/fileops.c b/libio/fileops.c
index f5ec0e2b9e..8d480ad08b 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
    Written by Per Bothner <bothner@cygnus.com>.
 
@@ -136,9 +136,18 @@ _IO_new_file_close_it (fp)
   close_status = _IO_SYSCLOSE (fp);
 
   /* Free buffer. */
-  _IO_setb (fp, NULL, NULL, 0);
-  _IO_setg (fp, NULL, NULL, NULL);
-  _IO_setp (fp, NULL, NULL);
+  if (fp->_mode <= 0)
+    {
+      _IO_setb (fp, NULL, NULL, 0);
+      _IO_setg (fp, NULL, NULL, NULL);
+      _IO_setp (fp, NULL, NULL);
+    }
+  else
+    {
+      _IO_wsetb (fp, NULL, NULL, 0);
+      _IO_wsetg (fp, NULL, NULL, NULL);
+      _IO_wsetp (fp, NULL, NULL);
+    }
 
   _IO_un_link (fp);
   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
@@ -277,14 +286,14 @@ _IO_new_file_setbuf (fp, p, len)
      char *p;
      _IO_ssize_t len;
 {
-    if (_IO_default_setbuf (fp, p, len) == NULL)
-      return NULL;
+  if (_IO_default_setbuf (fp, p, len) == NULL)
+    return NULL;
 
-    fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
-      = fp->_IO_buf_base;
-    _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
+  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
+    = fp->_IO_buf_base;
+  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
 
-    return fp;
+  return fp;
 }
 
 static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
@@ -319,7 +328,7 @@ new_do_write (fp, data, to_do)
     fp->_offset = _IO_pos_BAD;
   else if (fp->_IO_read_end != fp->_IO_write_base)
     {
-      _IO_fpos64_t new_pos
+      _IO_off64_t new_pos
 	= _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
       if (new_pos == _IO_pos_BAD)
 	return 0;
@@ -330,7 +339,8 @@ new_do_write (fp, data, to_do)
     fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
-  fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+  fp->_IO_write_end = (fp->_mode < 0
+		       && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
 		       ? fp->_IO_buf_base : fp->_IO_buf_end);
   return count;
 }
@@ -410,7 +420,7 @@ _IO_new_file_overflow (f, ch)
       return EOF;
     }
   /* If currently reading or no buffer allocated. */
-  if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
+  if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0)
     {
       /* Allocate a buffer if needed. */
       if (f->_IO_write_base == 0)
@@ -433,18 +443,20 @@ _IO_new_file_overflow (f, ch)
       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
 
       f->_flags |= _IO_CURRENTLY_PUTTING;
-      if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+      if (f->_mode < 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
 	f->_IO_write_end = f->_IO_write_ptr;
     }
   if (ch == EOF)
-    return _IO_do_flush (f);
+    return _IO_new_do_write(f, f->_IO_write_base,
+			    f->_IO_write_ptr - f->_IO_write_base);
   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
     if (_IO_do_flush (f) == EOF)
       return EOF;
   *f->_IO_write_ptr++ = ch;
   if ((f->_flags & _IO_UNBUFFERED)
       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
-    if (_IO_do_flush (f) == EOF)
+    if (_IO_new_do_write(f, f->_IO_write_base,
+			 f->_IO_write_ptr - f->_IO_write_base) == EOF)
       return EOF;
   return (unsigned char) ch;
 }
@@ -483,14 +495,14 @@ _IO_new_file_sync (fp)
   return retval;
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_new_file_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
      _IO_off64_t offset;
      int dir;
      int mode;
 {
-  _IO_fpos64_t result;
+  _IO_off64_t result;
   _IO_off64_t delta, new_offset;
   long count;
   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
@@ -534,7 +546,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
       if (fp->_offset == _IO_pos_BAD)
 	goto dumb;
       /* Make offset absolute, assuming current pointer is file_ptr(). */
-      offset += _IO_pos_as_off (fp->_offset);
+      offset += fp->_offset;
 
       dir = _IO_seek_set;
       break;
@@ -563,8 +575,8 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
       && !_IO_in_backup (fp))
     {
       /* Offset relative to start of main get area. */
-      _IO_fpos64_t rel_offset = (offset - fp->_offset
-				 + (fp->_IO_read_end - fp->_IO_read_base));
+      _IO_off64_t rel_offset = (offset - fp->_offset
+				+ (fp->_IO_read_end - fp->_IO_read_base));
       if (rel_offset >= 0)
 	{
 #if 0
@@ -678,7 +690,7 @@ _IO_file_read (fp, buf, size)
   return read (fp->_fileno, buf, size);
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_file_seek (fp, offset, dir)
      _IO_FILE *fp;
      _IO_off64_t offset;
@@ -720,7 +732,7 @@ _IO_new_file_write (f, data, n)
   while (to_do > 0)
     {
       _IO_ssize_t count = write (f->_fileno, data, to_do);
-      if (count == EOF)
+      if (count < 0)
 	{
 	  f->_flags |= _IO_ERR_SEEN;
 	  break;
@@ -740,7 +752,7 @@ _IO_new_file_xsputn (f, data, n)
      const void *data;
      _IO_size_t n;
 {
-  register const char *s = (char *) data;
+  register const char *s = (const char *) data;
   _IO_size_t to_do = n;
   int must_flush = 0;
   _IO_size_t count;
diff --git a/libio/fputwc.c b/libio/fputwc.c
new file mode 100644
index 0000000000..cc8451a98f
--- /dev/null
+++ b/libio/fputwc.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wint_t
+fputwc (wc, fp)
+     wint_t wc;
+     _IO_FILE *fp;
+{
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  if (_IO_fwide (fp, 1) < 0)
+    result = WEOF;
+  else
+    result = _IO_putwc_unlocked (wc, fp);
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/fputwc_u.c b/libio/fputwc_u.c
new file mode 100644
index 0000000000..343e34d90e
--- /dev/null
+++ b/libio/fputwc_u.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1993, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+#undef fputwc_unlocked
+
+wint_t
+fputwc_unlocked (wc, fp)
+     wint_t wc;
+     _IO_FILE *fp;
+{
+  CHECK_FILE (fp, EOF);
+  if (_IO_fwide (fp, 1) < 0)
+    return WEOF;
+  return _IO_putwc_unlocked (wc, fp);
+}
diff --git a/libio/ftello.c b/libio/ftello.c
index 2d8a8a7167..ed4ef8b603 100644
--- a/libio/ftello.c
+++ b/libio/ftello.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -32,13 +32,19 @@ off_t
 ftello (fp)
      _IO_FILE *fp;
 {
-  _IO_pos_t pos;
+  _IO_off_t pos;
   CHECK_FILE (fp, -1L);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
   if (_IO_in_backup (fp))
-    pos -= fp->_IO_save_end - fp->_IO_save_base;
+    {
+      if (fp->_mode <= 0)
+	pos -= fp->_IO_save_end - fp->_IO_save_base;
+      else
+	/* XXX Not done yet. */
+	abort ();
+    }
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   if (pos == _IO_pos_BAD)
@@ -49,5 +55,5 @@ ftello (fp)
 #endif
       return -1L;
     }
-  return _IO_pos_as_off (pos);
+  return pos;
 }
diff --git a/libio/ftello64.c b/libio/ftello64.c
index 621454974e..7cb75626cf 100644
--- a/libio/ftello64.c
+++ b/libio/ftello64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -33,13 +33,18 @@ ftello64 (fp)
      _IO_FILE *fp;
 {
 #ifdef _G_LSEEK64
-  _IO_pos_t pos;
+  _IO_off64_t pos;
   CHECK_FILE (fp, -1L);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
   if (_IO_in_backup (fp))
-    pos -= fp->_IO_save_end - fp->_IO_save_base;
+    {
+      if (fp->_mode <= 0)
+	pos -= fp->_IO_save_end - fp->_IO_save_base;
+      else
+	abort ();
+    }
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   if (pos == _IO_pos_BAD)
@@ -50,7 +55,7 @@ ftello64 (fp)
 #endif
       return -1L;
     }
-  return _IO_pos_as_off (pos);
+  return pos;
 #else
   __set_errno (ENOSYS);
   return -1;
diff --git a/libio/fwprintf.c b/libio/fwprintf.c
new file mode 100644
index 0000000000..c26a2ffcd3
--- /dev/null
+++ b/libio/fwprintf.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <wchar.h>
+
+
+/* Write formatted output to STREAM from the format string FORMAT.  */
+/* VARARGS2 */
+int
+fwprintf (FILE *stream, const wchar_t *format, ...)
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = vfwprintf (stream, format, arg);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/fwscanf.c b/libio/fwscanf.c
new file mode 100644
index 0000000000..4510fc5b5f
--- /dev/null
+++ b/libio/fwscanf.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <wchar.h>
+
+/* Read formatted input from STREAM according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+fwscanf (FILE *stream, const wchar_t *format, ...)
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = __vfwscanf (stream, format, arg);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/genops.c b/libio/genops.c
index 81752e3ccc..a8f34463ad 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -80,9 +80,9 @@ _IO_link_in (fp)
 
 /* Return minimum _pos markers
    Assumes the current get area is the main get area. */
-static _IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p));
+_IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p));
 
-static _IO_ssize_t
+_IO_ssize_t
 _IO_least_marker (fp, end_p)
      _IO_FILE *fp;
      char *end_p;
@@ -282,6 +282,9 @@ int
 __underflow (fp)
      _IO_FILE *fp;
 {
+  if (_IO_fwide (fp, -1) != -1)
+    return EOF;
+
   if (_IO_in_put_mode (fp))
     if (_IO_switch_to_get_mode (fp) == EOF)
       return EOF;
@@ -307,6 +310,9 @@ int
 __uflow (fp)
      _IO_FILE *fp;
 {
+  if (_IO_fwide (fp, -1) != -1)
+    return EOF;
+
   if (_IO_in_put_mode (fp))
     if (_IO_switch_to_get_mode (fp) == EOF)
       return EOF;
@@ -508,13 +514,13 @@ _IO_default_setbuf (fp, p, len)
     return fp;
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_default_seekpos (fp, pos, mode)
      _IO_FILE *fp;
-     _IO_fpos64_t pos;
+     _IO_off64_t pos;
      int mode;
 {
-  return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode);
+  return _IO_SEEKOFF (fp, pos, 0, mode);
 }
 
 int
@@ -533,6 +539,17 @@ _IO_init (fp, flags)
      _IO_FILE *fp;
      int flags;
 {
+  _IO_no_init (fp, flags, -1, NULL, NULL);
+}
+
+void
+_IO_no_init (fp, flags, orientation, wd, jmp)
+     _IO_FILE *fp;
+     int flags;
+     int orientation;
+     struct _IO_wide_data *wd;
+     struct _IO_jump_t *jmp;
+{
   fp->_flags = _IO_MAGIC|flags;
   fp->_IO_buf_base = NULL;
   fp->_IO_buf_end = NULL;
@@ -555,6 +572,24 @@ _IO_init (fp, flags)
 #ifdef _IO_MTSAFE_IO
   _IO_lock_init (*fp->_lock);
 #endif
+  fp->_mode = orientation;
+  if (orientation >= 0)
+    {
+      fp->_wide_data = wd;
+      fp->_wide_data->_IO_buf_base = NULL;
+      fp->_wide_data->_IO_buf_end = NULL;
+      fp->_wide_data->_IO_read_base = NULL;
+      fp->_wide_data->_IO_read_ptr = NULL;
+      fp->_wide_data->_IO_read_end = NULL;
+      fp->_wide_data->_IO_write_base = NULL;
+      fp->_wide_data->_IO_write_ptr = NULL;
+      fp->_wide_data->_IO_write_end = NULL;
+      fp->_wide_data->_IO_save_base = NULL;
+      fp->_wide_data->_IO_backup_base = NULL;
+      fp->_wide_data->_IO_save_end = NULL;
+
+      fp->_wide_data->_wide_vtable = jmp;
+    }
 }
 
 int
@@ -595,7 +630,7 @@ _IO_default_finish (fp, dummy)
   _IO_un_link (fp);
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_default_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
      _IO_off64_t offset;
@@ -706,7 +741,9 @@ _IO_flush_all ()
   int result = 0;
   _IO_FILE *fp;
   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
-    if (fp->_IO_write_ptr > fp->_IO_write_base
+    if (((fp->_mode < 0 && fp->_IO_write_ptr > fp->_IO_write_base)
+	 || (fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
+			       > fp->_wide_data->_IO_write_base)))
 	&& _IO_OVERFLOW (fp, EOF) == EOF)
       result = EOF;
   return result;
@@ -941,7 +978,7 @@ _IO_default_pbackfail (fp, c)
   return (unsigned char) c;
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_default_seek (fp, offset, dir)
      _IO_FILE *fp;
      _IO_off64_t offset;
diff --git a/libio/getwc.c b/libio/getwc.c
new file mode 100644
index 0000000000..0829ea0248
--- /dev/null
+++ b/libio/getwc.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+#undef _IO_getwc
+
+wint_t
+_IO_getwc (fp)
+     FILE *fp;
+{
+  wint_t result;
+  CHECK_FILE (fp, WEOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  result = _IO_getwc_unlocked (fp);
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
+
+#undef getwc
+
+#ifdef weak_alias
+weak_alias (_IO_getwc, getwc)
+weak_alias (_IO_getwc, fgetwc)
+#endif
diff --git a/libio/getwc_u.c b/libio/getwc_u.c
new file mode 100644
index 0000000000..606b4d24cc
--- /dev/null
+++ b/libio/getwc_u.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1993, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef getwc_unlocked
+
+wint_t
+__getwc_unlocked (FILE *fp)
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_getwc_unlocked (fp);
+}
+
+weak_alias (__getwc_unlocked, getwc_unlocked)
+weak_alias (__getwc_unlocked, fgetwc_unlocked)
diff --git a/libio/getwchar.c b/libio/getwchar.c
new file mode 100644
index 0000000000..6ef1f9b552
--- /dev/null
+++ b/libio/getwchar.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+#undef getwchar
+
+wint_t
+getwchar ()
+{
+  wint_t result;
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+			    _IO_stdin);
+  _IO_flockfile (_IO_stdin);
+  result = _IO_getwc_unlocked (_IO_stdin);
+  _IO_funlockfile (_IO_stdin);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/getwchar_u.c b/libio/getwchar_u.c
new file mode 100644
index 0000000000..18dc2ca158
--- /dev/null
+++ b/libio/getwchar_u.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1993, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+#undef getwchar_unlocked
+
+wint_t
+getwchar_unlocked ()
+{
+  return _IO_getwc_unlocked (_IO_stdin);
+}
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
index 40419bd267..3bfa40c7c6 100644
--- a/libio/iofdopen.c
+++ b/libio/iofdopen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -50,6 +50,7 @@ _IO_new_fdopen (fd, mode)
 #ifdef _IO_MTSAFE_IO
     _IO_lock_t lock;
 #endif
+    struct _IO_wide_data wd;
   } *new_f;
   int fd_flags;
 
@@ -112,7 +113,7 @@ _IO_new_fdopen (fd, mode)
 #ifdef _IO_MTSAFE_IO
   new_f->fp.file._lock = &new_f->lock;
 #endif
-  _IO_init (&new_f->fp.file, 0);
+  _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);
   _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;
   _IO_file_init (&new_f->fp.file);
 #if  !_IO_UNIFIED_JUMPTABLES
diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c
index 27f018d07f..5b8f6a4129 100644
--- a/libio/iofgetpos.c
+++ b/libio/iofgetpos.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -27,11 +27,11 @@
 #include <errno.h>
 
 int
-_IO_fgetpos (fp, posp)
+_IO_new_fgetpos (fp, posp)
      _IO_FILE *fp;
      _IO_fpos_t *posp;
 {
-  _IO_fpos_t pos;
+  _IO_off_t pos;
   CHECK_FILE (fp, EOF);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
@@ -50,10 +50,16 @@ _IO_fgetpos (fp, posp)
 #endif
       return EOF;
     }
-  *posp = pos;
+  posp->__pos = pos;
+  if (fp->_mode > 0
+      && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
+    /* This is a stateful encoding, safe the state.  */
+    posp->__state = fp->_wide_data->_IO_state;
   return 0;
 }
 
 #ifdef weak_alias
-weak_alias (_IO_fgetpos, fgetpos)
+strong_alias (_IO_new_fgetpos, __new_fgetpos)
+default_symbol_version (_IO_new_fgetpos, _IO_fgetpos, GLIBC_2.2);
+default_symbol_version (__new_fgetpos, fgetpos, GLIBC_2.2);
 #endif
diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c
index a705e9e91a..cc39a3a9e1 100644
--- a/libio/iofgetpos64.c
+++ b/libio/iofgetpos64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -27,12 +27,12 @@
 #include <errno.h>
 
 int
-_IO_fgetpos64 (fp, posp)
+_IO_new_fgetpos64 (fp, posp)
      _IO_FILE *fp;
      _IO_fpos64_t *posp;
 {
 #ifdef _G_LSEEK64
-  _IO_fpos64_t pos;
+  _IO_off64_t pos;
   CHECK_FILE (fp, EOF);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
@@ -45,13 +45,17 @@ _IO_fgetpos64 (fp, posp)
     {
       /* ANSI explicitly requires setting errno to a positive value on
 	 failure.  */
-#ifdef EIO
+# ifdef EIO
       if (errno == 0)
 	__set_errno (EIO);
-#endif
+# endif
       return EOF;
     }
-  *posp = pos;
+  posp->__pos = pos;
+  if (fp->_mode > 0
+      && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
+    /* This is a stateful encoding, safe the state.  */
+    posp->__state = fp->_wide_data->_IO_state;
   return 0;
 #else
   __set_errno (ENOSYS);
@@ -60,5 +64,7 @@ _IO_fgetpos64 (fp, posp)
 }
 
 #ifdef weak_alias
-weak_alias (_IO_fgetpos64, fgetpos64)
+default_symbol_version (_IO_new_fgetpos64, _IO_fgetpos64, GLIBC_2.2);
+strong_alias (_IO_new_fgetpos64, __new_fgetpos64)
+default_symbol_version (__new_fgetpos64, fgetpos64, GLIBC_2.2);
 #endif
diff --git a/libio/iofgetws.c b/libio/iofgetws.c
new file mode 100644
index 0000000000..25ed836560
--- /dev/null
+++ b/libio/iofgetws.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wchar_t *
+fgetws (buf, n, fp)
+     wchar_t *buf;
+     int n;
+     _IO_FILE *fp;
+{
+  _IO_size_t count;
+  wchar_t *result;
+  int old_error;
+  CHECK_FILE (fp, NULL);
+  if (n <= 0)
+    return NULL;
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  /* This is very tricky since a file descriptor may be in the
+     non-blocking mode. The error flag doesn't mean much in this
+     case. We return an error only when there is a new error. */
+  old_error = fp->_IO_file_flags & _IO_ERR_SEEN;
+  fp->_IO_file_flags &= ~_IO_ERR_SEEN;
+  count = _IO_getwline (fp, buf, n - 1, L'\n', 1);
+  /* If we read in some bytes and errno is EAGAIN, that error will
+     be reported for next read. */
+  if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN)
+		     && errno != EAGAIN))
+    result = NULL;
+  else
+    {
+      buf[count] = '\0';
+      result = buf;
+    }
+  fp->_IO_file_flags |= old_error;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/iofgetws_u.c b/libio/iofgetws_u.c
new file mode 100644
index 0000000000..951ab80d9d
--- /dev/null
+++ b/libio/iofgetws_u.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wchar_t *
+fgetws_unlocked (buf, n, fp)
+     wchar_t *buf;
+     int n;
+     _IO_FILE *fp;
+{
+  _IO_size_t count;
+  wchar_t *result;
+  int old_error;
+  CHECK_FILE (fp, NULL);
+  if (n <= 0)
+    return NULL;
+  /* This is very tricky since a file descriptor may be in the
+     non-blocking mode. The error flag doesn't mean much in this
+     case. We return an error only when there is a new error. */
+  old_error = fp->_IO_file_flags & _IO_ERR_SEEN;
+  fp->_IO_file_flags &= ~_IO_ERR_SEEN;
+  count = _IO_getwline (fp, buf, n - 1, L'\n', 1);
+  /* If we read in some bytes and errno is EAGAIN, that error will
+     be reported for next read. */
+  if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN)
+  		     && errno != EAGAIN))
+    result = NULL;
+  else
+    {
+      buf[count] = '\0';
+      result = buf;
+    }
+  fp->_IO_file_flags |= old_error;
+  return result;
+}
diff --git a/libio/iofopen.c b/libio/iofopen.c
index 92d58bb133..60b15a00f8 100644
--- a/libio/iofopen.c
+++ b/libio/iofopen.c
@@ -39,6 +39,7 @@ _IO_new_fopen (filename, mode)
 #ifdef _IO_MTSAFE_IO
     _IO_lock_t lock;
 #endif
+    struct _IO_wide_data wd;
   } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
 
   if (new_f == NULL)
@@ -46,7 +47,7 @@ _IO_new_fopen (filename, mode)
 #ifdef _IO_MTSAFE_IO
   new_f->fp.file._lock = &new_f->lock;
 #endif
-  _IO_init (&new_f->fp.file, 0);
+  _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);
   _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;
   _IO_file_init (&new_f->fp.file);
 #if  !_IO_UNIFIED_JUMPTABLES
diff --git a/libio/iofopen64.c b/libio/iofopen64.c
index b071a0e160..0dc19b2e1b 100644
--- a/libio/iofopen64.c
+++ b/libio/iofopen64.c
@@ -40,6 +40,7 @@ _IO_fopen64 (filename, mode)
 #ifdef _IO_MTSAFE_IO
     _IO_lock_t lock;
 #endif
+    struct _IO_wide_data wd;
   } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
 
   if (new_f == NULL)
@@ -47,7 +48,7 @@ _IO_fopen64 (filename, mode)
 #ifdef _IO_MTSAFE_IO
   new_f->fp.file._lock = &new_f->lock;
 #endif
-  _IO_init (&new_f->fp.file, 0);
+  _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);
   _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;
   _IO_file_init (&new_f->fp.file);
 #if  !_IO_UNIFIED_JUMPTABLES
diff --git a/libio/iofopncook.c b/libio/iofopncook.c
index f26744f39d..85ea35c22e 100644
--- a/libio/iofopncook.c
+++ b/libio/iofopncook.c
@@ -33,8 +33,8 @@ static _IO_ssize_t _IO_cookie_read __P ((register _IO_FILE* fp, void* buf,
 					 _IO_ssize_t size));
 static _IO_ssize_t _IO_cookie_write __P ((register _IO_FILE* fp,
 					  const void* buf, _IO_ssize_t size));
-static _IO_fpos64_t _IO_cookie_seek __P ((_IO_FILE *fp, _IO_off64_t offset,
-					  int dir));
+static _IO_off64_t _IO_cookie_seek __P ((_IO_FILE *fp, _IO_off64_t offset,
+					 int dir));
 static int _IO_cookie_close __P ((_IO_FILE* fp));
 
 
@@ -66,7 +66,7 @@ _IO_cookie_write (fp, buf, size)
   return cfile->__io_functions.write (cfile->__cookie, buf, size);
 }
 
-static _IO_fpos64_t
+static _IO_off64_t
 _IO_cookie_seek (fp, offset, dir)
      _IO_FILE *fp;
      _IO_off64_t offset;
diff --git a/libio/iofputs.c b/libio/iofputs.c
index 1805387303..ed41d5a49c 100644
--- a/libio/iofputs.c
+++ b/libio/iofputs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -32,13 +32,12 @@ _IO_fputs (str, fp)
       _IO_FILE *fp;
 {
   _IO_size_t len = strlen (str);
-  int result;
+  int result = EOF;
   CHECK_FILE (fp, EOF);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
-  if (_IO_sputn (fp, str, len) != len)
-    result = EOF;
-  else
+  if (_IO_fwide (fp, -1) == -1
+      && _IO_sputn (fp, str, len) == len)
     result = 1;
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
diff --git a/libio/iofputs_u.c b/libio/iofputs_u.c
index dfd91aba7e..556522bad1 100644
--- a/libio/iofputs_u.c
+++ b/libio/iofputs_u.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -33,11 +33,9 @@ fputs_unlocked (str, fp)
       _IO_FILE *fp;
 {
   _IO_size_t len = strlen (str);
-  int result;
+  int result = EOF;
   CHECK_FILE (fp, EOF);
-  if (_IO_sputn (fp, str, len) != len)
-    result = EOF;
-  else
+  if (_IO_fwide (fp, -1) == -1 && _IO_sputn (fp, str, len) == len)
     result = 1;
   return result;
 }
diff --git a/libio/iofputws.c b/libio/iofputws.c
new file mode 100644
index 0000000000..daad1b9836
--- /dev/null
+++ b/libio/iofputws.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+int
+fputws (str, fp)
+      const wchar_t *str;
+      _IO_FILE *fp;
+{
+  _IO_size_t len = wcslen (str);
+  int result = EOF;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  if (_IO_fwide (fp, 1) == 1
+      && _IO_sputn (fp, (char *) str, len) == len)
+    result = 1;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/iofputws_u.c b/libio/iofputws_u.c
new file mode 100644
index 0000000000..a5749cdbec
--- /dev/null
+++ b/libio/iofputws_u.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <stdio.h>
+#include <wchar.h>
+
+int
+fputws_unlocked (str, fp)
+      const wchar_t *str;
+      _IO_FILE *fp;
+{
+  _IO_size_t len = wcslen (str);
+  int result = EOF;
+  CHECK_FILE (fp, EOF);
+  if (_IO_fwide (fp, 1) == 1
+      && _IO_sputn (fp, (char *) str, len) == len)
+    result = 1;
+  return result;
+}
diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c
index cbf77347e7..bd49c13a83 100644
--- a/libio/iofsetpos.c
+++ b/libio/iofsetpos.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -27,7 +27,7 @@
 #include <errno.h>
 
 int
-_IO_fsetpos (fp, posp)
+_IO_new_fsetpos (fp, posp)
      _IO_FILE *fp;
      const _IO_fpos_t *posp;
 {
@@ -35,7 +35,7 @@ _IO_fsetpos (fp, posp)
   CHECK_FILE (fp, EOF);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
-  if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
+  if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
     {
       /* ANSI explicitly requires setting errno to a positive value on
 	 failure.  */
@@ -46,12 +46,20 @@ _IO_fsetpos (fp, posp)
       result = EOF;
     }
   else
-    result = 0;
+    {
+      result = 0;
+      if (fp->_mode > 0
+	  && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
+	/* This is a stateful encoding, restore the state.  */
+	fp->_wide_data->_IO_state = posp->__state;
+    }
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   return result;
 }
 
 #ifdef weak_alias
-weak_alias (_IO_fsetpos, fsetpos)
+default_symbol_version (_IO_new_fsetpos, _IO_fsetpos, GLIBC_2.2);
+strong_alias (_IO_new_fsetpos, __new_fsetpos)
+default_symbol_version (__new_fsetpos, fsetpos, GLIBC_2.2);
 #endif
diff --git a/libio/iofsetpos64.c b/libio/iofsetpos64.c
index 13ce0fb3cb..a70d5e215a 100644
--- a/libio/iofsetpos64.c
+++ b/libio/iofsetpos64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -27,7 +27,7 @@
 #include <errno.h>
 
 int
-_IO_fsetpos64 (fp, posp)
+_IO_new_fsetpos64 (fp, posp)
      _IO_FILE *fp;
      const _IO_fpos64_t *posp;
 {
@@ -36,7 +36,7 @@ _IO_fsetpos64 (fp, posp)
   CHECK_FILE (fp, EOF);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
-  if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
+  if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
     {
       /* ANSI explicitly requires setting errno to a positive value on
 	 failure.  */
@@ -47,7 +47,13 @@ _IO_fsetpos64 (fp, posp)
       result = EOF;
     }
   else
-    result = 0;
+    {
+      result = 0;
+      if (fp->_mode > 0
+	  && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0)
+	/* This is a stateful encoding, safe the state.  */
+	fp->_wide_data->_IO_state = posp->__state;
+    }
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   return result;
@@ -58,5 +64,7 @@ _IO_fsetpos64 (fp, posp)
 }
 
 #ifdef weak_alias
-weak_alias (_IO_fsetpos64, fsetpos64)
+default_symbol_version (_IO_new_fsetpos64, _IO_fsetpos64, GLIBC_2.2);
+strong_alias (_IO_new_fsetpos64, __new_fsetpos64)
+default_symbol_version (__new_fsetpos64, fsetpos64, GLIBC_2.2);
 #endif
diff --git a/libio/ioftell.c b/libio/ioftell.c
index 3de1ee9c02..1f25b66c2b 100644
--- a/libio/ioftell.c
+++ b/libio/ioftell.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -31,13 +31,19 @@ long int
 _IO_ftell (fp)
      _IO_FILE *fp;
 {
-  _IO_pos_t pos;
+  _IO_off_t pos;
   CHECK_FILE (fp, -1L);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
   if (_IO_in_backup (fp))
-    pos -= fp->_IO_save_end - fp->_IO_save_base;
+    {
+      if (fp->_mode < 0)
+	pos -= fp->_IO_save_end - fp->_IO_save_base;
+      else
+	/* XXX For now.  */
+	abort ();
+    }
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   if (pos == _IO_pos_BAD)
@@ -48,7 +54,7 @@ _IO_ftell (fp)
 #endif
       return -1L;
     }
-  return _IO_pos_as_off (pos);
+  return pos;
 }
 
 #ifdef weak_alias
diff --git a/libio/iofwide.c b/libio/iofwide.c
new file mode 100644
index 0000000000..853920a001
--- /dev/null
+++ b/libio/iofwide.c
@@ -0,0 +1,365 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include <libioP.h>
+#ifdef _LIBC
+# include <wchar.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# include <langinfo.h>
+# include <locale/localeinfo.h>
+# include <wcsmbs/wcsmbsload.h>
+#endif
+
+
+/* Prototypes of libio's codecvt functions.  */
+static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
+				     __mbstate_t *statep,
+				     const wchar_t *from_start,
+				     const wchar_t *from_end,
+				     const wchar_t **from_stop, char *to_start,
+				     char *to_end, char **to_stop);
+static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt,
+					 __mbstate_t *statep, char *to_start,
+					 char *to_end, char **to_stop);
+static enum __codecvt_result do_in (struct _IO_codecvt *codecvt,
+				    __mbstate_t *statep,
+				    const char *from_start,
+				    const char *from_end,
+				    const char **from_stop, wchar_t *to_start,
+				    wchar_t *to_end, wchar_t **to_stop);
+static int do_encoding (struct _IO_codecvt *codecvt);
+static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
+		      const char *from_start,
+		      const char *from_end, _IO_size_t max);
+static int do_max_length (struct _IO_codecvt *codecvt);
+static int do_always_noconv (struct _IO_codecvt *codecvt);
+
+
+/* The functions used in `codecvt' for libio are always the same.  */
+static struct _IO_codecvt libio_codecvt =
+{
+  .__codecvt_destr = NULL,		/* Destructor, never used.  */
+  .__codecvt_do_out = do_out,
+  .__codecvt_do_unshift = do_unshift,
+  .__codecvt_do_in = do_in,
+  .__codecvt_do_encoding = do_encoding,
+  .__codecvt_do_always_noconv = do_always_noconv,
+  .__codecvt_do_length = do_length,
+  .__codecvt_do_max_length = do_max_length
+};
+
+
+/* Return orientation of stream.  If mode is nonzero try to change
+   the orientation first.  */
+#undef _IO_fwide
+int
+_IO_fwide (fp, mode)
+     _IO_FILE *fp;
+     int mode;
+{
+  /* Normalize the value.  */
+  mode = mode < 0 ? -1 : (mode == 0 ? 0 : 1);
+
+  if (mode == 0 || fp->_mode != 0)
+    /* The caller simply wants to know about the current orientation
+       or the orientation already has been determined.  */
+    return fp->_mode;
+
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+
+  /* Set the orientation appropriately.  */
+  if (mode > 0)
+    {
+      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+      fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
+
+      /* Clear the state.  We start all over again.  */
+      memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
+      memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
+
+      /* Get the character conversion functions based on the currently
+	 selected locale for LC_CTYPE.  */
+#ifdef _LIBC
+      {
+	struct gconv_fcts fcts;
+	struct _IO_codecvt *cc = &fp->_wide_data->_codecvt;
+
+	__wcsmbs_clone_conv (&fcts);
+
+	/* The functions are always the same.  */
+	*cc = libio_codecvt;
+
+	cc->__cd_in.__cd.__nsteps = 1; /* Only one step allowed.  */
+	cc->__cd_in.__cd.__steps = fcts.towc;
+
+	cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
+	cc->__cd_in.__cd.__data[0].__internal_use = 1;
+	cc->__cd_in.__cd.__data[0].__is_last = 1;
+	cc->__cd_in.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;
+
+	cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed.  */
+	cc->__cd_out.__cd.__steps = fcts.tomb;
+
+	cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
+	cc->__cd_out.__cd.__data[0].__internal_use = 1;
+	cc->__cd_out.__cd.__data[0].__is_last = 1;
+	cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;
+      }
+#else
+# error "somehow determine this from LC_CTYPE"
+#endif
+
+      /* From now on use the wide character callback functions.  */
+      ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
+    }
+
+  /* Set the mode now.  */
+  fp->_mode = mode;
+
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+
+  return mode;
+}
+
+#ifdef weak_alias
+weak_alias (_IO_fwide, fwide)
+#endif
+
+
+static enum __codecvt_result
+do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep,
+	const wchar_t *from_start, const wchar_t *from_end,
+	const wchar_t **from_stop, char *to_start, char *to_end,
+	char **to_stop)
+{
+  enum __codecvt_result result;
+
+#ifdef _LIBC
+  struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
+  int status;
+  size_t written;
+  const unsigned char *from_start_copy = (unsigned char *) from_start;
+
+  codecvt->__cd_out.__cd.__data[0].__outbuf = to_start;
+  codecvt->__cd_out.__cd.__data[0].__outbufend = to_end;
+  codecvt->__cd_out.__cd.__data[0].__statep = statep;
+
+  status = (*gs->__fct) (gs, codecvt->__cd_out.__cd.__data, &from_start_copy,
+			 (const unsigned char *) from_end, &written, 0);
+
+  *from_stop = (wchar_t *) from_start_copy;
+  *to_stop = codecvt->__cd_out.__cd.__data[0].__outbuf;
+
+  switch (status)
+    {
+    case __GCONV_OK:
+    case __GCONV_EMPTY_INPUT:
+      result = __codecvt_ok;
+      break;
+
+    case __GCONV_FULL_OUTPUT:
+    case __GCONV_INCOMPLETE_INPUT:
+      result = __codecvt_partial;
+      break;
+
+    default:
+      result = __codecvt_error;
+      break;
+    }
+#else
+  /* Decide what to do.  */
+  result = __codecvt_error;
+#endif
+
+  return result;
+}
+
+
+static enum __codecvt_result
+do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep,
+	    char *to_start, char *to_end, char **to_stop)
+{
+  enum __codecvt_result result;
+
+#ifdef _LIBC
+  struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps;
+  int status;
+  size_t written;
+
+  codecvt->__cd_out.__cd.__data[0].__outbuf = to_start;
+  codecvt->__cd_out.__cd.__data[0].__outbufend = to_end;
+  codecvt->__cd_out.__cd.__data[0].__statep = statep;
+
+  status = (*gs->__fct) (gs, codecvt->__cd_out.__cd.__data, NULL, NULL,
+			 &written, 1);
+
+  *to_stop = codecvt->__cd_out.__cd.__data[0].__outbuf;
+
+  switch (status)
+    {
+    case __GCONV_OK:
+    case __GCONV_EMPTY_INPUT:
+      result = __codecvt_ok;
+      break;
+
+    case __GCONV_FULL_OUTPUT:
+    case __GCONV_INCOMPLETE_INPUT:
+      result = __codecvt_partial;
+      break;
+
+    default:
+      result = __codecvt_error;
+      break;
+    }
+#else
+  /* Decide what to do.  */
+  result = __codecvt_error;
+#endif
+
+  return result;
+}
+
+
+static enum __codecvt_result
+do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep,
+       const char *from_start, const char *from_end, const char **from_stop,
+       wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop)
+{
+  enum __codecvt_result result;
+
+#ifdef _LIBC
+  struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
+  int status;
+  size_t written;
+  const unsigned char *from_start_copy = (unsigned char *) from_start;
+
+  codecvt->__cd_in.__cd.__data[0].__outbuf = (char *) to_start;
+  codecvt->__cd_in.__cd.__data[0].__outbufend = (char *) to_end;
+  codecvt->__cd_in.__cd.__data[0].__statep = statep;
+
+  status = (*gs->__fct) (gs, codecvt->__cd_in.__cd.__data, &from_start_copy,
+			 from_end, &written, 0);
+
+  *from_stop = from_start_copy;
+  *to_stop = (wchar_t *) codecvt->__cd_in.__cd.__data[0].__outbuf;
+
+  switch (status)
+    {
+    case __GCONV_OK:
+    case __GCONV_EMPTY_INPUT:
+      result = __codecvt_ok;
+      break;
+
+    case __GCONV_FULL_OUTPUT:
+    case __GCONV_INCOMPLETE_INPUT:
+      result = __codecvt_partial;
+      break;
+
+    default:
+      result = __codecvt_error;
+      break;
+    }
+#else
+  /* Decide what to do.  */
+  result = __codecvt_error;
+#endif
+
+  return result;
+}
+
+
+static int
+do_encoding (struct _IO_codecvt *codecvt)
+{
+#ifdef _LIBC
+  /* See whether the encoding is stateful.  */
+  if (codecvt->__cd_in.__cd.__steps[0].__stateful)
+    return -1;
+  /* Fortunately not.  Now determine the input bytes for the conversion
+     necessary for each wide character.  */
+  if (codecvt->__cd_in.__cd.__steps[0].__min_needed_from
+      != codecvt->__cd_in.__cd.__steps[0].__max_needed_from)
+    /* Not a constant value.  */
+    return 0;
+
+  return codecvt->__cd_in.__cd.__steps[0].__min_needed_from;
+#else
+  /* Worst case scenario.  */
+  return -1;
+#endif
+}
+
+
+static int
+do_always_noconv (struct _IO_codecvt *codecvt)
+{
+  return 0;
+}
+
+
+static int
+do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
+	   const char *from_start, const char *from_end, _IO_size_t max)
+{
+  int result;
+#ifdef _LIBC
+  const unsigned char *cp = (const unsigned char *) from_start;
+  wchar_t to_buf[max];
+  struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps;
+  int status;
+  size_t written;
+
+  codecvt->__cd_in.__cd.__data[0].__outbuf = (char *) to_buf;
+  codecvt->__cd_in.__cd.__data[0].__outbufend = (char *) &to_buf[max];
+  codecvt->__cd_in.__cd.__data[0].__statep = statep;
+
+  status = (*gs->__fct) (gs, codecvt->__cd_in.__cd.__data, &cp, from_end,
+			 &written, 0);
+
+  result = cp - (const unsigned char *) from_start;
+#else
+  /* Decide what to do.  */
+  result = 0;
+#endif
+
+  return result;
+}
+
+
+static int
+do_max_length (struct _IO_codecvt *codecvt)
+{
+#ifdef _LIBC
+  return codecvt->__cd_in.__cd.__steps[0].__max_needed_from;
+#else
+  return MB_CUR_MAX;
+#endif
+}
diff --git a/libio/iofwrite.c b/libio/iofwrite.c
index d163d29361..886de7ae35 100644
--- a/libio/iofwrite.c
+++ b/libio/iofwrite.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -33,7 +33,7 @@ _IO_fwrite (buf, size, count, fp)
      _IO_FILE *fp;
 {
   _IO_size_t request = size * count;
-  _IO_size_t written;
+  _IO_size_t written = 0;
   CHECK_FILE (fp, 0);
   /* Many traditional implementations return 0 if size==0 && count > 0,
      but ANSI requires us to return count in this case. */
@@ -41,7 +41,8 @@ _IO_fwrite (buf, size, count, fp)
     return count;
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
-  written = _IO_sputn (fp, (const char *) buf, request);
+  if (_IO_fwide (fp, -1) == -1)
+    written = _IO_sputn (fp, (const char *) buf, request);
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
   if (written == request)
diff --git a/libio/iofwrite_u.c b/libio/iofwrite_u.c
index 38d1bd08a3..acb5b2f527 100644
--- a/libio/iofwrite_u.c
+++ b/libio/iofwrite_u.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -36,15 +36,18 @@ fwrite_unlocked (buf, size, count, fp)
      _IO_FILE *fp;
 {
   _IO_size_t request = size * count;
-  _IO_size_t written;
+  _IO_size_t written = 0;
   CHECK_FILE (fp, 0);
   /* Many traditional implementations return 0 if size==0 && count > 0,
      but ANSI requires us to return count in this case. */
   if (request == 0)
     return count;
-  written = _IO_sputn (fp, (const char *) buf, request);
-  if (written == request)
-    return count;
-  else
-    return written / size;
+  if (_IO_fwide (fp, -1) == -1)
+    {
+      written = _IO_sputn (fp, (const char *) buf, request);
+      if (written == request)
+	return count;
+    }
+
+  return written / size;
 }
diff --git a/libio/iogetwline.c b/libio/iogetwline.c
new file mode 100644
index 0000000000..402158a4ef
--- /dev/null
+++ b/libio/iogetwline.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <string.h>
+#include <wchar.h>
+
+#if defined _LIBC || !_G_HAVE_IO_GETLINE_INFO
+
+_IO_size_t
+_IO_getwline (fp, buf, n, delim, extract_delim)
+     _IO_FILE *fp;
+     wchar_t *buf;
+     _IO_size_t n;
+     wint_t delim;
+     int extract_delim;
+{
+  return _IO_getwline_info (fp, buf, n, delim, extract_delim, (wint_t *) 0);
+}
+
+/* Algorithm based on that used by Berkeley pre-4.4 fgets implementation.
+
+   Read chars into buf (of size n), until delim is seen.
+   Return number of chars read (at most n).
+   Does not put a terminating '\0' in buf.
+   If extract_delim < 0, leave delimiter unread.
+   If extract_delim > 0, insert delim in output. */
+
+_IO_size_t
+_IO_getwline_info (fp, buf, n, delim, extract_delim, eof)
+     _IO_FILE *fp;
+     wchar_t *buf;
+     _IO_size_t n;
+     wint_t delim;
+     int extract_delim;
+     wint_t *eof;
+{
+  wchar_t *ptr = buf;
+  if (eof != NULL)
+    *eof = 0;
+  while (n != 0)
+    {
+      _IO_ssize_t len = (fp->_wide_data->_IO_read_end
+			 - fp->_wide_data->_IO_read_ptr);
+      if (len <= 0)
+	{
+	  wint_t wc = __wuflow (fp);
+	  if (wc == WEOF)
+	    {
+	      if (eof)
+		*eof = wc;
+	      break;
+	    }
+	  if (wc == delim)
+	    {
+ 	      if (extract_delim > 0)
+		*ptr++ = wc;
+	      else if (extract_delim < 0)
+		_IO_sputbackc (fp, wc);
+	      return ptr - buf;
+	      if (extract_delim > 0)
+		++len;
+	    }
+	  *ptr++ = wc;
+	  n--;
+	}
+	else
+	  {
+	    wchar_t *t;
+	    if ((_IO_size_t) len >= n)
+	      len = n;
+	    t = (wchar_t *) memchr ((void *) fp->_wide_data->_IO_read_ptr,
+				    delim, len);
+	    if (t != NULL)
+	      {
+		_IO_size_t old_len = ptr - buf;
+		len = t - fp->_wide_data->_IO_read_ptr;
+		if (extract_delim >= 0)
+		  {
+		    ++t;
+		    if (extract_delim > 0)
+		      ++len;
+		  }
+		memcpy ((void *) ptr, (void *) fp->_wide_data->_IO_read_ptr,
+			len);
+		fp->_wide_data->_IO_read_ptr = t;
+		return old_len + len;
+	      }
+	    memcpy ((void *) ptr, (void *) fp->_wide_data->_IO_read_ptr, len);
+	    fp->_wide_data->_IO_read_ptr += len;
+	    ptr += len;
+	    n -= len;
+	  }
+    }
+  return ptr - buf;
+}
+
+#endif /* Defined _LIBC || !_G_HAVE_IO_GETLINE_INFO */
diff --git a/libio/iolibio.h b/libio/iolibio.h
index 7b25b40212..92f25cf9f9 100644
--- a/libio/iolibio.h
+++ b/libio/iolibio.h
@@ -41,13 +41,15 @@ extern int _IO_sprintf __P((char *, const char*, ...));
 extern int _IO_ungetc __P((int, _IO_FILE*));
 extern int _IO_vsscanf __P((const char *, const char *, _IO_va_list));
 extern int _IO_vsprintf __P((char*, const char*, _IO_va_list));
+extern int _IO_vswprintf __P((wchar_t*, _IO_size_t, const wchar_t*,
+			      _IO_va_list));
 
 struct obstack;
 extern int _IO_obstack_vprintf __P ((struct obstack *, const char *,
 				     _IO_va_list));
 extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...));
 #ifndef _IO_pos_BAD
-#define _IO_pos_BAD ((_IO_fpos64_t)(-1))
+#define _IO_pos_BAD ((_IO_off64_t)(-1))
 #endif
 #define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN))
 #define _IO_fseek(__fp, __offset, __whence) \
diff --git a/libio/iopopen.c b/libio/iopopen.c
index 6b2d7f5328..15c15023f7 100644
--- a/libio/iopopen.c
+++ b/libio/iopopen.c
@@ -101,6 +101,8 @@ struct _IO_proc_file
 };
 typedef struct _IO_proc_file _IO_proc_file;
 
+static struct _IO_jump_t _IO_wproc_jumps;
+
 static struct _IO_proc_file *proc_file_chain;
 
 _IO_FILE *
@@ -186,6 +188,7 @@ _IO_new_popen (command, mode)
 #ifdef _IO_MTSAFE_IO
     _IO_lock_t lock;
 #endif
+    struct _IO_wide_data wd;
   } *new_f;
   _IO_FILE *fp;
 
@@ -196,7 +199,7 @@ _IO_new_popen (command, mode)
   new_f->fpx.file.file._lock = &new_f->lock;
 #endif
   fp = &new_f->fpx.file.file;
-  _IO_init (fp, 0);
+  _IO_no_init (fp, 0, 0, &new_f->wd, &_IO_wproc_jumps);
   _IO_JUMPS (fp) = &_IO_proc_jumps;
   _IO_new_file_init (fp);
 #if  !_IO_UNIFIED_JUMPTABLES
@@ -273,6 +276,29 @@ struct _IO_jump_t _IO_proc_jumps = {
   JUMP_INIT(imbue, _IO_default_imbue)
 };
 
+static struct _IO_jump_t _IO_wproc_jumps = {
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_new_file_finish),
+  JUMP_INIT(overflow, _IO_new_file_overflow),
+  JUMP_INIT(underflow, _IO_new_file_underflow),
+  JUMP_INIT(uflow, _IO_default_uflow),
+  JUMP_INIT(pbackfail, _IO_default_pbackfail),
+  JUMP_INIT(xsputn, _IO_new_file_xsputn),
+  JUMP_INIT(xsgetn, _IO_default_xsgetn),
+  JUMP_INIT(seekoff, _IO_new_file_seekoff),
+  JUMP_INIT(seekpos, _IO_default_seekpos),
+  JUMP_INIT(setbuf, _IO_new_file_setbuf),
+  JUMP_INIT(sync, _IO_new_file_sync),
+  JUMP_INIT(doallocate, _IO_file_doallocate),
+  JUMP_INIT(read, _IO_file_read),
+  JUMP_INIT(write, _IO_new_file_write),
+  JUMP_INIT(seek, _IO_file_seek),
+  JUMP_INIT(close, _IO_new_proc_close),
+  JUMP_INIT(stat, _IO_file_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};
+
 #if defined PIC && DO_VERSIONING
 strong_alias (_IO_new_popen, __new_popen)
 default_symbol_version (_IO_new_popen, _IO_popen, GLIBC_2.1);
diff --git a/libio/ioputs.c b/libio/ioputs.c
index 9ed8fe60a2..954b0f294f 100644
--- a/libio/ioputs.c
+++ b/libio/ioputs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -30,16 +30,17 @@ int
 _IO_puts (str)
      const char *str;
 {
-  int result;
+  int result = EOF;
   _IO_size_t len = strlen (str);
   _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
 			    _IO_stdout);
   _IO_flockfile (_IO_stdout);
-  if (_IO_sputn (_IO_stdout, str, len) == len
+
+  if (_IO_fwide (_IO_stdout, -1) == -1
+      && _IO_sputn (_IO_stdout, str, len) == len
       && _IO_putc_unlocked ('\n', _IO_stdout) != EOF)
     result = len + 1;
-  else
-    result = EOF;
+
   _IO_funlockfile (_IO_stdout);
   _IO_cleanup_region_end (0);
   return result;
diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c
index 4a951dd7c1..4bd1be1e95 100644
--- a/libio/ioseekoff.c
+++ b/libio/ioseekoff.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -24,27 +24,27 @@
    General Public License.  */
 
 #include <libioP.h>
-#include <errno.h> 
-#ifndef errno 
-extern int errno; 
-#endif 
-#ifndef __set_errno 
-# define __set_errno(Val) errno = (Val)  
-#endif 
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
      _IO_off64_t offset;
      int dir;
      int mode;
 {
-  _IO_fpos64_t retval;
+  _IO_off64_t retval;
 
-  if (dir != _IO_seek_cur && dir != _IO_seek_set && dir != _IO_seek_end) 
-    { 
-      __set_errno (EINVAL); 
-      return EOF; 
+  if (dir != _IO_seek_cur && dir != _IO_seek_set && dir != _IO_seek_end)
+    {
+      __set_errno (EINVAL);
+      return EOF;
     }
 
   /* If we have a backup buffer, get rid of it, since the __seekoff
diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c
index c81c333676..3e692dae82 100644
--- a/libio/ioseekpos.c
+++ b/libio/ioseekpos.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -25,13 +25,13 @@
 
 #include <libioP.h>
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_seekpos (fp, pos, mode)
      _IO_FILE *fp;
-     _IO_fpos64_t pos;
+     _IO_off64_t pos;
      int mode;
 {
-  _IO_fpos64_t retval;
+  _IO_off64_t retval;
 
   /* If we have a backup buffer, get rid of it, since the __seekoff
      callback may not know to do the right thing about it.
diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c
index d615da570c..d119cd0032 100644
--- a/libio/iosetbuffer.c
+++ b/libio/iosetbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -38,6 +38,9 @@ _IO_setbuffer (fp, buf, size)
   if (!buf)
     size = 0;
   (void) _IO_SETBUF (fp, buf, size);
+  if (fp->_mode == 0)
+    /* We also have to set the buffer using the wide char function.  */
+    (*fp->_wide_data->_wide_vtable->__setbuf) (fp, buf, size);
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
 }
diff --git a/libio/iosetvbuf.c b/libio/iosetvbuf.c
index 02f4eefb5e..b9ef31a278 100644
--- a/libio/iosetvbuf.c
+++ b/libio/iosetvbuf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -90,6 +90,10 @@ _IO_setvbuf (fp, buf, mode, size)
       goto unlock_return;
     }
   result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0;
+  if (result == 0 && fp->_mode > 0)
+    /* We also have to set the buffer using the wide char function.  */
+    result = ((*fp->_wide_data->_wide_vtable->__setbuf) (fp, buf, size) == NULL
+	      ? EOF : 0);
 unlock_return:
   _IO_funlockfile (fp);
   _IO_cleanup_region_end (0);
diff --git a/libio/ioungetwc.c b/libio/ioungetwc.c
new file mode 100644
index 0000000000..88b4162c32
--- /dev/null
+++ b/libio/ioungetwc.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wint_t
+ungetwc (c, fp)
+     wint_t c;
+     _IO_FILE *fp;
+{
+  int result;
+  CHECK_FILE (fp, WEOF);
+  if (c == WEOF)
+    return WEOF;
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  result = _IO_sputbackwc (fp, c);
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/iovdprintf.c b/libio/iovdprintf.c
index d95af4742f..b951006975 100644
--- a/libio/iovdprintf.c
+++ b/libio/iovdprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -36,12 +36,13 @@ _IO_vdprintf (d, format, arg)
 #ifdef _IO_MTSAFE_IO
   _IO_lock_t lock;
 #endif
+  struct _IO_wide_data wd;
   int done;
 
 #ifdef _IO_MTSAFE_IO
   tmpfil.file._lock = &lock;
 #endif
-  _IO_init (&tmpfil.file, 0);
+  _IO_no_init (&tmpfil.file, 0, 0, &wd, &_IO_wfile_jumps);
   _IO_JUMPS (&tmpfil.file) = &_IO_file_jumps;
   _IO_file_init (&tmpfil.file);
 #if  !_IO_UNIFIED_JUMPTABLES
diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c
index a1ece2da47..84c24d8d59 100644
--- a/libio/iovsprintf.c
+++ b/libio/iovsprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -41,7 +41,7 @@ _IO_vsprintf (string, format, args)
 #ifdef _IO_MTSAFE_IO
   sf._sbf._f._lock = &lock;
 #endif
-  _IO_init (&sf._sbf._f, 0);
+  _IO_no_init (&sf._sbf._f, 0, -1, NULL, NULL);
   _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps;
   _IO_str_init_static (&sf._sbf._f, string, -1, string);
   ret = _IO_vfprintf (&sf._sbf._f, format, args);
diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c
index 923e8290a4..2b1e44dfd8 100644
--- a/libio/iovsscanf.c
+++ b/libio/iovsscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -38,7 +38,7 @@ _IO_vsscanf (string, format, args)
   _IO_lock_t lock;
   sf._sbf._f._lock = &lock;
 #endif
-  _IO_init (&sf._sbf._f, 0);
+  _IO_no_init (&sf._sbf._f, 0, -1, NULL, NULL);
   _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps;
   _IO_str_init_static (&sf._sbf._f, (char*)string, 0, NULL);
   ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL);
diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c
new file mode 100644
index 0000000000..f0ab62a19c
--- /dev/null
+++ b/libio/iovswscanf.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include "strfile.h"
+#include <wchar.h>
+
+int
+vswscanf (string, format, args)
+     const wchar_t *string;
+     const wchar_t *format;
+     _IO_va_list args;
+{
+  int ret;
+  _IO_strfile sf;
+  struct _IO_wide_data wd;
+#ifdef _IO_MTSAFE_IO
+  _IO_lock_t lock;
+  sf._sbf._f._lock = &lock;
+#endif
+  _IO_no_init (&sf._sbf._f, 0, 1, &wd, &_IO_wstr_jumps);
+  _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps;
+  _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL);
+  ret = _IO_vfwscanf (&sf._sbf._f, format, args, NULL);
+  return ret;
+}
diff --git a/libio/iowpadn.c b/libio/iowpadn.c
new file mode 100644
index 0000000000..b4904589a2
--- /dev/null
+++ b/libio/iowpadn.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+
+#define PADSIZE 16
+static wchar_t const blanks[PADSIZE] =
+{
+  L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ',
+  L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' '
+};
+static wchar_t const zeroes[PADSIZE] =
+{
+  L'0', L'0', L'0', L'0', L'0', L'0', L'0', L'0',
+  L'0', L'0', L'0', L'0', L'0', L'0', L'0', L'0'
+};
+
+_IO_ssize_t
+_IO_wpadn (fp, pad, count)
+      _IO_FILE *fp;
+      wint_t pad;
+      _IO_ssize_t count;
+{
+  wchar_t padbuf[PADSIZE];
+  const wchar_t *padptr;
+  int i;
+  _IO_size_t written = 0;
+  _IO_size_t w;
+
+  if (pad == L' ')
+    padptr = blanks;
+  else if (pad == L'0')
+    padptr = zeroes;
+  else
+    {
+      for (i = PADSIZE; --i >= 0; )
+	padbuf[i] = pad;
+      padptr = padbuf;
+    }
+  for (i = count; i >= PADSIZE; i -= PADSIZE)
+    {
+      w = _IO_sputn (fp, (char *) padptr, PADSIZE);
+      written += w;
+      if (w != PADSIZE)
+	return written;
+    }
+
+  if (i > 0)
+    {
+      w = _IO_sputn (fp, (char *) padptr, i);
+      written += w;
+    }
+  return written;
+}
diff --git a/libio/libio.h b/libio/libio.h
index b4be610fbd..a3852886fc 100644
--- a/libio/libio.h
+++ b/libio/libio.h
@@ -37,10 +37,12 @@
 #define _IO_off64_t _G_off64_t
 #define _IO_pid_t _G_pid_t
 #define _IO_uid_t _G_uid_t
+#define _IO_iconv_t _G_iconv_t
 #define _IO_HAVE_SYS_WAIT _G_HAVE_SYS_WAIT
 #define _IO_HAVE_ST_BLKSIZE _G_HAVE_ST_BLKSIZE
 #define _IO_BUFSIZ _G_BUFSIZ
 #define _IO_va_list _G_va_list
+#define _IO_wint_t _G_wint_t
 
 #ifdef _G_NEED_STDARG_H
 /* This define avoids name pollution if we're using GNU stdarg.h */
@@ -186,6 +188,70 @@ struct _IO_marker {
 #endif
 };
 
+/* This is the structure from the libstdc++ codecvt class.  */
+enum __codecvt_result
+{
+  __codecvt_ok,
+  __codecvt_partial,
+  __codecvt_error,
+  __codecvt_noconv
+};
+
+/* The order of the elements in the following struct must match the order
+   of the virtual functions in the libstdc++ codecvt class.  */
+struct _IO_codecvt
+{
+  void (*__codecvt_destr) __P ((struct _IO_codecvt *));
+  enum __codecvt_result (*__codecvt_do_out) __P ((struct _IO_codecvt *,
+						  __mbstate_t *,
+						  const wchar_t *,
+						  const wchar_t *,
+						  const wchar_t **, char *,
+						  char *, char **));
+  enum __codecvt_result (*__codecvt_do_unshift) __P ((struct _IO_codecvt *,
+						      __mbstate_t *, char *,
+						      char *, char **));
+  enum __codecvt_result (*__codecvt_do_in) __P ((struct _IO_codecvt *,
+						 __mbstate_t *,
+						 const char *, const char *,
+						 const char **, wchar_t *,
+						 wchar_t *, wchar_t **));
+  int (*__codecvt_do_encoding) __P ((struct _IO_codecvt *));
+  int (*__codecvt_do_always_noconv) __P ((struct _IO_codecvt *));
+  int (*__codecvt_do_length) __P ((struct _IO_codecvt *, __mbstate_t *,
+				   const char *, const char *, _IO_size_t));
+  int (*__codecvt_do_max_length) __P ((struct _IO_codecvt *));
+
+  _IO_iconv_t __cd_in;
+  _IO_iconv_t __cd_out;
+};
+
+/* Extra data for wide character streams.  */
+struct _IO_wide_data
+{
+  wchar_t *_IO_read_ptr;	/* Current read pointer */
+  wchar_t *_IO_read_end;	/* End of get area. */
+  wchar_t *_IO_read_base;	/* Start of putback+get area. */
+  wchar_t *_IO_write_base;	/* Start of put area. */
+  wchar_t *_IO_write_ptr;	/* Current put pointer. */
+  wchar_t *_IO_write_end;	/* End of put area. */
+  wchar_t *_IO_buf_base;	/* Start of reserve area. */
+  wchar_t *_IO_buf_end;		/* End of reserve area. */
+  /* The following fields are used to support backing up and undo. */
+  wchar_t *_IO_save_base;	/* Pointer to start of non-current get area. */
+  wchar_t *_IO_backup_base;	/* Pointer to first valid character of
+				   backup area */
+  wchar_t *_IO_save_end;	/* Pointer to end of non-current get area. */
+
+  __mbstate_t _IO_state;
+  __mbstate_t _IO_last_state;
+  struct _IO_codecvt _codecvt;
+
+  wchar_t _shortbuf[1];
+
+  struct _IO_jump_t *_wide_vtable;
+};
+
 struct _IO_FILE {
   int _flags;		/* High-order word is _IO_MAGIC; rest is flags. */
 #define _IO_file_flags _flags
@@ -231,8 +297,12 @@ struct _IO_FILE_complete
 #endif
 #if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
   _IO_off64_t _offset;
+  /* Wide character stream stuff.  */
+  struct _IO_codecvt *_codecvt;
+  struct _IO_wide_data *_wide_data;
+  int _mode;
   /* Make sure we don't get into trouble again.  */
-  int _unused2[16];
+  char _unused2[15 * sizeof (int) - 2 * sizeof (void *)];
 #endif
 };
 
@@ -318,6 +388,9 @@ extern "C" {
 extern int __underflow __P ((_IO_FILE *));
 extern int __uflow __P ((_IO_FILE *));
 extern int __overflow __P ((_IO_FILE *, int));
+extern _IO_wint_t __wunderflow __P ((_IO_FILE *));
+extern _IO_wint_t __wuflow __P ((_IO_FILE *));
+extern _IO_wint_t __woverflow __P ((_IO_FILE *, _IO_wint_t));
 
 #define _IO_getc_unlocked(_fp) \
        ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow (_fp) \
@@ -331,16 +404,44 @@ extern int __overflow __P ((_IO_FILE *, int));
     ? __overflow (_fp, (unsigned char) (_ch)) \
     : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
 
+#define _IO_getwc_unlocked(_fp) \
+  ((_fp)->_wide_data->_IO_read_ptr >= (_fp)->_wide_data->_IO_read_end \
+   ? __wuflow (_fp) : (_IO_wint_t) *(_fp)->_wide_data->_IO_read_ptr++)
+#define _IO_putwc_unlocked(_wch, _fp) \
+  ((_fp)->_wide_data->_IO_write_ptr >= (_fp)->_wide_data->_IO_write_end \
+   ? __woverflow (_fp, _wch) \
+   : (_IO_wint_t) (*(_fp)->_wide_data->_IO_write_ptr++ = (_wch)))
+
 #define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
 #define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
 
 extern int _IO_getc __P ((_IO_FILE *__fp));
 extern int _IO_putc __P ((int __c, _IO_FILE *__fp));
+extern _IO_wint_t _IO_getwc __P ((_IO_FILE *__fp));
+extern _IO_wint_t _IO_putwc __P ((_IO_wint_t __wc, _IO_FILE *__fp));
 extern int _IO_feof __P ((_IO_FILE *__fp));
 extern int _IO_ferror __P ((_IO_FILE *__fp));
 
 extern int _IO_peekc_locked __P ((_IO_FILE *__fp));
 
+extern int _IO_fwide __P ((_IO_FILE *__fp, int __mode));
+#if __GNUC__ >= 2
+/* A special optimized version of the function above.  It optimizes the
+   case of initializing an unoriented byte stream.  */
+# define _IO_fwide(__fp, __mode) \
+  ({ int __result = (__mode);						      \
+     if (__result < 0)							      \
+       {								      \
+	 if ((__fp)->_mode == 0)					      \
+	   /* We know that all we have to do is to set the flag.  */	      \
+	   (__fp)->_mode = -1;						      \
+	 __result = (__fp)->_mode;					      \
+       }								      \
+     else								      \
+       __result = _IO_fwide (__fp, __result);				      \
+     __result; })
+#endif
+
 /* This one is for Emacs. */
 #define _IO_PENDING_OUTPUT_COUNT(_fp)	\
 	((_fp)->_IO_write_ptr - (_fp)->_IO_write_base)
@@ -362,15 +463,22 @@ extern int _IO_ftrylockfile __P ((_IO_FILE *));
 
 extern int _IO_vfscanf __P ((_IO_FILE * __restrict, const char * __restrict,
 			     _IO_va_list, int *__restrict));
+extern int _IO_vfwscanf __P ((_IO_FILE * __restrict,
+			      const wchar_t * __restrict,
+			      _IO_va_list, int *__restrict));
 extern int _IO_vfprintf __P ((_IO_FILE *__restrict, const char *__restrict,
 			      _IO_va_list));
+extern int _IO_vfwprintf __P ((_IO_FILE *__restrict, const wchar_t *__restrict,
+			       _IO_va_list));
 extern _IO_ssize_t _IO_padn __P ((_IO_FILE *, int, _IO_ssize_t));
+extern _IO_ssize_t _IO_wpadn __P ((_IO_FILE *, wint_t, _IO_ssize_t));
 extern _IO_size_t _IO_sgetn __P ((_IO_FILE *, void *, _IO_size_t));
 
-extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
-extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int));
+extern _IO_off64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+extern _IO_off64_t _IO_seekpos __P ((_IO_FILE *, _IO_off64_t, int));
 
 extern void _IO_free_backup_area __P ((_IO_FILE *));
+extern void _IO_free_wbackup_area __P ((_IO_FILE *));
 
 #ifdef __cplusplus
 }
diff --git a/libio/libioP.h b/libio/libioP.h
index a9577cec74..6ed79b7169 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -70,6 +70,7 @@ extern "C" {
 #endif
 
 #define _IO_JUMPS(THIS) ((struct _IO_FILE_plus *) (THIS))->vtable
+#define _IO_WIDE_JUMPS(THIS) ((struct _IO_FILE *) (THIS))->_wide_data->_wide_vtable
 #if _IO_JUMPS_OFFSET
 # define _IO_JUMPS_FUNC(THIS) \
  (*(struct _IO_jump_t **) ((void *) &((struct _IO_FILE_plus *) (THIS))->vtable\
@@ -146,8 +147,8 @@ typedef _IO_size_t (*_IO_xsgetn_t) __PMT ((_IO_FILE *FP, void *DATA,
    (MODE==1), or the end of the file (MODE==2).
    It matches the streambuf::seekoff virtual function.
    It is also used for the ANSI fseek function. */
-typedef _IO_fpos64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF,
-					      int DIR, int MODE));
+typedef _IO_off64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF,
+					     int DIR, int MODE));
 #define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3 (__seekoff, FP, OFF, DIR, MODE)
 
 /* The 'seekpos' hook also moves the stream position,
@@ -155,7 +156,7 @@ typedef _IO_fpos64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF,
    It matches the streambuf::seekpos virtual function.
    It is also used for the ANSI fgetpos and fsetpos functions.  */
 /* The _IO_seek_cur and _IO_seek_end options are not allowed. */
-typedef _IO_fpos64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_fpos64_t, int));
+typedef _IO_off64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_off64_t, int));
 #define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2 (__seekpos, FP, POS, FLAGS)
 
 /* The 'setbuf' hook gives a buffer to the file.
@@ -205,7 +206,7 @@ typedef _IO_ssize_t (*_IO_write_t) __PMT ((_IO_FILE *, const void *,
    It generalizes the Unix lseek(2) function.
    It matches the streambuf::sys_seek virtual function, which is
    specific to this implementation. */
-typedef _IO_fpos64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int));
+typedef _IO_off64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int));
 #define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2 (__seek, FP, OFFSET, MODE)
 
 /* The 'sysclose' hook is used to finalize (close, finish up) an
@@ -282,9 +283,6 @@ struct _IO_FILE_plus
 
 /* Generic functions */
 
-extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
-extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int));
-
 extern void _IO_switch_to_main_get_area __P ((_IO_FILE *));
 extern void _IO_switch_to_backup_area __P ((_IO_FILE *));
 extern int _IO_switch_to_get_mode __P ((_IO_FILE *));
@@ -299,56 +297,94 @@ extern void _IO_setb __P ((_IO_FILE *, char *, char *, int));
 extern unsigned _IO_adjust_column __P ((unsigned, const char *, int));
 #define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n)
 
+extern void _IO_switch_to_main_wget_area __P ((_IO_FILE *));
+extern void _IO_switch_to_wbackup_area __P ((_IO_FILE *));
+extern int _IO_switch_to_wget_mode __P ((_IO_FILE *));
+extern void _IO_wsetb __P ((_IO_FILE *, wchar_t *, wchar_t *, int));
+extern wint_t _IO_sputbackwc __P ((_IO_FILE *, wint_t));
+extern wint_t _IO_sungetwc __P ((_IO_FILE *));
+extern void _IO_wdoallocbuf __P ((_IO_FILE *));
+extern void _IO_unsave_wmarkers __P ((_IO_FILE *));
+extern void _IO_wsetb __P ((_IO_FILE *, wchar_t *, wchar_t *, int));
+extern unsigned _IO_adjust_wcolumn __P ((unsigned, const wchar_t *, int));
+
 /* Marker-related function. */
 
 extern void _IO_init_marker __P ((struct _IO_marker *, _IO_FILE *));
+extern void _IO_init_wmarker __P ((struct _IO_marker *, _IO_FILE *));
 extern void _IO_remove_marker __P ((struct _IO_marker *));
 extern int _IO_marker_difference __P ((struct _IO_marker *,
 				       struct _IO_marker *));
 extern int _IO_marker_delta __P ((struct _IO_marker *));
+extern int _IO_wmarker_delta __P ((struct _IO_marker *));
 extern int _IO_seekmark __P ((_IO_FILE *, struct _IO_marker *, int));
+extern int _IO_seekwmark __P ((_IO_FILE *, struct _IO_marker *, int));
 
 /* Default jumptable functions. */
 
 extern int _IO_default_underflow __P ((_IO_FILE *));
 extern int _IO_default_uflow __P ((_IO_FILE *));
+extern wint_t _IO_wdefault_uflow __P ((_IO_FILE *));
 extern int _IO_default_doallocate __P ((_IO_FILE *));
+extern int _IO_wdefault_doallocate __P ((_IO_FILE *));
 extern void _IO_default_finish __P ((_IO_FILE *, int));
+extern void _IO_wdefault_finish __P ((_IO_FILE *, int));
 extern int _IO_default_pbackfail __P ((_IO_FILE *, int));
+extern wint_t _IO_wdefault_pbackfail __P ((_IO_FILE *, wint_t));
 extern _IO_FILE* _IO_default_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t));
+extern _IO_FILE* _IO_wdefault_setbuf __P ((_IO_FILE *, wchar_t *,
+					   _IO_ssize_t));
 extern _IO_size_t _IO_default_xsputn __P ((_IO_FILE *, const void *,
 					   _IO_size_t));
+extern _IO_size_t _IO_wdefault_xsputn __P ((_IO_FILE *, const void *,
+					    _IO_size_t));
 extern _IO_size_t _IO_default_xsgetn __P ((_IO_FILE *, void *, _IO_size_t));
-extern _IO_fpos64_t _IO_default_seekoff __P ((_IO_FILE *,
-					      _IO_off64_t, int, int));
-extern _IO_fpos64_t _IO_default_seekpos __P ((_IO_FILE *,
-					      _IO_fpos64_t, int));
+extern _IO_size_t _IO_wdefault_xsgetn __P ((_IO_FILE *, void *, _IO_size_t));
+extern _IO_off64_t _IO_default_seekoff __P ((_IO_FILE *,
+					     _IO_off64_t, int, int));
+extern _IO_off64_t _IO_default_seekpos __P ((_IO_FILE *, _IO_off64_t, int));
 extern _IO_ssize_t _IO_default_write __P ((_IO_FILE *, const void *,
 					   _IO_ssize_t));
 extern _IO_ssize_t _IO_default_read __P ((_IO_FILE *, void *, _IO_ssize_t));
 extern int _IO_default_stat __P ((_IO_FILE *, void *));
-extern _IO_fpos64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int));
+extern _IO_off64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int));
 extern int _IO_default_sync __P ((_IO_FILE *));
 #define _IO_default_close ((_IO_close_t) _IO_default_sync)
 extern int _IO_default_showmanyc __P ((_IO_FILE *));
 extern void _IO_default_imbue __P ((_IO_FILE *, void *));
 
 extern struct _IO_jump_t _IO_file_jumps;
+extern struct _IO_jump_t _IO_wfile_jumps;
 extern struct _IO_jump_t _IO_old_file_jumps;
 extern struct _IO_jump_t _IO_streambuf_jumps;
 extern struct _IO_jump_t _IO_proc_jumps;
 extern struct _IO_jump_t _IO_old_proc_jumps;
 extern struct _IO_jump_t _IO_str_jumps;
+extern struct _IO_jump_t _IO_wstr_jumps;
 extern int _IO_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
 extern int _IO_new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
 extern int _IO_old_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
+extern int _IO_wdo_write __P ((_IO_FILE *, const wchar_t *, _IO_size_t));
 extern int _IO_flush_all __P ((void));
 extern int _IO_cleanup __P ((void));
 extern void _IO_flush_all_linebuffered __P ((void));
+extern int _IO_new_fgetpos __P ((_IO_FILE *, _IO_fpos_t *));
+extern int _IO_old_fgetpos __P ((_IO_FILE *, _IO_fpos_t *));
+extern int _IO_new_fsetpos __P ((_IO_FILE *, const _IO_fpos_t *));
+extern int _IO_old_fsetpos __P ((_IO_FILE *, const _IO_fpos_t *));
+extern int _IO_new_fgetpos64 __P ((_IO_FILE *, _IO_fpos64_t *));
+extern int _IO_old_fgetpos64 __P ((_IO_FILE *, _IO_fpos64_t *));
+extern int _IO_new_fsetpos64 __P ((_IO_FILE *, const _IO_fpos64_t *));
+extern int _IO_old_fsetpos64 __P ((_IO_FILE *, const _IO_fpos64_t *));
+
 
 #define _IO_do_flush(_f) \
-  _IO_do_write(_f, (_f)->_IO_write_base, \
-	       (_f)->_IO_write_ptr-(_f)->_IO_write_base)
+  ((_f)->_mode <= 0							      \
+   ? _IO_do_write(_f, (_f)->_IO_write_base,				      \
+		  (_f)->_IO_write_ptr-(_f)->_IO_write_base)		      \
+   : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base,		      \
+		   ((_f)->_wide_data->_IO_write_ptr			      \
+		    - (_f)->_wide_data->_IO_write_base)))
 #define _IO_old_do_flush(_f) \
   _IO_old_do_write(_f, (_f)->_IO_write_base, \
 		   (_f)->_IO_write_ptr-(_f)->_IO_write_base)
@@ -357,18 +393,29 @@ extern void _IO_flush_all_linebuffered __P ((void));
        ((fp)->_flags = ((fp)->_flags & ~(mask)) | ((f) & (mask)))
 #define _IO_setg(fp, eb, g, eg)  ((fp)->_IO_read_base = (eb),\
 	(fp)->_IO_read_ptr = (g), (fp)->_IO_read_end = (eg))
+#define _IO_wsetg(fp, eb, g, eg)  ((fp)->_wide_data->_IO_read_base = (eb),\
+	(fp)->_wide_data->_IO_read_ptr = (g), \
+	(fp)->_wide_data->_IO_read_end = (eg))
 #define _IO_setp(__fp, __p, __ep) \
-       ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr = __p, (__fp)->_IO_write_end = (__ep))
+       ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr \
+	= __p, (__fp)->_IO_write_end = (__ep))
+#define _IO_wsetp(__fp, __p, __ep) \
+       ((__fp)->_wide_data->_IO_write_base \
+	= (__fp)->_wide_data->_IO_write_ptr = __p, \
+	(__fp)->_wide_data->_IO_write_end = (__ep))
 #define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
+#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL)
 #define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
 #define _IO_have_markers(fp) ((fp)->_markers != NULL)
 #define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
+#define _IO_wblen(fp) ((fp)->_wide_data->_IO_buf_end \
+		       - (fp)->_wide_data->_IO_buf_base)
 
 /* Jumptable functions for files. */
 
 extern int _IO_file_doallocate __P ((_IO_FILE *));
 extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t));
-extern _IO_fpos64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+extern _IO_off64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
 extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t));
 extern _IO_size_t _IO_file_xsgetn __P ((_IO_FILE *, void *, _IO_size_t));
 extern int _IO_file_stat __P ((_IO_FILE *, void *));
@@ -387,7 +434,7 @@ extern _IO_ssize_t _IO_file_write __P ((_IO_FILE *, const void *,
 extern _IO_ssize_t _IO_file_read __P ((_IO_FILE *, void *, _IO_ssize_t));
 extern int _IO_file_sync __P ((_IO_FILE *));
 extern int _IO_file_close_it __P ((_IO_FILE *));
-extern _IO_fpos64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int));
+extern _IO_off64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int));
 extern void _IO_file_finish __P ((_IO_FILE *, int));
 
 extern _IO_FILE* _IO_new_file_attach __P ((_IO_FILE *, int));
@@ -395,19 +442,21 @@ extern int _IO_new_file_close_it __P ((_IO_FILE *));
 extern void _IO_new_file_finish __P ((_IO_FILE *, int));
 extern _IO_FILE* _IO_new_file_fopen __P ((_IO_FILE *, const char *, const char *,
 					  int));
+extern void _IO_no_init __P ((_IO_FILE *, int, int, struct _IO_wide_data *,
+			      struct _IO_jump_t *));
 extern void _IO_new_file_init __P ((_IO_FILE *));
 extern _IO_FILE* _IO_new_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t));
 extern int _IO_new_file_sync __P ((_IO_FILE *));
 extern int _IO_new_file_underflow __P ((_IO_FILE *));
 extern int _IO_new_file_overflow __P ((_IO_FILE *, int));
-extern _IO_fpos64_t _IO_new_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+extern _IO_off64_t _IO_new_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
 extern _IO_ssize_t _IO_new_file_write __P ((_IO_FILE *, const void *,
 					    _IO_ssize_t));
 extern _IO_size_t _IO_new_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t));
 
 extern _IO_FILE* _IO_old_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t));
-extern _IO_fpos64_t _IO_old_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int,
-					       int));
+extern _IO_off64_t _IO_old_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int,
+					      int));
 extern _IO_size_t _IO_old_file_xsputn __P ((_IO_FILE *, const void *,
 					    _IO_size_t));
 extern int _IO_old_file_underflow __P ((_IO_FILE *));
@@ -422,6 +471,15 @@ extern int _IO_old_file_sync __P ((_IO_FILE *));
 extern int _IO_old_file_close_it __P ((_IO_FILE *));
 extern void _IO_old_file_finish __P ((_IO_FILE *, int));
 
+extern int _IO_wfile_doallocate __P ((_IO_FILE *));
+extern _IO_size_t _IO_wfile_xsputn __P ((_IO_FILE *, const void *,
+					 _IO_size_t));
+extern _IO_FILE* _IO_wfile_setbuf __P ((_IO_FILE *, wchar_t *, _IO_ssize_t));
+extern wint_t _IO_wfile_sync __P ((_IO_FILE *));
+extern wint_t _IO_wfile_underflow __P ((_IO_FILE *));
+extern wint_t _IO_wfile_overflow __P ((_IO_FILE *, wint_t));
+extern _IO_off64_t _IO_wfile_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+
 /* Jumptable functions for proc_files. */
 extern _IO_FILE* _IO_proc_open __P ((_IO_FILE *, const char *, const char *));
 extern _IO_FILE* _IO_new_proc_open __P ((_IO_FILE *, const char *, const char *));
@@ -434,7 +492,7 @@ extern int _IO_old_proc_close __P ((_IO_FILE *));
 extern int _IO_str_underflow __P ((_IO_FILE *));
 extern int _IO_str_overflow __P ((_IO_FILE *, int));
 extern int _IO_str_pbackfail __P ((_IO_FILE *, int));
-extern _IO_fpos64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+extern _IO_off64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
 extern void _IO_str_finish __P ((_IO_FILE *, int));
 
 /* Other strfile functions */
@@ -442,6 +500,16 @@ extern void _IO_str_init_static __P ((_IO_FILE *, char *, int, char *));
 extern void _IO_str_init_readonly __P ((_IO_FILE *, const char *, int));
 extern _IO_ssize_t _IO_str_count __P ((_IO_FILE *));
 
+/* And the wide character versions.  */
+extern void _IO_wstr_init_static __P ((_IO_FILE *, wchar_t *, int, wchar_t *));
+extern void _IO_wstr_init_readonly __P ((_IO_FILE *, const char *, int));
+extern _IO_ssize_t _IO_wstr_count __P ((_IO_FILE *));
+extern _IO_wint_t _IO_wstr_overflow __P ((_IO_FILE *, _IO_wint_t));
+extern _IO_wint_t _IO_wstr_underflow __P ((_IO_FILE *));
+extern _IO_off64_t _IO_wstr_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
+extern _IO_wint_t _IO_wstr_pbackfail __P ((_IO_FILE *, _IO_wint_t));
+extern void _IO_wstr_finish __P ((_IO_FILE *, int));
+
 extern int _IO_vasprintf __P ((char **result_ptr, __const char *format,
 			       _IO_va_list args));
 extern int _IO_vdprintf __P ((int d, __const char *format, _IO_va_list arg));
@@ -453,6 +521,10 @@ extern _IO_size_t _IO_getline __P ((_IO_FILE *,char *, _IO_size_t, int, int));
 extern _IO_size_t _IO_getline_info __P ((_IO_FILE *,char *, _IO_size_t,
 					 int, int, int *));
 extern _IO_ssize_t _IO_getdelim __P ((char **, _IO_size_t *, int, _IO_FILE *));
+extern _IO_size_t _IO_getwline __P ((_IO_FILE *,wchar_t *, _IO_size_t, wint_t,
+				     int));
+extern _IO_size_t _IO_getwline_info __P ((_IO_FILE *,wchar_t *, _IO_size_t,
+					  wint_t, int, wint_t *));
 extern double _IO_strtod __P ((const char *, char **));
 extern char *_IO_dtoa __P ((double __d, int __mode, int __ndigits,
 			    int *__decpt, int *__sign, char **__rve));
@@ -516,7 +588,15 @@ extern void (*_IO_cleanup_registration_needed) __PMT ((void));
 	  (_B) = (char *) mmap (0, ROUND_TO_PAGE (_S),			      \
 				PROT_READ | PROT_WRITE,			      \
 				MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);	      \
-	  if ((_B) == (char *) -1)					      \
+	  if ((_B) == (char *) MAP_FAILED)				      \
+	    return (_R);						      \
+       } while (0)
+# define ALLOC_WBUF(_B, _S, _R) \
+       do {								      \
+	  (_B) = (wchar_t *) mmap (0, ROUND_TO_PAGE (_S),		      \
+				   PROT_READ | PROT_WRITE,		      \
+				   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);	      \
+	  if ((_B) == (wchar_t *) MAP_FAILED)				      \
 	    return (_R);						      \
        } while (0)
 
@@ -544,26 +624,17 @@ extern int _IO_close __P ((int));
 extern int _IO_fstat __P ((int, struct stat *));
 extern int _IO_vscanf __P ((const char *, _IO_va_list));
 
-/* Operations on _IO_fpos64_t.
-   Normally, these are trivial, but we provide hooks for configurations
-   where an _IO_fpos64_t is a struct.
-   Note that _IO_off64_t must be an integral type. */
-
-/* _IO_pos_BAD is an _IO_fpos64_t value indicating error, unknown, or EOF. */
+/* _IO_pos_BAD is an _IO_off64_t value indicating error, unknown, or EOF. */
 #ifndef _IO_pos_BAD
-# define _IO_pos_BAD ((_IO_fpos64_t) -1)
+# define _IO_pos_BAD ((_IO_off64_t) -1)
 #endif
-/* _IO_pos_as_off converts an _IO_fpos64_t value to an _IO_off64_t value. */
-#ifndef _IO_pos_as_off
-# define _IO_pos_as_off(__pos) ((_IO_off64_t) (__pos))
-#endif
-/* _IO_pos_adjust adjust an _IO_fpos64_t by some number of bytes. */
+/* _IO_pos_adjust adjust an _IO_off64_t by some number of bytes. */
 #ifndef _IO_pos_adjust
-# define _IO_pos_adjust(__pos, __delta) ((__pos) += (__delta))
+# define _IO_pos_adjust(pos, delta) ((pos) += (delta))
 #endif
-/* _IO_pos_0 is an _IO_fpos64_t value indicating beginning of file. */
+/* _IO_pos_0 is an _IO_off64_t value indicating beginning of file. */
 #ifndef _IO_pos_0
-# define _IO_pos_0 ((_IO_fpos64_t) 0)
+# define _IO_pos_0 ((_IO_off64_t) 0)
 #endif
 
 #ifdef __cplusplus
@@ -573,15 +644,16 @@ extern int _IO_vscanf __P ((const char *, _IO_va_list));
 #ifdef _IO_MTSAFE_IO
 /* check following! */
 # ifdef _IO_USE_OLD_IO_FILE
-#  define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \
+#  define FILEBUF_LITERAL(CHAIN, FLAGS, FD, WDP) \
        { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \
 	   0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock }
 # else
-#  define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \
+#  define FILEBUF_LITERAL(CHAIN, FLAGS, FD, WDP) \
        { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \
-	   0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock, _IO_pos_BAD }
+	 0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock, _IO_pos_BAD,\
+	 NULL, WDP, 0 }
 # endif
 #else
 # ifdef _IO_USE_OLD_IO_FILE
@@ -592,7 +664,8 @@ extern int _IO_vscanf __P ((const char *, _IO_va_list));
 #  define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \
        { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \
-	   0, _IO_pos_BAD, 0, 0, { 0 }, 0, _IO_pos_BAD }
+	 0, _IO_pos_BAD, 0, 0, { 0 }, 0, _IO_pos_BAD, \
+	 NULL, WDP, 0 }
 # endif
 #endif
 
diff --git a/libio/memstream.c b/libio/memstream.c
index 71aab2f6ea..840d0e6968 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -32,9 +32,11 @@ struct _IO_FILE_memstream
 
 static int _IO_mem_sync __P ((_IO_FILE* fp));
 static void _IO_mem_finish __P ((_IO_FILE* fp, int));
+static int _IO_wmem_sync __P ((_IO_FILE* fp));
+static void _IO_wmem_finish __P ((_IO_FILE* fp, int));
 
 
-static const struct _IO_jump_t _IO_mem_jumps =
+static struct _IO_jump_t _IO_mem_jumps =
 {
   JUMP_INIT_DUMMY,
   JUMP_INIT (finish, _IO_mem_finish),
@@ -58,6 +60,30 @@ static const struct _IO_jump_t _IO_mem_jumps =
   JUMP_INIT(imbue, _IO_default_imbue)
 };
 
+static struct _IO_jump_t _IO_wmem_jumps =
+{
+  JUMP_INIT_DUMMY,
+  JUMP_INIT (finish, (_IO_finish_t) _IO_wmem_finish),
+  JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow),
+  JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow),
+  JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+  JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
+  JUMP_INIT (xsputn, (_IO_xsputn_t) _IO_wdefault_xsputn),
+  JUMP_INIT (xsgetn, (_IO_xsgetn_t) _IO_wdefault_xsgetn),
+  JUMP_INIT (seekoff, _IO_wstr_seekoff),
+  JUMP_INIT (seekpos, _IO_default_seekpos),
+  JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf),
+  JUMP_INIT (sync, (_IO_sync_t) _IO_wmem_sync),
+  JUMP_INIT (doallocate, _IO_wdefault_doallocate),
+  JUMP_INIT (read, _IO_default_read),
+  JUMP_INIT (write, _IO_default_write),
+  JUMP_INIT (seek, _IO_default_seek),
+  JUMP_INIT (close, _IO_default_close),
+  JUMP_INIT (stat, _IO_default_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};
+
 /* Open a stream that writes into a malloc'd buffer that is expanded as
    necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
    and the number of characters written on fflush or fclose.  */
@@ -72,6 +98,7 @@ open_memstream (bufloc, sizeloc)
 #ifdef _IO_MTSAFE_IO
     _IO_lock_t lock;
 #endif
+    struct _IO_wide_data wd;
   } *new_f;
   char *buf;
 
@@ -85,7 +112,7 @@ open_memstream (bufloc, sizeloc)
   buf = malloc (_IO_BUFSIZ);
   if (buf == NULL)
     return NULL;
-  _IO_init (&new_f->fp._sf._sbf._f, 0);
+  _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps);
   _IO_JUMPS (&new_f->fp._sf._sbf._f) = &_IO_mem_jumps;
   _IO_str_init_static (&new_f->fp._sf._sbf._f, buf, _IO_BUFSIZ, buf);
   new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
@@ -144,3 +171,55 @@ _IO_mem_finish (fp, dummy)
 
   _IO_default_finish (fp, 0);
 }
+
+
+static int
+_IO_wmem_sync (fp)
+     _IO_FILE* fp;
+{
+  struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
+  int res;
+
+  res = _IO_default_sync (fp);
+  if (res < 0)
+    return res;
+
+  if (fp->_wide_data->_IO_write_ptr == fp->_wide_data->_IO_write_end)
+    {
+      _IO_wstr_overflow (fp, L'\0');
+      --fp->_wide_data->_IO_write_ptr;
+    }
+  else
+    *fp->_wide_data->_IO_write_ptr = '\0';
+
+  *mp->bufloc = (char *) fp->_wide_data->_IO_write_base;
+  *mp->sizeloc = (fp->_wide_data->_IO_write_ptr
+		  - fp->_wide_data->_IO_write_base);
+
+  return 0;
+}
+
+
+static void
+_IO_wmem_finish (fp, dummy)
+     _IO_FILE* fp;
+     int dummy;
+{
+  struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
+
+  *mp->bufloc = (char *) realloc (fp->_wide_data->_IO_write_base,
+				  (fp->_wide_data->_IO_write_ptr
+				   - fp->_wide_data->_IO_write_base + 1)
+				  * sizeof (wchar_t));
+  if (*mp->bufloc != NULL)
+    {
+      ((wchar_t *) (*mp->bufloc))[fp->_wide_data->_IO_write_ptr
+				 - fp->_wide_data->_IO_write_base] = '\0';
+      *mp->sizeloc = (fp->_wide_data->_IO_write_ptr
+		      - fp->_wide_data->_IO_write_base);
+    }
+
+  fp->_wide_data->_IO_buf_base = NULL;
+
+  _IO_default_finish (fp, 0);
+}
diff --git a/libio/obprintf.c b/libio/obprintf.c
index 0e947b25ad..29e09d4281 100644
--- a/libio/obprintf.c
+++ b/libio/obprintf.c
@@ -127,11 +127,11 @@ _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
   new_f.ofile.file.file._lock = &new_f.lock;
 #endif
 
-  _IO_init (&new_f.ofile.file.file, 0);
-  _IO_JUMPS (&new_f.ofile.file.file) = &_IO_obstack_jumps;
+  _IO_no_init (&new_f.ofile.file.file, 0, -1, NULL, NULL);
+  _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
   _IO_str_init_static (&new_f.ofile.file.file, obstack_base (obstack),
-		       obstack_object_size (obstack) + obstack_room (obstack),
-		       obstack_next_free (obstack));
+		       (obstack_object_size (obstack) +
+			obstack_room (obstack)), obstack_next_free (obstack));
   /* Now allocate the rest of the current chunk.  */
   obstack_blank_fast (obstack,
 		      (new_f.ofile.file.file._IO_write_end
diff --git a/libio/oldfileops.c b/libio/oldfileops.c
index fe29a7965b..d65c272d48 100644
--- a/libio/oldfileops.c
+++ b/libio/oldfileops.c
@@ -285,7 +285,7 @@ old_do_write (fp, data, to_do)
     fp->_old_offset = _IO_pos_BAD;
   else if (fp->_IO_read_end != fp->_IO_write_base)
     {
-      _IO_pos_t new_pos
+      _IO_off_t new_pos
 	= _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
       if (new_pos == _IO_pos_BAD)
 	return 0;
@@ -449,14 +449,14 @@ _IO_old_file_sync (fp)
   return retval;
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_old_file_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
      _IO_off64_t offset;
      int dir;
      int mode;
 {
-  _IO_pos_t result;
+  _IO_off_t result;
   _IO_off64_t delta, new_offset;
   long count;
   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
@@ -500,7 +500,7 @@ _IO_old_file_seekoff (fp, offset, dir, mode)
       if (fp->_old_offset == _IO_pos_BAD)
 	goto dumb;
       /* Make offset absolute, assuming current pointer is file_ptr(). */
-      offset += _IO_pos_as_off (fp->_old_offset);
+      offset += fp->_old_offset;
 
       dir = _IO_seek_set;
       break;
@@ -529,7 +529,7 @@ _IO_old_file_seekoff (fp, offset, dir, mode)
       && !_IO_in_backup (fp))
     {
       /* Offset relative to start of main get area. */
-      _IO_pos_t rel_offset = (offset - fp->_old_offset
+      _IO_off_t rel_offset = (offset - fp->_old_offset
 			      + (fp->_IO_read_end - fp->_IO_read_base));
       if (rel_offset >= 0)
 	{
diff --git a/libio/oldiofgetpos.c b/libio/oldiofgetpos.c
new file mode 100644
index 0000000000..2b4d10ad3e
--- /dev/null
+++ b/libio/oldiofgetpos.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <errno.h>
+
+int
+_IO_old_fgetpos (fp, posp)
+     _IO_FILE *fp;
+     _IO_fpos_t *posp;
+{
+  _IO_off_t pos;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
+  if (_IO_in_backup (fp))
+    pos -= fp->_IO_save_end - fp->_IO_save_base;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  if (pos == _IO_pos_BAD)
+    {
+      /* ANSI explicitly requires setting errno to a positive value on
+	 failure.  */
+#ifdef EIO
+      if (errno == 0)
+	__set_errno (EIO);
+#endif
+      return EOF;
+    }
+  posp->__pos = pos;
+  return 0;
+}
+
+#ifdef weak_alias
+symbol_version (_IO_old_fgetpos, _IO_fgetpos, GLIBC_2.0);
+strong_alias (_IO_old_fgetpos, __old_fgetpos)
+symbol_version (__old_fgetpos, fgetpos, GLIBC_2.0);
+#endif
diff --git a/libio/oldiofgetpos64.c b/libio/oldiofgetpos64.c
new file mode 100644
index 0000000000..9695c6f53d
--- /dev/null
+++ b/libio/oldiofgetpos64.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <errno.h>
+
+int
+_IO_old_fgetpos64 (fp, posp)
+     _IO_FILE *fp;
+     _IO_fpos64_t *posp;
+{
+#ifdef _G_LSEEK64
+  _IO_off64_t pos;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
+  if (_IO_in_backup (fp))
+    pos -= fp->_IO_save_end - fp->_IO_save_base;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  if (pos == _IO_pos_BAD)
+    {
+      /* ANSI explicitly requires setting errno to a positive value on
+	 failure.  */
+#ifdef EIO
+      if (errno == 0)
+	__set_errno (EIO);
+#endif
+      return EOF;
+    }
+  posp->__pos = pos;
+  return 0;
+#else
+  __set_errno (ENOSYS);
+  return EOF;
+#endif
+}
+
+#ifdef weak_alias
+symbol_version (_IO_old_fgetpos64, _IO_fgetpos64, GLIBC_2.0);
+strong_alias (_IO_old_fgetpos64, __old_fgetpos64)
+symbol_version (__old_fgetpos64, fgetpos64, GLIBC_2.0);
+#endif
diff --git a/libio/oldiofsetpos.c b/libio/oldiofsetpos.c
new file mode 100644
index 0000000000..87a78d2eea
--- /dev/null
+++ b/libio/oldiofsetpos.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include <libioP.h>
+#include <errno.h>
+
+int
+_IO_old_fsetpos (fp, posp)
+     _IO_FILE *fp;
+     const _IO_fpos_t *posp;
+{
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
+    {
+      /* ANSI explicitly requires setting errno to a positive value on
+	 failure.  */
+#ifdef EIO
+      if (errno == 0)
+	__set_errno (EIO);
+#endif
+      result = EOF;
+    }
+  else
+    result = 0;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
+
+#ifdef weak_alias
+symbol_version (_IO_old_fsetpos, _IO_fsetpos, GLIBC_2.0);
+strong_alias (_IO_old_fsetpos, __old_fsetpos)
+symbol_version (__old_fsetpos, fsetpos, GLIBC_2.0);
+#endif
diff --git a/libio/oldiofsetpos64.c b/libio/oldiofsetpos64.c
new file mode 100644
index 0000000000..9207dd71bd
--- /dev/null
+++ b/libio/oldiofsetpos64.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include <libioP.h>
+#include <errno.h>
+
+int
+_IO_old_fsetpos64 (fp, posp)
+     _IO_FILE *fp;
+     const _IO_fpos64_t *posp;
+{
+#ifdef _G_LSEEK64
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
+    {
+      /* ANSI explicitly requires setting errno to a positive value on
+	 failure.  */
+#ifdef EIO
+      if (errno == 0)
+	__set_errno (EIO);
+#endif
+      result = EOF;
+    }
+  else
+    result = 0;
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+#else
+  __set_errno (ENOSYS);
+  return EOF;
+#endif
+}
+
+#ifdef weak_alias
+symbol_version (_IO_old_fsetpos64, _IO_fsetpos64, GLIBC_2.0);
+strong_alias (_IO_fsetpos64, __old_fsetpos64)
+symbol_version (__old_fsetpos64, _IO_fsetpos64, GLIBC_2.0);
+#endif
diff --git a/libio/oldstdfiles.c b/libio/oldstdfiles.c
index 7781a17449..3629ab8123 100644
--- a/libio/oldstdfiles.c
+++ b/libio/oldstdfiles.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -37,11 +37,12 @@
 #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
   static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \
   struct _IO_FILE_plus NAME \
-    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_old_file_jumps};
+    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, NULL), &_IO_old_file_jumps};
 #else
 #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
+  static struct _IO_wide_data _IO_wide_data_##FD; \
   struct _IO_FILE_plus NAME \
-    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_old_file_jumps};
+    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, NULL), &_IO_old_file_jumps};
 #endif
 
 DEF_STDFILE(_IO_stdin_, 0, 0, _IO_NO_WRITES);
diff --git a/libio/putwc.c b/libio/putwc.c
new file mode 100644
index 0000000000..07557ac8c4
--- /dev/null
+++ b/libio/putwc.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wint_t
+putwc (wc, fp)
+     wint_t wc;
+     _IO_FILE *fp;
+{
+  wint_t result;
+  CHECK_FILE (fp, WEOF);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_flockfile (fp);
+  result = _IO_putwc_unlocked (wc, fp);
+  _IO_funlockfile (fp);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/putwc_u.c b/libio/putwc_u.c
new file mode 100644
index 0000000000..3f7a26fad2
--- /dev/null
+++ b/libio/putwc_u.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+wint_t
+putwc_unlocked (wc, fp)
+     wint_t wc;
+     _IO_FILE *fp;
+{
+  CHECK_FILE (fp, WEOF);
+  return _IO_putc_unlocked (wc, fp);
+}
diff --git a/libio/putwchar.c b/libio/putwchar.c
new file mode 100644
index 0000000000..0a2854f16d
--- /dev/null
+++ b/libio/putwchar.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "libioP.h"
+#include "stdio.h"
+
+wint_t
+putwchar (wc)
+     wint_t wc;
+{
+  wint_t result;
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+			    _IO_stdout);
+  _IO_flockfile (_IO_stdout);
+  result = _IO_putwc_unlocked (wc, _IO_stdout);
+  _IO_funlockfile (_IO_stdout);
+  _IO_cleanup_region_end (0);
+  return result;
+}
diff --git a/libio/putwchar_u.c b/libio/putwchar_u.c
new file mode 100644
index 0000000000..0da7dcfa30
--- /dev/null
+++ b/libio/putwchar_u.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "libioP.h"
+#include "stdio.h"
+
+wint_t
+putwchar_unlocked (c)
+     wint_t c;
+{
+  CHECK_FILE (stdout, WEOF);
+  return _IO_putwc_unlocked (wc, stdout);
+}
diff --git a/libio/stdfiles.c b/libio/stdfiles.c
index 8c09c2c441..6feff4d392 100644
--- a/libio/stdfiles.c
+++ b/libio/stdfiles.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -35,12 +35,18 @@
 #ifdef _IO_MTSAFE_IO
 #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
   static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \
+  static struct _IO_wide_data _IO_wide_data_##FD \
+    = { ._wide_vtable = &_IO_wfile_jumps }; \
   struct _IO_FILE_plus NAME \
-    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_file_jumps};
+    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, &_IO_wide_data_##FD), \
+       &_IO_file_jumps};
 #else
 #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \
+  static struct _IO_wide_data _IO_wide_data_##FD \
+    = { ._wide_vtable = &_IO_wfile_jumps }; \
   struct _IO_FILE_plus NAME \
-    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_file_jumps};
+    = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, &_IO_wide_data_##FD), \
+       &_IO_file_jumps};
 #endif
 
 DEF_STDFILE(_IO_2_1_stdin_, 0, 0, _IO_NO_WRITES);
diff --git a/libio/strops.c b/libio/strops.c
index c3e245f605..83fd794251 100644
--- a/libio/strops.c
+++ b/libio/strops.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -147,10 +147,10 @@ _IO_str_overflow (fp, c)
 	      /*	  __ferror(fp) = 1; */
 	      return EOF;
 	    }
-	  if (fp->_IO_buf_base)
+	  if (old_buf)
 	    {
 	      memcpy (new_buf, old_buf, _IO_blen (fp));
-	      (*((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
+	      (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
 	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
 	      fp->_IO_buf_base = NULL;
 	    }
@@ -205,14 +205,14 @@ _IO_str_count (fp)
 	  - fp->_IO_read_base);
 }
 
-_IO_fpos64_t
+_IO_off64_t
 _IO_str_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
      _IO_off64_t offset;
      int dir;
      int mode;
 {
-  _IO_fpos64_t new_pos;
+  _IO_off64_t new_pos;
 
   if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
     mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
diff --git a/libio/swprintf.c b/libio/swprintf.c
new file mode 100644
index 0000000000..f0cb637b27
--- /dev/null
+++ b/libio/swprintf.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <wchar.h>
+
+/* Write formatted output into S, according to the format string FORMAT.  */
+/* VARARGS3 */
+int
+swprintf (s, n, format)
+     wchar_t *s;
+     size_t n;
+     const wchar_t *format;
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = vswprintf (s, n, format, arg);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/swscanf.c b/libio/swscanf.c
new file mode 100644
index 0000000000..6876d4b793
--- /dev/null
+++ b/libio/swscanf.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1991, 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <wchar.h>
+
+/* Read formatted input from S, according to the format string FORMAT.  */
+/* VARARGS2 */
+int
+swscanf (s, format)
+     const wchar_t *s;
+     const wchar_t *format;
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = vswscanf (s, format, arg);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/tst_swprintf.c b/libio/tst_swprintf.c
new file mode 100644
index 0000000000..67d10a006d
--- /dev/null
+++ b/libio/tst_swprintf.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+  wchar_t buf[100];
+  int n;
+  int result = 0;
+
+  puts ("test 1");
+  n = swprintf (buf, sizeof (buf) / sizeof (buf[0]), L"Hello %s", "world");
+  if (n != 11)
+    {
+      printf ("incorrect return value: %d instead of 11\n", n);
+      result = 1;
+    }
+
+  if (wcscmp (buf, L"Hello world") != 0)
+    {
+      printf ("incorrect string: L\"%ls\" instead of L\"Hello world\"\n", buf);
+      result = 1;
+    }
+
+  puts ("test 2");
+  n = swprintf (buf, sizeof (buf) / sizeof (buf[0]), L"Is this >%g< 3.1?",
+		3.1);
+  if (n != 18)
+{
+      printf ("incorrect return value: %d instead of 18\n", n);
+      result = 1;
+    }
+
+  if (wcscmp (buf, L"Is this >3.1< 3.1?") != 0)
+    {
+      printf ("incorrect string: L\"%ls\" instead of L\"Is this >3.1< 3.1?\"\n",
+	      buf);
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/libio/tst_swscanf.c b/libio/tst_swscanf.c
new file mode 100644
index 0000000000..ce56144bb0
--- /dev/null
+++ b/libio/tst_swscanf.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+  const wchar_t in[] = L"7 + 35 is 42";
+  size_t n;
+  int a, b, c;
+  int result = 0;
+  char buf1[20];
+  wchar_t wbuf2[20];
+  char buf3[20];
+  char c4;
+  wchar_t wc5;
+
+  puts ("Test 1");
+  a = b = c = 0;
+  n = swscanf (in, L"%d + %d is %d", &a, &b, &c);
+  if (n != 3 || a + b != c || c != 42)
+    {
+      printf ("*** FAILED, n = %Zu, a = %d, b = %d, c = %d\n", n, a, b, c);
+      result = 1;
+    }
+
+  puts ("Test 2");
+  n = swscanf (L"one two three !!", L"%s %S %s %c%C",
+	       buf1, wbuf2, buf3, &c4, &wc5);
+  if (n != 5 || strcmp (buf1, "one") != 0 || wcscmp (wbuf2, L"two") != 0
+      || strcmp (buf3, "three") != 0 || c4 != '!' || wc5 != L'!')
+    {
+      printf ("*** FAILED, n = %Zu, buf1 = \"%s\", wbuf2 = L\"%S\", buf3 = \"%s\", c4 = '%c', wc5 = L'%C'\n",
+	      n, buf1, wbuf2, buf3, c4, wc5);
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/libio/tst_wprintf.c b/libio/tst_wprintf.c
new file mode 100644
index 0000000000..0838441d2c
--- /dev/null
+++ b/libio/tst_wprintf.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+  fputws (L"Hello world!\n", stdout);
+  wprintf (L"This %s a %ls string: %d\n", "is", L"mixed", 42);
+  return 0;
+}
diff --git a/libio/tst_wscanf.c b/libio/tst_wscanf.c
new file mode 100644
index 0000000000..719f37867e
--- /dev/null
+++ b/libio/tst_wscanf.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+  int n;
+  int result = 0;
+  char buf1[20];
+  wchar_t wbuf2[20];
+  char c3;
+  wchar_t wc4;
+  int d;
+
+  puts ("Test 1");
+
+  n = wscanf (L"%s %S %c%C %d", buf1, wbuf2, &c3, &wc4, &d);
+
+  if (n != 5 || strcmp (buf1, "Hello") != 0 || wcscmp (wbuf2, L"World") != 0
+      || c3 != '!' || wc4 != L'!' || d != 42)
+    {
+      printf ("*** FAILED, n = %d, buf1 = \"%s\", wbuf2 = L\"%S\", c3 = '%c', wc4 = L'%C', d = %d\n",
+	      n, buf1, wbuf2, c3, wc4, d);
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/libio/tst_wscanf.input b/libio/tst_wscanf.input
new file mode 100644
index 0000000000..93e1eb55d4
--- /dev/null
+++ b/libio/tst_wscanf.input
@@ -0,0 +1 @@
+Hello World !! 42
diff --git a/libio/vasprintf.c b/libio/vasprintf.c
index 15513d0fca..a656961167 100644
--- a/libio/vasprintf.c
+++ b/libio/vasprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -49,7 +49,7 @@ _IO_vasprintf (result_ptr, format, args)
 #ifdef _IO_MTSAFE_IO
   sf._sbf._f._lock = &lock;
 #endif
-  _IO_init ((_IO_FILE *) &sf, 0);
+  _IO_no_init ((_IO_FILE *) &sf, 0, -1, NULL, NULL);
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps;
   _IO_str_init_static ((_IO_FILE *) &sf, string, init_string_size, string);
   sf._sbf._f._flags &= ~_IO_USER_BUF;
diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c
index e223e5dec2..2b82df5788 100644
--- a/libio/vsnprintf.c
+++ b/libio/vsnprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU IO Library.
 
    This library is free software; you can redistribute it and/or
@@ -122,7 +122,7 @@ _IO_vsnprintf (string, maxlen, format, args)
       maxlen = sizeof (sf.overflow_buf);
     }
 
-  _IO_init ((_IO_FILE *) &sf, 0);
+  _IO_no_init ((_IO_FILE *) &sf, 0, -1, NULL, NULL);
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_strn_jumps;
   string[0] = '\0';
   _IO_str_init_static ((_IO_FILE *) &sf, string, maxlen - 1, string);
diff --git a/libio/vswprintf.c b/libio/vswprintf.c
new file mode 100644
index 0000000000..addf39089c
--- /dev/null
+++ b/libio/vswprintf.c
@@ -0,0 +1,144 @@
+/* Copyright (C) 1994, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include "strfile.h"
+
+
+typedef struct
+{
+  _IO_strfile f;
+  /* This is used for the characters which do not fit in the buffer
+     provided by the user.  */
+  wchar_t overflow_buf[64];
+} _IO_strnfile;
+
+
+static wint_t _IO_wstrn_overflow __P ((_IO_FILE *fp, wint_t c));
+
+static wint_t
+_IO_wstrn_overflow (fp, c)
+     _IO_FILE *fp;
+     wint_t c;
+{
+  /* When we come to here this means the user supplied buffer is
+     filled.  But since we must return the number of characters which
+     would have been written in total we must provide a buffer for
+     further use.  We can do this by writing on and on in the overflow
+     buffer in the _IO_strnfile structure.  */
+  _IO_strnfile *snf = (_IO_strnfile *) fp;
+
+  if (fp->_wide_data->_IO_buf_base != snf->overflow_buf)
+    {
+      /* Terminate the string.  We know that there is room for at
+	 least one more character since we initialized the stream with
+	 a size to make this possible.  */
+      *fp->_wide_data->_IO_write_ptr = '\0';
+
+      _IO_wsetb (fp, snf->overflow_buf,
+		 snf->overflow_buf + (sizeof (snf->overflow_buf)
+				      / sizeof (wchar_t)), 0);
+
+      fp->_wide_data->_IO_write_base = snf->overflow_buf;
+      fp->_wide_data->_IO_read_base = snf->overflow_buf;
+      fp->_wide_data->_IO_read_ptr = snf->overflow_buf;
+      fp->_wide_data->_IO_read_end = (snf->overflow_buf
+				      + (sizeof (snf->overflow_buf)
+					 / sizeof (wchar_t)));
+    }
+
+  fp->_wide_data->_IO_write_ptr = snf->overflow_buf;
+  fp->_wide_data->_IO_write_end = snf->overflow_buf;
+
+  /* Since we are not really interested in storing the characters
+     which do not fit in the buffer we simply ignore it.  */
+  return c;
+}
+
+
+static struct _IO_jump_t _IO_wstrn_jumps =
+{
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_wstr_finish),
+  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstrn_overflow),
+  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
+  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
+  JUMP_INIT(xsputn, _IO_wdefault_xsputn),
+  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
+  JUMP_INIT(seekoff, _IO_wstr_seekoff),
+  JUMP_INIT(seekpos, _IO_default_seekpos),
+  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf),
+  JUMP_INIT(sync, _IO_default_sync),
+  JUMP_INIT(doallocate, _IO_wdefault_doallocate),
+  JUMP_INIT(read, _IO_default_read),
+  JUMP_INIT(write, _IO_default_write),
+  JUMP_INIT(seek, _IO_default_seek),
+  JUMP_INIT(close, _IO_default_close),
+  JUMP_INIT(stat, _IO_default_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};
+
+
+int
+_IO_vswprintf (string, maxlen, format, args)
+     wchar_t *string;
+     _IO_size_t maxlen;
+     const wchar_t *format;
+     _IO_va_list args;
+{
+  _IO_strnfile sf;
+  int ret;
+  struct _IO_wide_data wd;
+#ifdef _IO_MTSAFE_IO
+  _IO_lock_t lock;
+  sf.f._sbf._f._lock = &lock;
+#endif
+
+  /* We need to handle the special case where MAXLEN is 0.  Use the
+     overflow buffer right from the start.  */
+  if (maxlen == 0)
+    {
+      string = sf.overflow_buf;
+      maxlen = sizeof (sf.overflow_buf) / sizeof (wchar_t);
+    }
+
+  _IO_no_init ((_IO_FILE *) &sf, 0, 0, &wd, NULL);
+  _IO_WIDE_JUMPS ((_IO_FILE *) &sf) = &_IO_wstrn_jumps;
+  _IO_fwide (&sf.f._sbf._f, 1);
+  string[0] = L'\0';
+  _IO_wstr_init_static ((_IO_FILE *) &sf, string, maxlen - 1, string);
+  ret = _IO_vfwprintf ((_IO_FILE *) &sf, format, args);
+
+  if (sf.f._sbf._f._wide_data->_IO_buf_base != sf.overflow_buf)
+    *sf.f._sbf._f._wide_data->_IO_write_ptr = '\0';
+  return ret;
+}
+
+#ifdef weak_alias
+weak_alias (_IO_vswprintf, __vswprintf)
+weak_alias (_IO_vswprintf, vswprintf)
+#endif
diff --git a/libio/vwprintf.c b/libio/vwprintf.c
new file mode 100644
index 0000000000..1f3102e4ff
--- /dev/null
+++ b/libio/vwprintf.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991, 1993, 1995, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#undef	__OPTIMIZE__	/* Avoid inline `vwprintf' function.  */
+#include <stdio.h>
+
+/* Write formatted output to stdout according to the
+   format string FORMAT, using the argument list in ARG.  */
+int
+vwprintf (format, arg)
+     const wchar_t *format;
+     __gnuc_va_list arg;
+{
+  return vfwprintf (stdout, format, arg);
+}
diff --git a/libio/vwscanf.c b/libio/vwscanf.c
new file mode 100644
index 0000000000..fb24fc9baa
--- /dev/null
+++ b/libio/vwscanf.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "libioP.h"
+#include <wchar.h>
+
+int
+vwscanf (format, args)
+     const wchar_t *format;
+     _IO_va_list args;
+{
+  return _IO_vfwscanf (_IO_stdin, format, args, NULL);
+}
diff --git a/libio/wfiledoalloc.c b/libio/wfiledoalloc.c
new file mode 100644
index 0000000000..7f5cb7f960
--- /dev/null
+++ b/libio/wfiledoalloc.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Modified for GNU iostream by Per Bothner 1991, 1992. */
+
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include "libioP.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#ifdef _LIBC
+# undef isatty
+# define isatty(Fd) __isatty (Fd)
+#endif
+
+/*
+ * Allocate a file buffer, or switch to unbuffered I/O.
+ * Per the ANSI C standard, ALL tty devices default to line buffered.
+ *
+ * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
+ * optimisation) right after the _fstat() that finds the buffer size.
+ */
+
+int
+_IO_wfile_doallocate (fp)
+     _IO_FILE *fp;
+{
+  _IO_size_t size;
+  int couldbetty;
+  wchar_t *p;
+  struct _G_stat64 st;
+
+  /* Allocate room for the external buffer.  */
+  _IO_file_doallocate (fp);
+
+  if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0)
+    {
+      couldbetty = 0;
+      size = _IO_BUFSIZ * sizeof (wchar_t);
+#if 0
+      /* do not try to optimise fseek() */
+      fp->_flags |= __SNPT;
+#endif
+    }
+  else
+    {
+      couldbetty = S_ISCHR (st.st_mode);
+#if _IO_HAVE_ST_BLKSIZE
+      size = ((st.st_blksize <= 0 ? _IO_BUFSIZ : st.st_blksize)
+	      * sizeof (wchar_t));
+#else
+      size = _IO_BUFSIZ * sizeof (wchar_t);
+#endif
+    }
+  ALLOC_WBUF (p, size, EOF);
+  _IO_wsetb (fp, p, p + size, 1);
+  if (couldbetty && isatty (fp->_fileno))
+    fp->_flags |= _IO_LINE_BUF;
+  return 1;
+}
diff --git a/libio/wfileops.c b/libio/wfileops.c
new file mode 100644
index 0000000000..b040b97491
--- /dev/null
+++ b/libio/wfileops.c
@@ -0,0 +1,716 @@
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+   Written by Ulrich Drepper <drepper@cygnus.com>.
+   Based on the single byte version by Per Bothner <bothner@cygnus.com>.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include <assert.h>
+#include <libioP.h>
+#include <wchar.h>
+#include <gconv.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+_IO_FILE *
+_IO_wfile_setbuf (fp, p, len)
+     _IO_FILE *fp;
+     wchar_t *p;
+     _IO_ssize_t len;
+{
+  if (_IO_wdefault_setbuf (fp, p, len) == NULL)
+    return NULL;
+
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr =
+    fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base;
+  _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base,
+	     fp->_wide_data->_IO_buf_base);
+
+  return fp;
+}
+
+
+/* Convert TO_DO wide character from DATA to FP.
+   Then mark FP as having empty buffers. */
+int
+_IO_wdo_write (fp, data, to_do)
+     _IO_FILE *fp;
+     const wchar_t *data;
+     _IO_size_t to_do;
+{
+  struct _IO_codecvt *cc = &fp->_wide_data->_codecvt;
+  _IO_size_t count = 0;
+
+  while (to_do > 0)
+    {
+      enum __codecvt_result result;
+      const wchar_t *new_data;
+
+      if (fp->_IO_write_end == fp->_IO_write_ptr)
+	{
+	  _IO_new_file_overflow (fp, EOF);
+	  assert (fp->_IO_write_end > fp->_IO_write_ptr);
+	}
+
+      /* Now convert from the internal format into the external buffer.  */
+      result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state,
+					data, data + to_do, &new_data,
+					fp->_IO_write_ptr,
+					fp->_IO_write_end,
+					&fp->_IO_write_ptr);
+
+      /* Write out what we produced so far.  */
+      if (_IO_new_do_write (fp, fp->_IO_write_base,
+			    fp->_IO_write_ptr - fp->_IO_write_base) == EOF)
+	/* Something went wrong.  */
+	return EOF;
+
+      count += new_data - data;
+      to_do -= new_data - data;
+      data = new_data;
+
+      /* Next see whether we had problems during the conversion.  If yes,
+	 we cannot go on.  */
+      if (result != __codecvt_ok)
+	break;
+    }
+
+  _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base,
+	     fp->_wide_data->_IO_buf_base);
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
+    = fp->_wide_data->_IO_buf_base;
+  fp->_wide_data->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+				   ? fp->_wide_data->_IO_buf_base
+				   : fp->_wide_data->_IO_buf_end);
+
+  return count;
+}
+
+
+wint_t
+_IO_wfile_underflow (fp)
+     _IO_FILE *fp;
+{
+  struct _IO_codecvt *cd;
+  enum __codecvt_result status;
+  _IO_ssize_t count;
+  int tries;
+  const char *read_ptr_copy;
+
+  if (fp->_flags & _IO_NO_READS)
+    {
+      __set_errno (EBADF);
+      return WEOF;
+    }
+  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+    return *fp->_wide_data->_IO_read_ptr;
+
+  cd = &fp->_wide_data->_codecvt;
+
+  /* Maybe there is something left in the external buffer.  */
+  if (fp->_IO_read_ptr < fp->_IO_read_end)
+    {
+      /* Convert it.  */
+      size_t avail_bytes = fp->_IO_read_end - fp->_IO_read_ptr;
+
+      if (avail_bytes >= (*cd->__codecvt_do_max_length) (cd))
+	{
+	  /* There is more in the external.  */
+	  const char *read_stop = (const char *) fp->_IO_read_ptr;
+
+	  fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
+	  status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
+					   fp->_IO_read_ptr, fp->_IO_read_end,
+					   &read_stop,
+					   fp->_wide_data->_IO_read_end,
+					   fp->_wide_data->_IO_buf_end,
+					   &fp->_wide_data->_IO_read_end);
+
+	  fp->_IO_read_ptr = (char *) read_stop;
+
+	  /* If we managed to generate some text return the next character.  */
+	  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+	    return *fp->_wide_data->_IO_read_ptr;
+
+	  if (status == __codecvt_error)
+	    {
+	      __set_errno (EILSEQ);
+	      fp->_flags |= _IO_ERR_SEEN;
+	      return WEOF;
+	    }
+	}
+
+      /* Move the remaining content of the read buffer to the beginning.  */
+      memmove (fp->_IO_buf_base, fp->_IO_read_ptr,
+	       fp->_IO_read_end - fp->_IO_read_ptr);
+      fp->_IO_read_end = (fp->_IO_buf_base
+			  + (fp->_IO_read_end - fp->_IO_read_ptr));
+      fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
+    }
+  else
+    fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
+      fp->_IO_buf_base;
+
+  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end =
+    fp->_IO_buf_base;
+
+  if (fp->_IO_buf_base == NULL)
+    {
+      /* Maybe we already have a push back pointer.  */
+      if (fp->_IO_save_base != NULL)
+	{
+	  free (fp->_IO_save_base);
+	  fp->_flags &= ~_IO_IN_BACKUP;
+	}
+      _IO_doallocbuf (fp);
+    }
+
+  if (fp->_wide_data->_IO_buf_base == NULL)
+    {
+      /* Maybe we already have a push back pointer.  */
+      if (fp->_wide_data->_IO_save_base != NULL)
+	{
+	  free (fp->_wide_data->_IO_save_base);
+	  fp->_flags &= ~_IO_IN_BACKUP;
+	}
+      _IO_wdoallocbuf (fp);
+    }
+
+  /* Flush all line buffered files before reading. */
+  /* FIXME This can/should be moved to genops ?? */
+  if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
+    _IO_flush_all_linebuffered ();
+
+  _IO_switch_to_get_mode (fp);
+
+  fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
+  fp->_IO_read_end = fp->_IO_buf_base;
+  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
+    = fp->_IO_buf_base;
+
+  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
+    fp->_wide_data->_IO_buf_base;
+  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base;
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr =
+    fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base;
+
+  tries = 0;
+ again:
+  count = _IO_SYSREAD (fp, fp->_IO_read_end,
+		       fp->_IO_buf_end - fp->_IO_read_end);
+  if (count <= 0)
+    {
+      if (count == 0 && tries == 0)
+	fp->_flags |= _IO_EOF_SEEN;
+      else
+	fp->_flags |= _IO_ERR_SEEN, count = 0;
+    }
+  fp->_IO_read_end += count;
+  if (count == 0)
+    {
+      if (tries != 0)
+	/* There are some bytes in the external buffer but they don't
+           convert to anything.  */
+	__set_errno (EILSEQ);
+      return WEOF;
+    }
+  if (fp->_offset != _IO_pos_BAD)
+    _IO_pos_adjust (fp->_offset, count);
+
+  /* Now convert the read input.  */
+  fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
+  fp->_IO_read_base = fp->_IO_read_ptr;
+  status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
+				   fp->_IO_read_ptr, fp->_IO_read_end,
+				   &read_ptr_copy,
+				   fp->_wide_data->_IO_read_end,
+				   fp->_wide_data->_IO_buf_end,
+				   &fp->_wide_data->_IO_read_end);
+
+  fp->_IO_read_ptr = (char *) read_ptr_copy;
+  if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base)
+    {
+      if (status == __codecvt_error || fp->_IO_read_end == fp->_IO_buf_end)
+	{
+	  __set_errno (EILSEQ);
+	  fp->_flags |= _IO_ERR_SEEN;
+	  return WEOF;
+	}
+
+      /* The read bytes make no complete character.  Try reading again.  */
+      assert (status == __codecvt_partial);
+      ++tries;
+      goto again;
+    }
+
+  return *fp->_wide_data->_IO_read_ptr;
+}
+
+
+wint_t
+_IO_wfile_overflow (f, wch)
+     _IO_FILE *f;
+     wint_t wch;
+{
+  if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
+    {
+      f->_flags |= _IO_ERR_SEEN;
+      __set_errno (EBADF);
+      return WEOF;
+    }
+  /* If currently reading or no buffer allocated. */
+  if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
+    {
+      /* Allocate a buffer if needed. */
+      if (f->_wide_data->_IO_write_base == 0)
+	{
+	  _IO_wdoallocbuf (f);
+	  _IO_wsetg (f, f->_wide_data->_IO_buf_base,
+		     f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
+	}
+      else
+	{
+	  /* Otherwise must be currently reading.  If _IO_read_ptr
+	     (and hence also _IO_read_end) is at the buffer end,
+	     logically slide the buffer forwards one block (by setting
+	     the read pointers to all point at the beginning of the
+	     block).  This makes room for subsequent output.
+	     Otherwise, set the read pointers to _IO_read_end (leaving
+	     that alone, so it can continue to correspond to the
+	     external position). */
+	  if (f->_wide_data->_IO_read_ptr == f->_wide_data->_IO_buf_end)
+	    {
+	      f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
+	      f->_wide_data->_IO_read_end = f->_wide_data->_IO_read_ptr =
+		f->_wide_data->_IO_buf_base;
+	    }
+	}
+      f->_wide_data->_IO_write_ptr = f->_wide_data->_IO_read_ptr;
+      f->_wide_data->_IO_write_base = f->_wide_data->_IO_write_ptr;
+      f->_wide_data->_IO_write_end = f->_wide_data->_IO_buf_end;
+      f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr =
+	f->_wide_data->_IO_read_end;
+
+      f->_flags |= _IO_CURRENTLY_PUTTING;
+      if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+	f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr;
+    }
+  if (wch == WEOF)
+    return _IO_do_flush (f);
+  if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end )
+    /* Buffer is really full */
+    if (_IO_do_flush (f) == WEOF)
+      return WEOF;
+  *f->_wide_data->_IO_write_ptr++ = wch;
+  if ((f->_flags & _IO_UNBUFFERED)
+      || ((f->_flags & _IO_LINE_BUF) && wch == L'\n'))
+    if (_IO_do_flush (f) == WEOF)
+      return WEOF;
+  return wch;
+}
+
+wint_t
+_IO_wfile_sync (fp)
+     _IO_FILE *fp;
+{
+  _IO_ssize_t delta;
+  wint_t retval = 0;
+
+  /*    char* ptr = cur_ptr(); */
+  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
+    if (_IO_do_flush (fp))
+      return WEOF;
+  delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
+  if (delta != 0)
+    {
+      /* We have to find out how many bytes we have to go back in the
+	 external buffer.  */
+      struct _IO_codecvt *cv = &fp->_wide_data->_codecvt;
+      _IO_off64_t new_pos;
+
+      int clen = (*cv->__codecvt_do_encoding) (cv);
+
+      if (clen > 0)
+	/* It is easy, a fixed number of input bytes are used for each
+	   wide character.  */
+	delta *= clen;
+      else
+	{
+	  /* We have to find out the hard way how much to back off.
+             To do this we determine how much input we needed to
+             generate the wide characters up to the current reading
+             position.  */
+	  int nread;
+
+	  fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
+	  nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
+					      fp->_IO_read_base,
+					      fp->_IO_read_end, delta);
+	  fp->_IO_read_ptr = fp->_IO_read_base + nread;
+	  delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
+	}
+
+      new_pos = _IO_SYSSEEK (fp, delta, 1);
+      if (new_pos != (_IO_off64_t) EOF)
+	{
+	  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
+	  fp->_IO_read_end = fp->_IO_read_ptr;
+	}
+#ifdef ESPIPE
+      else if (errno == ESPIPE)
+	; /* Ignore error from unseekable devices. */
+#endif
+      else
+	retval = WEOF;
+    }
+  if (retval != WEOF)
+    fp->_offset = _IO_pos_BAD;
+  /* FIXME: Cleanup - can this be shared? */
+  /*    setg(base(), ptr, ptr); */
+  return retval;
+}
+
+_IO_off64_t
+_IO_wfile_seekoff (fp, offset, dir, mode)
+     _IO_FILE *fp;
+     _IO_off64_t offset;
+     int dir;
+     int mode;
+{
+  _IO_off64_t result;
+  _IO_off64_t delta, new_offset;
+  long int count;
+  /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
+     offset of the underlying file must be exact.  */
+  int must_be_exact = ((fp->_wide_data->_IO_read_base
+			== fp->_wide_data->_IO_read_end)
+		       && (fp->_wide_data->_IO_write_base
+			   == fp->_wide_data->_IO_write_ptr));
+
+  if (mode == 0)
+    dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
+
+  /* Flush unwritten characters.
+     (This may do an unneeded write if we seek within the buffer.
+     But to be able to switch to reading, we would need to set
+     egptr to ptr.  That can't be done in the current design,
+     which assumes file_ptr() is eGptr.  Anyway, since we probably
+     end up flushing when we close(), it doesn't make much difference.)
+     FIXME: simulate mem-papped files. */
+
+  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
+      || _IO_in_put_mode (fp))
+    if (_IO_switch_to_get_mode (fp))
+      return WEOF;
+
+  if (fp->_wide_data->_IO_buf_base == NULL)
+    {
+      /* It could be that we already have a pushback buffer.  */
+      if (fp->_wide_data->_IO_read_base != NULL)
+	{
+	  free (fp->_wide_data->_IO_read_base);
+	  fp->_flags &= ~_IO_IN_BACKUP;
+	}
+      _IO_doallocbuf (fp);
+      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+      _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
+      _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
+		 fp->_wide_data->_IO_buf_base);
+      _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
+		 fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
+    }
+
+  switch (dir)
+    {
+      struct _IO_codecvt *cv;
+      int clen;
+
+    case _IO_seek_cur:
+      /* Adjust for read-ahead (bytes is buffer).  To do this we must
+         find out which position in the external buffer corresponds to
+         the current position in the internal buffer.  */
+      cv = &fp->_wide_data->_codecvt;
+      clen = (*cv->__codecvt_do_encoding) (cv);
+
+      if (clen > 0)
+	offset -= (fp->_wide_data->_IO_read_end
+		   - fp->_wide_data->_IO_read_ptr) * clen;
+      else
+	{
+	  int nread;
+
+	  delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
+	  fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
+	  nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
+					      fp->_IO_read_base,
+					      fp->_IO_read_end, delta);
+	  fp->_IO_read_ptr = fp->_IO_read_base + nread;
+	  offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
+	}
+
+      if (fp->_offset == _IO_pos_BAD)
+	goto dumb;
+      /* Make offset absolute, assuming current pointer is file_ptr(). */
+      offset += fp->_offset;
+
+      dir = _IO_seek_set;
+      break;
+    case _IO_seek_set:
+      break;
+    case _IO_seek_end:
+      {
+	struct _G_stat64 st;
+	if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
+	  {
+	    offset += st.st_size;
+	    dir = _IO_seek_set;
+	  }
+	else
+	  goto dumb;
+      }
+    }
+  /* At this point, dir==_IO_seek_set. */
+
+  /* If we are only interested in the current position we've found it now.  */
+  if (mode == 0)
+    return offset;
+
+  /* If destination is within current buffer, optimize: */
+  if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
+      && !_IO_in_backup (fp))
+    {
+      /* Offset relative to start of main get area. */
+      _IO_off64_t rel_offset = (offset - fp->_offset
+				+ (fp->_IO_read_end - fp->_IO_read_base));
+      if (rel_offset >= 0)
+	{
+#if 0
+	  if (_IO_in_backup (fp))
+	    _IO_switch_to_main_get_area (fp);
+#endif
+	  if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
+	    {
+	      fp->_IO_read_ptr = fp->_IO_read_base + rel_offset;
+	      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+
+	      /* Now set the pointer for the internal buffer.  This
+                 might be an iterative process.  Though the read
+                 pointer is somewhere in the current external buffer
+                 this does not mean we can convert this whole buffer
+                 at once fitting in the internal buffer.  */
+	      do
+		{
+
+		}
+	      while (0);
+
+	      _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
+	      goto resync;
+	    }
+#ifdef TODO
+	    /* If we have streammarkers, seek forward by reading ahead. */
+	    if (_IO_have_markers (fp))
+	      {
+		int to_skip = rel_offset
+		  - (fp->_IO_read_ptr - fp->_IO_read_base);
+		if (ignore (to_skip) != to_skip)
+		  goto dumb;
+		_IO_mask_flags (fp, 0, _IO_EOF_SEEN);
+		goto resync;
+	      }
+#endif
+	}
+#ifdef TODO
+      if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
+	{
+	  if (!_IO_in_backup (fp))
+	    _IO_switch_to_backup_area (fp);
+	  gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
+	  _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
+	  goto resync;
+	}
+#endif
+    }
+
+#ifdef TODO
+  _IO_unsave_markers (fp);
+#endif
+
+  if (fp->_flags & _IO_NO_READS)
+    goto dumb;
+
+  /* Try to seek to a block boundary, to improve kernel page management. */
+  new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
+  delta = offset - new_offset;
+  if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
+    {
+      new_offset = offset;
+      delta = 0;
+    }
+  result = _IO_SYSSEEK (fp, new_offset, 0);
+  if (result < 0)
+    return EOF;
+  if (delta == 0)
+    count = 0;
+  else
+    {
+      count = _IO_SYSREAD (fp, fp->_IO_buf_base,
+			   (must_be_exact
+			    ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
+      if (count < delta)
+	{
+	  /* We weren't allowed to read, but try to seek the remainder. */
+	  offset = count == EOF ? delta : delta-count;
+	  dir = _IO_seek_cur;
+	  goto dumb;
+	}
+    }
+  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
+	    fp->_IO_buf_base + count);
+  _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+  fp->_offset = result + count;
+  _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
+  return offset;
+ dumb:
+
+  _IO_unsave_markers (fp);
+  result = _IO_SYSSEEK (fp, offset, dir);
+  if (result != EOF)
+    {
+      _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
+      fp->_offset = result;
+      _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
+      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+    }
+  return result;
+
+resync:
+  /* We need to do it since it is possible that the file offset in
+     the kernel may be changed behind our back. It may happen when
+     we fopen a file and then do a fork. One process may access the
+     the file and the kernel file offset will be changed. */
+  if (fp->_offset >= 0)
+    _IO_SYSSEEK (fp, fp->_offset, 0);
+
+  return offset;
+}
+
+
+_IO_size_t
+_IO_wfile_xsputn (f, data, n)
+     _IO_FILE *f;
+     const void *data;
+     _IO_size_t n;
+{
+  register const wchar_t *s = (const wchar_t *) data;
+  _IO_size_t to_do = n;
+  int must_flush = 0;
+  _IO_size_t count;
+
+  if (n <= 0)
+    return 0;
+  /* This is an optimized implementation.
+     If the amount to be written straddles a block boundary
+     (or the filebuf is unbuffered), use sys_write directly. */
+
+  /* First figure out how much space is available in the buffer. */
+  count = f->_wide_data->_IO_write_end - f->_wide_data->_IO_write_ptr;
+  if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
+    {
+      count = f->_wide_data->_IO_buf_end - f->_wide_data->_IO_write_ptr;
+      if (count >= n)
+	{
+	  register const wchar_t *p;
+	  for (p = s + n; p > s; )
+	    {
+	      if (*--p == L'\n')
+		{
+		  count = p - s + 1;
+		  must_flush = 1;
+		  break;
+		}
+	    }
+	}
+    }
+  /* Then fill the buffer. */
+  if (count > 0)
+    {
+      if (count > to_do)
+	count = to_do;
+      if (count > 20)
+	{
+#ifdef _LIBC
+	  f->_wide_data->_IO_write_ptr =
+	    __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
+#else
+	  wmemcpy (f->_wide_data->_IO_write_ptr, s, count);
+	  f->_wide_data->_IO_write_ptr += count;
+#endif
+	  s += count;
+	}
+      else
+	{
+	  register wchar_t *p = f->_wide_data->_IO_write_ptr;
+	  register int i = (int) count;
+	  while (--i >= 0)
+	    *p++ = *s++;
+	  f->_wide_data->_IO_write_ptr = p;
+	}
+      to_do -= count;
+    }
+  if (to_do > 0)
+    to_do -= _IO_wdefault_xsputn (f, s, to_do);
+  if (must_flush
+      && f->_wide_data->_IO_write_ptr != f->_wide_data->_IO_write_base)
+    _IO_wdo_write (f, f->_wide_data->_IO_write_base,
+		   f->_wide_data->_IO_write_ptr
+		   - f->_wide_data->_IO_write_base);
+
+  return n - to_do;
+}
+
+
+struct _IO_jump_t _IO_wfile_jumps =
+{
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_new_file_finish),
+  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
+  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),
+  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+  JUMP_INIT(pbackfail, _IO_default_pbackfail),
+  JUMP_INIT(xsputn, _IO_wfile_xsputn),
+  JUMP_INIT(xsgetn, _IO_file_xsgetn),
+  JUMP_INIT(seekoff, _IO_wfile_seekoff),
+  JUMP_INIT(seekpos, _IO_default_seekpos),
+  JUMP_INIT(setbuf, _IO_new_file_setbuf),
+  JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
+  JUMP_INIT(doallocate, _IO_wfile_doallocate),
+  JUMP_INIT(read, _IO_file_read),
+  JUMP_INIT(write, _IO_new_file_write),
+  JUMP_INIT(seek, _IO_file_seek),
+  JUMP_INIT(close, _IO_file_close),
+  JUMP_INIT(stat, _IO_file_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};
diff --git a/libio/wgenops.c b/libio/wgenops.c
new file mode 100644
index 0000000000..496d080014
--- /dev/null
+++ b/libio/wgenops.c
@@ -0,0 +1,747 @@
+/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+   Written by Ulrich Drepper <drepper@cygnus.com>.
+   Based on the single byte version by Per Bothner <bothner@cygnus.com>.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+/* Generic or default I/O operations. */
+
+#include "libioP.h"
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <wchar.h>
+
+
+
+static int save_for_wbackup __P ((_IO_FILE *fp, wchar_t *end_p))
+#ifdef _LIBC
+     internal_function
+#endif
+     ;
+
+/* Return minimum _pos markers
+   Assumes the current get area is the main get area. */
+_IO_ssize_t _IO_least_wmarker __P ((_IO_FILE *fp, wchar_t *end_p));
+
+_IO_ssize_t
+_IO_least_wmarker (fp, end_p)
+     _IO_FILE *fp;
+     wchar_t *end_p;
+{
+  _IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base;
+  struct _IO_marker *mark;
+  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
+    if (mark->_pos < least_so_far)
+      least_so_far = mark->_pos;
+  return least_so_far;
+}
+
+/* Switch current get area from backup buffer to (start of) main get area. */
+void
+_IO_switch_to_main_wget_area (fp)
+     _IO_FILE *fp;
+{
+  wchar_t *tmp;
+  fp->_flags &= ~_IO_IN_BACKUP;
+  /* Swap _IO_read_end and _IO_save_end. */
+  tmp = fp->_wide_data->_IO_read_end;
+  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
+  fp->_wide_data->_IO_save_end= tmp;
+  /* Swap _IO_read_base and _IO_save_base. */
+  tmp = fp->_wide_data->_IO_read_base;
+  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
+  fp->_wide_data->_IO_save_base = tmp;
+  /* Set _IO_read_ptr. */
+  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
+}
+
+
+/* Switch current get area from main get area to (end of) backup area. */
+void
+_IO_switch_to_wbackup_area (fp)
+     _IO_FILE *fp;
+{
+  wchar_t *tmp;
+  fp->_flags |= _IO_IN_BACKUP;
+  /* Swap _IO_read_end and _IO_save_end. */
+  tmp = fp->_wide_data->_IO_read_end;
+  fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
+  fp->_wide_data->_IO_save_end = tmp;
+  /* Swap _IO_read_base and _IO_save_base. */
+  tmp = fp->_wide_data->_IO_read_base;
+  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
+  fp->_wide_data->_IO_save_base = tmp;
+  /* Set _IO_read_ptr.  */
+  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+}
+
+
+void
+_IO_wsetb (f, b, eb, a)
+     _IO_FILE *f;
+     wchar_t *b;
+     wchar_t *eb;
+     int a;
+{
+  if (f->_wide_data->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
+    FREE_BUF (f->_wide_data->_IO_buf_base, _IO_wblen (f));
+  f->_wide_data->_IO_buf_base = b;
+  f->_wide_data->_IO_buf_end = eb;
+  if (a)
+    f->_flags &= ~_IO_USER_BUF;
+  else
+    f->_flags |= _IO_USER_BUF;
+}
+
+
+wint_t
+_IO_wdefault_pbackfail (fp, c)
+     _IO_FILE *fp;
+     wint_t c;
+{
+  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
+      && !_IO_in_backup (fp)
+      && (wint_t) fp->_IO_read_ptr[-1] == c)
+    --fp->_IO_read_ptr;
+  else
+    {
+      /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
+      if (!_IO_in_backup (fp))
+	{
+	  /* We need to keep the invariant that the main get area
+	     logically follows the backup area.  */
+	  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
+	      && _IO_have_wbackup (fp))
+	    {
+	      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr))
+		return WEOF;
+	    }
+	  else if (!_IO_have_wbackup (fp))
+	    {
+	      /* No backup buffer: allocate one. */
+	      /* Use nshort buffer, if unused? (probably not)  FIXME */
+	      int backup_size = 128;
+	      wchar_t *bbuf = (wchar_t *) malloc (backup_size
+						  * sizeof (wchar_t));
+	      if (bbuf == NULL)
+		return WEOF;
+	      fp->_wide_data->_IO_save_base = bbuf;
+	      fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base
+					      + backup_size);
+	      fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end;
+	    }
+	  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr;
+	  _IO_switch_to_wbackup_area (fp);
+	}
+      else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base)
+	{
+	  /* Increase size of existing backup buffer. */
+	  _IO_size_t new_size;
+	  _IO_size_t old_size = (fp->_wide_data->_IO_read_end
+				 - fp->_wide_data->_IO_read_base);
+	  wchar_t *new_buf;
+	  new_size = 2 * old_size;
+	  new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t));
+	  if (new_buf == NULL)
+	    return WEOF;
+	  __wmemcpy (new_buf + (new_size - old_size),
+		     fp->_wide_data->_IO_read_base, old_size);
+	  free (fp->_wide_data->_IO_read_base);
+	  _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size),
+		     new_buf + new_size);
+	  fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr;
+	}
+
+      *--fp->_wide_data->_IO_read_ptr = c;
+    }
+  return c;
+}
+
+
+void
+_IO_wdefault_finish (fp, dummy)
+     _IO_FILE *fp;
+     int dummy;
+{
+  struct _IO_marker *mark;
+  if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
+    {
+      FREE_BUF (fp->_wide_data->_IO_buf_base,
+		_IO_wblen (fp) * sizeof (wchar_t));
+      fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL;
+    }
+
+  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
+    mark->_sbuf = NULL;
+
+  if (fp->_IO_save_base)
+    {
+      free (fp->_wide_data->_IO_save_base);
+      fp->_IO_save_base = NULL;
+    }
+
+#ifdef _IO_MTSAFE_IO
+  _IO_lock_fini (*fp->_lock);
+#endif
+
+  _IO_un_link (fp);
+}
+
+
+wint_t
+_IO_wdefault_uflow (fp)
+     _IO_FILE *fp;
+{
+  wint_t wch;
+  wch = _IO_UNDERFLOW (fp);
+  if (wch == WEOF)
+    return WEOF;
+  return *fp->_wide_data->_IO_read_ptr++;
+}
+
+
+wint_t
+__woverflow (f, wch)
+     _IO_FILE *f;
+     wint_t wch;
+{
+  if (f->_mode == 0)
+    _IO_fwide (f, 1);
+  return _IO_OVERFLOW (f, wch);
+}
+
+
+wint_t
+__wuflow (fp)
+     _IO_FILE *fp;
+{
+  if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
+    return EOF;
+
+  if (fp->_mode == 0)
+    _IO_fwide (fp, 1);
+  if (_IO_in_put_mode (fp))
+    if (_IO_switch_to_get_mode (fp) == EOF)
+      return WEOF;
+  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+    return *fp->_wide_data->_IO_read_ptr++;
+  if (_IO_in_backup (fp))
+    {
+      _IO_switch_to_main_wget_area (fp);
+      if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+	return *fp->_wide_data->_IO_read_ptr++;
+    }
+  if (_IO_have_markers (fp))
+    {
+      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
+	return WEOF;
+    }
+  else if (_IO_have_wbackup (fp))
+    _IO_free_wbackup_area (fp);
+  return _IO_UFLOW (fp);
+}
+
+
+wint_t
+__wunderflow (fp)
+     _IO_FILE *fp;
+{
+  if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
+    return EOF;
+
+  if (_IO_in_put_mode (fp))
+    if (_IO_switch_to_wget_mode (fp) == WEOF)
+      return WEOF;
+  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+    return *fp->_wide_data->_IO_read_ptr;
+  if (_IO_in_backup (fp))
+    {
+      _IO_switch_to_main_wget_area (fp);
+      if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+	return *fp->_wide_data->_IO_read_ptr;
+    }
+  if (_IO_have_markers (fp))
+    {
+      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
+	return EOF;
+    }
+  else if (_IO_have_backup (fp))
+    _IO_free_wbackup_area (fp);
+  return _IO_UNDERFLOW (fp);
+}
+
+
+_IO_size_t
+_IO_wdefault_xsputn (f, data, n)
+     _IO_FILE *f;
+     const void *data;
+     _IO_size_t n;
+{
+  const wchar_t *s = (const wchar_t *) data;
+  _IO_size_t more = n;
+  if (more <= 0)
+    return 0;
+  for (;;)
+    {
+      /* Space available. */
+      _IO_ssize_t count = (f->_wide_data->_IO_write_end
+			   - f->_wide_data->_IO_write_ptr);
+      if (count > 0)
+	{
+	  if ((_IO_size_t) count > more)
+	    count = more;
+	  if (count > 20)
+	    {
+#ifdef _LIBC
+	      f->_wide_data->_IO_write_ptr =
+		__wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
+#else
+	      memcpy (f->_wide_data->_IO_write_ptr, s, count);
+	      f->_wide_data->_IO_write_ptr += count;
+#endif
+	      s += count;
+            }
+	  else if (count <= 0)
+	    count = 0;
+	  else
+	    {
+	      wchar_t *p = f->_wide_data->_IO_write_ptr;
+	      _IO_ssize_t i;
+	      for (i = count; --i >= 0; )
+		*p++ = *s++;
+	      f->_wide_data->_IO_write_ptr = p;
+            }
+	  more -= count;
+        }
+      if (more == 0 || __woverflow (f, *s++) == WEOF)
+	break;
+      more--;
+    }
+  return n - more;
+}
+
+
+_IO_size_t
+_IO_wdefault_xsgetn (fp, data, n)
+     _IO_FILE *fp;
+     void *data;
+     _IO_size_t n;
+{
+  _IO_size_t more = n;
+  wchar_t *s = (wchar_t*) data;
+  for (;;)
+    {
+      /* Data available. */
+      _IO_ssize_t count = (fp->_wide_data->_IO_read_end
+			   - fp->_wide_data->_IO_read_ptr);
+      if (count > 0)
+	{
+	  if ((_IO_size_t) count > more)
+	    count = more;
+	  if (count > 20)
+	    {
+#ifdef _LIBC
+	      s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count);
+#else
+	      memcpy (s, fp->_wide_data->_IO_read_ptr, count);
+	      s += count;
+#endif
+	      fp->_wide_data->_IO_read_ptr += count;
+	    }
+	  else if (count <= 0)
+	    count = 0;
+	  else
+	    {
+	      wchar_t *p = fp->_wide_data->_IO_read_ptr;
+	      int i = (int) count;
+	      while (--i >= 0)
+		*s++ = *p++;
+	      fp->_wide_data->_IO_read_ptr = p;
+            }
+            more -= count;
+        }
+      if (more == 0 || __wunderflow (fp) == WEOF)
+	break;
+    }
+  return n - more;
+}
+
+
+void
+_IO_wdoallocbuf (fp)
+     _IO_FILE *fp;
+{
+  if (fp->_wide_data->_IO_buf_base)
+    return;
+  if (!(fp->_flags & _IO_UNBUFFERED))
+    if (_IO_DOALLOCATE (fp) != WEOF)
+      return;
+  _IO_wsetb (fp, fp->_wide_data->_shortbuf, fp->_wide_data->_shortbuf + 1, 0);
+}
+
+
+_IO_FILE *
+_IO_wdefault_setbuf (fp, p, len)
+     _IO_FILE *fp;
+     wchar_t *p;
+     _IO_ssize_t len;
+{
+  if (_IO_SYNC (fp) == EOF)
+    return NULL;
+  if (p == NULL || len == 0)
+    {
+      fp->_flags |= _IO_UNBUFFERED;
+      _IO_wsetb (fp, fp->_wide_data->_shortbuf, fp->_wide_data->_shortbuf + 1,
+		 0);
+    }
+  else
+    {
+      fp->_flags &= ~_IO_UNBUFFERED;
+      _IO_wsetb (fp, p, p + len, 0);
+    }
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
+    = fp->_wide_data->_IO_write_end = 0;
+  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr
+    = fp->_wide_data->_IO_read_end = 0;
+  return fp;
+}
+
+
+int
+_IO_wdefault_doallocate (fp)
+     _IO_FILE *fp;
+{
+  wchar_t *buf;
+
+  ALLOC_WBUF (buf, _IO_BUFSIZ, EOF);
+  _IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1);
+  return 1;
+}
+
+
+int
+_IO_switch_to_wget_mode (fp)
+     _IO_FILE *fp;
+{
+  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
+    if (_IO_OVERFLOW (fp, EOF) == EOF)
+      return EOF;
+  if (_IO_in_backup (fp))
+    fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base;
+  else
+    {
+      fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base;
+      if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
+	fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
+    }
+  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
+
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
+    = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr;
+
+  fp->_flags &= ~_IO_CURRENTLY_PUTTING;
+  return 0;
+}
+
+void
+_IO_free_wbackup_area (fp)
+     _IO_FILE *fp;
+{
+  if (_IO_in_backup (fp))
+    _IO_switch_to_main_wget_area (fp);  /* Just in case. */
+  free (fp->_wide_data->_IO_save_base);
+  fp->_wide_data->_IO_save_base = NULL;
+  fp->_wide_data->_IO_save_end = NULL;
+  fp->_wide_data->_IO_backup_base = NULL;
+}
+
+#if 0
+int
+_IO_switch_to_wput_mode (fp)
+     _IO_FILE *fp;
+{
+  fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr;
+  fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
+  /* Following is wrong if line- or un-buffered? */
+  fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
+				   ? fp->_wide_data->_IO_read_end
+				   : fp->_wide_data->_IO_buf_end);
+
+  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end;
+
+  fp->_flags |= _IO_CURRENTLY_PUTTING;
+  return 0;
+}
+#endif
+
+
+static int
+#ifdef _LIBC
+internal_function
+#endif
+save_for_wbackup (fp, end_p)
+     _IO_FILE *fp;
+     wchar_t *end_p;
+{
+  /* Append [_IO_read_base..end_p] to backup area. */
+  _IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p);
+  /* needed_size is how much space we need in the backup area. */
+  _IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base)
+			    - least_mark);
+  /* FIXME: Dubious arithmetic if pointers are NULL */
+  _IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end
+			      - fp->_wide_data->_IO_save_base);
+  _IO_size_t avail; /* Extra space available for future expansion. */
+  _IO_ssize_t delta;
+  struct _IO_marker *mark;
+  if (needed_size > current_Bsize)
+    {
+      wchar_t *new_buffer;
+      avail = 100;
+      new_buffer = (wchar_t *) malloc ((avail + needed_size)
+				       * sizeof (wchar_t));
+      if (new_buffer == NULL)
+	return EOF;		/* FIXME */
+      if (least_mark < 0)
+	{
+#ifdef _LIBC
+	  __wmempcpy (__wmempcpy (new_buffer + avail,
+				  fp->_wide_data->_IO_save_end + least_mark,
+				  -least_mark),
+		      fp->_wide_data->_IO_read_base,
+		      end_p - fp->_wide_data->_IO_read_base);
+#else
+	  memcpy (new_buffer + avail,
+		  fp->_wide_data->_IO_save_end + least_mark,
+		  -least_mark * sizeof (wchar_t));
+	  memcpy (new_buffer + avail - least_mark,
+		  fp->_wide_data->_IO_read_base,
+		  (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
+#endif
+	}
+      else
+	{
+#ifdef _LIBC
+	  __wmemcpy (new_buffer + avail,
+		     fp->_wide_data->_IO_read_base + least_mark,
+		     needed_size);
+#else
+	  memcpy (new_buffer + avail,
+		  fp->_wide_data->_IO_read_base + least_mark,
+		  needed_size * sizeof (wchar_t));
+#endif
+	}
+      if (fp->_wide_data->_IO_save_base)
+	free (fp->_wide_data->_IO_save_base);
+      fp->_wide_data->_IO_save_base = new_buffer;
+      fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size;
+    }
+  else
+    {
+      avail = current_Bsize - needed_size;
+      if (least_mark < 0)
+	{
+#ifdef _LIBC
+	  __wmemmove (fp->_wide_data->_IO_save_base + avail,
+		      fp->_wide_data->_IO_save_end + least_mark,
+		      -least_mark);
+	  __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
+		     fp->_wide_data->_IO_read_base,
+		     end_p - fp->_wide_data->_IO_read_base);
+#else
+	  memmove (fp->_wide_data->_IO_save_base + avail,
+		   fp->_wide_data->_IO_save_end + least_mark,
+		   -least_mark * sizeof (wchar_t));
+	  memcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
+		  fp->_wide_data->_IO_read_base,
+		  (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
+#endif
+	}
+      else if (needed_size > 0)
+#ifdef _LIBC
+	__wmemcpy (fp->_wide_data->_IO_save_base + avail,
+		   fp->_wide_data->_IO_read_base + least_mark,
+		   needed_size);
+#else
+	memcpy (fp->_wide_data->_IO_save_base + avail,
+		fp->_wide_data->_IO_read_base + least_mark,
+		needed_size * sizeof (wchar_t));
+#endif
+    }
+  fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail;
+  /* Adjust all the streammarkers. */
+  delta = end_p - fp->_wide_data->_IO_read_base;
+  for (mark = fp->_markers; mark != NULL; mark = mark->_next)
+    mark->_pos -= delta;
+  return 0;
+}
+
+wint_t
+_IO_sputbackwc (fp, c)
+     _IO_FILE *fp;
+     wint_t c;
+{
+  wint_t result;
+
+  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
+      && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c)
+    {
+      fp->_wide_data->_IO_read_ptr--;
+      result = c;
+    }
+  else
+    result = _IO_PBACKFAIL (fp, c);
+
+  if (result != EOF)
+    fp->_flags &= ~_IO_EOF_SEEN;
+
+  return result;
+}
+
+wint_t
+_IO_sungetwc (fp)
+     _IO_FILE *fp;
+{
+  int result;
+
+  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base)
+    {
+      fp->_wide_data->_IO_read_ptr--;
+      result = *fp->_wide_data->_IO_read_ptr;
+    }
+  else
+    result = _IO_PBACKFAIL (fp, EOF);
+
+  if (result != WEOF)
+    fp->_flags &= ~_IO_EOF_SEEN;
+
+  return result;
+}
+
+
+unsigned
+_IO_adjust_wcolumn (start, line, count)
+     unsigned start;
+     const wchar_t *line;
+     int count;
+{
+  const wchar_t *ptr = line + count;
+  while (ptr > line)
+    if (*--ptr == L'\n')
+      return line + count - ptr - 1;
+  return start + count;
+}
+
+void
+_IO_init_wmarker (marker, fp)
+     struct _IO_marker *marker;
+     _IO_FILE *fp;
+{
+  marker->_sbuf = fp;
+  if (_IO_in_put_mode (fp))
+    _IO_switch_to_get_mode (fp);
+  if (_IO_in_backup (fp))
+    marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
+  else
+    marker->_pos = (fp->_wide_data->_IO_read_ptr
+		    - fp->_wide_data->_IO_read_base);
+
+  /* Should perhaps sort the chain? */
+  marker->_next = fp->_markers;
+  fp->_markers = marker;
+}
+
+#define BAD_DELTA EOF
+
+/* Return difference between MARK and current position of MARK's stream. */
+int
+_IO_wmarker_delta (mark)
+     struct _IO_marker *mark;
+{
+  int cur_pos;
+  if (mark->_sbuf == NULL)
+    return BAD_DELTA;
+  if (_IO_in_backup (mark->_sbuf))
+    cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
+	       - mark->_sbuf->_wide_data->_IO_read_end);
+  else
+    cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
+	       - mark->_sbuf->_wide_data->_IO_read_base);
+  return mark->_pos - cur_pos;
+}
+
+int
+_IO_seekwmark (fp, mark, delta)
+     _IO_FILE *fp;
+     struct _IO_marker *mark;
+     int delta;
+{
+  if (mark->_sbuf != fp)
+    return EOF;
+ if (mark->_pos >= 0)
+    {
+      if (_IO_in_backup (fp))
+	_IO_switch_to_main_wget_area (fp);
+      fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
+				      + mark->_pos);
+    }
+  else
+    {
+      if (!_IO_in_backup (fp))
+	_IO_switch_to_wbackup_area (fp);
+      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos;
+    }
+  return 0;
+}
+
+void
+_IO_unsave_wmarkers (fp)
+     _IO_FILE *fp;
+{
+  struct _IO_marker *mark = fp->_markers;
+  if (mark)
+    {
+#ifdef TODO
+      streampos offset = seekoff (0, ios::cur, ios::in);
+      if (offset != EOF)
+	{
+	  offset += eGptr () - Gbase ();
+	  for ( ; mark != NULL; mark = mark->_next)
+	    mark->set_streampos (mark->_pos + offset);
+	}
+    else
+      {
+	for ( ; mark != NULL; mark = mark->_next)
+	  mark->set_streampos (EOF);
+      }
+#endif
+      fp->_markers = 0;
+    }
+
+  if (_IO_have_backup (fp))
+    _IO_free_wbackup_area (fp);
+}
diff --git a/libio/wprintf.c b/libio/wprintf.c
new file mode 100644
index 0000000000..6fb6c32554
--- /dev/null
+++ b/libio/wprintf.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+/* Write formatted output to stdout from the format string FORMAT.  */
+/* VARARGS1 */
+int
+wprintf (const wchar_t *format, ...)
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = vfwprintf (stdout, format, arg);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/wscanf.c b/libio/wscanf.c
new file mode 100644
index 0000000000..a530d6fcfa
--- /dev/null
+++ b/libio/wscanf.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/* Read formatted input from stdin according to the format string FORMAT.  */
+/* VARARGS1 */
+int
+wscanf (const wchar_t *format, ...)
+{
+  va_list arg;
+  int done;
+
+  va_start (arg, format);
+  done = _IO_vfwscanf (stdin, format, arg, NULL);
+  va_end (arg);
+
+  return done;
+}
diff --git a/libio/wstrops.c b/libio/wstrops.c
new file mode 100644
index 0000000000..af2c957b05
--- /dev/null
+++ b/libio/wstrops.c
@@ -0,0 +1,330 @@
+/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU IO Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this library; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with a GNU compiler to produce an executable, this does
+   not cause the resulting executable to be covered by the GNU General
+   Public License.  This exception does not however invalidate any
+   other reasons why the executable file might be covered by the GNU
+   General Public License.  */
+
+#include "strfile.h"
+#include "libioP.h"
+#include <string.h>
+#include <wchar.h>
+
+#if 0
+/* The following definitions are for exposition only.
+   They map the terminology used in the ANSI/ISO C++ draft standard
+   to the implementation. */
+
+/* allocated:  set  when a dynamic array object has been allocated, and
+   hence should be freed by the destructor for the strstreambuf object. */
+#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
+
+/* constant:  set when the array object has const elements,
+   so the output sequence cannot be written. */
+#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
+
+/* alsize:  the suggested minimum size for a dynamic array object. */
+#define ALSIZE(FP) ??? /* not stored */
+
+/* palloc: points to the function to call to allocate a dynamic array object.*/
+#define PALLOC(FP) \
+  ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
+
+/* pfree: points  to  the  function  to call to free a dynamic array object. */
+#define PFREE(FP) \
+  ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
+
+#endif
+
+#ifdef TODO
+/* An "unbounded buffer" is when a buffer is supplied, but with no
+   specified length.  An example is the buffer argument to sprintf.
+   */
+#endif
+
+void
+_IO_wstr_init_static (fp, ptr, size, pstart)
+     _IO_FILE *fp;
+     wchar_t *ptr;
+     int size;
+     wchar_t *pstart;
+{
+  if (size == 0)
+    size = __wcslen (ptr);
+  else if (size < 0)
+    {
+      /* If size is negative 'the characters are assumed to
+	 continue indefinitely.'  This is kind of messy ... */
+      int s;
+      size = 512;
+      /* Try increasing powers of 2, as long as we don't wrap around. */
+      for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
+	size = s;
+      /* Try increasing size as much as we can without wrapping around. */
+      for (s = size >> 1; s > 0; s >>= 1)
+	{
+	  if (ptr + size + s > ptr)
+	    size += s;
+	}
+    }
+  _IO_wsetb (fp, ptr, ptr + size, 0);
+
+  fp->_wide_data->_IO_write_base = ptr;
+  fp->_wide_data->_IO_read_base = ptr;
+  fp->_wide_data->_IO_read_ptr = ptr;
+  if (pstart)
+    {
+      fp->_wide_data->_IO_write_ptr = pstart;
+      fp->_wide_data->_IO_write_end = ptr + size;
+      fp->_wide_data->_IO_read_end = pstart;
+    }
+  else
+    {
+      fp->_wide_data->_IO_write_ptr = ptr;
+      fp->_wide_data->_IO_write_end = ptr;
+      fp->_wide_data->_IO_read_end = ptr + size;
+    }
+  /* A null _allocate_buffer function flags the strfile as being static. */
+  (((_IO_strfile *) fp)->_s._allocate_buffer) =  (_IO_alloc_type)0;
+}
+
+void
+_IO_wstr_init_readonly (fp, ptr, size)
+     _IO_FILE *fp;
+     const char *ptr;
+     int size;
+{
+  _IO_wstr_init_static (fp, (wchar_t *) ptr, size, NULL);
+  fp->_IO_file_flags |= _IO_NO_WRITES;
+}
+
+_IO_wint_t
+_IO_wstr_overflow (fp, c)
+     _IO_FILE *fp;
+     _IO_wint_t c;
+{
+  int flush_only = c == WEOF;
+  _IO_size_t pos;
+  if (fp->_flags & _IO_NO_WRITES)
+      return flush_only ? 0 : WEOF;
+  if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
+    {
+      fp->_flags |= _IO_CURRENTLY_PUTTING;
+      fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
+      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+    }
+  pos =  fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
+  if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
+    {
+      if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
+	return WEOF;
+      else
+	{
+	  wchar_t *new_buf;
+	  wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
+	  _IO_size_t new_size = 2 * _IO_wblen (fp) + 100;
+	  new_buf
+	    = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
+									* sizeof (wchar_t));
+	  if (new_buf == NULL)
+	    {
+	      /*	  __ferror(fp) = 1; */
+	      return WEOF;
+	    }
+	  if (old_buf)
+	    {
+	      __wmemcpy (new_buf, old_buf, _IO_wblen (fp));
+	      (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
+	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
+	      fp->_wide_data->_IO_buf_base = NULL;
+	    }
+	  _IO_wsetb (fp, new_buf, new_buf + new_size, 1);
+	  fp->_wide_data->_IO_read_base =
+	    new_buf + (fp->_wide_data->_IO_read_base - old_buf);
+	  fp->_wide_data->_IO_read_ptr =
+	    new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
+	  fp->_wide_data->_IO_read_end =
+	    new_buf + (fp->_wide_data->_IO_read_end - old_buf);
+	  fp->_wide_data->_IO_write_ptr =
+	    new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
+
+	  fp->_wide_data->_IO_write_base = new_buf;
+	  fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
+	}
+    }
+
+  if (!flush_only)
+    *fp->_wide_data->_IO_write_ptr++ = c;
+  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
+    fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
+  return c;
+}
+
+_IO_wint_t
+_IO_wstr_underflow (fp)
+     _IO_FILE *fp;
+{
+  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
+    fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
+  if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
+    {
+      fp->_flags &= ~_IO_CURRENTLY_PUTTING;
+      fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
+      fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
+    }
+  if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
+    return *fp->_wide_data->_IO_read_ptr;
+  else
+    return WEOF;
+}
+
+/* The size of the valid part of the buffer.  */
+
+_IO_ssize_t
+_IO_wstr_count (fp)
+     _IO_FILE *fp;
+{
+  return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end
+	   ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end)
+	  - fp->_wide_data->_IO_read_base);
+}
+
+_IO_off64_t
+_IO_wstr_seekoff (fp, offset, dir, mode)
+     _IO_FILE *fp;
+     _IO_off64_t offset;
+     int dir;
+     int mode;
+{
+  _IO_off64_t new_pos;
+
+  if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
+    mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
+
+  if (mode == 0)
+    {
+      /* Don't move any pointers. But there is no clear indication what
+	 mode FP is in. Let's guess. */
+      if (fp->_IO_file_flags & _IO_NO_WRITES)
+        new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
+      else
+        new_pos = (fp->_wide_data->_IO_write_ptr
+		   - fp->_wide_data->_IO_write_base);
+    }
+  else
+    {
+      _IO_ssize_t cur_size = _IO_wstr_count (fp);
+      new_pos = EOF;
+
+      /* Move the get pointer, if requested. */
+      if (mode & _IOS_INPUT)
+	{
+	  switch (dir)
+	    {
+	    case _IO_seek_end:
+	      offset += cur_size;
+	      break;
+	    case _IO_seek_cur:
+	      offset += (fp->_wide_data->_IO_read_ptr
+			 - fp->_wide_data->_IO_read_base);
+	      break;
+	    default: /* case _IO_seek_set: */
+	      break;
+	    }
+	  if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+	    return EOF;
+	  fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
+					  + offset);
+	  fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
+					  + cur_size);
+	  new_pos = offset;
+	}
+
+      /* Move the put pointer, if requested. */
+      if (mode & _IOS_OUTPUT)
+	{
+	  switch (dir)
+	    {
+	    case _IO_seek_end:
+	      offset += cur_size;
+	      break;
+	    case _IO_seek_cur:
+	      offset += (fp->_wide_data->_IO_write_ptr
+			 - fp->_wide_data->_IO_write_base);
+	      break;
+	    default: /* case _IO_seek_set: */
+	      break;
+	    }
+	  if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+	    return EOF;
+	  fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
+					   + offset);
+	  new_pos = offset;
+	}
+    }
+  return new_pos;
+}
+
+_IO_wint_t
+_IO_wstr_pbackfail (fp, c)
+     _IO_FILE *fp;
+     _IO_wint_t c;
+{
+  if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
+    return WEOF;
+  return _IO_wdefault_pbackfail (fp, c);
+}
+
+void
+_IO_wstr_finish (fp, dummy)
+     _IO_FILE *fp;
+     int dummy;
+{
+  if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
+    (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
+  fp->_wide_data->_IO_buf_base = NULL;
+
+  _IO_wdefault_finish (fp, 0);
+}
+
+struct _IO_jump_t _IO_wstr_jumps =
+{
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_wstr_finish),
+  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
+  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
+  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
+  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
+  JUMP_INIT(xsputn, _IO_wdefault_xsputn),
+  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
+  JUMP_INIT(seekoff, _IO_wstr_seekoff),
+  JUMP_INIT(seekpos, _IO_default_seekpos),
+  JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf),
+  JUMP_INIT(sync, _IO_default_sync),
+  JUMP_INIT(doallocate, _IO_wdefault_doallocate),
+  JUMP_INIT(read, _IO_default_read),
+  JUMP_INIT(write, _IO_default_write),
+  JUMP_INIT(seek, _IO_default_seek),
+  JUMP_INIT(close, _IO_default_close),
+  JUMP_INIT(stat, _IO_default_stat),
+  JUMP_INIT(showmanyc, _IO_default_showmanyc),
+  JUMP_INIT(imbue, _IO_default_imbue)
+};