about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog232
-rw-r--r--Versions.def1
-rw-r--r--iconv/gconv.c30
-rw-r--r--iconv/gconv.h102
-rw-r--r--iconv/gconv_builtin.c46
-rw-r--r--iconv/gconv_close.c18
-rw-r--r--iconv/gconv_db.c118
-rw-r--r--iconv/gconv_dl.c28
-rw-r--r--iconv/gconv_int.h27
-rw-r--r--iconv/gconv_open.c49
-rw-r--r--iconv/gconv_simple.c42
-rw-r--r--iconv/iconv.c14
-rw-r--r--iconv/iconv_close.c4
-rw-r--r--iconv/iconv_open.c6
-rw-r--r--iconv/loop.c19
-rw-r--r--iconv/skeleton.c78
-rw-r--r--iconvdata/8bit-gap.c10
-rw-r--r--iconvdata/8bit-generic.c6
-rw-r--r--iconvdata/ansi_x3.110.c16
-rw-r--r--iconvdata/big5.c12
-rw-r--r--iconvdata/cns11643.h22
-rw-r--r--iconvdata/cns11643l1.h14
-rw-r--r--iconvdata/euc-cn.c18
-rw-r--r--iconvdata/euc-jp.c26
-rw-r--r--iconvdata/euc-kr.c16
-rw-r--r--iconvdata/euc-tw.c26
-rw-r--r--iconvdata/gb2312.h14
-rw-r--r--iconvdata/iso-2022-jp.c137
-rw-r--r--iconvdata/iso-2022-kr.c41
-rw-r--r--iconvdata/iso646.c204
-rw-r--r--iconvdata/iso8859-1.c4
-rw-r--r--iconvdata/iso_6937-2.c16
-rw-r--r--iconvdata/iso_6937.c16
-rw-r--r--iconvdata/jis0201.h6
-rw-r--r--iconvdata/jis0208.h16
-rw-r--r--iconvdata/jis0212.h14
-rw-r--r--iconvdata/johab.c32
-rw-r--r--iconvdata/ksc5601.h18
-rw-r--r--iconvdata/sjis.c18
-rw-r--r--iconvdata/t.61.c14
-rw-r--r--iconvdata/uhc.c28
-rw-r--r--include/limits.h4
-rw-r--r--include/wchar.h29
-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
-rw-r--r--locale/C-time.c56
-rw-r--r--locale/categories.def17
-rw-r--r--locale/langinfo.h60
-rw-r--r--locale/localeinfo.h7
-rw-r--r--localedata/Makefile2
-rw-r--r--manual/stdio.texi6
-rw-r--r--manual/time.texi25
-rw-r--r--stdio-common/Makefile3
-rw-r--r--stdio-common/_itoa.c4
-rw-r--r--stdio-common/_itowa.c346
-rw-r--r--stdio-common/_itowa.h63
-rw-r--r--stdio-common/itoa-digits.c7
-rw-r--r--stdio-common/itowa-digits.c27
-rw-r--r--stdio-common/printf-parse.h71
-rw-r--r--stdio-common/printf-prs.c4
-rw-r--r--stdio-common/printf.h3
-rw-r--r--stdio-common/printf_fp.c13
-rw-r--r--stdio-common/printf_size.c3
-rw-r--r--stdio-common/vfprintf.c585
-rw-r--r--stdio-common/vfscanf.c1313
-rw-r--r--stdio-common/vfwprintf.c3
-rw-r--r--stdio-common/vfwscanf.c2
-rw-r--r--stdlib/mblen.c4
-rw-r--r--stdlib/mbtowc.c4
-rw-r--r--stdlib/strfmon.c3
-rw-r--r--stdlib/wctomb.c4
-rw-r--r--sysdeps/generic/_G_config.h18
-rw-r--r--sysdeps/generic/printf_fphex.c8
-rw-r--r--sysdeps/unix/sysv/linux/_G_config.h24
-rw-r--r--time/Makefile4
-rw-r--r--time/Versions4
-rw-r--r--time/strftime.c518
-rw-r--r--time/tst_wcsftime.c28
-rw-r--r--time/wcsftime.c4
-rw-r--r--wcsmbs/Makefile6
-rw-r--r--wcsmbs/Versions4
-rw-r--r--wcsmbs/btowc.c22
-rw-r--r--wcsmbs/mbrtowc.c40
-rw-r--r--wcsmbs/mbsnrtowcs.c55
-rw-r--r--wcsmbs/mbsrtowcs.c55
-rw-r--r--wcsmbs/wchar.h181
-rw-r--r--wcsmbs/wcrtomb.c49
-rw-r--r--wcsmbs/wcschrnul.c36
-rw-r--r--wcsmbs/wcsmbsload.c140
-rw-r--r--wcsmbs/wcsmbsload.h10
-rw-r--r--wcsmbs/wcsnrtombs.c71
-rw-r--r--wcsmbs/wcsrtombs.c73
-rw-r--r--wcsmbs/wctob.c28
-rw-r--r--wcsmbs/wmemcpy.c7
-rw-r--r--wcsmbs/wmemmove.c5
-rw-r--r--wcsmbs/wmempcpy.c33
174 files changed, 8495 insertions, 1921 deletions
diff --git a/ChangeLog b/ChangeLog
index 1f191fecc1..94e8bc7c76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,237 @@
 1999-06-16  Ulrich Drepper  <drepper@cygnus.com>
 
+	* Versions.def: Add GLIBC_2.2 for libc.
+
+	* iconv/gconv.h: Make header suitable for inclusion in public header
+	by protecting all names with __.
+	* iconv/gconv.c: Adapt for symbol name changes.
+	* iconv/gconv.h: Likewise.
+	* iconv/gconv_builtin.c: Likewise.
+	* iconv/gconv_close.c: Likewise.
+	* iconv/gconv_db.c: Likewise.
+	* iconv/gconv_dl.c: Likewise.
+	* iconv/gconv_int.h: Likewise.
+	* iconv/gconv_open.c: Likewise.
+	* iconv/gconv_simple.c: Likewise.
+	* iconv/iconv.c: Likewise.
+	* iconv/iconv_close.c: Likewise.
+	* iconv/iconv_open.c: Likewise.
+	* iconv/loop.c: Likewise.
+	* iconv/skeleton.c: Likewise.
+	* iconvdata/8bit-gap.c: Likewise.
+	* iconvdata/8bit-generic.c: Likewise.
+	* iconvdata/ansi_x3.110.c: Likewise.
+	* iconvdata/big5.c: Likewise.
+	* iconvdata/cns11643.h: Likewise.
+	* iconvdata/cns11643l1.h: Likewise.
+	* iconvdata/euc-cn.c: Likewise.
+	* iconvdata/euc-jp.c: Likewise.
+	* iconvdata/euc-kr.c: Likewise.
+	* iconvdata/euc-tw.c: Likewise.
+	* iconvdata/gb2312.h: Likewise.
+	* iconvdata/iso-2022-jp.c: Likewise.
+	* iconvdata/iso-2022-kr.c: Likewise.
+	* iconvdata/iso646.c: Likewise.
+	* iconvdata/iso8859-1.c: Likewise.
+	* iconvdata/iso_6937-2.c: Likewise.
+	* iconvdata/iso_6937.c: Likewise.
+	* iconvdata/jis0201.h: Likewise.
+	* iconvdata/jis0208.h: Likewise.
+	* iconvdata/jis0212.h: Likewise.
+	* iconvdata/johab.c: Likewise.
+	* iconvdata/ksc5601.h: Likewise.
+	* iconvdata/sjis.c: Likewise.
+	* iconvdata/t.61.c: Likewise.
+	* iconvdata/uhc.c: Likewise.
+	* stdlib/mblen.c: Likewise.
+	* stdlib/mbtowc.c: Likewise.
+	* stdlib/wctomb.c: Likewise.
+	* wcsmbs/btowc.c: Likewise.
+	* wcsmbs/mbrtowc.c: Likewise.
+	* wcsmbs/mbsnrtowcs.c: Likewise.
+	* wcsmbs/mbsrtowcs.c: Likewise.
+	* wcsmbs/wchar.h: Likewise.
+	* wcsmbs/wcrtomb.c: Likewise.
+	* wcsmbs/wcsmbsload.c: Likewise.
+	* wcsmbs/wcsmbsload.h: Likewise.
+	* wcsmbs/wcsnrtombs.c: Likewise.
+	* wcsmbs/wcsrtombs.c: Likewise.
+	* wcsmbs/wctob.c: Likewise.
+
+	* include/limits.h (MB_LEN_MAX): Increase to 16.
+
+	* sysdeps/generic/_G_config.h: Define _G_fpos_t as struct.  Define
+	_G_iconv_t.
+	* sysdeps/unix/sysv/linux/_G_config.h: Likewise.
+	* include/wchar.h: Change mbstate_t to __mbstate_t.
+
+	* libio/Makefile (routines): Add wfiledoalloc, 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,
+	and iofwide.
+	(tests): Add tst_swprintf, tst_wprintf, tst_swscanf, and tst_wscanf.
+	* libio/Versions: Add _IO_fgetpos, _IO_fgetpos64, _IO_fsetpos,
+	_IO_fsetpos64, fgetpos, fgetpos64, fgetwc, fgetwc_unlocked, fgetws,
+	fgetws_unlocked, fputwc, fputwc_unlocked, fputws, fputws_unlocked,
+	fsetpos, fsetpos64, fwide, fwprintf, fwscanf, getwc, getwc_unlocked,
+	getwchar, getwchar_unlocked, putwc, putwc_unlocked, putwchar,
+	putwchar_unlocked, swprintf, swscanf, ungetwc, vfwprintf, vswprintf,
+	vwprintf, vfwscanf, vswscanf, vwscanf, wprintf, and wscanf to
+	GLIBC_2.2 for libc.
+	* libio/libio.h: Define codecvt struct.  Define _IO_wide_data.
+	Extend _IO_file contain pointer to codecvt, widedata and mode.
+	(_IO_getwc_unlocked): New macro.
+	(_IO_putwc_unlocked): New macro.
+	(_IO_fwide): New macro.
+	* libio/libioP.h: Add new prototypes and adjust existing declarations.
+	* libio/fileops.c (_IO_new_file_close_it): Reset normal or widedata
+	buffers based on mode.
+	(new_do_write): Set _IO_write_end to _IO_buf_end if stream is wide
+	oriented.
+	(_IO_new_file_overflow): Don't depend only on _IO_CURRENTLY_PUTTING
+	flag to be enough to signal unallocated buffer.  For wide oriented
+	stream don't make it linebuffered.  Don't use _IO_do_flush, use
+	_IO_new_do_write directly.
+	(_IO_new_file_seekoff): Change return value type to _IO_off64_t.
+	(_IO_file_seek): Likewise.
+	* libio/genops.c (_IO_least_marker): Make global.
+	(__underflow): Orient stream if not already done.
+	(__uflow): Likewise.
+	(_IO_default_seekpos): Change to type _IO_off64_t.
+	(_IO_default_seekoff): Likewise.
+	(_IO_default_seek): Likewise.
+	(_IO_no_init): New function.  Similar to _IO_init but allows to orient
+	in initialization.
+	* libio/iolibio.h: Add prototype for _IO_vswprintf.  Change _IO_pos_BAD
+	to use _IO_off64_t.
+	* libio/ftello.c: Use _IO_off_t.  For now abort when use with wide
+	char stream.
+	* libio/ftello64.c: Likewise.
+	* libio/ioftell.c: Likewise.
+	* libio/iofopncook.c: Likewise.
+	* libio/ioseekoff.c: Likewise.
+	* libio/ioseekpos.c: Likewise.
+	* libio/oldfileops.c: Likewise.
+	* libio/iofgetpos.c: Store state of conversion if necessary.
+	* libio/iofgetpos64.c: Likewise.
+	* libio/iofsetpos.c: Restore conversion state if necessary.
+	* libio/iofsetpos64.c: Likewise.
+	* libio/iofdopen.c: Initialize so that stream can be wide oriented.
+	* libio/iofopen.c: Likewise.
+	* libio/iofopen64.c: Likewise.
+	* libio/iopopen.c: Likewise.
+	* libio/iovdprintf.c: Likewise.
+	* libio/iovsprintf.c: Likewise.
+	* libio/iovsscanf.c: Likewise.
+	* libio/memstream.c: Likewise.
+	* libio/obprintf.c: Likewise.
+	* libio/iofputs.c: Orient stream if not already happened.
+	* libio/iofputs_u.c: Likewise.
+	* libio/iofwrite.c: Likewise.
+	* libio/iofwrite_u.c: Likewise.
+	* libio/ioputs.c: Likewise.
+	* libio/iosetbuffer.c: Handle not yet oriented stream.
+	* libio/iosetvbuf.c: Likewise.
+	* libio/oldstdfiles.c: Adjust FILEBUF_LITERAL call.
+	* libio/stdfiles.c: Likewise.
+	* libio/strops.c (_IO_str_overflow): Correctly free buffer after
+	failed allocation.
+	(_IO_str_seekoff): Use _IO_off64_t.
+	* libio/vasprintf.c: Pre-orient stream.
+	* libio/vsnprintf.c: Likewise.
+	* libio/fputwc.c: New file.
+	* libio/fputwc_u.c: New file.
+	* libio/fwprintf.c: New file.
+	* libio/fwscanf.c: New file.
+	* libio/getwc.c: New file.
+	* libio/getwc_u.c: New file.
+	* libio/getwchar.c: New file.
+	* libio/getwchar_u.c: New file.
+	* libio/iofgetws.c: New file.
+	* libio/iofgetws_u.c: New file.
+	* libio/iofputws.c: New file.
+	* libio/iofputws_u.c: New file.
+	* libio/iofwide.c: New file.
+	* libio/iogetwline.c: New file.
+	* libio/ioungetwc.c: New file.
+	* libio/iovswscanf.c: New file.
+	* libio/iowpadn.c: New file.
+	* libio/oldiofgetpos.c: New file.
+	* libio/oldiofgetpos64.c: New file.
+	* libio/oldiofsetpos.c: New file.
+	* libio/oldiofsetpos64.c: New file.
+	* libio/putwc.c: New file.
+	* libio/putwc_u.c: New file.
+	* libio/putwchar.c: New file.
+	* libio/putwchar_u.c: New file.
+	* libio/swprintf.c: New file.
+	* libio/swscanf.c: New file.
+	* libio/tst_swprintf.c: New file.
+	* libio/tst_swscanf.c: New file.
+	* libio/tst_wprintf.c: New file.
+	* libio/tst_wscanf.c: New file.
+	* libio/tst_wscanf.input: New file.
+	* libio/vswprintf.c: New file.
+	* libio/vwprintf.c: New file.
+	* libio/vwscanf.c: New file.
+	* libio/wfiledoalloc.c: New file.
+	* libio/wfileops.c: New file.
+	* libio/wgenops.c: New file.
+	* libio/wprintf.c: New file.
+	* libio/wscanf.c: New file.
+	* libio/wstrops.c: New file.
+	* stdio-common/Makefile (routines): Add _itowa, itowa-digits,
+	vfwprintf, and vfwscanf.
+	* stdio-common/_itoa.c (base_table): Rename to _IO_base_table and
+	make global.
+	* stdio-common/_itowa.c: New file.
+	* stdio-common/_itowa.h: New file.
+	* stdio-common/itoa-digits.c: Minimal optimization.
+	* stdio-common/itowa-digits.c: New file.
+	* stdio-common/printf-parse.h: Allow use in wide character context.
+	* stdio-common/printf-prs.c: Define ISASCII and MBRLEN.
+	* stdio-common/printf.h (printf_info): Add wide bit.
+	* stdio-common/printf_fp.c: Determine from wide bit whether stream
+	is wide oriented or not.
+	* stdio-common/printf_size.c: Likewise.
+	* sysdeps/generic/printf_fphex.c: Likewise.
+	* stdlib/strfmon.c: Call __printf_fp with wide bit cleared.
+	* stdio-common/vfprintf.c: Rewrite to allow use in wide character
+	context.
+	* stdio-common/vfscand.c: Likewise.
+	* stdio-common/vfwprintf.c: New file.
+	* stdio-common/vfwscanf.c: New file.
+
+	* time/Makefile (routines): Add wcsftime.
+	(tests): Add tst_wcsftime.
+	* time/Versions: Add wcsftime to GLIBC_2.2 for libc.
+	* time/strftime.c: Make usable as wcsftime.
+	* time/wcsftime.c: New file.
+	* time/tst_wcsftime.c: New file.
+
+	* wcsmbs/Makefile (routines): Add wmempcpy and wcschrnul.
+	* wcsmbs/Versions: Add wmempcpy and wcschrnul to GLIBC_2.2 for libc.
+	* wcsmbs/wcschrnul.c: New file.
+	* wcsmbs/wmemcpy.c: New file.
+	* wcsmbs/wmemcpy.c: Rename to __wmemcpy and make wmemcpy weak alias.
+	* wcsmbs/wmemmove.c: Likewise for wmemmove.
+
+	* manual/stdio.texi: Document is_char and wide element if printf_info.
+
+	* manual/time.texi: Document wcsftime.
+
+	* include/wchar.h: Add prototypes for __wmemcpy, __wmempcpy,
+	__wmemmove, __wcschrnul, and __vfwscanf.
+
+	* locale/langinfo.h: Add new LC_TIME entries for wchar_t data.
+	* locale/C-time.c: Adapt for above change.
+	* locale/categories.def: Likewise.
+	* locale/localeinfo.h: Likewise.
+	* localedata/Makefile: Don't run tests for now.
+
 	* manual/errno.texi: Fix typos.
 	* manual/memory.texi: Likewise.
 	* manual/ctype.texi: Likewise.
diff --git a/Versions.def b/Versions.def
index 0c46092fee..1353a08bf6 100644
--- a/Versions.def
+++ b/Versions.def
@@ -5,6 +5,7 @@ libc {
   GLIBC_2.0
   GLIBC_2.1 GLIBC_2.0
   GLIBC_2.1.1 GLIBC_2.1
+  GLIBC_2.2 GLIBC_2.1.1
 }
 libcrypt {
   GLIBC_2.0
diff --git a/iconv/gconv.c b/iconv/gconv.c
index 14398e2e37..828db9d6f8 100644
--- a/iconv/gconv.c
+++ b/iconv/gconv.c
@@ -27,43 +27,45 @@
 
 int
 internal_function
-__gconv (gconv_t cd, const unsigned char **inbuf, const unsigned char *inbufend,
-	 unsigned char **outbuf, unsigned char *outbufend, size_t *converted)
+__gconv (__gconv_t cd, const unsigned char **inbuf,
+	 const unsigned char *inbufend, unsigned char **outbuf,
+	 unsigned char *outbufend, size_t *converted)
 {
-  size_t last_step = cd->nsteps - 1;
+  size_t last_step = cd->__nsteps - 1;
   int result;
 
-  if (cd == (gconv_t) -1L)
-    return GCONV_ILLEGAL_DESCRIPTOR;
+  if (cd == (__gconv_t) -1L)
+    return __GCONV_ILLEGAL_DESCRIPTOR;
 
   assert (converted != NULL);
   *converted = 0;
 
   if (inbuf == NULL || *inbuf == NULL)
     /* We just flush.  */
-    result = _CALL_DL_FCT (cd->steps->fct,
-			   (cd->steps, cd->data, NULL, NULL, converted, 1));
+    result = _CALL_DL_FCT (cd->__steps->__fct,
+			   (cd->__steps, cd->__data, NULL, NULL,
+			    converted, 1));
   else
     {
       const unsigned char *last_start;
 
       assert (outbuf != NULL && *outbuf != NULL);
-      cd->data[last_step].outbuf = *outbuf;
-      cd->data[last_step].outbufend = outbufend;
+      cd->__data[last_step].__outbuf = *outbuf;
+      cd->__data[last_step].__outbufend = outbufend;
 
       do
 	{
 	  last_start = *inbuf;
-	  result = _CALL_DL_FCT (cd->steps->fct,
-				 (cd->steps, cd->data, inbuf, inbufend,
+	  result = _CALL_DL_FCT (cd->__steps->__fct,
+				 (cd->__steps, cd->__data, inbuf, inbufend,
 				  converted, 0));
 	}
-      while (result == GCONV_EMPTY_INPUT && last_start != *inbuf
-	     && *inbuf + cd->steps->min_needed_from <= inbufend);
+      while (result == __GCONV_EMPTY_INPUT && last_start != *inbuf
+	     && *inbuf + cd->__steps->__min_needed_from <= inbufend);
     }
 
   if (outbuf != NULL && *outbuf != NULL)
-    *outbuf = cd->data[last_step].outbuf;
+    *outbuf = cd->__data[last_step].__outbuf;
 
   return result;
 }
diff --git a/iconv/gconv.h b/iconv/gconv.h
index 4b71ccf4b8..f4a66c68d4 100644
--- a/iconv/gconv.h
+++ b/iconv/gconv.h
@@ -24,106 +24,108 @@
 #define _GCONV_H	1
 
 #include <features.h>
+#define __need_mbstate_t
 #include <wchar.h>
 #define __need_size_t
 #include <stddef.h>
 
 /* ISO 10646 value used to signal invalid value.  */
-#define UNKNOWN_10646_CHAR	((wchar_t) 0xfffd)
+#define __UNKNOWN_10646_CHAR	((wchar_t) 0xfffd)
 
 /* Error codes for gconv functions.  */
 enum
 {
-  GCONV_OK = 0,
-  GCONV_NOCONV,
-  GCONV_NODB,
-  GCONV_NOMEM,
-
-  GCONV_EMPTY_INPUT,
-  GCONV_FULL_OUTPUT,
-  GCONV_ILLEGAL_INPUT,
-  GCONV_INCOMPLETE_INPUT,
-
-  GCONV_ILLEGAL_DESCRIPTOR,
-  GCONV_INTERNAL_ERROR
+  __GCONV_OK = 0,
+  __GCONV_NOCONV,
+  __GCONV_NODB,
+  __GCONV_NOMEM,
+
+  __GCONV_EMPTY_INPUT,
+  __GCONV_FULL_OUTPUT,
+  __GCONV_ILLEGAL_INPUT,
+  __GCONV_INCOMPLETE_INPUT,
+
+  __GCONV_ILLEGAL_DESCRIPTOR,
+  __GCONV_INTERNAL_ERROR
 };
 
 
 /* Forward declarations.  */
-struct gconv_step;
-struct gconv_step_data;
-struct gconv_loaded_object;
+struct __gconv_step;
+struct __gconv_step_data;
+struct __gconv_loaded_object;
 
 
 /* Type of a conversion function.  */
-typedef int (*gconv_fct) __PMT ((struct gconv_step *,
-				 struct gconv_step_data *,
-				 __const unsigned char **,
-				 __const unsigned char *, size_t *, int));
+typedef int (*__gconv_fct) __PMT ((struct __gconv_step *,
+				   struct __gconv_step_data *,
+				   __const unsigned char **,
+				   __const unsigned char *, size_t *, int));
 
 /* Constructor and destructor for local data for conversion step.  */
-typedef int (*gconv_init_fct) __PMT ((struct gconv_step *));
-typedef void (*gconv_end_fct) __PMT ((struct gconv_step *));
+typedef int (*__gconv_init_fct) __PMT ((struct __gconv_step *));
+typedef void (*__gconv_end_fct) __PMT ((struct __gconv_step *));
 
 
 /* Description of a conversion step.  */
-struct gconv_step
+struct __gconv_step
 {
-  struct gconv_loaded_object *shlib_handle;
-  __const char *modname;
+  struct __gconv_loaded_object *__shlib_handle;
+  __const char *__modname;
 
-  int counter;
+  int __counter;
 
-  __const char *from_name;
-  __const char *to_name;
+  __const char *__from_name;
+  __const char *__to_name;
 
-  gconv_fct fct;
-  gconv_init_fct init_fct;
-  gconv_end_fct end_fct;
+  __gconv_fct __fct;
+  __gconv_init_fct __init_fct;
+  __gconv_end_fct __end_fct;
 
   /* Information about the number of bytes needed or produced in this
      step.  This helps optimizing the buffer sizes.  */
-  int min_needed_from;
-  int max_needed_from;
-  int min_needed_to;
-  int max_needed_to;
+  int __min_needed_from;
+  int __max_needed_from;
+  int __min_needed_to;
+  int __max_needed_to;
 
   /* Flag whether this is a stateful encoding or not.  */
-  int stateful;
+  int __stateful;
 
-  void *data;		/* Pointer to step-local data.  */
+  void *__data;		/* Pointer to step-local data.  */
 };
 
 /* Additional data for steps in use of conversion descriptor.  This is
    allocated by the `init' function.  */
-struct gconv_step_data
+struct __gconv_step_data
 {
-  unsigned char *outbuf;    /* Output buffer for this step.  */
-  unsigned char *outbufend; /* Address of first byte after the output buffer.*/
+  unsigned char *__outbuf;    /* Output buffer for this step.  */
+  unsigned char *__outbufend; /* Address of first byte after the output
+				 buffer.*/
 
   /* Is this the last module in the chain.  */
-  int is_last;
+  int __is_last;
 
   /* Counter for number of invocations of the module function for this
      descriptor.  */
-  int invocation_counter;
+  int __invocation_counter;
 
   /* Flag whether this is an internal use of the module (in the mb*towc*
      and wc*tomb* functions) or regular with iconv(3).  */
-  int internal_use;
+  int __internal_use;
 
-  mbstate_t *statep;
-  mbstate_t __state;	/* This element should not be used directly by
+  __mbstate_t *__statep;
+  __mbstate_t __state;	/* This element should not be used directly by
 			   any module; always use STATEP!  */
 };
 
 
 /* Combine conversion step description with data.  */
-typedef struct gconv_info
+typedef struct __gconv_info
 {
-  size_t nsteps;
-  struct gconv_step *steps;
-  struct gconv_step_data data[0];
-} *gconv_t;
+  size_t __nsteps;
+  struct __gconv_step *__steps;
+  struct __gconv_step_data __data[0];
+} *__gconv_t;
 
 #endif /* gconv.h */
diff --git a/iconv/gconv_builtin.c b/iconv/gconv_builtin.c
index 4f3ca565ac..ca3ca3e5e6 100644
--- a/iconv/gconv_builtin.c
+++ b/iconv/gconv_builtin.c
@@ -1,5 +1,5 @@
 /* Table for builtin transformation mapping.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -29,9 +29,9 @@
 static struct builtin_map
 {
   const char *name;
-  gconv_fct fct;
-  gconv_init_fct init;
-  gconv_end_fct end;
+  __gconv_fct fct;
+  __gconv_init_fct init;
+  __gconv_end_fct end;
 
   int min_needed_from;
   int max_needed_from;
@@ -43,15 +43,15 @@ static struct builtin_map
 #define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \
 			       Fct, Init, End, MinF, MaxF, MinT, MaxT) \
   {									      \
-    name: Name,								      \
-    fct: Fct,								      \
-    init: Init,								      \
-    end: End,								      \
+    .name = Name,							      \
+    .fct = Fct,								      \
+    .init = Init,							      \
+    .end = End,								      \
 									      \
-    min_needed_from: MinF,						      \
-    max_needed_from: MaxF,						      \
-    min_needed_to: MinT,						      \
-    max_needed_to: MaxT							      \
+    .min_needed_from = MinF,						      \
+    .max_needed_from = MaxF,						      \
+    .min_needed_to = MinT,						      \
+    .max_needed_to = MaxT						      \
   },
 #define BUILTIN_ALIAS(From, To)
 
@@ -61,7 +61,7 @@ static struct builtin_map
 
 void
 internal_function
-__gconv_get_builtin_trans (const char *name, struct gconv_step *step)
+__gconv_get_builtin_trans (const char *name, struct __gconv_step *step)
 {
   size_t cnt;
 
@@ -71,17 +71,17 @@ __gconv_get_builtin_trans (const char *name, struct gconv_step *step)
 
   assert (cnt < sizeof (map) / sizeof (map[0]));
 
-  step->fct = map[cnt].fct;
-  step->init_fct = map[cnt].init;
-  step->end_fct = map[cnt].end;
-  step->counter = INT_MAX;
-  step->shlib_handle = NULL;
+  step->__fct = map[cnt].fct;
+  step->__init_fct = map[cnt].init;
+  step->__end_fct = map[cnt].end;
+  step->__counter = INT_MAX;
+  step->__shlib_handle = NULL;
 
-  step->min_needed_from = map[cnt].min_needed_from;
-  step->max_needed_from = map[cnt].max_needed_from;
-  step->min_needed_to = map[cnt].min_needed_to;
-  step->max_needed_to = map[cnt].max_needed_to;
+  step->__min_needed_from = map[cnt].min_needed_from;
+  step->__max_needed_from = map[cnt].max_needed_from;
+  step->__min_needed_to = map[cnt].min_needed_to;
+  step->__max_needed_to = map[cnt].max_needed_to;
 
   /* None of the builtin converters handles stateful encoding.  */
-  step->stateful = 0;
+  step->__stateful = 0;
 }
diff --git a/iconv/gconv_close.c b/iconv/gconv_close.c
index 2fe842467b..a22123b1c9 100644
--- a/iconv/gconv_close.c
+++ b/iconv/gconv_close.c
@@ -25,23 +25,23 @@
 
 int
 internal_function
-__gconv_close (gconv_t cd)
+__gconv_close (__gconv_t cd)
 {
-  struct gconv_step *srunp;
-  struct gconv_step_data *drunp;
+  struct __gconv_step *srunp;
+  struct __gconv_step_data *drunp;
   size_t nsteps;
 
   /* Free all resources by calling destructor functions and release
      the implementations.  */
-  srunp = cd->steps;
-  nsteps = cd->nsteps;
-  drunp = cd->data;
+  srunp = cd->__steps;
+  nsteps = cd->__nsteps;
+  drunp = cd->__data;
   do
     {
-      if (!drunp->is_last && drunp->outbuf != NULL)
-	free (drunp->outbuf);
+      if (!drunp->__is_last && drunp->__outbuf != NULL)
+	free (drunp->__outbuf);
     }
-  while (!(drunp++)->is_last);
+  while (!(drunp++)->__is_last);
 
   /* Free the data allocated for the descriptor.  */
   free (cd);
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index 4abc1ae48b..727be41c25 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -82,7 +82,7 @@ struct known_derivation
 {
   const char *from;
   const char *to;
-  struct gconv_step *steps;
+  struct __gconv_step *steps;
   size_t nsteps;
 };
 
@@ -107,7 +107,7 @@ static void *known_derivations;
 static int
 internal_function
 derivation_lookup (const char *fromset, const char *toset,
-		   struct gconv_step **handle, size_t *nsteps)
+		   struct __gconv_step **handle, size_t *nsteps)
 {
   struct known_derivation key = { fromset, toset, NULL, 0 };
   struct known_derivation **result;
@@ -115,21 +115,21 @@ derivation_lookup (const char *fromset, const char *toset,
   result = __tfind (&key, &known_derivations, derivation_compare);
 
   if (result == NULL)
-    return GCONV_NOCONV;
+    return __GCONV_NOCONV;
 
   *handle = (*result)->steps;
   *nsteps = (*result)->nsteps;
 
   /* Please note that we return GCONV_OK even if the last search for
      this transformation was unsuccessful.  */
-  return GCONV_OK;
+  return __GCONV_OK;
 }
 
 /* Add new derivation to list of known ones.  */
 static void
 internal_function
 add_derivation (const char *fromset, const char *toset,
-		struct gconv_step *handle, size_t nsteps)
+		struct __gconv_step *handle, size_t nsteps)
 {
   struct known_derivation *new_deriv;
   size_t fromset_len = strlen (fromset) + 1;
@@ -163,14 +163,14 @@ free_derivation (void *p)
   size_t cnt;
 
   for (cnt = 0; cnt < deriv->nsteps; ++cnt)
-    if (deriv->steps[cnt].end_fct)
-      _CALL_DL_FCT (deriv->steps[cnt].end_fct, (&deriv->steps[cnt]));
+    if (deriv->steps[cnt].__end_fct)
+      _CALL_DL_FCT (deriv->steps[cnt].__end_fct, (&deriv->steps[cnt]));
 
   /* Free the name strings.  */
-  free ((char *) deriv->steps[0].from_name);
-  free ((char *) deriv->steps[deriv->nsteps - 1].to_name);
+  free ((char *) deriv->steps[0].__from_name);
+  free ((char *) deriv->steps[deriv->nsteps - 1].__to_name);
 
-  free ((struct gconv_step *) deriv->steps);
+  free ((struct __gconv_step *) deriv->steps);
   free (deriv);
 }
 
@@ -178,40 +178,40 @@ free_derivation (void *p)
 static int
 internal_function
 gen_steps (struct derivation_step *best, const char *toset,
-	   const char *fromset, struct gconv_step **handle, size_t *nsteps)
+	   const char *fromset, struct __gconv_step **handle, size_t *nsteps)
 {
   size_t step_cnt = 0;
-  struct gconv_step *result;
+  struct __gconv_step *result;
   struct derivation_step *current;
-  int status = GCONV_NOMEM;
+  int status = __GCONV_NOMEM;
 
   /* First determine number of steps.  */
   for (current = best; current->last != NULL; current = current->last)
     ++step_cnt;
 
-  result = (struct gconv_step *) malloc (sizeof (struct gconv_step)
-					 * step_cnt);
+  result = (struct __gconv_step *) malloc (sizeof (struct __gconv_step)
+					   * step_cnt);
   if (result != NULL)
     {
       int failed = 0;
 
-      status = GCONV_OK;
+      status = __GCONV_OK;
       *nsteps = step_cnt;
       current = best;
       while (step_cnt-- > 0)
 	{
-	  result[step_cnt].from_name = (step_cnt == 0
-					? __strdup (fromset)
-					: current->last->result_set);
-	  result[step_cnt].to_name = (step_cnt + 1 == *nsteps
-				      ? __strdup (current->result_set)
-				      : result[step_cnt + 1].from_name);
+	  result[step_cnt].__from_name = (step_cnt == 0
+					  ? __strdup (fromset)
+					  : current->last->result_set);
+	  result[step_cnt].__to_name = (step_cnt + 1 == *nsteps
+					? __strdup (current->result_set)
+					: result[step_cnt + 1].__from_name);
 
 #ifndef STATIC_GCONV
 	  if (current->code->module_name[0] == '/')
 	    {
 	      /* Load the module, return handle for it.  */
-	      struct gconv_loaded_object *shlib_handle =
+	      struct __gconv_loaded_object *shlib_handle =
 		__gconv_find_shlib (current->code->module_name);
 
 	      if (shlib_handle == NULL)
@@ -220,12 +220,12 @@ gen_steps (struct derivation_step *best, const char *toset,
 		  break;
 		}
 
-	      result[step_cnt].shlib_handle = shlib_handle;
-	      result[step_cnt].modname = shlib_handle->name;
-	      result[step_cnt].counter = 0;
-	      result[step_cnt].fct = shlib_handle->fct;
-	      result[step_cnt].init_fct = shlib_handle->init_fct;
-	      result[step_cnt].end_fct = shlib_handle->end_fct;
+	      result[step_cnt].__shlib_handle = shlib_handle;
+	      result[step_cnt].__modname = shlib_handle->name;
+	      result[step_cnt].__counter = 0;
+	      result[step_cnt].__fct = shlib_handle->fct;
+	      result[step_cnt].__init_fct = shlib_handle->init_fct;
+	      result[step_cnt].__end_fct = shlib_handle->end_fct;
 	    }
 	  else
 #endif
@@ -234,12 +234,12 @@ gen_steps (struct derivation_step *best, const char *toset,
 				       &result[step_cnt]);
 
 	  /* Call the init function.  */
-	  if (result[step_cnt].init_fct != NULL)
+	  if (result[step_cnt].__init_fct != NULL)
 	     {
-	       status = _CALL_DL_FCT (result[step_cnt].init_fct,
+	       status = _CALL_DL_FCT (result[step_cnt].__init_fct,
 				      (&result[step_cnt]));
 
-	       if (status != GCONV_OK)
+	       if (status != __GCONV_OK)
 		 {
 		   failed = 1;
 		   /* Make sure we unload this modules.  */
@@ -256,17 +256,17 @@ gen_steps (struct derivation_step *best, const char *toset,
 	  /* Something went wrong while initializing the modules.  */
 	  while (++step_cnt < *nsteps)
 	    {
-	      if (result[step_cnt].end_fct != NULL)
-		_CALL_DL_FCT (result[step_cnt].end_fct, (&result[step_cnt]));
+	      if (result[step_cnt].__end_fct != NULL)
+		_CALL_DL_FCT (result[step_cnt].__end_fct, (&result[step_cnt]));
 #ifndef STATIC_GCONV
-	      __gconv_release_shlib (result[step_cnt].shlib_handle);
+	      __gconv_release_shlib (result[step_cnt].__shlib_handle);
 #endif
 	    }
 	  free (result);
 	  *nsteps = 0;
 	  *handle = NULL;
-	  if (status == GCONV_OK)
-	    status = GCONV_NOCONV;
+	  if (status == __GCONV_OK)
+	    status = __GCONV_NOCONV;
 	}
       else
 	*handle = result;
@@ -287,7 +287,7 @@ static int
 internal_function
 find_derivation (const char *toset, const char *toset_expand,
 		 const char *fromset, const char *fromset_expand,
-		 struct gconv_step **handle, size_t *nsteps)
+		 struct __gconv_step **handle, size_t *nsteps)
 {
   __libc_lock_define_initialized (static, lock)
   struct derivation_step *first, *current, **lastp, *solution = NULL;
@@ -297,7 +297,7 @@ find_derivation (const char *toset, const char *toset_expand,
 
   result = derivation_lookup (fromset_expand ?: fromset, toset_expand ?: toset,
 			      handle, nsteps);
-  if (result == GCONV_OK)
+  if (result == __GCONV_OK)
     return result;
 
   __libc_lock_lock (lock);
@@ -307,7 +307,7 @@ find_derivation (const char *toset, const char *toset_expand,
      find it but at the same time another thread looked for this derivation. */
   result = derivation_lookup (fromset_expand ?: fromset, toset_expand ?: toset,
 			      handle, nsteps);
-  if (result == GCONV_OK)
+  if (result == __GCONV_OK)
     {
       __libc_lock_unlock (lock);
       return result;
@@ -613,7 +613,7 @@ find_derivation (const char *toset, const char *toset_expand,
 int
 internal_function
 __gconv_find_transform (const char *toset, const char *fromset,
-			struct gconv_step **handle, size_t *nsteps)
+			struct __gconv_step **handle, size_t *nsteps)
 {
   __libc_once_define (static, once);
   const char *fromset_expand = NULL;
@@ -630,7 +630,7 @@ __gconv_find_transform (const char *toset, const char *fromset,
   if (__gconv_modules_db == NULL)
     {
       __libc_lock_unlock (lock);
-      return GCONV_NOCONV;
+      return __GCONV_NOCONV;
     }
 
   /* See whether the names are aliases.  */
@@ -653,23 +653,23 @@ __gconv_find_transform (const char *toset, const char *fromset,
 
 #ifndef STATIC_GCONV
   /* Increment the user counter.  */
-  if (result == GCONV_OK)
+  if (result == __GCONV_OK)
     {
       size_t cnt = *nsteps;
-      struct gconv_step *steps = *handle;
+      struct __gconv_step *steps = *handle;
 
       while (cnt > 0)
-	if (steps[--cnt].counter++ == 0)
+	if (steps[--cnt].__counter++ == 0)
 	  {
-	    steps[cnt].shlib_handle =
-	      __gconv_find_shlib (steps[cnt].modname);
-	    if (steps[cnt].shlib_handle == NULL)
+	    steps[cnt].__shlib_handle =
+	      __gconv_find_shlib (steps[cnt].__modname);
+	    if (steps[cnt].__shlib_handle == NULL)
 	      {
 		/* Oops, this is the second time we use this module (after
 		   unloading) and this time loading failed!?  */
 		while (++cnt < *nsteps)
-		  __gconv_release_shlib (steps[cnt].shlib_handle);
-		result = GCONV_NOCONV;
+		  __gconv_release_shlib (steps[cnt].__shlib_handle);
+		result = __GCONV_NOCONV;
 		break;
 	      }
 	  }
@@ -682,8 +682,8 @@ __gconv_find_transform (const char *toset, const char *fromset,
   /* The following code is necessary since `find_derivation' will return
      GCONV_OK even when no derivation was found but the same request
      was processed before.  I.e., negative results will also be cached.  */
-  return (result == GCONV_OK
-	  ? (*handle == NULL ? GCONV_NOCONV : GCONV_OK)
+  return (result == __GCONV_OK
+	  ? (*handle == NULL ? __GCONV_NOCONV : __GCONV_OK)
 	  : result);
 }
 
@@ -691,22 +691,22 @@ __gconv_find_transform (const char *toset, const char *fromset,
 /* Release the entries of the modules list.  */
 int
 internal_function
-__gconv_close_transform (struct gconv_step *steps, size_t nsteps)
+__gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
 {
-  int result = GCONV_OK;
+  int result = __GCONV_OK;
 
 #ifndef STATIC_GCONV
   /* Acquire the lock.  */
   __libc_lock_lock (lock);
 
   while (nsteps-- > 0)
-    if (steps[nsteps].shlib_handle != NULL
-	&& --steps[nsteps].counter == 0)
+    if (steps[nsteps].__shlib_handle != NULL
+	&& --steps[nsteps].__counter == 0)
       {
-	result = __gconv_release_shlib (steps[nsteps].shlib_handle);
-	if (result != GCONV_OK)
+	result = __gconv_release_shlib (steps[nsteps].__shlib_handle);
+	if (result != __GCONV_OK)
 	  break;
-	steps[nsteps].shlib_handle = NULL;
+	steps[nsteps].__shlib_handle = NULL;
       }
 
   /* Release the lock.  */
diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
index 52cf9d3064..dc90986077 100644
--- a/iconv/gconv_dl.c
+++ b/iconv/gconv_dl.c
@@ -50,10 +50,10 @@ static void *loaded;
 static int
 known_compare (const void *p1, const void *p2)
 {
-  const struct gconv_loaded_object *s1 =
-    (const struct gconv_loaded_object *) p1;
-  const struct gconv_loaded_object *s2 =
-    (const struct gconv_loaded_object *) p2;
+  const struct __gconv_loaded_object *s1 =
+    (const struct __gconv_loaded_object *) p1;
+  const struct __gconv_loaded_object *s2 =
+    (const struct __gconv_loaded_object *) p2;
 
   return (intptr_t) s1->handle - (intptr_t) s2->handle;
 }
@@ -62,7 +62,7 @@ known_compare (const void *p1, const void *p2)
 static void
 do_open (void *a)
 {
-  struct gconv_loaded_object *args = (struct gconv_loaded_object *) a;
+  struct __gconv_loaded_object *args = (struct __gconv_loaded_object *) a;
   /* Open and relocate the shared object.  */
   args->handle = _dl_open (args->name, RTLD_LAZY, NULL);
 }
@@ -124,11 +124,11 @@ __gconv_find_func (void *handle, const char *name)
 
 /* Open the gconv database if necessary.  A non-negative return value
    means success.  */
-struct gconv_loaded_object *
+struct __gconv_loaded_object *
 internal_function
 __gconv_find_shlib (const char *name)
 {
-  struct gconv_loaded_object *found;
+  struct __gconv_loaded_object *found;
   void *keyp;
 
   /* Search the tree of shared objects previously requested.  Data in
@@ -144,7 +144,7 @@ __gconv_find_shlib (const char *name)
   if (keyp == NULL)
     {
       /* This name was not known before.  */
-      found = malloc (sizeof (struct gconv_loaded_object));
+      found = malloc (sizeof (struct __gconv_loaded_object));
       if (found != NULL)
 	{
 	  /* Point the tree node at this new structure.  */
@@ -161,7 +161,7 @@ __gconv_find_shlib (const char *name)
 	}
     }
   else
-    found = *(struct gconv_loaded_object **) keyp;
+    found = *(struct __gconv_loaded_object **) keyp;
 
   /* Try to load the shared object if the usage count is 0.  This
      implies that if the shared object is not loadable, the handle is
@@ -206,12 +206,12 @@ __gconv_find_shlib (const char *name)
 /* This is very ugly but the tsearch functions provide no way to pass
    information to the walker function.  So we use a global variable.
    It is MT safe since we use a lock.  */
-static struct gconv_loaded_object *release_handle;
+static struct __gconv_loaded_object *release_handle;
 
 static void
 do_release_shlib (const void *nodep, VISIT value, int level)
 {
-  struct gconv_loaded_object *obj = *(struct gconv_loaded_object **) nodep;
+  struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
 
   if (value != preorder && value != leaf)
     return;
@@ -238,7 +238,7 @@ do_release_shlib (const void *nodep, VISIT value, int level)
 /* Notify system that a shared object is not longer needed.  */
 int
 internal_function
-__gconv_release_shlib (struct gconv_loaded_object *handle)
+__gconv_release_shlib (struct __gconv_loaded_object *handle)
 {
   /* Urgh, this is ugly but we have no other possibility.  */
   release_handle = handle;
@@ -248,7 +248,7 @@ __gconv_release_shlib (struct gconv_loaded_object *handle)
      if necessary.  */
   __twalk (loaded, do_release_shlib);
 
-  return GCONV_OK;
+  return __GCONV_OK;
 }
 
 
@@ -256,7 +256,7 @@ __gconv_release_shlib (struct gconv_loaded_object *handle)
 static void
 do_release_all (void *nodep)
 {
-  struct gconv_loaded_object *obj = (struct gconv_loaded_object *) nodep;
+  struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
 
   /* Unload the shared object.  We don't use the trick to
      catch errors since in the case an error is signalled
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 9b00e6522c..29f495c30f 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -41,7 +41,7 @@ struct gconv_alias
 /* Structure describing one loaded shared object.  This normally are
    objects to perform conversation but as a special case the db shared
    object is also handled.  */
-struct gconv_loaded_object
+struct __gconv_loaded_object
 {
   /* Name of the object.  */
   const char *name;
@@ -54,9 +54,9 @@ struct gconv_loaded_object
   struct link_map *handle;
 
   /* Pointer to the functions the module defines.  */
-  gconv_fct fct;
-  gconv_init_fct init_fct;
-  gconv_end_fct end_fct;
+  __gconv_fct fct;
+  __gconv_init_fct init_fct;
+  __gconv_end_fct end_fct;
 };
 
 
@@ -95,18 +95,18 @@ extern struct gconv_module *__gconv_modules_db;
 
 /* Return in *HANDLE decriptor for transformation from FROMSET to TOSET.  */
 extern int __gconv_open (const char *__toset, const char *__fromset,
-			 gconv_t *__handle)
+			 __gconv_t *__handle)
      internal_function;
 
 /* Free resources associated with transformation descriptor CD.  */
-extern int __gconv_close (gconv_t cd)
+extern int __gconv_close (__gconv_t cd)
      internal_function;
 
 /* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF
    according to rules described by CD and place up to *OUTBYTESLEFT
    bytes in buffer starting at *OUTBUF.  Return number of written
    characters in *CONVERTED if this pointer is not null.  */
-extern int __gconv (gconv_t __cd, const unsigned char **__inbuf,
+extern int __gconv (__gconv_t __cd, const unsigned char **__inbuf,
 		    const unsigned char *inbufend, unsigned char **__outbuf,
 		    unsigned char *outbufend, size_t *converted)
      internal_function;
@@ -114,7 +114,7 @@ extern int __gconv (gconv_t __cd, const unsigned char **__inbuf,
 /* Return in *HANDLE a pointer to an array with *NSTEPS elements describing
    the single steps necessary for transformation from FROMSET to TOSET.  */
 extern int __gconv_find_transform (const char *__toset, const char *__fromset,
-				   struct gconv_step **__handle,
+				   struct __gconv_step **__handle,
 				   size_t *__nsteps)
      internal_function;
 
@@ -126,13 +126,13 @@ extern int __gconv_alias_compare (const void *__p1, const void *__p2);
 
 /* Clear reference to transformation step implementations which might
    cause the code to be unloaded.  */
-extern int __gconv_close_transform (struct gconv_step *__steps,
+extern int __gconv_close_transform (struct __gconv_step *__steps,
 				    size_t __nsteps)
      internal_function;
 
 /* Load shared object named by NAME.  If already loaded increment reference
    count.  */
-extern struct gconv_loaded_object *__gconv_find_shlib (const char *__name)
+extern struct __gconv_loaded_object *__gconv_find_shlib (const char *__name)
      internal_function;
 
 /* Find function named NAME in shared object referenced by HANDLE.  */
@@ -141,12 +141,12 @@ void *__gconv_find_func (void *handle, const char *name)
 
 /* Release shared object.  If no further reference is available unload
    the object.  */
-extern int __gconv_release_shlib (struct gconv_loaded_object *__handle)
+extern int __gconv_release_shlib (struct __gconv_loaded_object *__handle)
      internal_function;
 
 /* Fill STEP with information about builtin module with NAME.  */
 extern void __gconv_get_builtin_trans (const char *__name,
-				       struct gconv_step *__step)
+				       struct __gconv_step *__step)
      internal_function;
 
 
@@ -154,7 +154,8 @@ extern void __gconv_get_builtin_trans (const char *__name,
 /* Builtin transformations.  */
 #ifdef _LIBC
 # define __BUILTIN_TRANS(Name) \
-  extern int Name (struct gconv_step *__step, struct gconv_step_data *__data, \
+  extern int Name (struct __gconv_step *__step,				      \
+		   struct __gconv_step_data *__data,			      \
 		   const unsigned char **__inbuf,			      \
 		   const unsigned char *__inbufend, size_t *__written,	      \
 		   int __do_flush)
diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c
index f3b6dfa86e..e10abbbd4f 100644
--- a/iconv/gconv_open.c
+++ b/iconv/gconv_open.c
@@ -26,31 +26,32 @@
 
 int
 internal_function
-__gconv_open (const char *toset, const char *fromset, gconv_t *handle)
+__gconv_open (const char *toset, const char *fromset, __gconv_t *handle)
 {
-  struct gconv_step *steps;
+  struct __gconv_step *steps;
   size_t nsteps;
-  gconv_t result = NULL;
+  __gconv_t result = NULL;
   size_t cnt = 0;
   int res;
 
   res = __gconv_find_transform (toset, fromset, &steps, &nsteps);
-  if (res == GCONV_OK)
+  if (res == __GCONV_OK)
     {
       /* Allocate room for handle.  */
-      result = (gconv_t) malloc (sizeof (struct gconv_info)
-				 + nsteps * sizeof (struct gconv_step_data));
+      result = (__gconv_t) malloc (sizeof (struct __gconv_info)
+				   + (nsteps
+				      * sizeof (struct __gconv_step_data)));
       if (result == NULL)
-	res = GCONV_NOMEM;
+	res = __GCONV_NOMEM;
       else
 	{
 	  /* Remember the list of steps.  */
-	  result->steps = steps;
-	  result->nsteps = nsteps;
+	  result->__steps = steps;
+	  result->__nsteps = nsteps;
 
 	  /* Clear the array for the step data.  */
-	  memset (result->data, '\0',
-		  nsteps * sizeof (struct gconv_step_data));
+	  memset (result->__data, '\0',
+		  nsteps * sizeof (struct __gconv_step_data));
 
 	  /* Call all initialization functions for the transformation
 	     step implemenations.  */
@@ -58,37 +59,37 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
 	    {
 	      /* If this is the last step we must not allocate an
 		 output buffer.  */
-	      result->data[cnt].is_last = cnt == nsteps - 1;
+	      result->__data[cnt].__is_last = cnt == nsteps - 1;
 
 	      /* Reset the counter.  */
-	      result->data[cnt].invocation_counter = 0;
+	      result->__data[cnt].__invocation_counter = 0;
 
 	      /* It's a regular use.  */
-	      result->data[cnt].internal_use = 0;
+	      result->__data[cnt].__internal_use = 0;
 
 	      /* We use the `mbstate_t' member in DATA.  */
-	      result->data[cnt].statep = &result->data[cnt].__state;
+	      result->__data[cnt].__statep = &result->__data[cnt].__state;
 
 	      /* Allocate the buffer.  */
-	      if (!result->data[cnt].is_last)
+	      if (!result->__data[cnt].__is_last)
 		{
 		  size_t size = (GCONV_NCHAR_GOAL
-				 * steps[cnt].max_needed_to);
+				 * steps[cnt].__max_needed_to);
 
-		  result->data[cnt].outbuf = (char *) malloc (size);
-		  if (result->data[cnt].outbuf == NULL)
+		  result->__data[cnt].__outbuf = (char *) malloc (size);
+		  if (result->__data[cnt].__outbuf == NULL)
 		    {
-		      res = GCONV_NOMEM;
+		      res = __GCONV_NOMEM;
 		      break;
 		    }
-		  result->data[cnt].outbufend = (result->data[cnt].outbuf
-						 + size);
+		  result->__data[cnt].__outbufend =
+		    result->__data[cnt].__outbuf + size;
 		}
 	    }
 	}
     }
 
-  if (res != GCONV_OK)
+  if (res != __GCONV_OK)
     {
       /* Something went wrong.  Free all the resources.  */
       int serrno = errno;
@@ -96,7 +97,7 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
       if (result != NULL)
 	{
 	  while (cnt-- > 0)
-	    free (result->data[cnt].outbuf);
+	    free (result->__data[cnt].__outbuf);
 
 	  free (result);
 	  result = NULL;
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index 74dbfc0356..3f9df34de2 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -90,11 +90,11 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 
   /* Determine the status.  */
   if (*outptrp == outend)
-    result = GCONV_FULL_OUTPUT;
+    result = __GCONV_FULL_OUTPUT;
   else if (*inptrp == inend)
-    result = GCONV_EMPTY_INPUT;
+    result = __GCONV_EMPTY_INPUT;
   else
-    result = GCONV_INCOMPLETE_INPUT;
+    result = __GCONV_INCOMPLETE_INPUT;
 
   if (converted != NULL)
     converted += n_convert;
@@ -123,7 +123,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
     if (*inptr > '\x7f')						      \
       {									      \
 	/* This is no correct ANSI_X3.4-1968 character.  */		      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -152,7 +152,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
     if (*((uint32_t *) inptr) > 0x7f)					      \
       {									      \
 	/* This is no correct ANSI_X3.4-1968 character.  */		      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -200,7 +200,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	if (outptr + step >= outend)					      \
 	  {								      \
 	    /* Too long.  */						      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -287,14 +287,14 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	else								      \
 	  {								      \
 	    /* This is an illegal encoding.  */				      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
 	if (NEED_LENGTH_TEST && inptr + cnt > inend)			      \
 	  {								      \
 	    /* We don't have enough input.  */				      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -306,7 +306,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	    if ((byte & 0xc0) != 0x80)					      \
 	      {								      \
 		/* This is an illegal encoding.  */			      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -366,7 +366,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
   {									      \
     if (*((uint32_t *) inptr) >= 0x10000)				      \
       {									      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     /* Please note that we use the `uint32_t' from-pointer as an `uint16_t'   \
@@ -379,7 +379,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
   {									      \
     if (*((uint32_t *) inptr) >= 0x10000)				      \
       {									      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     *((uint16_t *) outptr)++ = *((uint32_t *) inptr)++;			      \
@@ -432,7 +432,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
   {									      \
     if (*((uint32_t *) inptr) >= 0x10000)				      \
       {									      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     *((uint16_t *) outptr)++ = *((uint32_t *) inptr)++;			      \
@@ -442,7 +442,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
   {									      \
     if (*((uint32_t *) inptr) >= 0x10000)				      \
       {									      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     *((uint16_t *) outptr)++ = bswap_16 (((uint16_t *) inptr)[1]);	      \
@@ -475,7 +475,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
       {									      \
 	if (*((uint32_t *) inptr) >= 0x110000)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -483,7 +483,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	if (NEED_LENGTH_TEST && outptr + 4 > outend)			      \
 	  {								      \
 	    /* Overflow in the output buffer.  */			      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -506,7 +506,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
       {									      \
 	if (*((uint32_t *) inptr) >= 0x110000)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -514,7 +514,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	if (NEED_LENGTH_TEST && outptr + 4 > outend)			      \
 	  {								      \
 	    /* Overflow in the output buffer.  */			      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -565,7 +565,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	  {								      \
 	    /* We don't have enough input for another complete input	      \
 	       character.  */						      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -573,7 +573,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	if (u2 < 0xdc00 || u2 >= 0xdfff)				      \
 	  {								      \
 	    /* This is no valid second word for a surrogate.  */	      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -602,7 +602,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	  {								      \
 	    /* We don't have enough input for another complete input	      \
 	       character.  */						      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -610,7 +610,7 @@ internal_ucs4_loop (const unsigned char **inptrp, const unsigned char *inend,
 	if (u2 < 0xdc00 || u2 >= 0xdfff)				      \
 	  {								      \
 	    /* This is no valid second word for a surrogate.  */	      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
diff --git a/iconv/iconv.c b/iconv/iconv.c
index a6c84367a7..85a39e3fa5 100644
--- a/iconv/iconv.c
+++ b/iconv/iconv.c
@@ -31,7 +31,7 @@ size_t
 iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
        size_t *outbytesleft)
 {
-  gconv_t gcd = (gconv_t) cd;
+  __gconv_t gcd = (__gconv_t) cd;
   char *outstart = outbuf ? *outbuf : NULL;
   size_t converted;
   int result;
@@ -59,28 +59,28 @@ iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
 
   switch (result)
     {
-    case GCONV_ILLEGAL_DESCRIPTOR:
+    case __GCONV_ILLEGAL_DESCRIPTOR:
       __set_errno (EBADF);
       converted = (size_t) -1L;
       break;
 
-    case GCONV_ILLEGAL_INPUT:
+    case __GCONV_ILLEGAL_INPUT:
       __set_errno (EILSEQ);
       converted = (size_t) -1L;
       break;
 
-    case GCONV_FULL_OUTPUT:
+    case __GCONV_FULL_OUTPUT:
       __set_errno (E2BIG);
       converted = (size_t) -1L;
       break;
 
-    case GCONV_INCOMPLETE_INPUT:
+    case __GCONV_INCOMPLETE_INPUT:
       __set_errno (EINVAL);
       converted = (size_t) -1L;
       break;
 
-    case GCONV_EMPTY_INPUT:
-    case GCONV_OK:
+    case __GCONV_EMPTY_INPUT:
+    case __GCONV_OK:
       /* Nothing.  */
       break;
 
diff --git a/iconv/iconv_close.c b/iconv/iconv_close.c
index d3974c5799..6f81aa2595 100644
--- a/iconv/iconv_close.c
+++ b/iconv/iconv_close.c
@@ -1,5 +1,5 @@
 /* Release any resource associated with given conversion descriptor.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -33,5 +33,5 @@ iconv_close (iconv_t cd)
       return -1;
     }
 
-  return __gconv_close ((gconv_t) cd) ? -1 : 0;
+  return __gconv_close ((__gconv_t) cd) ? -1 : 0;
 }
diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c
index 51dcf0baaa..e566c6a544 100644
--- a/iconv/iconv_open.c
+++ b/iconv/iconv_open.c
@@ -69,7 +69,7 @@ iconv_open (const char *tocode, const char *fromcode)
   char *fromcode_conv;
   size_t tocode_len;
   size_t fromcode_len;
-  gconv_t cd;
+  __gconv_t cd;
   int res;
 
   /* Normalize the name.  We remove all characters beside alpha-numeric,
@@ -87,10 +87,10 @@ iconv_open (const char *tocode, const char *fromcode)
 
   res = __gconv_open (tocode, fromcode, &cd);
 
-  if (res != GCONV_OK)
+  if (res != __GCONV_OK)
     {
       /* We must set the error number according to the specs.  */
-      if (res == GCONV_NOCONV || res == GCONV_NODB)
+      if (res == __GCONV_NOCONV || res == __GCONV_NODB)
 	__set_errno (EINVAL);
 
       return (iconv_t) -1;
diff --git a/iconv/loop.c b/iconv/loop.c
index eac4c758e0..ada4f0a755 100644
--- a/iconv/loop.c
+++ b/iconv/loop.c
@@ -1,5 +1,5 @@
 /* Conversion loop frame work.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -51,6 +51,7 @@
 */
 
 #include <gconv.h>
+#include <wchar.h>
 #include <sys/param.h>		/* For MIN.  */
 #define __need_size_t
 #include <stddef.h>
@@ -124,7 +125,7 @@ LOOPFCT (const unsigned char **inptrp, const unsigned char *inend,
 	 unsigned char **outptrp, unsigned char *outend, mbstate_t *state,
 	 void *data, size_t *converted EXTRA_LOOP_DECLS)
 {
-  int result = GCONV_OK;
+  int result = __GCONV_OK;
   const unsigned char *inptr = *inptrp;
   unsigned char *outptr = *outptrp;
 #ifndef COUNT_CONVERTED
@@ -157,7 +158,7 @@ LOOPFCT (const unsigned char **inptrp, const unsigned char *inend,
 #endif
     }
 
-  if (result == GCONV_OK)
+  if (result == __GCONV_OK)
     {
 #if MIN_NEEDED_INPUT == MAX_NEEDED_INPUT \
     && MIN_NEEDED_OUTPUT == MAX_NEEDED_OUTPUT
@@ -166,16 +167,16 @@ LOOPFCT (const unsigned char **inptrp, const unsigned char *inend,
 	 to be determined is the status.  */
       if (inptr == inend)
 	/* No more input.  */
-	result = GCONV_EMPTY_INPUT;
+	result = __GCONV_EMPTY_INPUT;
       else if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
 	       || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
 	/* Overflow in the output buffer.  */
-	result = GCONV_FULL_OUTPUT;
+	result = __GCONV_FULL_OUTPUT;
       else
 	/* We have something left in the input buffer.  */
-	result = GCONV_INCOMPLETE_INPUT;
+	result = __GCONV_INCOMPLETE_INPUT;
 #else
-      result = GCONV_EMPTY_INPUT;
+      result = __GCONV_EMPTY_INPUT;
 
 # undef NEED_LENGTH_TEST
 # define NEED_LENGTH_TEST	1
@@ -188,14 +189,14 @@ LOOPFCT (const unsigned char **inptrp, const unsigned char *inend,
 	      || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
 	    {
 	      /* Overflow in the output buffer.  */
-	      result = GCONV_FULL_OUTPUT;
+	      result = __GCONV_FULL_OUTPUT;
 	      break;
 	    }
 	  if (MIN_NEEDED_INPUT > 1 && inptr + MIN_NEEDED_INPUT > inend)
 	    {
 	      /* We don't have enough input for another complete input
 		 character.  */
-	      result = GCONV_INCOMPLETE_INPUT;
+	      result = __GCONV_INCOMPLETE_INPUT;
 	      break;
 	    }
 
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
index a9fc2495f1..cd750ba8ae 100644
--- a/iconv/skeleton.c
+++ b/iconv/skeleton.c
@@ -95,7 +95,7 @@ static int from_object;
 static int to_object;
 
 # ifndef FROM_DIRECTION
-#  define FROM_DIRECTION (step->data == &from_object)
+#  define FROM_DIRECTION (step->__data == &from_object)
 # endif
 #else
 # ifndef FROM_DIRECTION
@@ -140,37 +140,37 @@ static int to_object;
 # endif
 
 int
-gconv_init (struct gconv_step *step)
+gconv_init (struct __gconv_step *step)
 {
   /* Determine which direction.  */
-  if (strcmp (step->from_name, CHARSET_NAME) == 0)
+  if (strcmp (step->__from_name, CHARSET_NAME) == 0)
     {
-      step->data = &from_object;
+      step->__data = &from_object;
 
-      step->min_needed_from = MIN_NEEDED_FROM;
-      step->max_needed_from = MAX_NEEDED_FROM;
-      step->min_needed_to = MIN_NEEDED_TO;
-      step->max_needed_to = MAX_NEEDED_TO;
+      step->__min_needed_from = MIN_NEEDED_FROM;
+      step->__max_needed_from = MAX_NEEDED_FROM;
+      step->__min_needed_to = MIN_NEEDED_TO;
+      step->__max_needed_to = MAX_NEEDED_TO;
     }
-  else if (strcmp (step->to_name, CHARSET_NAME) == 0)
+  else if (strcmp (step->__to_name, CHARSET_NAME) == 0)
     {
-      step->data = &to_object;
+      step->__data = &to_object;
 
-      step->min_needed_from = MIN_NEEDED_TO;
-      step->max_needed_from = MAX_NEEDED_TO;
-      step->min_needed_to = MIN_NEEDED_FROM;
-      step->max_needed_to = MAX_NEEDED_FROM;
+      step->__min_needed_from = MIN_NEEDED_TO;
+      step->__max_needed_from = MAX_NEEDED_TO;
+      step->__min_needed_to = MIN_NEEDED_FROM;
+      step->__max_needed_to = MAX_NEEDED_FROM;
     }
   else
-    return GCONV_NOCONV;
+    return __GCONV_NOCONV;
 
 #ifdef RESET_STATE
-  step->stateful = 1;
+  step->__stateful = 1;
 #else
-  step->stateful = 0;
+  step->__stateful = 0;
 #endif
 
-  return GCONV_OK;
+  return __GCONV_OK;
 }
 #endif
 
@@ -195,13 +195,13 @@ gconv_init (struct gconv_step *step)
 #endif
 
 int
-FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
+FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
 	       const unsigned char **inbuf, const unsigned char *inbufend,
 	       size_t *written, int do_flush)
 {
-  struct gconv_step *next_step = step + 1;
-  struct gconv_step_data *next_data = data + 1;
-  gconv_fct fct = next_step->fct;
+  struct __gconv_step *next_step = step + 1;
+  struct __gconv_step_data *next_data = data + 1;
+  __gconv_fct fct = next_step->__fct;
   int status;
 
   /* If the function is called with no input this means we have to reset
@@ -209,7 +209,7 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
      dropped.  */
   if (do_flush)
     {
-      status = GCONV_OK;
+      status = __GCONV_OK;
 
 #ifdef EMIT_SHIFT_TO_INIT
       /* Emit the escape sequence to reset the state.  */
@@ -217,7 +217,7 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 #endif
       /* Call the steps down the chain if there are any but only if we
          successfully emitted the escape sequence.  */
-      if (status == GCONV_OK && ! data->is_last)
+      if (status == __GCONV_OK && ! data->__is_last)
 	status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
 				    written, 1));
     }
@@ -225,8 +225,8 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
     {
       /* We preserve the initial values of the pointer variables.  */
       const unsigned char *inptr = *inbuf;
-      unsigned char *outbuf = data->outbuf;
-      unsigned char *outend = data->outbufend;
+      unsigned char *outbuf = data->__outbuf;
+      unsigned char *outend = data->__outbufend;
       unsigned char *outstart;
 
       /* This variable is used to count the number of characters we
@@ -251,20 +251,20 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 	  if (FROM_DIRECTION)
 	    /* Run the conversion loop.  */
 	    status = FROM_LOOP (inbuf, inbufend, &outbuf, outend,
-				data->statep, step->data, &converted
+				data->__statep, step->__data, &converted
 				EXTRA_LOOP_ARGS);
 	  else
 	    /* Run the conversion loop.  */
 	    status = TO_LOOP (inbuf, inbufend, &outbuf, outend,
-			      data->statep, step->data, &converted
+			      data->__statep, step->__data, &converted
 			      EXTRA_LOOP_ARGS);
 
 	  /* If this is the last step leave the loop, there is nothing
              we can do.  */
-	  if (data->is_last)
+	  if (data->__is_last)
 	    {
 	      /* Store information about how many bytes are available.  */
-	      data->outbuf = outbuf;
+	      data->__outbuf = outbuf;
 
 	      /* Remember how many characters we converted.  */
 	      *written += converted;
@@ -275,13 +275,13 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 	  /* Write out all output which was produced.  */
 	  if (outbuf > outstart)
 	    {
-	      const unsigned char *outerr = data->outbuf;
+	      const unsigned char *outerr = data->__outbuf;
 	      int result;
 
 	      result = DL_CALL_FCT (fct, (next_step, next_data, &outerr,
 					  outbuf, written, 0));
 
-	      if (result != GCONV_EMPTY_INPUT)
+	      if (result != __GCONV_EMPTY_INPUT)
 		{
 		  if (outerr != outbuf)
 		    {
@@ -307,7 +307,7 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 					     (const unsigned char *) inbufend,
 					     (unsigned char **) &outbuf,
 					     (unsigned char *) outerr,
-					     data->statep, step->data,
+					     data->__statep, step->__data,
 					     &converted EXTRA_LOOP_ARGS);
 		      else
 			/* Run the conversion loop.  */
@@ -315,13 +315,13 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 					   (const unsigned char *) inbufend,
 					   (unsigned char **) &outbuf,
 					   (unsigned char *) outerr,
-					   data->statep, step->data,
+					   data->__statep, step->__data,
 					   &converted EXTRA_LOOP_ARGS);
 
 		      /* We must run out of output buffer space in this
 			 rerun.  */
 		      assert (outbuf == outerr);
-		      assert (nstatus == GCONV_FULL_OUTPUT);
+		      assert (nstatus == __GCONV_FULL_OUTPUT);
 #endif	/* reset input buffer */
 		    }
 
@@ -331,18 +331,18 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 	      else
 		/* All the output is consumed, we can make another run
 		   if everything was ok.  */
-		if (status == GCONV_FULL_OUTPUT)
-		  status = GCONV_OK;
+		if (status == __GCONV_FULL_OUTPUT)
+		  status = __GCONV_OK;
 	    }
 	}
-      while (status == GCONV_OK);
+      while (status == __GCONV_OK);
 
 #ifdef END_LOOP
       END_LOOP
 #endif
 
       /* We finished one use of this step.  */
-      ++data->invocation_counter;
+      ++data->__invocation_counter;
     }
 
   return status;
diff --git a/iconvdata/8bit-gap.c b/iconvdata/8bit-gap.c
index d9fe4dd8ae..5ab2975bde 100644
--- a/iconvdata/8bit-gap.c
+++ b/iconvdata/8bit-gap.c
@@ -1,6 +1,6 @@
 /* Generic conversion to and from 8bit charsets,
    converting from UCS using gaps.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -51,7 +51,7 @@ struct gap
     if (HAS_HOLES && ch == L'\0' && *inptr != '\0')			      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -74,7 +74,7 @@ struct gap
     if (ch >= 0xffff)							      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     while (ch > rp->end)						      \
@@ -82,7 +82,7 @@ struct gap
     if (ch < rp->start)							      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -90,7 +90,7 @@ struct gap
     if (ch != 0 && res == '\0')						      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
diff --git a/iconvdata/8bit-generic.c b/iconvdata/8bit-generic.c
index 2ea333199e..bd9da7a576 100644
--- a/iconvdata/8bit-generic.c
+++ b/iconvdata/8bit-generic.c
@@ -1,5 +1,5 @@
 /* Generic conversion to and from 8bit charsets.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -37,7 +37,7 @@
     if (HAS_HOLES && ch == L'\0' && *inptr != '\0')			      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -59,7 +59,7 @@
 	|| (ch != 0 && from_ucs4[ch] == '\0'))				      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
diff --git a/iconvdata/ansi_x3.110.c b/iconvdata/ansi_x3.110.c
index c754ce05f6..9371c5ae55 100644
--- a/iconvdata/ansi_x3.110.c
+++ b/iconvdata/ansi_x3.110.c
@@ -1,5 +1,5 @@
 /* Generic conversion to and from ANSI_X3.110-1983.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -409,7 +409,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && inptr + 1 >= inend)			      \
 	  {								      \
 	    /* The second character is not available.  */		      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -418,7 +418,7 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -435,7 +435,7 @@ static const char from_ucs4[][2] =
     if (ch == 0 && *inptr != '\0')					      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -477,7 +477,7 @@ static const char from_ucs4[][2] =
 	    if (tmp[0] == '\0')						      \
 	      {								      \
 		/* Illegal characters.  */				      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 	    tmp[1] = '\0';						      \
@@ -518,7 +518,7 @@ static const char from_ucs4[][2] =
 	else								      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -529,7 +529,7 @@ static const char from_ucs4[][2] =
 	if (cp[0] == '\0' && ch != 0)					      \
 	  {								      \
 	    /* Illegal.  */						      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -542,7 +542,7 @@ static const char from_ucs4[][2] =
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
 	    --outptr;							      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
diff --git a/iconvdata/big5.c b/iconvdata/big5.c
index b9ffce6905..5551bbaba8 100644
--- a/iconvdata/big5.c
+++ b/iconvdata/big5.c
@@ -1,5 +1,5 @@
 /* Mapping tables for Big5 handling.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -8441,7 +8441,7 @@ static const char from_ucs4_tab13[][2] =
 	if (NEED_LENGTH_TEST && inptr + 1 >= inend)			      \
 	  {								      \
 	    /* The second character is not available.  */		      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -8455,7 +8455,7 @@ static const char from_ucs4_tab13[][2] =
 	else								      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -8466,7 +8466,7 @@ static const char from_ucs4_tab13[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -8566,7 +8566,7 @@ static const char from_ucs4_tab13[][2] =
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -8574,7 +8574,7 @@ static const char from_ucs4_tab13[][2] =
     if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
       {									      \
 	/* We have not enough room.  */					      \
-	result = GCONV_FULL_OUTPUT;					      \
+	result = __GCONV_FULL_OUTPUT;					      \
 	break;								      \
       }									      \
 									      \
diff --git a/iconvdata/cns11643.h b/iconvdata/cns11643.h
index 342c8777b6..27c484bbd2 100644
--- a/iconvdata/cns11643.h
+++ b/iconvdata/cns11643.h
@@ -1,5 +1,5 @@
 /* Access functions for CNS 11643, plane 2 handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -35,46 +35,46 @@ cns11643_to_ucs4 (const char **s, size_t avail, unsigned char offset)
   int idx;
 
   if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) > 0x30)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 3)
     return 0;
 
   ch2 = (*s)[1];
   if ((ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   ch3 = (*s)[2];
   if ((ch3 - offset) <= 0x20 || (ch3 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch2 - 0x21 - offset) * 94 + (ch3 - 0x21 - offset);
 
   if ((ch - 0x21 - offset) == 1)
     {
       if (idx > 0x2196)
-	return UNKNOWN_10646_CHAR;
+	return __UNKNOWN_10646_CHAR;
       result = __cns11643l1_to_ucs4_tab[idx];
     }
   else if ((ch - 0x21 - offset) == 2)
     {
       if (idx > 0x1de1)
-	return UNKNOWN_10646_CHAR;
+	return __UNKNOWN_10646_CHAR;
       result = __cns11643l2_to_ucs4_tab[idx];
     }
   else if ((ch - 0x21 - offset) == 0xe)
     {
       if (idx > 0x19bd)
-	return UNKNOWN_10646_CHAR;
+	return __UNKNOWN_10646_CHAR;
       result = __cns11643l14_to_ucs4_tab[idx];
     }
   else
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (result != L'\0')
     (*s) += 3;
   else
-    result = UNKNOWN_10646_CHAR;
+    result = __UNKNOWN_10646_CHAR;
 
   return result;
 }
@@ -200,11 +200,11 @@ ucs4_to_cns11643 (uint32_t wch, char *s, size_t avail)
       cp = "\x22\x64";
       break;
     default:
-      return UNKNOWN_10646_CHAR;
+      return __UNKNOWN_10646_CHAR;
     }
 
   if (cp[0] == '\0')
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < needed)
     return 0;
diff --git a/iconvdata/cns11643l1.h b/iconvdata/cns11643l1.h
index 5e5abb76e4..3e0d042fa1 100644
--- a/iconvdata/cns11643l1.h
+++ b/iconvdata/cns11643l1.h
@@ -1,5 +1,5 @@
 /* Access functions for CNS 11643, plane 1 handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -33,22 +33,22 @@ cns11643l1_to_ucs4 (const char **s, size_t avail, unsigned char offset)
   int idx;
 
   if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) > 0x7d)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
 
   ch2 = (*s)[1];
   if ((ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset);
   if (idx > 0x2196)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   (*s) += 2;
 
-  return __cns11643l1_to_ucs4_tab[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR);
+  return __cns11643l1_to_ucs4_tab[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
 }
 
 
@@ -163,11 +163,11 @@ ucs4_to_cns11643l1 (uint32_t wch, char *s, size_t avail)
       cp = "\x22\x64";
       break;
     default:
-      return UNKNOWN_10646_CHAR;
+      return __UNKNOWN_10646_CHAR;
     }
 
   if (cp[0] == '\0')
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
diff --git a/iconvdata/euc-cn.c b/iconvdata/euc-cn.c
index 89b8f48ebb..fa2f7cb579 100644
--- a/iconvdata/euc-cn.c
+++ b/iconvdata/euc-cn.c
@@ -1,5 +1,5 @@
 /* Mapping tables for EUC-CN handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -47,7 +47,7 @@
       if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f)	      \
 	{								      \
 	  /* This is illegal.  */					      \
-	  result = GCONV_ILLEGAL_INPUT;					      \
+	  result = __GCONV_ILLEGAL_INPUT;				      \
 	  break;							      \
 	}								      \
       else								      \
@@ -60,7 +60,7 @@
 	    {								      \
 	      /* The second character is not available.  Store		      \
 		 the intermediate result.  */				      \
-	      result = GCONV_INCOMPLETE_INPUT;				      \
+	      result = __GCONV_INCOMPLETE_INPUT;			      \
 	      break;							      \
 	    }								      \
 									      \
@@ -70,7 +70,7 @@
 	  if (ch < 0xa1)						      \
 	    {								      \
 	      /* This is an illegal character.  */			      \
-	      result = GCONV_ILLEGAL_INPUT;				      \
+	      result = __GCONV_ILLEGAL_INPUT;				      \
 	      break;							      \
 	    }								      \
 									      \
@@ -78,10 +78,10 @@
 	  endp = inptr;							      \
 									      \
 	  ch = gb2312_to_ucs4 (&endp, 2, 0x80);				      \
-	  if (ch == UNKNOWN_10646_CHAR)					      \
+	  if (ch == __UNKNOWN_10646_CHAR)				      \
 	    {								      \
 	      /* This is an illegal character.  */			      \
-	      result = GCONV_ILLEGAL_INPUT;				      \
+	      result = __GCONV_ILLEGAL_INPUT;				      \
 	      break;							      \
 	    }								      \
 									      \
@@ -114,10 +114,10 @@
 				 ? outend - outptr : MAX_NEEDED_OUTPUT));     \
 	if (!NEED_LENGTH_TEST || found != 0)				      \
 	  {								      \
-	    if (found == UNKNOWN_10646_CHAR)				      \
+	    if (found == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal character.  */				      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -128,7 +128,7 @@
 	else								      \
 	  {								      \
 	    /* We ran out of space.  */					      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
diff --git a/iconvdata/euc-jp.c b/iconvdata/euc-jp.c
index 4936e40b62..3d97c01ce9 100644
--- a/iconvdata/euc-jp.c
+++ b/iconvdata/euc-jp.c
@@ -1,5 +1,5 @@
 /* Mapping tables for EUC-JP handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -49,7 +49,7 @@
     else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f)	      \
       {									      \
 	/* This is illegal.  */						      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -62,7 +62,7 @@
 	  {								      \
 	    /* The second character is not available.  Store the	      \
 	       intermediate result.  */					      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -72,7 +72,7 @@
 	if (ch2 < 0xa1)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -108,13 +108,13 @@
 	    if (NEED_LENGTH_TEST && ch == 0)				      \
 	      {								      \
 		/* Not enough input available.  */			      \
-		result = GCONV_INCOMPLETE_INPUT;			      \
+		result = __GCONV_INCOMPLETE_INPUT;			      \
 		break;							      \
 	      }								      \
-	    if (ch == UNKNOWN_10646_CHAR)				      \
+	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal character.  */				      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 	    inptr = endp;						      \
@@ -152,12 +152,12 @@
 	/* See whether we have room for at least two characters.  */	      \
 	if (NEED_LENGTH_TEST && outptr + 1 >= outend)			      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
 	found = ucs4_to_jisx0201 (ch, outptr + 1);			      \
-	if (found != UNKNOWN_10646_CHAR)				      \
+	if (found != __UNKNOWN_10646_CHAR)				      \
 	  {								      \
 	    /* Yes, it's a JIS 0201 character.  Store the shift byte.  */     \
 	    *outptr = 0x8e;						      \
@@ -168,7 +168,7 @@
 	    /* No JIS 0201 character.  */				      \
 	    found = ucs4_to_jisx0208 (ch, outptr, 2);			      \
 	    /* Please note that we always have enough room for the output. */ \
-	    if (found != UNKNOWN_10646_CHAR)				      \
+	    if (found != __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* It's a JIS 0208 character, adjust it for EUC-JP.  */	      \
 		*outptr++ += 0x80;					      \
@@ -184,10 +184,10 @@
 		if (found == 0)						      \
 		  {							      \
 		    /* We ran out of space.  */				      \
-		    result = GCONV_FULL_OUTPUT;				      \
+		    result = __GCONV_FULL_OUTPUT;			      \
 		    break;						      \
 		  }							      \
-		else if (found != UNKNOWN_10646_CHAR)			      \
+		else if (found != __UNKNOWN_10646_CHAR)			      \
 		  {							      \
 		    /* It's a JIS 0212 character, adjust it for EUC-JP.  */   \
 		    *outptr++ = 0x8f;					      \
@@ -197,7 +197,7 @@
 		else							      \
 		  {							      \
 		    /* Illegal character.  */				      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 	      }								      \
diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c
index 61046b392b..4f511705a4 100644
--- a/iconvdata/euc-kr.c
+++ b/iconvdata/euc-kr.c
@@ -1,5 +1,5 @@
 /* Mapping tables for EUC-KR handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jungshik Shin <jshin@pantheon.yale.edu>
    and Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -28,7 +28,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
 {
   if (ch > 0x7f)
     {
-      if (ucs4_to_ksc5601 (ch, cp, 2) != UNKNOWN_10646_CHAR)
+      if (ucs4_to_ksc5601 (ch, cp, 2) != __UNKNOWN_10646_CHAR)
 	{
 	  cp[0] |= 0x80;
 	  cp[1] |= 0x80;
@@ -79,7 +79,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
     else if (ch <= 0xa0 || ch > 0xfe || ch == 0xc9)			      \
       {									      \
 	/* This is illegal.  */						      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -91,13 +91,13 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
 	if (NEED_LENGTH_TEST && ch == 0)				      \
 	  {								      \
 	    /* The second character is not available.  */		      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
-	if (ch == UNKNOWN_10646_CHAR)					      \
+	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -124,7 +124,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -136,7 +136,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
 	    --outptr;							      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 	*outptr++ = cp[1];						      \
diff --git a/iconvdata/euc-tw.c b/iconvdata/euc-tw.c
index ca1cdac40e..477290889d 100644
--- a/iconvdata/euc-tw.c
+++ b/iconvdata/euc-tw.c
@@ -1,5 +1,5 @@
 /* Mapping tables for EUC-TW handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -48,7 +48,7 @@
     else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e)			      \
       {									      \
 	/* This is illegal.  */						      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -61,7 +61,7 @@
 	  {								      \
 	    /* The second character is not available.  Store the	      \
 	       intermediate result.  */					      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -71,7 +71,7 @@
 	if (ch2 < 0xa1 || ch2 == 0xff)					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -85,10 +85,10 @@
 				   0x80);				      \
 	    /* Please note that we need not test for the missing input	      \
 	       characters here anymore.  */				      \
-	    if (ch == UNKNOWN_10646_CHAR)				      \
+	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal input.  */					      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -104,10 +104,10 @@
 				     0x80);				      \
 	    /* Please note that we need not test for the missing input	      \
 	       characters here anymore.  */				      \
-	    if (ch == UNKNOWN_10646_CHAR)				      \
+	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal input.  */					      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -142,10 +142,10 @@
 	if (NEED_LENGTH_TEST && found == 0)				      \
 	  {								      \
 	    /* We ran out of space.  */					      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
-	if (found != UNKNOWN_10646_CHAR)				      \
+	if (found != __UNKNOWN_10646_CHAR)				      \
 	  {								      \
 	    /* It's a CNS 11643, plane 1 character, adjust it for EUC-TW.  */ \
 	    *outptr++ += 0x80;						      \
@@ -161,13 +161,13 @@
 	    if (NEED_LENGTH_TEST && found == 0)				      \
 	      {								      \
 		/* We ran out of space.  */				      \
-		result = GCONV_INCOMPLETE_INPUT;			      \
+		result = __GCONV_INCOMPLETE_INPUT;			      \
 		break;							      \
 	      }								      \
-	    if (found == UNKNOWN_10646_CHAR)				      \
+	    if (found == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* No legal input.  */					      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
diff --git a/iconvdata/gb2312.h b/iconvdata/gb2312.h
index cde9375e84..5cac987f2f 100644
--- a/iconvdata/gb2312.h
+++ b/iconvdata/gb2312.h
@@ -1,5 +1,5 @@
 /* Access functions for GB2312 conversion.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -37,22 +37,22 @@ gb2312_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
   int idx;
 
   if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) > 0x77)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
 
   ch2 = (*s)[1];
   if ((ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset);
   if (idx > 0x1ff1)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   (*s) += 2;
 
-  return __gb2312_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR);
+  return __gb2312_to_ucs[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
 }
 
 
@@ -210,11 +210,11 @@ ucs4_to_gb2312 (uint32_t wch, unsigned char *s, size_t avail)
       cp = "\x23\x24";
       break;
     default:
-      return UNKNOWN_10646_CHAR;
+      return __UNKNOWN_10646_CHAR;
     }
 
   if (cp[0] == '\0')
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   assert (cp[1] != '\0');
 
diff --git a/iconvdata/iso-2022-jp.c b/iconvdata/iso-2022-jp.c
index bb158491f2..31b1cbcd14 100644
--- a/iconvdata/iso-2022-jp.c
+++ b/iconvdata/iso-2022-jp.c
@@ -53,10 +53,10 @@ struct gap
 #define MAX_NEEDED_TO		4
 #define FROM_DIRECTION		(dir == from_iso2022jp)
 #define PREPARE_LOOP \
-  enum direction dir = ((struct iso2022jp_data *) step->data)->dir;	      \
-  enum variant var = ((struct iso2022jp_data *) step->data)->var;	      \
+  enum direction dir = ((struct iso2022jp_data *) step->__data)->dir;	      \
+  enum variant var = ((struct iso2022jp_data *) step->__data)->var;	      \
   int save_set;								      \
-  int *setp = &data->statep->count;
+  int *setp = &data->__statep->count;
 #define EXTRA_LOOP_ARGS		, var, setp
 
 
@@ -109,7 +109,7 @@ enum
 
 
 int
-gconv_init (struct gconv_step *step)
+gconv_init (struct __gconv_step *step)
 {
   /* Determine which direction.  */
   struct iso2022jp_data *new_data;
@@ -117,59 +117,59 @@ gconv_init (struct gconv_step *step)
   enum variant var = illegal_var;
   int result;
 
-  if (__strcasecmp (step->from_name, "ISO-2022-JP//") == 0)
+  if (__strcasecmp (step->__from_name, "ISO-2022-JP//") == 0)
     {
       dir = from_iso2022jp;
       var = iso2022jp;
     }
-  else if (__strcasecmp (step->to_name, "ISO-2022-JP//") == 0)
+  else if (__strcasecmp (step->__to_name, "ISO-2022-JP//") == 0)
     {
       dir = to_iso2022jp;
       var = iso2022jp;
     }
-  else if (__strcasecmp (step->from_name, "ISO-2022-JP-2//") == 0)
+  else if (__strcasecmp (step->__from_name, "ISO-2022-JP-2//") == 0)
     {
       dir = from_iso2022jp;
       var = iso2022jp2;
     }
-  else if (__strcasecmp (step->to_name, "ISO-2022-JP-2//") == 0)
+  else if (__strcasecmp (step->__to_name, "ISO-2022-JP-2//") == 0)
     {
       dir = to_iso2022jp;
       var = iso2022jp2;
     }
 
-  result = GCONV_NOCONV;
+  result = __GCONV_NOCONV;
   if (dir != illegal_dir)
     {
       new_data
 	= (struct iso2022jp_data *) malloc (sizeof (struct iso2022jp_data));
 
-      result = GCONV_NOMEM;
+      result = __GCONV_NOMEM;
       if (new_data != NULL)
 	{
 	  new_data->dir = dir;
 	  new_data->var = var;
-	  step->data = new_data;
+	  step->__data = new_data;
 
 	  if (dir == from_iso2022jp)
 	    {
-	      step->min_needed_from = MIN_NEEDED_FROM;
-	      step->max_needed_from = MAX_NEEDED_FROM;
-	      step->min_needed_to = MIN_NEEDED_TO;
-	      step->max_needed_to = MAX_NEEDED_TO;
+	      step->__min_needed_from = MIN_NEEDED_FROM;
+	      step->__max_needed_from = MAX_NEEDED_FROM;
+	      step->__min_needed_to = MIN_NEEDED_TO;
+	      step->__max_needed_to = MAX_NEEDED_TO;
 	    }
 	  else
 	    {
-	      step->min_needed_from = MIN_NEEDED_TO;
-	      step->max_needed_from = MAX_NEEDED_TO;
-	      step->min_needed_to = MIN_NEEDED_FROM;
-	      step->max_needed_to = MAX_NEEDED_FROM + 2;
+	      step->__min_needed_from = MIN_NEEDED_TO;
+	      step->__max_needed_from = MAX_NEEDED_TO;
+	      step->__min_needed_to = MIN_NEEDED_FROM;
+	      step->__max_needed_to = MAX_NEEDED_FROM + 2;
 	    }
 
 	  /* Yes, this is a stateful encoding.  */
-	  step->stateful = 1;
+	  step->__stateful = 1;
 
-	  result = GCONV_OK;
+	  result = __GCONV_OK;
 	}
     }
 
@@ -178,9 +178,9 @@ gconv_init (struct gconv_step *step)
 
 
 void
-gconv_end (struct gconv_step *data)
+gconv_end (struct __gconv_step *data)
 {
-  free (data->data);
+  free (data->__data);
 }
 
 
@@ -188,33 +188,33 @@ gconv_end (struct gconv_step *data)
    the output state to the initial state.  This has to be done during the
    flushing.  */
 #define EMIT_SHIFT_TO_INIT \
-  if (data->statep->count != ASCII_set)					      \
+  if (data->__statep->count != ASCII_set)				      \
     {									      \
-      enum direction dir = ((struct iso2022jp_data *) step->data)->dir;	      \
+      enum direction dir = ((struct iso2022jp_data *) step->__data)->dir;     \
 									      \
       if (dir == from_iso2022jp)					      \
 	/* It's easy, we don't have to emit anything, we just reset the	      \
 	   state for the input.  Note that this also clears the G2	      \
 	   designation.  */						      \
-	data->statep->count = ASCII_set;				      \
+	data->__statep->count = ASCII_set;				      \
       else								      \
 	{								      \
-	  unsigned char *outbuf = data->outbuf;				      \
+	  unsigned char *outbuf = data->__outbuf;			      \
 									      \
 	  /* We are not in the initial state.  To switch back we have	      \
 	     to emit the sequence `Esc ( B'.  */			      \
-	  if (outbuf + 3 > data->outbufend)				      \
+	  if (outbuf + 3 > data->__outbufend)				      \
 	    /* We don't have enough room in the output buffer.  */	      \
-	    status = GCONV_FULL_OUTPUT;					      \
+	    status = __GCONV_FULL_OUTPUT;				      \
 	  else								      \
 	    {								      \
 	      /* Write out the shift sequence.  */			      \
 	      *outbuf++ = ESC;						      \
 	      *outbuf++ = '(';						      \
 	      *outbuf++ = 'B';						      \
-	      data->outbuf = outbuf;					      \
+	      data->__outbuf = outbuf;					      \
 	      /* Note that this also clears the G2 designation.  */	      \
-	      data->statep->count = ASCII_set;				      \
+	      data->__statep->count = ASCII_set;			      \
 	    }								      \
 	}								      \
     }
@@ -251,7 +251,7 @@ gconv_end (struct gconv_step *data)
 		&& inptr + 3 >= inend))					      \
 	  {								      \
 	    /* Not enough input available.  */				      \
-	    result = GCONV_EMPTY_INPUT;					      \
+	    result = __GCONV_EMPTY_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -354,20 +354,20 @@ gconv_end (struct gconv_step *data)
 	    /* We use the table from the ISO 8859-7 module.  */		      \
 	    if (inptr[2] < 0x20 || inptr[2] > 0x80)			      \
 	      {								      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 	    ch = iso88597_to_ucs4[inptr[2] - 0x20];			      \
 	    if (ch == 0)						      \
 	      {								      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 	    inptr += 3;							      \
 	  }								      \
 	else								      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -378,9 +378,9 @@ gconv_end (struct gconv_step *data)
       {									      \
 	/* Use the JIS X 0201 table.  */				      \
 	ch = jisx0201_to_ucs4 (ch);					      \
-	if (ch == UNKNOWN_10646_CHAR)					      \
+	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	++inptr;							      \
@@ -389,9 +389,9 @@ gconv_end (struct gconv_step *data)
       {									      \
 	/* Use the JIS X 0201 table.  */				      \
 	ch = jisx0201_to_ucs4 (ch + 0x80);				      \
-	if (ch == UNKNOWN_10646_CHAR)					      \
+	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	++inptr;							      \
@@ -424,12 +424,12 @@ gconv_end (struct gconv_step *data)
 									      \
 	if (NEED_LENGTH_TEST && ch == 0)				      \
 	  {								      \
-	    result = GCONV_EMPTY_INPUT;					      \
+	    result = __GCONV_EMPTY_INPUT;				      \
 	    break;							      \
 	  }								      \
-	else if (ch == UNKNOWN_10646_CHAR)				      \
+	else if (ch == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -474,25 +474,27 @@ gconv_end (struct gconv_step *data)
       {									      \
 	unsigned char buf[2];						      \
 	written = ucs4_to_jisx0201 (ch, buf);				      \
-	if (written != UNKNOWN_10646_CHAR && buf[0] > 0x20 && buf[0] < 0x80)  \
+	if (written != __UNKNOWN_10646_CHAR && buf[0] > 0x20		      \
+	    && buf[0] < 0x80)						      \
 	  {								      \
 	    *outptr++ = buf[0];						      \
 	    written = 1;						      \
 	  }								      \
 	else								      \
-	  written = UNKNOWN_10646_CHAR;					      \
+	  written = __UNKNOWN_10646_CHAR;				      \
       }									      \
     else if (set == JISX0201_Kana_set)					      \
       {									      \
 	unsigned char buf[2];						      \
 	written = ucs4_to_jisx0201 (ch, buf);				      \
-	if (written != UNKNOWN_10646_CHAR && buf[0] > 0xa0 && buf[0] < 0xe0)  \
+	if (written != __UNKNOWN_10646_CHAR && buf[0] > 0xa0		      \
+	    && buf[0] < 0xe0)						      \
 	  {								      \
 	    *outptr++ = buf[0] - 0x80;					      \
 	    written = 1;						      \
 	  }								      \
 	else								      \
-	  written = UNKNOWN_10646_CHAR;					      \
+	  written = __UNKNOWN_10646_CHAR;				      \
       }									      \
     else								      \
       {									      \
@@ -518,14 +520,14 @@ gconv_end (struct gconv_step *data)
 									      \
 	if (NEED_LENGTH_TEST && written == 0)				      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
-	else if (written != UNKNOWN_10646_CHAR)				      \
+	else if (written != __UNKNOWN_10646_CHAR)			      \
 	  outptr += written;						      \
       }									      \
 									      \
-    if (written == UNKNOWN_10646_CHAR || written == 0)			      \
+    if (written == __UNKNOWN_10646_CHAR || written == 0)		      \
       {									      \
 	if (set2 == ISO88591_set)					      \
 	  {								      \
@@ -557,7 +559,7 @@ gconv_end (struct gconv_step *data)
 	  }								      \
       }									      \
 									      \
-    if (written == UNKNOWN_10646_CHAR || written == 0)			      \
+    if (written == __UNKNOWN_10646_CHAR || written == 0)		      \
       {									      \
 	/* Either this is an unknown character or we have to switch	      \
 	   the currently selected character set.  The character sets	      \
@@ -576,7 +578,7 @@ gconv_end (struct gconv_step *data)
 	       escape sequence.  */					      \
 	    if (NEED_LENGTH_TEST && outptr + 4 > outend)		      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -600,12 +602,12 @@ gconv_end (struct gconv_step *data)
 	    unsigned char buf[2];					      \
 									      \
 	    written = ucs4_to_jisx0201 (ch, buf);			      \
-	    if (written != UNKNOWN_10646_CHAR && buf[0] < 0x80)		      \
+	    if (written != __UNKNOWN_10646_CHAR && buf[0] < 0x80)	      \
 	      {								      \
 		/* We use JIS X 0201.  */				      \
 		if (NEED_LENGTH_TEST && outptr + 4 > outend)		      \
 		  {							      \
-		    result = GCONV_FULL_OUTPUT;				      \
+		    result = __GCONV_FULL_OUTPUT;			      \
 		    break;						      \
 		  }							      \
 									      \
@@ -618,12 +620,12 @@ gconv_end (struct gconv_step *data)
 	    else							      \
 	      {								      \
 		written = ucs4_to_jisx0208 (ch, buf, 2);		      \
-		if (written != UNKNOWN_10646_CHAR)			      \
+		if (written != __UNKNOWN_10646_CHAR)			      \
 		  {							      \
 		    /* We use JIS X 0208.  */				      \
 		    if (NEED_LENGTH_TEST && outptr + 5 > outend)	      \
 		      {							      \
-			result = GCONV_FULL_OUTPUT;			      \
+			result = __GCONV_FULL_OUTPUT;			      \
 			break;						      \
 		      }							      \
 									      \
@@ -637,18 +639,18 @@ gconv_end (struct gconv_step *data)
 		else if (var == iso2022jp)				      \
 		  {							      \
 		    /* We have no other choice.  */			      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 		else							      \
 		  {							      \
 		    written = ucs4_to_jisx0212 (ch, buf, 2);		      \
-		    if (written != UNKNOWN_10646_CHAR)			      \
+		    if (written != __UNKNOWN_10646_CHAR)		      \
 		      {							      \
 			/* We use JIS X 0212.  */			      \
 			if (NEED_LENGTH_TEST && outptr + 6 > outend)	      \
 			  {						      \
-			    result = GCONV_FULL_OUTPUT;			      \
+			    result = __GCONV_FULL_OUTPUT;		      \
 			    break;					      \
 			  }						      \
 			*outptr++ = ESC;				      \
@@ -662,12 +664,13 @@ gconv_end (struct gconv_step *data)
 		    else						      \
 		      {							      \
 			written = ucs4_to_jisx0201 (ch, buf);		      \
-			if (written != UNKNOWN_10646_CHAR && buf[0] >= 0x80)  \
+			if (written != __UNKNOWN_10646_CHAR		      \
+			    && buf[0] >= 0x80)				      \
 			  {						      \
 			    /* We use JIS X 0201.  */			      \
 			    if (NEED_LENGTH_TEST && outptr + 4 > outend)      \
 			      {						      \
-			        result = GCONV_FULL_OUTPUT;		      \
+			        result = __GCONV_FULL_OUTPUT;		      \
 			        break;					      \
 			      }						      \
 									      \
@@ -682,7 +685,7 @@ gconv_end (struct gconv_step *data)
 			    /* ISO 8859-1 upper half.   */		      \
 			    if (NEED_LENGTH_TEST && outptr + 6 > outend)      \
 			      {						      \
-				result = GCONV_FULL_OUTPUT;		      \
+				result = __GCONV_FULL_OUTPUT;		      \
 				break;					      \
 			      }						      \
 									      \
@@ -697,12 +700,12 @@ gconv_end (struct gconv_step *data)
 			else						      \
 			  {						      \
 			    written = ucs4_to_gb2312 (ch, buf, 2);	      \
-			    if (written != UNKNOWN_10646_CHAR)		      \
+			    if (written != __UNKNOWN_10646_CHAR)	      \
 			      {						      \
 				/* We use GB 2312.  */			      \
 				if (NEED_LENGTH_TEST && outptr + 5 > outend)  \
 				  {					      \
-				    result = GCONV_FULL_OUTPUT;		      \
+				    result = __GCONV_FULL_OUTPUT;	      \
 				    break;				      \
 				  }					      \
 									      \
@@ -716,13 +719,13 @@ gconv_end (struct gconv_step *data)
 			    else					      \
 			      {						      \
 				written = ucs4_to_ksc5601 (ch, buf, 2);	      \
-				if (written != UNKNOWN_10646_CHAR)	      \
+				if (written != __UNKNOWN_10646_CHAR)	      \
 				  {					      \
 				    /* We use KSC 5601.  */		      \
 				    if (NEED_LENGTH_TEST		      \
 					&& outptr + 6 > outend)		      \
 				      {					      \
-					result = GCONV_FULL_OUTPUT;	      \
+					result = __GCONV_FULL_OUTPUT;	      \
 					break;				      \
 				      }					      \
 				    *outptr++ = ESC;			      \
@@ -752,7 +755,7 @@ gconv_end (struct gconv_step *data)
 					if (NEED_LENGTH_TEST		      \
 					    && outptr + 6 > outend)	      \
 					  {				      \
-					    result = GCONV_FULL_OUTPUT;	      \
+					    result = __GCONV_FULL_OUTPUT;     \
 					    break;			      \
 					  }				      \
 					*outptr++ = ESC;		      \
@@ -765,7 +768,7 @@ gconv_end (struct gconv_step *data)
 				      }					      \
 				    else				      \
 				      {					      \
-					result = GCONV_ILLEGAL_INPUT;	      \
+					result = __GCONV_ILLEGAL_INPUT;	      \
 					break;				      \
 				      }					      \
 				  }					      \
diff --git a/iconvdata/iso-2022-kr.c b/iconvdata/iso-2022-kr.c
index a0c213cdfe..178753f5c8 100644
--- a/iconvdata/iso-2022-kr.c
+++ b/iconvdata/iso-2022-kr.c
@@ -44,12 +44,13 @@
 #define MAX_NEEDED_TO		4
 #define PREPARE_LOOP \
   int save_set;								      \
-  int *setp = &data->statep->count;					      \
-  if (!FROM_DIRECTION && !data->internal_use && data->invocation_counter == 0)\
+  int *setp = &data->__statep->count;					      \
+  if (!FROM_DIRECTION && !data->__internal_use				      \
+      && data->__invocation_counter == 0)				      \
     {									      \
       /* Emit the designator sequence.  */				      \
       if (outbuf + 4 > outend)						      \
-	return GCONV_FULL_OUTPUT;					      \
+	return __GCONV_FULL_OUTPUT;					      \
 									      \
       *outbuf++ = ESC;							      \
       *outbuf++ = '$';							      \
@@ -72,27 +73,27 @@ enum
    the output state to the initial state.  This has to be done during the
    flushing.  */
 #define EMIT_SHIFT_TO_INIT \
-  if (data->statep->count != ASCII_set)					      \
+  if (data->__statep->count != ASCII_set)				      \
     {									      \
       if (FROM_DIRECTION)						      \
 	/* It's easy, we don't have to emit anything, we just reset the	      \
 	   state for the input.  */					      \
-	data->statep->count = ASCII_set;				      \
+	data->__statep->count = ASCII_set;				      \
       else								      \
 	{								      \
-	  unsigned char *outbuf = data->outbuf;				      \
+	  unsigned char *outbuf = data->__outbuf;			      \
 	  								      \
 	  /* We are not in the initial state.  To switch back we have	      \
 	     to emit `SI'.  */						      \
-	  if (outbuf == data->outbufend)				      \
+	  if (outbuf == data->__outbufend)				      \
 	    /* We don't have enough room in the output buffer.  */	      \
-	    status = GCONV_FULL_OUTPUT;					      \
+	    status = __GCONV_FULL_OUTPUT;				      \
 	  else								      \
 	    {								      \
 	      /* Write out the shift sequence.  */			      \
 	      *outbuf++ = SI;						      \
-	      data->outbuf = outbuf;					      \
-	      data->statep->count = ASCII_set;				      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->count = ASCII_set;			      \
 	    }								      \
 	}								      \
     }
@@ -119,7 +120,7 @@ enum
     /* This is a 7bit character set, disallow all 8bit characters.  */	      \
     if (ch > 0x7f)							      \
       {									      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -136,7 +137,7 @@ enum
 		    || (inptr[2] == ')' && inptr + 3 > inend))))	      \
 									      \
 	  {								      \
-	    result = GCONV_EMPTY_INPUT;					      \
+	    result = __GCONV_EMPTY_INPUT;				      \
 	    break;							      \
 	  }								      \
 	if (inptr[1] == '$' && inptr[2] == ')' && inptr[3] == 'C')	      \
@@ -165,7 +166,7 @@ enum
       {									      \
 	if (ch >= 0x80)							      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	/* Almost done, just advance the input pointer.  */		      \
@@ -181,12 +182,12 @@ enum
 									      \
 	if (NEED_LENGTH_TEST && ch == 0)				      \
 	  {								      \
-	    result = GCONV_EMPTY_INPUT;					      \
+	    result = __GCONV_EMPTY_INPUT;				      \
 	    break;							      \
 	  }								      \
-	else if (ch == UNKNOWN_10646_CHAR)				      \
+	else if (ch == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -221,7 +222,7 @@ enum
 	    set = ASCII_set;						      \
 	    if (NEED_LENGTH_TEST && outptr == outend)			      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
 	  }								      \
@@ -235,10 +236,10 @@ enum
 									      \
 	written = ucs4_to_ksc5601 (ch, buf, 2);				      \
 									      \
-	if (written == UNKNOWN_10646_CHAR)				      \
+	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	assert (written == 2);						      \
@@ -252,7 +253,7 @@ enum
 									      \
 	if (NEED_LENGTH_TEST && outptr + 2 > outend)			      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
diff --git a/iconvdata/iso646.c b/iconvdata/iso646.c
index 701a71db44..5b2ba7282f 100644
--- a/iconvdata/iso646.c
+++ b/iconvdata/iso646.c
@@ -1,5 +1,5 @@
 /* Conversion to and from the various ISO 646 CCS.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -45,8 +45,8 @@
 #define MIN_NEEDED_TO		4
 #define FROM_DIRECTION		(dir == from_iso646)
 #define PREPARE_LOOP \
-  enum direction dir = ((struct iso646_data *) step->data)->dir;	      \
-  enum variant var = ((struct iso646_data *) step->data)->var;
+  enum direction dir = ((struct iso646_data *) step->__data)->dir;	      \
+  enum variant var = ((struct iso646_data *) step->__data)->var;
 #define EXTRA_LOOP_ARGS		, var
 
 
@@ -124,7 +124,7 @@ struct iso646_data
 
 
 int
-gconv_init (struct gconv_step *step)
+gconv_init (struct __gconv_step *step)
 {
   /* Determine which direction.  */
   struct iso646_data *new_data;
@@ -133,47 +133,47 @@ gconv_init (struct gconv_step *step)
   int result;
 
   for (var = sizeof (names) / sizeof (names[0]) - 1; var > illegal_var; --var)
-    if (__strcasecmp (step->from_name, names[var]) == 0)
+    if (__strcasecmp (step->__from_name, names[var]) == 0)
       {
 	dir = from_iso646;
 	break;
       }
-    else if (__strcasecmp (step->to_name, names[var]) == 0)
+    else if (__strcasecmp (step->__to_name, names[var]) == 0)
       {
 	dir = to_iso646;
 	break;
       }
 
-  result = GCONV_NOCONV;
+  result = __GCONV_NOCONV;
   if (dir != illegal_dir)
     {
       new_data = (struct iso646_data *) malloc (sizeof (struct iso646_data));
 
-      result = GCONV_NOMEM;
+      result = __GCONV_NOMEM;
       if (new_data != NULL)
 	{
 	  new_data->dir = dir;
 	  new_data->var = var;
-	  step->data = new_data;
+	  step->__data = new_data;
 
 	  if (var == from_iso646)
 	    {
-	      step->min_needed_from = MIN_NEEDED_FROM;
-	      step->max_needed_from = MIN_NEEDED_FROM;
-	      step->min_needed_to = MIN_NEEDED_TO;
-	      step->max_needed_to = MIN_NEEDED_TO;
+	      step->__min_needed_from = MIN_NEEDED_FROM;
+	      step->__max_needed_from = MIN_NEEDED_FROM;
+	      step->__min_needed_to = MIN_NEEDED_TO;
+	      step->__max_needed_to = MIN_NEEDED_TO;
 	    }
 	  else
 	    {
-	      step->min_needed_from = MIN_NEEDED_TO;
-	      step->max_needed_from = MIN_NEEDED_TO;
-	      step->min_needed_to = MIN_NEEDED_FROM;
-	      step->max_needed_to = MIN_NEEDED_FROM;
+	      step->__min_needed_from = MIN_NEEDED_TO;
+	      step->__max_needed_from = MIN_NEEDED_TO;
+	      step->__min_needed_to = MIN_NEEDED_FROM;
+	      step->__max_needed_to = MIN_NEEDED_FROM;
 	    }
 
-	  step->stateful = 0;
+	  step->__stateful = 0;
 
-	  result = GCONV_OK;
+	  result = __GCONV_OK;
 	}
     }
 
@@ -182,9 +182,9 @@ gconv_init (struct gconv_step *step)
 
 
 void
-gconv_end (struct gconv_step *data)
+gconv_end (struct __gconv_step *data)
 {
-  free (data->data);
+  free (data->__data);
 }
 
 
@@ -195,7 +195,7 @@ gconv_end (struct gconv_step *data)
 #define BODY \
   {									      \
     uint32_t ch;							      \
-    int failure = GCONV_OK;						      \
+    int failure = __GCONV_OK;						      \
 									      \
     ch = *inptr;							      \
     switch (ch)								      \
@@ -308,7 +308,7 @@ gconv_end (struct gconv_step *data)
 	  ch = 0xf9;							      \
 	else if (var == JP_OCR_B)					      \
 	  /* Illegal character.  */					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	else if (var == YU)						      \
 	  ch = 0x17e;							      \
 	else if (var == HU)						      \
@@ -382,7 +382,7 @@ gconv_end (struct gconv_step *data)
 	  ch = 0xec;							      \
 	else if (var == JP_OCR_B)					      \
 	  /* Illegal character.  */					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	else if (var == YU)						      \
 	  ch = 0x10d;							      \
 	else if (var == HU)						      \
@@ -398,13 +398,13 @@ gconv_end (struct gconv_step *data)
 	break;								      \
       case 0x80 ... 0xff:						      \
 	/* Illegal character.  */					      \
-	failure = GCONV_ILLEGAL_INPUT;					      \
+	failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       }									      \
 									      \
     /* Hopefully gcc can recognize that the following `if' is only true	      \
        when we reach the default case in the `switch' statement.  */	      \
-    if (failure == GCONV_ILLEGAL_INPUT)					      \
+    if (failure == __GCONV_ILLEGAL_INPUT)				      \
       {									      \
 	/* Exit the loop with an error.  */				      \
 	result = failure;						      \
@@ -424,7 +424,7 @@ gconv_end (struct gconv_step *data)
 #define BODY \
   {									      \
     unsigned char ch;							      \
-    int failure = GCONV_OK;						      \
+    int failure = __GCONV_OK;						      \
 									      \
     ch = *((uint32_t *) inptr);						      \
     switch (*((uint32_t *) inptr))					      \
@@ -432,17 +432,17 @@ gconv_end (struct gconv_step *data)
       case 0x23:							      \
 	if (var == GB || var == ES || var == IT || var == FR || var == FR1    \
 	    || var == NO2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x24:							      \
 	if (var == CN || var == HU || var == CU || var == SE || var == SE2)   \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x40:							      \
 	if (var == CA || var == CA2 || var == DE || var == ES || var == ES2   \
 	    || var == IT || var == YU || var == HU || var == FR || var == FR1 \
 	    || var == PT || var == PT2 || var == SE2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x5b:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -450,7 +450,7 @@ gconv_end (struct gconv_step *data)
 	    || var == HU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	else if (var == CU)						      \
 	  ch = 0x7d;							      \
 	break;								      \
@@ -460,7 +460,7 @@ gconv_end (struct gconv_step *data)
 	    || var == YU || var == KR || var == HU || var == CU || var == FR  \
 	    || var == FR1 || var == NO || var == NO2 || var == PT	      \
 	    || var == PT2 || var == SE || var == SE2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x5d:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -468,17 +468,17 @@ gconv_end (struct gconv_step *data)
 	    || var == HU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x5e:							      \
 	if (var == CA || var == CA2 || var == ES2 || var == YU || var == CU   \
 	    || var == SE2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x60:							      \
 	if (var == CA || var == CA2 || var == IT || var == JP_OCR_B	      \
 	    || var == YU || var == HU || var == FR || var == SE2)	      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x7b:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
@@ -486,14 +486,14 @@ gconv_end (struct gconv_step *data)
 	    || var == CU || var == FR || var == FR1 || var == NO	      \
 	    || var == NO2 || var == PT || var == PT2 || var == SE	      \
 	    || var == SE2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x7c:							      \
 	if (var == CA || var == CA2 || var == DE || var == DK || var == ES    \
 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
 	    || var == FR || var == FR1 || var == NO || var == PT	      \
 	    || var == PT2 || var == SE || var == SE2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	else if (var == NO2)						      \
 	  ch = 0x7e;							      \
 	break;								      \
@@ -502,7 +502,7 @@ gconv_end (struct gconv_step *data)
 	    || var == ES2 || var == IT || var == YU || var == HU || var == CU \
 	    || var == FR || var == FR1 || var == NO || var == NO2	      \
 	    || var == PT || var == PT2 || var == SE || var == SE2)	      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x7e:							      \
 	if (var == GB || var == CA || var == CA2 || var == DE || var == ES2   \
@@ -510,21 +510,21 @@ gconv_end (struct gconv_step *data)
 	    || var == YU || var == HU || var == CU || var == FR || var == FR1 \
 	    || var == NO || var == NO2 || var == PT || var == SE	      \
 	    || var == SE2)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xa1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xa3:							      \
 	if (var != GB && var != ES && var != IT && var != FR && var != FR1)   \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x23;							      \
 	break;								      \
       case 0xa4:							      \
 	if (var != HU && var != CU && var != SE && var != SE2)		      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x24;							      \
 	break;								      \
       case 0xa5:							      \
@@ -533,7 +533,7 @@ gconv_end (struct gconv_step *data)
 	else if (var == JP || var == JP_OCR_B)				      \
 	  ch = 0x5c;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xa7:							      \
 	if (var == DE || var == ES || var == IT || var == PT)		      \
@@ -543,11 +543,11 @@ gconv_end (struct gconv_step *data)
 	else if (var == NO2)						      \
 	  ch = 0x23;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xa8:							      \
 	if (var != ES2 && var != CU && var != FR && var != FR1)		      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xb0:							      \
@@ -558,7 +558,7 @@ gconv_end (struct gconv_step *data)
 	else if (var == PT)						      \
 	  ch = 0x7e;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xb4:							      \
 	if (var == ES2 || var == CU)					      \
@@ -566,11 +566,11 @@ gconv_end (struct gconv_step *data)
 	else if (var == PT2)						      \
 	  ch = 0x40;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xb5:							      \
 	if (var != FR)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xbf:							      \
@@ -579,31 +579,31 @@ gconv_end (struct gconv_step *data)
 	else if (var == ES2 || var == CU)				      \
 	  ch = 0x5e;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xc1:							      \
 	if (var != HU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x40;							      \
 	break;								      \
       case 0xc3:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc4:							      \
 	if (var != DE && var != SE && var != SE2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc5:							      \
 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xc6:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xc7:							      \
@@ -612,7 +612,7 @@ gconv_end (struct gconv_step *data)
 	else if (var == PT || var == PT2)				      \
 	  ch = 0x5c;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xc9:							      \
 	if (var == CA2)							      \
@@ -622,26 +622,26 @@ gconv_end (struct gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x40;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xd1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xd5:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xd6:							      \
 	if (var != DE && var != HU && var != SE && var != SE2)		      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xd8:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0xdc:							      \
@@ -650,11 +650,11 @@ gconv_end (struct gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x5e;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xdf:							      \
 	if (var != DE)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xe0:							      \
@@ -663,36 +663,36 @@ gconv_end (struct gconv_step *data)
 	else if (var == IT)						      \
 	  ch = 0x7b;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xe1:							      \
 	if (var != HU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xe2:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0xe3:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe4:							      \
 	if (var != DE && var != SE && var != SE2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe5:							      \
 	if (var != DK && var != NO && var != NO2 && var != SE && var != SE2)  \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xe6:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0xe7:							      \
@@ -703,11 +703,11 @@ gconv_end (struct gconv_step *data)
 	else if (var == PT || var == PT2)				      \
 	  ch = 0x7c;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xe8:							      \
 	if (var != CA && var != CA2 && var != IT && var != FR && var != FR1)  \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xe9:							      \
@@ -718,51 +718,51 @@ gconv_end (struct gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x60;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xea:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0xec:							      \
 	if (var != IT)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xee:							      \
 	if (var != CA)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5e;							      \
 	break;								      \
       case 0xf1:							      \
 	if (var != ES && var != ES2 && var != CU)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf2:							      \
 	if (var != IT)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf4:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x60;							      \
 	break;								      \
       case 0xf5:							      \
 	if (var != PT && var != PT2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0xf6:							      \
 	if (var != DE && var != HU && var != SE && var != SE2)		      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf8:							      \
 	if (var != DK && var != NO && var != NO2)			      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0xf9:							      \
@@ -771,11 +771,11 @@ gconv_end (struct gconv_step *data)
 	else if (var == IT)						      \
 	  ch = 0x60;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0xfb:							      \
 	if (var != CA && var != CA2)					      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0xfc:							      \
@@ -784,95 +784,95 @@ gconv_end (struct gconv_step *data)
 	else if (var == SE2)						      \
 	  ch = 0x7e;							      \
 	else								      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       case 0x160:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0x106:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5d;							      \
 	break;								      \
       case 0x107:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7d;							      \
 	break;								      \
       case 0x10c:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5e;							      \
 	break;								      \
       case 0x10d:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x110:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0x111:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7c;							      \
 	break;								      \
       case 0x161:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7b;							      \
 	break;								      \
       case 0x17d:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x40;							      \
 	break;								      \
       case 0x17e:							      \
 	if (var != YU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x60;							      \
 	break;								      \
       case 0x2dd:							      \
 	if (var != HU)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x2022:							      \
 	if (var != ES2)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x40;							      \
 	break;								      \
       case 0x203e:							      \
 	if (var != GB && var != CN && var != JP && var != NO && var != SE)    \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x7e;							      \
 	break;								      \
       case 0x20a9:							      \
 	if (var != KR)							      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5c;							      \
 	break;								      \
       case 0x2329:							      \
 	if (var != JP_OCR_B)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5b;							      \
 	break;								      \
       case 0x232a:							      \
 	if (var != JP_OCR_B)						      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	ch = 0x5d;							      \
 	break;								      \
       default:								      \
 	if (*((uint32_t *) inptr) > 0x7f)				      \
-	  failure = GCONV_ILLEGAL_INPUT;				      \
+	  failure = __GCONV_ILLEGAL_INPUT;				      \
 	break;								      \
       }									      \
 									      \
-    if (failure == GCONV_ILLEGAL_INPUT)					      \
+    if (failure == __GCONV_ILLEGAL_INPUT)				      \
       {									      \
 	/* Exit the loop with an error.  */				      \
 	result = failure;						      \
diff --git a/iconvdata/iso8859-1.c b/iconvdata/iso8859-1.c
index db6cbdf0f9..06eeda5664 100644
--- a/iconvdata/iso8859-1.c
+++ b/iconvdata/iso8859-1.c
@@ -1,5 +1,5 @@
 /* Conversion to and from ISO 8859-1.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -48,7 +48,7 @@
     if (ch > 0xff)							      \
       {									      \
 	/* We have an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     *outptr++ = (unsigned char) ch;					      \
diff --git a/iconvdata/iso_6937-2.c b/iconvdata/iso_6937-2.c
index c104d8358b..1ec0976aac 100644
--- a/iconvdata/iso_6937-2.c
+++ b/iconvdata/iso_6937-2.c
@@ -1,5 +1,5 @@
 /* Generic conversion to and from ISO 6937-2.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -409,7 +409,7 @@ static const char from_ucs4[][2] =
 	  {								      \
 	    /* The second character is not available.  Store the	      \
 	       intermediate result.  */					      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -418,7 +418,7 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -427,7 +427,7 @@ static const char from_ucs4[][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -440,7 +440,7 @@ static const char from_ucs4[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	++inptr;							      \
@@ -542,14 +542,14 @@ static const char from_ucs4[][2] =
 	if (fail)							      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
     else if (from_ucs4[ch][0] == '\0' && ch != 0)			      \
       {									      \
 	/* Illegal characters.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -562,7 +562,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && outptr >= outend)			      \
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 	*outptr++ = cp[1];						      \
diff --git a/iconvdata/iso_6937.c b/iconvdata/iso_6937.c
index 5e9f25f995..ca4ab0fada 100644
--- a/iconvdata/iso_6937.c
+++ b/iconvdata/iso_6937.c
@@ -1,5 +1,5 @@
 /* Generic conversion to and from ISO 6937.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -401,7 +401,7 @@ static const char from_ucs4[][2] =
 	  {								      \
 	    /* The second character is not available.  Store the	      \
 	       intermediate result.  */					      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -410,7 +410,7 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -419,7 +419,7 @@ static const char from_ucs4[][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -432,7 +432,7 @@ static const char from_ucs4[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	++inptr;							      \
@@ -513,14 +513,14 @@ static const char from_ucs4[][2] =
 	if (fail)							      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
     else if (from_ucs4[ch][0] == '\0' && ch != 0)			      \
       {									      \
 	/* Illegal characters.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -533,7 +533,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && outptr >= outend)			      \
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 	*outptr++ = cp[1];						      \
diff --git a/iconvdata/jis0201.h b/iconvdata/jis0201.h
index 362da17c0e..5a555372ae 100644
--- a/iconvdata/jis0201.h
+++ b/iconvdata/jis0201.h
@@ -1,5 +1,5 @@
 /* Access functions for JISX0201 conversion.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -31,7 +31,7 @@ jisx0201_to_ucs4 (char ch)
   uint32_t val = __jisx0201_to_ucs4[(unsigned char) ch];
 
   if (val == 0 && ch != '\0')
-    val = UNKNOWN_10646_CHAR;
+    val = __UNKNOWN_10646_CHAR;
 
   return val;
 }
@@ -51,7 +51,7 @@ ucs4_to_jisx0201 (uint32_t wch, char *s)
   else if (wch >= 0xff61 && wch <= 0xff9f)
     ch = wch - 0xfec0;
   else
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   s[0] = ch;
   return 1;
diff --git a/iconvdata/jis0208.h b/iconvdata/jis0208.h
index 67d7be52ae..df8eb0ddd6 100644
--- a/iconvdata/jis0208.h
+++ b/iconvdata/jis0208.h
@@ -1,5 +1,5 @@
 /* Access functions for JISX0208 conversion.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -50,22 +50,22 @@ jisx0208_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
   int idx;
 
   if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) > 0xea)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
 
   ch2 = (*s)[1];
   if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset);
   if (idx >= 0x1e80)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   (*s) += 2;
 
-  return __jis0208_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR);
+  return __jis0208_to_ucs[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
 }
 
 
@@ -87,17 +87,17 @@ ucs4_to_jisx0208 (uint32_t wch, char *s, size_t avail)
       const struct jisx0208_ucs_idx *rp = __jisx0208_from_ucs_idx;
 
       if (ch >= 0xffff)
-	return UNKNOWN_10646_CHAR;
+	return __UNKNOWN_10646_CHAR;
       while (ch > rp->end)
 	++rp;
       if (ch >= rp->start)
 	cp = __jisx0208_from_ucs_tab[rp->idx + ch - rp->start];
       else
-	return UNKNOWN_10646_CHAR;
+	return __UNKNOWN_10646_CHAR;
     }
 
   if (cp[0] == '\0')
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   s[0] = cp[0];
   s[1] = cp[1];
diff --git a/iconvdata/jis0212.h b/iconvdata/jis0212.h
index 28d4b3ff5a..f08fdd8370 100644
--- a/iconvdata/jis0212.h
+++ b/iconvdata/jis0212.h
@@ -1,5 +1,5 @@
 /* Access functions for JISX0212 conversion.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -51,14 +51,14 @@ jisx0212_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
   int idx;
 
   if (ch < offset || (ch - offset) < 0x22 || (ch - offset) > 0x6d)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
 
   ch2 = (*s)[1];
   if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch - offset - 0x21) * 94 + (ch2 - offset - 0x21);
 
@@ -70,7 +70,7 @@ jisx0212_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
   if (wch != L'\0')
     (*s) += 2;
   else
-    wch = UNKNOWN_10646_CHAR;
+    wch = __UNKNOWN_10646_CHAR;
 
   return wch;
 }
@@ -84,16 +84,16 @@ ucs4_to_jisx0212 (uint32_t wch, char *s, size_t avail)
   const char *cp;
 
   if (ch >= 0xffff)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
   while (ch > rp->end)
     ++rp;
   if (ch >= rp->start)
     cp = __jisx0212_from_ucs[rp->idx + ch - rp->start];
   else
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (cp[0] == '\0')
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   s[0] = cp[0];
   if (cp[1] != '\0')
diff --git a/iconvdata/johab.c b/iconvdata/johab.c
index 6a5d8be68f..21a9c9b6a6 100644
--- a/iconvdata/johab.c
+++ b/iconvdata/johab.c
@@ -1,5 +1,5 @@
 /* Mapping tables for JOHAB handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jungshik Shin <jshin@pantheon.yale.edu>
    and Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -183,7 +183,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	    || (ch > 0xd3 && ch < 0xd9))				      \
 	  {								      \
 	    /* These are illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	else								      \
@@ -197,7 +197,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	      {								      \
 		/* The second character is not available.  Store the	      \
 		   intermediate result.  */				      \
-		result = GCONV_INCOMPLETE_INPUT;			      \
+		result = __GCONV_INCOMPLETE_INPUT;			      \
 		break;							      \
 	      }								      \
 									      \
@@ -215,7 +215,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		if (i == -1 || m == -1 || f == -1)			      \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 		else if (i > 0 && m > 0)				      \
@@ -229,7 +229,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		else							      \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 	      }								      \
@@ -238,14 +238,14 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		if (ch2 < 0x31 || (ch2 > 0x7e && ch2 < 0x91) || ch2 == 0xff)  \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 		else if (ch == 0xda && ch2 > 0xa0 && ch2 < 0xd4)	      \
 		  {							      \
 		    /* This is illegal.  Modern Hangul Jaso is defined	      \
 		       elsewhere in Johab */				      \
-		    result = GCONV_ILLEGAL_INPUT;			      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
 		    break;						      \
 		  }							      \
 		else							      \
@@ -267,7 +267,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	if (ch == 0)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -315,7 +315,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 									      \
 	    if (NEED_LENGTH_TEST && outptr + 2 > outend)		      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -330,7 +330,7 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 									      \
 	    if (NEED_LENGTH_TEST && outptr + 2 > outend)		      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -346,12 +346,12 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 					      ? outend - outptr : 2));	      \
 	    if (NEED_LENGTH_TEST && written == 0)			      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
-	    if (written == UNKNOWN_10646_CHAR)				      \
+	    if (written == __UNKNOWN_10646_CHAR)			      \
 	      {								      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -375,12 +375,12 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 					    ? outend - outptr : 2));	      \
 	    if (NEED_LENGTH_TEST && written == 0)			      \
 	      {								      \
-		result = GCONV_FULL_OUTPUT;				      \
+		result = __GCONV_FULL_OUTPUT;				      \
 		break;							      \
 	      }								      \
-	    if (written == UNKNOWN_10646_CHAR)				      \
+	    if (written == __UNKNOWN_10646_CHAR)			      \
 	      {								      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
diff --git a/iconvdata/ksc5601.h b/iconvdata/ksc5601.h
index e67d91199e..ebe3a825d8 100644
--- a/iconvdata/ksc5601.h
+++ b/iconvdata/ksc5601.h
@@ -1,5 +1,5 @@
 /* Access functions for KS C 5601-1992 based encoding conversion.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -54,14 +54,14 @@ ksc5601_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
 
   if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e
       || (ch - offset) == 0x49)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   if (avail < 2)
     return 0;
 
   ch2 = (*s)[1];
   if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
-    return UNKNOWN_10646_CHAR;
+    return __UNKNOWN_10646_CHAR;
 
   idx = (ch - offset - 0x21) * 94 + (ch2 - offset - 0x21);
 
@@ -72,13 +72,13 @@ ksc5601_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
 
   if (idx >= 1410 && idx < 3760)
     return (__ksc5601_hangul_to_ucs[idx - 1410]
-	    ?: ((*s) -= 2, UNKNOWN_10646_CHAR));
+	    ?: ((*s) -= 2, __UNKNOWN_10646_CHAR));
   else if (idx >= 3854)
     /* Hanja : row 42 - row 93 : 3854 = 94 * (42-1) */
    return (__ksc5601_hanja_to_ucs[idx - 3854]
-	   ?: ((*s) -= 2, UNKNOWN_10646_CHAR));
+	   ?: ((*s) -= 2, __UNKNOWN_10646_CHAR));
   else
-    return __ksc5601_sym_to_ucs[idx] ?: ((*s) -= 2, UNKNOWN_10646_CHAR);
+    return __ksc5601_sym_to_ucs[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
 }
 
 static inline size_t
@@ -108,7 +108,7 @@ ucs4_to_ksc5601_hangul (uint32_t wch, unsigned char *s, size_t avail)
 	}
     }
 
-  return UNKNOWN_10646_CHAR;
+  return __UNKNOWN_10646_CHAR;
 }
 
 
@@ -139,7 +139,7 @@ ucs4_to_ksc5601_hanja (uint32_t wch, unsigned char *s, size_t avail)
 	}
     }
 
-  return UNKNOWN_10646_CHAR;
+  return __UNKNOWN_10646_CHAR;
 }
 
 static inline  size_t
@@ -169,7 +169,7 @@ ucs4_to_ksc5601_sym (uint32_t wch, unsigned char *s, size_t avail)
 	}
     }
 
-  return UNKNOWN_10646_CHAR;
+  return __UNKNOWN_10646_CHAR;
 }
 
 
diff --git a/iconvdata/sjis.c b/iconvdata/sjis.c
index fe54c8c9f9..d18ab9b25e 100644
--- a/iconvdata/sjis.c
+++ b/iconvdata/sjis.c
@@ -1,5 +1,5 @@
 /* Mapping tables for SJIS handling.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -4291,7 +4291,7 @@ static const char from_ucs4_extra[0x100][2] =
   [0x0055] = "\x82\x95", [0x0056] = "\x82\x96", [0x0057] = "\x82\x97",
   [0x0058] = "\x82\x98", [0x0059] = "\x82\x99", [0x005a] = "\x82\x9a",
   [0x005b] = "\x81\x6f", [0x005c] = "\x81\x62", [0x005d] = "\x81\x70",
-  [0x005e] = "\x00\x00", [0x005f] = "\x00\x00", 
+  [0x005e] = "\x00\x00", [0x005f] = "\x00\x00",
   [0x0060] = "\x00\x00", [0x0061] = "\xa1\x00", [0x0062] = "\xa2\x00",
   [0x0063] = "\xa3\x00", [0x0064] = "\xa4\x00", [0x0065] = "\xa5\x00",
   [0x0066] = "\xa6\x00", [0x0067] = "\xa7\x00", [0x0068] = "\xa8\x00",
@@ -4357,7 +4357,7 @@ static const char from_ucs4_extra[0x100][2] =
     else if (ch > 0xea || ch == 0xa0 || ch == 0x7f || ch == 0x80)	      \
       {									      \
 	/* These are illegal.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -4371,7 +4371,7 @@ static const char from_ucs4_extra[0x100][2] =
 	  {								      \
 	    /* The second character is not available.  Store		      \
 	       the intermediate result.  */				      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -4382,7 +4382,7 @@ static const char from_ucs4_extra[0x100][2] =
 	    || (idx > 0x9ffc && idx < 0xe040) || idx > 0xeaa4)		      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	else								      \
@@ -4405,7 +4405,7 @@ static const char from_ucs4_extra[0x100][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -4436,7 +4436,7 @@ static const char from_ucs4_extra[0x100][2] =
 	else								      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -4446,7 +4446,7 @@ static const char from_ucs4_extra[0x100][2] =
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -4457,7 +4457,7 @@ static const char from_ucs4_extra[0x100][2] =
 	if (NEED_LENGTH_TEST && outptr >= outend)			      \
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 	*outptr++ = cp[1];						      \
diff --git a/iconvdata/t.61.c b/iconvdata/t.61.c
index d1ef6c2193..c9f674a60f 100644
--- a/iconvdata/t.61.c
+++ b/iconvdata/t.61.c
@@ -1,5 +1,5 @@
 /* Generic conversion to and from T.61.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -392,7 +392,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && inptr + 1 >= inend)			      \
 	  {								      \
 	    /* The second character is not available.  */		      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -401,7 +401,7 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -418,7 +418,7 @@ static const char from_ucs4[][2] =
     if (ch == 0 && *inptr != '\0')					      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
 									      \
@@ -447,7 +447,7 @@ static const char from_ucs4[][2] =
 	else if (ch < 0x2d8 || ch > 0x2dd || ch == 0x02dc)		      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 	else								      \
@@ -466,7 +466,7 @@ static const char from_ucs4[][2] =
 	if (cp[0] == '\0' && ch != 0)					      \
 	  {								      \
 	    /* Illegal.  */						      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
       }									      \
@@ -479,7 +479,7 @@ static const char from_ucs4[][2] =
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
 	    --outptr;							      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
diff --git a/iconvdata/uhc.c b/iconvdata/uhc.c
index 5aef36cdd0..ac4be8a5aa 100644
--- a/iconvdata/uhc.c
+++ b/iconvdata/uhc.c
@@ -1,5 +1,5 @@
 /* Mapping tables for UHC handling.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jungshik Shin <jshin@pantheon.yale.edu>, 1998.
 
@@ -3066,7 +3066,7 @@ static const char uhc_hangul_from_ucs[11172][2] =
     else if (ch <= 0x80 || ch >= 0xfe || ch == 0xc9)			      \
       {									      \
 	/* This is illegal.  */						      \
-	result = GCONV_ILLEGAL_INPUT;					      \
+	result = __GCONV_ILLEGAL_INPUT;					      \
 	break;								      \
       }									      \
     else								      \
@@ -3079,7 +3079,7 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	  {								      \
 	    /* The second character is not available.  Store		      \
 	       the intermediate result.  */				      \
-	    result = GCONV_INCOMPLETE_INPUT;				      \
+	    result = __GCONV_INCOMPLETE_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -3109,7 +3109,7 @@ static const char uhc_hangul_from_ucs[11172][2] =
 		|| (ch2 > 0x7a && ch2 < 0x81) || (ch == 0xc6 && ch2 > 0x52))  \
 	      {								      \
 		/* This is not legal.  */				      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -3122,7 +3122,7 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	    if (ch == 0)						      \
 	      {								      \
 		/* This is an illegal character.  */			      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 									      \
@@ -3131,10 +3131,10 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	else								      \
 	  {								      \
 	    ch = ksc5601_to_ucs4 (&inptr, 2, 0x80);			      \
-	    if (ch == UNKNOWN_10646_CHAR)				      \
+	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal.  */						      \
-		result = GCONV_ILLEGAL_INPUT;				      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
 	  }								      \
@@ -3163,7 +3163,7 @@ static const char uhc_hangul_from_ucs[11172][2] =
 									      \
 	if (NEED_LENGTH_TEST && outptr + 2 > outend)			      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -3178,12 +3178,12 @@ static const char uhc_hangul_from_ucs[11172][2] =
 									      \
 	if (NEED_LENGTH_TEST && written == 0)				      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
-	if (written == UNKNOWN_10646_CHAR)				      \
+	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
@@ -3202,12 +3202,12 @@ static const char uhc_hangul_from_ucs[11172][2] =
 									      \
 	if (NEED_LENGTH_TEST && written == 0)				      \
 	  {								      \
-	    result = GCONV_FULL_OUTPUT;					      \
+	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
-	if (written == UNKNOWN_10646_CHAR)				      \
+	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = GCONV_ILLEGAL_INPUT;				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
 	    break;							      \
 	  }								      \
 									      \
diff --git a/include/limits.h b/include/limits.h
index 21520f3c94..71222d7a67 100644
--- a/include/limits.h
+++ b/include/limits.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 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
@@ -42,7 +42,7 @@
 /* Maximum length of any multibyte character in any locale.
    We define this value here since the gcc header does not define
    the correct value.  */
-#define MB_LEN_MAX	6
+#define MB_LEN_MAX	16
 
 
 /* If we are not using GNU CC we have to define all the symbols ourself.
diff --git a/include/wchar.h b/include/wchar.h
index 33166edfdd..fb8ece58f2 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -1,32 +1,47 @@
 #ifndef _WCHAR_H
 #include <wcsmbs/wchar.h>
 
+# ifdef _WCHAR_H
 /* Now define the internal interfaces.  */
 extern int __wcscasecmp __P ((__const wchar_t *__s1, __const wchar_t *__s2));
 extern int __wcsncasecmp __P ((__const wchar_t *__s1, __const wchar_t *__s2,
                                size_t __n));
 extern size_t __wcsnlen __P ((__const wchar_t *__s, size_t __maxlen));
 extern wint_t __btowc __P ((int __c));
-extern int __mbsinit __P ((__const mbstate_t *__ps));
+extern int __mbsinit __P ((__const __mbstate_t *__ps));
 extern size_t __mbrtowc __P ((wchar_t *__restrict __pwc,
 			      __const char *__restrict __s, size_t __n,
-			      mbstate_t *__restrict __p));
+			      __mbstate_t *__restrict __p));
 extern size_t __wcrtomb __P ((char *__restrict __s, wchar_t __wc,
-			      mbstate_t *__restrict __ps));
+			      __mbstate_t *__restrict __ps));
 extern size_t __mbsrtowcs __P ((wchar_t *__restrict __dst,
 				__const char **__restrict __src,
-				size_t __len, mbstate_t *__restrict __ps));
+				size_t __len, __mbstate_t *__restrict __ps));
 extern size_t __wcsrtombs __P ((char *__restrict __dst,
 				__const wchar_t **__restrict __src,
-				size_t __len, mbstate_t *__restrict __ps));
+				size_t __len, __mbstate_t *__restrict __ps));
 extern size_t __mbsnrtowcs __P ((wchar_t *__restrict __dst,
 				 __const char **__restrict __src, size_t __nmc,
-				 size_t __len, mbstate_t *__restrict __ps));
+				 size_t __len, __mbstate_t *__restrict __ps));
 extern size_t __wcsnrtombs __P ((char *__restrict __dst,
 				 __const wchar_t **__restrict __src,
 				 size_t __nwc, size_t __len,
-				 mbstate_t *__restrict __ps));
+				 __mbstate_t *__restrict __ps));
 extern wchar_t *__wcpcpy __P ((wchar_t *__dest, __const wchar_t *__src));
 extern wchar_t *__wcpncpy __P ((wchar_t *__dest, __const wchar_t *__src,
 				size_t __n));
+extern wchar_t *__wmemcpy __P ((wchar_t *__s1, __const wchar_t *s2,
+				size_t __n));
+extern wchar_t *__wmempcpy __P ((wchar_t *__restrict __s1,
+				 __const wchar_t *__restrict __s2,
+				 size_t __n));
+extern wchar_t *__wmemmove __P ((wchar_t *__s1, __const wchar_t *__s2,
+				 size_t __n));
+extern wchar_t *__wcschrnul __P ((__const wchar_t *__s, wchar_t __wc));
+
+extern int __vfwscanf __P ((FILE *__restrict __s,
+			    __const wchar_t *__restrict __format,
+			    va_list __arg))
+     /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */;
+# endif
 #endif
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)
+};
diff --git a/locale/C-time.c b/locale/C-time.c
index 673d9bd478..6a846e4cae 100644
--- a/locale/C-time.c
+++ b/locale/C-time.c
@@ -1,6 +1,6 @@
-/* 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.
-   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
    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
@@ -27,7 +27,7 @@ const struct locale_data _nl_C_LC_TIME =
   _nl_C_name,
   NULL, 0, 0, /* no file mapped */
   UNDELETABLE,
-  54,
+  104,
   {
     { string: "Sun" },
     { string: "Mon" },
@@ -83,5 +83,55 @@ const struct locale_data _nl_C_LC_TIME =
     { word: 0 },
     { string: "" },
     { string: "" },
+    { wstr: L"Sun" },
+    { wstr: L"Mon" },
+    { wstr: L"Tue" },
+    { wstr: L"Wed" },
+    { wstr: L"Thu" },
+    { wstr: L"Fri" },
+    { wstr: L"Sat" },
+    { wstr: L"Sunday" },
+    { wstr: L"Monday" },
+    { wstr: L"Tuesday" },
+    { wstr: L"Wednesday" },
+    { wstr: L"Thursday" },
+    { wstr: L"Friday" },
+    { wstr: L"Saturday" },
+    { wstr: L"Jan" },
+    { wstr: L"Feb" },
+    { wstr: L"Mar" },
+    { wstr: L"Apr" },
+    { wstr: L"May" },
+    { wstr: L"Jun" },
+    { wstr: L"Jul" },
+    { wstr: L"Aug" },
+    { wstr: L"Sep" },
+    { wstr: L"Oct" },
+    { wstr: L"Nov" },
+    { wstr: L"Dec" },
+    { wstr: L"January" },
+    { wstr: L"February" },
+    { wstr: L"March" },
+    { wstr: L"April" },
+    { wstr: L"May" },
+    { wstr: L"June" },
+    { wstr: L"July" },
+    { wstr: L"August" },
+    { wstr: L"September" },
+    { wstr: L"October" },
+    { wstr: L"November" },
+    { wstr: L"December" },
+    { wstr: L"AM" },
+    { wstr: L"PM" },
+    { wstr: L"%a %b %e %H:%M:%S %Y" },
+    { wstr: L"%m/%d/%y" },
+    { wstr: L"%H:%M:%S" },
+    { wstr: L"%I:%M:%S %p" },
+    { string: NULL },
+    { string: "" },
+    { string: "" },
+    { string: "" },
+    { string: "" },
+    { string: "" },
   }
 };
diff --git a/locale/categories.def b/locale/categories.def
index 098d712172..71cb86d9f3 100644
--- a/locale/categories.def
+++ b/locale/categories.def
@@ -1,5 +1,5 @@
 /* Definition of all available locale categories and their items.  -*- C -*-
-   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
 
    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
@@ -147,6 +147,21 @@ DEFINE_CATEGORY
   DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES, "time-era-num-entries", opt, word)
   DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES_EB,  "time-era-entries-eb", opt, string)
   DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES_EL,  "time-era-entries-el", opt, string)
+  DEFINE_ELEMENT (_NL_WABDAY_1,     "wide-abday",       std, stringarray,  7,  7)
+  DEFINE_ELEMENT (_NL_WDAY_1,       "wide-day",         std, stringarray,  7,  7)
+  DEFINE_ELEMENT (_NL_WABMON_1,     "wide-abmon",       std, stringarray, 12, 12)
+  DEFINE_ELEMENT (_NL_WMON_1,       "wide-mon",         std, stringarray, 12, 12)
+  DEFINE_ELEMENT (_NL_WAM_STR,      "wide-am_pm",       std, stringarray,  2,  2)
+  DEFINE_ELEMENT (_NL_WD_T_FMT,     "wide-d_t_fmt",     std, string)
+  DEFINE_ELEMENT (_NL_WD_FMT,       "wide-d_fmt",       std, string)
+  DEFINE_ELEMENT (_NL_WT_FMT,       "wide-t_fmt",       std, string)
+  DEFINE_ELEMENT (_NL_WT_FMT_AMPM,  "wide-t_fmt_ampm",  std, string)
+  DEFINE_ELEMENT (_NL_WERA,         "wide-era",         opt, stringarray)
+  DEFINE_ELEMENT (_NL_WERA_YEAR,    "wide-era_year",    opt, string)
+  DEFINE_ELEMENT (_NL_WERA_D_FMT,   "wide-era_d_fmt",   opt, string)
+  DEFINE_ELEMENT (_NL_WALT_DIGITS,  "wide-alt_digits",  opt, stringarray,  0, 100)
+  DEFINE_ELEMENT (_NL_WERA_D_T_FMT, "wide-era_d_t_fmt", opt, string)
+  DEFINE_ELEMENT (_NL_WERA_T_FMT,   "wide-era_t_fmt",   opt, string)
   ), _nl_postload_time, NULL, NULL, NULL)
 
 
diff --git a/locale/langinfo.h b/locale/langinfo.h
index a96e52f902..935a3818bf 100644
--- a/locale/langinfo.h
+++ b/locale/langinfo.h
@@ -161,6 +161,66 @@ enum
   _NL_TIME_ERA_ENTRIES_EB,	/* Structure with era entries in usable form.*/
   _NL_TIME_ERA_ENTRIES_EL,
 
+  _NL_WABDAY_1, /* Sun */
+  _NL_WABDAY_2,
+  _NL_WABDAY_3,
+  _NL_WABDAY_4,
+  _NL_WABDAY_5,
+  _NL_WABDAY_6,
+  _NL_WABDAY_7,
+
+  /* Long-named days of the week. */
+  _NL_WDAY_1,			/* Sunday */
+  _NL_WDAY_2,			/* Monday */
+  _NL_WDAY_3,			/* Tuesday */
+  _NL_WDAY_4,			/* Wednesday */
+  _NL_WDAY_5,			/* Thursday */
+  _NL_WDAY_6,			/* Friday */
+  _NL_WDAY_7,			/* Saturday */
+
+  /* Abbreviated month names.  */
+  _NL_WABMON_1,			/* Jan */
+  _NL_WABMON_2,
+  _NL_WABMON_3,
+  _NL_WABMON_4,
+  _NL_WABMON_5,
+  _NL_WABMON_6,
+  _NL_WABMON_7,
+  _NL_WABMON_8,
+  _NL_WABMON_9,
+  _NL_WABMON_10,
+  _NL_WABMON_11,
+  _NL_WABMON_12,
+
+  /* Long month names.  */
+  _NL_WMON_1,			/* January */
+  _NL_WMON_2,
+  _NL_WMON_3,
+  _NL_WMON_4,
+  _NL_WMON_5,
+  _NL_WMON_6,
+  _NL_WMON_7,
+  _NL_WMON_8,
+  _NL_WMON_9,
+  _NL_WMON_10,
+  _NL_WMON_11,
+  _NL_WMON_12,
+
+  _NL_WAM_STR,			/* Ante meridian string.  */
+  _NL_WPM_STR,			/* Post meridian string.  */
+
+  _NL_WD_T_FMT,			/* Date and time format for strftime.  */
+  _NL_WD_FMT,			/* Date format for strftime.  */
+  _NL_WT_FMT,			/* Time format for strftime.  */
+  _NL_WT_FMT_AMPM,		/* 12-hour time format for strftime.  */
+
+  _NL_WERA,			/* Alternate era.  */
+  _NL_WERA_YEAR,		/* Year in alternate era format.  */
+  _NL_WERA_D_FMT,		/* Date in alternate era format.  */
+  _NL_WALT_DIGITS,		/* Alternate symbols for digits.  */
+  _NL_WERA_D_T_FMT,		/* Date and time in alternate era format.  */
+  _NL_WERA_T_FMT,		/* Time in alternate era format.  */
+
   _NL_NUM_LC_TIME,		/* Number of indices in LC_TIME category.  */
 
   /* LC_COLLATE category: text sorting.
diff --git a/locale/localeinfo.h b/locale/localeinfo.h
index dddacfe28d..2c1ce65557 100644
--- a/locale/localeinfo.h
+++ b/locale/localeinfo.h
@@ -112,9 +112,14 @@ extern struct locale_data * *const _nl_current[LC_ALL + 1];
 extern const char _nl_C_name[];
 extern const char _nl_POSIX_name[];
 
+/* XXX Temporily until the locale data has everything.  */
+extern struct locale_data _nl_C_LC_TIME;
+
 /* Extract the current CATEGORY locale's string for ITEM.  */
 #define _NL_CURRENT(category, item) \
-  (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
+  ((item) < _NL_WABDAY_1 || (item) > _NL_WALT_DIGITS			      \
+   ? (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)	      \
+   : _nl_C_LC_TIME.values[_NL_ITEM_INDEX (item)].string)
 
 /* Extract the current CATEGORY locale's word for ITEM.  */
 #define _NL_CURRENT_WORD(category, item) \
diff --git a/localedata/Makefile b/localedata/Makefile
index f4260cbeaf..099a301b1a 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -72,7 +72,7 @@ $(inst_i18ndir)/repertoiremaps/%: repertoiremaps/% $(+force); $(do-install)
 ifeq (no,$(cross-compiling))
 ifeq (yes,$(build-shared))
 .PHONY: do-collate-test do-tst-fmon do-tst-locale do-tst-rpmatch
-tests: do-collate-test do-tst-fmon do-tst-locale do-tst-rpmatch
+#tests: do-collate-test do-tst-fmon do-tst-locale do-tst-rpmatch
 do-collate-test: sort-test.sh $(objpfx)collate-test $(objpfx)xfrm-test \
 		 $(test-input-data)
 	$(SHELL) -e $< $(common-objpfx) $(test-input)
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 8c6c009c4c..75c3937939 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2170,6 +2170,9 @@ type modifier was specified.  For integer conversions, this indicates
 @code{long long int}, as opposed to @code{long double} for floating
 point conversions.
 
+@item unsigned int is_char
+This is a boolean that is true if the @samp{hh} type modifier was specified.
+
 @item unsigned int is_short
 This is a boolean that is true if the @samp{h} type modifier was specified.
 
@@ -2197,6 +2200,9 @@ be used freely by the user-defined handlers but when called from
 the @code{printf} function this variable always contains the value
 @code{0}.
 
+@item unsigned int wide
+This flag is set if the stream is wide oriented.
+
 @item wchar_t pad
 This is the character to use for padding the output to the minimum field
 width.  The value is @code{'0'} if the @samp{0} flag was specified, and
diff --git a/manual/time.texi b/manual/time.texi
index e9548b9b5e..7d5cfdaa65 100644
--- a/manual/time.texi
+++ b/manual/time.texi
@@ -1005,6 +1005,31 @@ is examined before any output is produced.
 For an example of @code{strftime}, see @ref{Time Functions Example}.
 @end deftypefun
 
+@comment time.h
+@comment ISO/Amend1
+@deftypefun size_t wcsftime (wchar_t *@var{s}, size_t @var{size}, const wchar_t *@var{template}, const struct tm *@var{brokentime})
+The @code{wcsftime} function is equivalent to the @code{strftime}
+function with the difference that it operates one wide character
+strings.  The buffer where the result is stored, pointed to by @var{s},
+must be an array of wide characters.  The parameter @var{size} which
+specifies the size of the output buffer gives the number of wide
+character, not the number of bytes.
+
+Also the format string @var{template} is a wide character string.  Since
+all characters needed to specify the format string are in the basic
+characater set it is portably possible to write format strings in the C
+source code using the @code{L"..."} notation.  The parameter
+@var{brokentime} has the same meaning as in the @code{strftime} call.
+
+The @code{wcsftime} function supports the same flags, modifiers, and
+format specifiers as the @code{strftime} function.
+
+The return value of @code{wcsftime} is the number of wide characters
+stored in @code{s}.  When more characters would have to be written than
+can be placed in the buffer @var{s} the return value is zero, with the
+same problems indicated in the @code{strftime} documentation.
+@end deftypefun
+
 @node Parsing Date and Time
 @subsection Convert textual time and date information back
 
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 9fb0c5d15d..74900189a8 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -25,11 +25,12 @@ headers	:= printf.h
 
 routines	:=							      \
 	ctermid cuserid							      \
-	_itoa itoa-digits						      \
+	_itoa _itowa itoa-digits itowa-digits				      \
 	vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex	      \
 	printf_size fprintf printf snprintf sprintf asprintf dprintf	      \
 	vfscanf 							      \
 	fscanf scanf sscanf						      \
+	vfwprintf vfwscanf						      \
 	perror psignal							      \
 	tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname		      \
 	getline getw putw						      \
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index 3a7cd78003..2eca838229 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -78,7 +78,7 @@ struct base_table_t
 
 
 /* Local variables.  */
-static const struct base_table_t base_table[] =
+const struct base_table_t _itoa_base_table[] =
 {
 #if BITS_PER_MP_LIMB == 64
   /*  2 */ {SEL1(0ul) 1, 1},
@@ -171,7 +171,7 @@ _itoa (value, buflim, base, upper_case)
 {
   const char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
   char *bp = buflim;
-  const struct base_table_t *brec = &base_table[base - 2];
+  const struct base_table_t *brec = &_itoa_base_table[base - 2];
 
   switch (base)
     {
diff --git a/stdio-common/_itowa.c b/stdio-common/_itowa.c
new file mode 100644
index 0000000000..430415b96b
--- /dev/null
+++ b/stdio-common/_itowa.c
@@ -0,0 +1,346 @@
+/* Internal function for converting integers to ASCII.
+   Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund <tege@matematik.su.se>
+   and Ulrich Drepper <drepper@gnu.org>.
+
+   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 <gmp-mparam.h>
+#include <stdlib/gmp.h>
+#include <stdlib/gmp-impl.h>
+#include <stdlib/longlong.h>
+
+#include "_itowa.h"
+
+
+/* Canonize environment.  For some architectures not all values might
+   be defined in the GMP header files.  */
+#ifndef UMUL_TIME
+# define UMUL_TIME 1
+#endif
+#ifndef UDIV_TIME
+# define UDIV_TIME 3
+#endif
+
+/* Control memory layout.  */
+#ifdef PACK
+# undef PACK
+# define PACK __attribute__ ((packed))
+#else
+# define PACK
+#endif
+
+
+/* Declare local types.  */
+struct base_table_t
+{
+#if (UDIV_TIME > 2 * UMUL_TIME)
+  mp_limb_t base_multiplier;
+#endif
+  char flag;
+  char post_shift;
+#if BITS_PER_MP_LIMB == 32
+  struct
+    {
+      char normalization_steps;
+      char ndigits;
+      mp_limb_t base PACK;
+#if UDIV_TIME > 2 * UMUL_TIME
+      mp_limb_t base_ninv PACK;
+#endif
+    } big;
+#endif
+};
+
+/* To reduce the memory needed we include some fields of the tables
+   only conditionally.  */
+#if UDIV_TIME > 2 * UMUL_TIME
+# define SEL1(X) X,
+# define SEL2(X) ,X
+#else
+# define SEL1(X)
+# define SEL2(X)
+#endif
+
+/* Factor table for the different bases.  */
+extern const struct base_table_t _itoa_base_table[];
+
+/* Lower-case digits.  */
+extern const wchar_t _itowa_lower_digits[];
+/* Upper-case digits.  */
+extern const wchar_t _itowa_upper_digits[];
+
+
+wchar_t *
+_itowa (value, buflim, base, upper_case)
+     unsigned long long int value;
+     wchar_t *buflim;
+     unsigned int base;
+     int upper_case;
+{
+  const wchar_t *digits = (upper_case
+			   ? _itowa_upper_digits : _itowa_lower_digits);
+  wchar_t *bp = buflim;
+  const struct base_table_t *brec = &_itoa_base_table[base - 2];
+
+  switch (base)
+    {
+#define RUN_2N(BITS) \
+      do								      \
+        {								      \
+	  /* `unsigned long long int' always has 64 bits.  */		      \
+	  mp_limb_t work_hi = value >> (64 - BITS_PER_MP_LIMB);		      \
+									      \
+	  if (BITS_PER_MP_LIMB == 32)					      \
+	    {								      \
+	      if (work_hi != 0)						      \
+		{							      \
+		  mp_limb_t work_lo;					      \
+		  int cnt;						      \
+									      \
+		  work_lo = value & 0xfffffffful;			      \
+		  for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt)	      \
+		    {							      \
+		      *--bp = digits[work_lo & ((1ul << BITS) - 1)];	      \
+		      work_lo >>= BITS;					      \
+		    }							      \
+		  if (BITS_PER_MP_LIMB % BITS != 0)			      \
+		    {							      \
+		      work_lo						      \
+			|= ((work_hi					      \
+			     & ((1 << (BITS - BITS_PER_MP_LIMB%BITS))	      \
+				- 1))					      \
+			    << BITS_PER_MP_LIMB % BITS);		      \
+		      work_hi >>= BITS - BITS_PER_MP_LIMB % BITS;	      \
+		      if (work_hi == 0)					      \
+			work_hi = work_lo;				      \
+		      else						      \
+			*--bp = digits[work_lo];			      \
+		    }							      \
+		}							      \
+	      else							      \
+		work_hi = value & 0xfffffffful;				      \
+	    }								      \
+	  do								      \
+	    {								      \
+	      *--bp = digits[work_hi & ((1 << BITS) - 1)];		      \
+	      work_hi >>= BITS;						      \
+	    }								      \
+	  while (work_hi != 0);						      \
+	}								      \
+      while (0)
+    case 8:
+      RUN_2N (3);
+      break;
+
+    case 16:
+      RUN_2N (4);
+      break;
+
+    default:
+      {
+#if BITS_PER_MP_LIMB == 64
+	mp_limb_t base_multiplier = brec->base_multiplier;
+	if (brec->flag)
+	  while (value != 0)
+	    {
+	      mp_limb_t quo, rem, x, dummy;
+
+	      umul_ppmm (x, dummy, value, base_multiplier);
+	      quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1);
+	      rem = value - quo * base;
+	      *--bp = digits[rem];
+	      value = quo;
+	    }
+	else
+	  while (value != 0)
+	    {
+	      mp_limb_t quo, rem, x, dummy;
+
+	      umul_ppmm (x, dummy, value, base_multiplier);
+	      quo = x >> brec->post_shift;
+	      rem = value - quo * base;
+	      *--bp = digits[rem];
+	      value = quo;
+	    }
+#endif
+#if BITS_PER_MP_LIMB == 32
+	mp_limb_t t[3];
+	int n;
+
+	/* First convert x0 to 1-3 words in base s->big.base.
+	   Optimize for frequent cases of 32 bit numbers.  */
+	if ((mp_limb_t) (value >> 32) >= 1)
+	  {
+#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
+	    int big_normalization_steps = brec->big.normalization_steps;
+	    mp_limb_t big_base_norm
+	      = brec->big.base << big_normalization_steps;
+#endif
+	    if ((mp_limb_t) (value >> 32) >= brec->big.base)
+	      {
+		mp_limb_t x1hi, x1lo, r;
+		/* If you want to optimize this, take advantage of
+		   that the quotient in the first udiv_qrnnd will
+		   always be very small.  It might be faster just to
+		   subtract in a tight loop.  */
+
+#if UDIV_TIME > 2 * UMUL_TIME
+		mp_limb_t x, xh, xl;
+
+		if (big_normalization_steps == 0)
+		  xh = 0;
+		else
+		  xh = (mp_limb_t) (value >> (64 - big_normalization_steps));
+		xl = (mp_limb_t) (value >> (32 - big_normalization_steps));
+		udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm,
+				   brec->big.base_ninv);
+
+		xl = ((mp_limb_t) value) << big_normalization_steps;
+		udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm,
+				   brec->big.base_ninv);
+		t[2] = x >> big_normalization_steps;
+
+		if (big_normalization_steps == 0)
+		  xh = x1hi;
+		else
+		  xh = ((x1hi << big_normalization_steps)
+			| (x1lo >> (32 - big_normalization_steps)));
+		xl = x1lo << big_normalization_steps;
+		udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
+				   brec->big.base_ninv);
+		t[1] = x >> big_normalization_steps;
+#elif UDIV_NEEDS_NORMALIZATION
+		mp_limb_t x, xh, xl;
+
+		if (big_normalization_steps == 0)
+		  xh = 0;
+		else
+		  xh = (mp_limb_t) (value >> 64 - big_normalization_steps);
+		xl = (mp_limb_t) (value >> 32 - big_normalization_steps);
+		udiv_qrnnd (x1hi, r, xh, xl, big_base_norm);
+
+		xl = ((mp_limb_t) value) << big_normalization_steps;
+		udiv_qrnnd (x1lo, x, r, xl, big_base_norm);
+		t[2] = x >> big_normalization_steps;
+
+		if (big_normalization_steps == 0)
+		  xh = x1hi;
+		else
+		  xh = ((x1hi << big_normalization_steps)
+			| (x1lo >> 32 - big_normalization_steps));
+		xl = x1lo << big_normalization_steps;
+		udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
+		t[1] = x >> big_normalization_steps;
+#else
+		udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32),
+			    brec->big.base);
+		udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base);
+		udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
+#endif
+		n = 3;
+	      }
+	    else
+	      {
+#if (UDIV_TIME > 2 * UMUL_TIME)
+		mp_limb_t x;
+
+		value <<= brec->big.normalization_steps;
+		udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32),
+				   (mp_limb_t) value, big_base_norm,
+				   brec->big.base_ninv);
+		t[1] = x >> brec->big.normalization_steps;
+#elif UDIV_NEEDS_NORMALIZATION
+		mp_limb_t x;
+
+		value <<= big_normalization_steps;
+		udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32),
+			    (mp_limb_t) value, big_base_norm);
+		t[1] = x >> big_normalization_steps;
+#else
+		udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32),
+			    (mp_limb_t) value, brec->big.base);
+#endif
+		n = 2;
+	      }
+	  }
+	else
+	  {
+	    t[0] = value;
+	    n = 1;
+	  }
+
+	/* Convert the 1-3 words in t[], word by word, to ASCII.  */
+	do
+	  {
+	    mp_limb_t ti = t[--n];
+	    int ndig_for_this_limb = 0;
+
+#if UDIV_TIME > 2 * UMUL_TIME
+	    mp_limb_t base_multiplier = brec->base_multiplier;
+	    if (brec->flag)
+	      while (ti != 0)
+		{
+		  mp_limb_t quo, rem, x, dummy;
+
+		  umul_ppmm (x, dummy, ti, base_multiplier);
+		  quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1);
+		  rem = ti - quo * base;
+		  *--bp = digits[rem];
+		  ti = quo;
+		  ++ndig_for_this_limb;
+		}
+	    else
+	      while (ti != 0)
+		{
+		  mp_limb_t quo, rem, x, dummy;
+
+		  umul_ppmm (x, dummy, ti, base_multiplier);
+		  quo = x >> brec->post_shift;
+		  rem = ti - quo * base;
+		  *--bp = digits[rem];
+		  ti = quo;
+		  ++ndig_for_this_limb;
+		}
+#else
+	    while (ti != 0)
+	      {
+		mp_limb_t quo, rem;
+
+		quo = ti / base;
+		rem = ti % base;
+		*--bp = digits[rem];
+		ti = quo;
+		++ndig_for_this_limb;
+	      }
+#endif
+	    /* If this wasn't the most significant word, pad with zeros.  */
+	    if (n != 0)
+	      while (ndig_for_this_limb < brec->big.ndigits)
+		{
+		  *--bp = '0';
+		  ++ndig_for_this_limb;
+		}
+	  }
+	while (n != 0);
+#endif
+      }
+      break;
+    }
+
+  return bp;
+}
diff --git a/stdio-common/_itowa.h b/stdio-common/_itowa.h
new file mode 100644
index 0000000000..e219f298ee
--- /dev/null
+++ b/stdio-common/_itowa.h
@@ -0,0 +1,63 @@
+/* Internal function for converting integers to ASCII.
+   Copyright (C) 1994, 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.  */
+
+#ifndef _ITOWA_H
+#define _ITOWA_H	1
+#include <features.h>
+#include <wchar.h>
+
+/* Convert VALUE into ASCII in base BASE (2..36).
+   Write backwards starting the character just before BUFLIM.
+   Return the address of the first (left-to-right) character in the number.
+   Use upper case letters iff UPPER_CASE is nonzero.  */
+
+extern wchar_t *_itowa __P ((unsigned long long int value, wchar_t *buflim,
+			     unsigned int base, int upper_case));
+
+static inline wchar_t *
+__attribute__ ((unused))
+_itowa_word (unsigned long value, wchar_t *buflim,
+	     unsigned int base, int upper_case)
+{
+  extern const wchar_t _itowa_upper_digits[], _itowa_lower_digits[];
+  const wchar_t *digits = (upper_case
+			   ? _itowa_upper_digits : _itowa_lower_digits);
+  wchar_t *bp = buflim;
+
+  switch (base)
+    {
+#define SPECIAL(Base)							      \
+    case Base:								      \
+      do								      \
+	*--bp = digits[value % Base];					      \
+      while ((value /= Base) != 0);					      \
+      break
+
+      SPECIAL (10);
+      SPECIAL (16);
+      SPECIAL (8);
+    default:
+      do
+	*--bp = digits[value % base];
+      while ((value /= base) != 0);
+    }
+  return bp;
+}
+
+#endif	/* itowa.h */
diff --git a/stdio-common/itoa-digits.c b/stdio-common/itoa-digits.c
index b475bbca42..34699dbcc8 100644
--- a/stdio-common/itoa-digits.c
+++ b/stdio-common/itoa-digits.c
@@ -1,5 +1,5 @@
 /* Digits.
-   Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 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
@@ -18,9 +18,8 @@
    Boston, MA 02111-1307, USA.  */
 
 /* Lower-case digits.  */
-const char _itoa_lower_digits[]
+const char _itoa_lower_digits[36]
 	= "0123456789abcdefghijklmnopqrstuvwxyz";
 /* Upper-case digits.  */
-const char _itoa_upper_digits[]
+const char _itoa_upper_digits[36]
 	= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
diff --git a/stdio-common/itowa-digits.c b/stdio-common/itowa-digits.c
new file mode 100644
index 0000000000..60a85789e3
--- /dev/null
+++ b/stdio-common/itowa-digits.c
@@ -0,0 +1,27 @@
+/* Digits.
+   Copyright (C) 1994, 1995, 1996, 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 <wchar.h>
+
+/* Lower-case digits.  */
+const wchar_t _itowa_lower_digits[36]
+	= L"0123456789abcdefghijklmnopqrstuvwxyz";
+/* Upper-case digits.  */
+const wchar_t _itowa_upper_digits[36]
+	= L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index a915f03f18..d62f3a835e 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -35,7 +35,7 @@ struct printf_spec
 
     /* Pointers into the format string for the end of this format
        spec and the next (or to the end of the string if no more).  */
-    const char *end_of_fmt, *next_fmt;
+    const UCHAR_T *end_of_fmt, *next_fmt;
 
     /* Position of arguments for precision and width, or -1 if `info' has
        the constant value.  */
@@ -90,21 +90,29 @@ read_int (const UCHAR_T * *pstr)
 
 /* Find the next spec in FORMAT, or the end of the string.  Returns
    a pointer into FORMAT, to a '%' or a '\0'.  */
-static inline const char *
-find_spec (const char *format, mbstate_t *ps)
+static inline const UCHAR_T *
+#ifdef COMPILE_WPRINTF
+find_spec (const UCHAR_T *format)
+#else
+find_spec (const UCHAR_T *format, mbstate_t *ps)
+#endif
 {
-  while (*format != '\0' && *format != '%')
+#ifdef COMPILE_WPRINTF
+  return (const UCHAR_T *) __wcschrnul ((const CHAR_T *) format, L'%');
+#else
+  while (*format != L_('\0') && *format != L_('%'))
     {
       int len;
 
       /* Remove any hints of a wrong encoding.  */
       ps->count = 0;
-      if (isascii (*format) || (len = mbrlen (format, MB_CUR_MAX, ps)) <= 0)
-	++format;
-      else
+      if (! ISASCII (*format) && (len = MBRLEN (format, MB_CUR_MAX, ps)) > 0)
 	format += len;
+      else
+	++format;
     }
   return format;
+#endif
 }
 
 
@@ -119,8 +127,13 @@ extern printf_function **__printf_function_table;
    the number of args consumed by this spec; *MAX_REF_ARG is updated so it
    remains the highest argument index used.  */
 static inline size_t
+#ifdef COMPILE_WPRINTF
+parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
+		size_t *max_ref_arg)
+#else
 parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
 		size_t *max_ref_arg, mbstate_t *ps)
+#endif
 {
   unsigned int n;
   size_t nargs = 0;
@@ -342,12 +355,12 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
 
       switch (spec->info.spec)
 	{
-	case L'i':
-	case L'd':
-	case L'u':
-	case L'o':
-	case L'X':
-	case L'x':
+	case L_('i'):
+	case L_('d'):
+	case L_('u'):
+	case L_('o'):
+	case L_('X'):
+	case L_('x'):
 #if LONG_MAX != LONG_LONG_MAX
 	  if (spec->info.is_long_double)
 	    spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
@@ -362,38 +375,38 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
 	    else
 	      spec->data_arg_type = PA_INT;
 	  break;
-	case L'e':
-	case L'E':
-	case L'f':
-	case L'g':
-	case L'G':
-	case L'a':
-	case L'A':
+	case L_('e'):
+	case L_('E'):
+	case L_('f'):
+	case L_('g'):
+	case L_('G'):
+	case L_('a'):
+	case L_('A'):
 	  if (spec->info.is_long_double)
 	    spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
 	  else
 	    spec->data_arg_type = PA_DOUBLE;
 	  break;
-	case L'c':
+	case L_('c'):
 	  spec->data_arg_type = PA_CHAR;
 	  break;
-	case L'C':
+	case L_('C'):
 	  spec->data_arg_type = PA_WCHAR;
 	  break;
-	case L's':
+	case L_('s'):
 	  spec->data_arg_type = PA_STRING;
 	  break;
-	case L'S':
+	case L_('S'):
 	  spec->data_arg_type = PA_WSTRING;
 	  break;
-	case L'p':
+	case L_('p'):
 	  spec->data_arg_type = PA_POINTER;
 	  break;
-	case L'n':
+	case L_('n'):
 	  spec->data_arg_type = PA_INT|PA_FLAG_PTR;
 	  break;
 
-	case L'm':
+	case L_('m'):
 	default:
 	  /* An unknown spec will consume no args.  */
 	  spec->ndata_args = 0;
@@ -416,7 +429,11 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
     {
       /* Find the next format spec.  */
       spec->end_of_fmt = format;
+#ifdef COMPILE_WPRINTF
+      spec->next_fmt = find_spec (format);
+#else
       spec->next_fmt = find_spec (format, ps);
+#endif
     }
 
   return nargs;
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
index 4f15373544..19869cad19 100644
--- a/stdio-common/printf-prs.c
+++ b/stdio-common/printf-prs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1995, 1996, 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
@@ -29,6 +29,8 @@
 # define INT_T		int
 # define L_(Str)	Str
 # define ISDIGIT(Ch)	isdigit (Ch)
+# define ISASCII(Ch)	isascii (Ch)
+# define MBRLEN(Cp, L, St) mbrlen (Cp, L, St)
 
 # ifdef USE_IN_LIBIO
 #  define PUT(F, S, N)	_IO_sputn (F, S, N)
diff --git a/stdio-common/printf.h b/stdio-common/printf.h
index 18b2f4ab8a..66ac5d0742 100644
--- a/stdio-common/printf.h
+++ b/stdio-common/printf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,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
@@ -45,6 +45,7 @@ struct printf_info
   unsigned int group:1;		/* ' flag.  */
   unsigned int extra:1;		/* For special use.  */
   unsigned int is_char:1;	/* hh flag.  */
+  unsigned int wide:1;		/* Nonzero for wide character streams.  */
   wchar_t pad;			/* Padding character.  */
 };
 
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index c75289a3a9..1b550abe4f 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -52,11 +52,12 @@
    the GNU I/O library.	 */
 #ifdef USE_IN_LIBIO
 #  define PUT(f, s, n) _IO_sputn (f, s, n)
-#  define PAD(f, c, n) _IO_padn (f, c, n)
+#  define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
 /* We use this file GNU C library and GNU I/O library.	So make
    names equal.	 */
 #  undef putc
-#  define putc(c, f) _IO_putc_unlocked (c, f)
+#  define putc(c, f) (wide \
+		      ? _IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
 #  define size_t     _IO_size_t
 #  define FILE	     _IO_FILE
 #else	/* ! USE_IN_LIBIO */
@@ -188,6 +189,9 @@ __printf_fp (FILE *fp,
   /* General helper (carry limb).  */
   mp_limb_t cy;
 
+  /* Nonzero if this is output on a wide character stream.  */
+  int wide = info->wide;
+
   char hack_digit (void)
     {
       mp_limb_t hi;
@@ -765,7 +769,10 @@ __printf_fp (FILE *fp,
 	if ((expsign == 0 && exponent >= dig_max)
 	    || (expsign != 0 && exponent > 4))
 	  {
-	    type = isupper (info->spec) ? 'E' : 'e';
+	    if ('g' - 'G' == 'e' - 'E')
+	      type = 'E' + (info->spec - 'G');
+	    else
+	      type = isupper (info->spec) ? 'E' : 'e';
 	    fracdig_max = dig_max - 1;
 	    intdig_max = 1;
 	    chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4;
diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
index 34581067dc..654675a0d7 100644
--- a/stdio-common/printf_size.c
+++ b/stdio-common/printf_size.c
@@ -1,5 +1,5 @@
 /* Print size value using units for orders of magnitude.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
    Based on a proposal by Larry McVoy <lm@sgi.com>.
@@ -212,6 +212,7 @@ printf_size (FILE *fp, const struct printf_info *info, const void *const *args)
   fp_info.group = info->group;
   fp_info.extra = info->extra;
   fp_info.pad = info->pad;
+  fp_info.wide = 0;
 
   if (fp_info.left && fp_info.pad == L' ')
     {
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 390ce91f71..fe145d6a3d 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -36,74 +36,16 @@
    Beside this it is also shared between the normal and wide character
    implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995.  */
 
-#ifndef COMPILE_WPRINTF
-# define CHAR_T		char
-# define UCHAR_T	unsigned char
-# define INT_T		int
-# define L_(Str)	Str
-# define ISDIGIT(Ch)	isdigit (Ch)
-
-# ifdef USE_IN_LIBIO
-#  define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
-#  define PAD(Padchar)							      \
-  if (width > 0)							      \
-    done += _IO_padn (s, (Padchar), width)
-# else
-#  define PUTC(C, F)	putc (C, F)
-ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
-# define PAD(Padchar)							      \
-  if (width > 0)							      \
-    { ssize_t __res = __printf_pad (s, (Padchar), width);		      \
-      if (__res == -1)							      \
-	{								      \
-	  done = -1;							      \
-	  goto all_done;						      \
-	}								      \
-      done += __res; }
-# endif
-#else
-# define vfprintf	vfwprintf
-# define CHAR_T		wchar_t
-# define UCHAR_T	uwchar_t
-# define INT_T		wint_t
-# define L_(Str)	L##Str
-# define ISDIGIT(Ch)	iswdigit (Ch)
-
-# ifdef USE_IN_LIBIO
-#  define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
-#  define PAD(Padchar)							      \
-  if (width > 0)							      \
-    done += _IO_wpadn (s, (Padchar), width)
-# else
-#  define PUTC(C, F)	wputc (C, F)
-ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
-#  define PAD(Padchar)							      \
-  if (width > 0)							      \
-    { ssize_t __res = __wprintf_pad (s, (Padchar), width);		      \
-      if (__res == -1)							      \
-	{								      \
-	  done = -1;							      \
-	  goto all_done;						      \
-	}								      \
-      done += __res; }
-# endif
-#endif
-
-/* Include the shared code for parsing the format string.  */
-#include "printf-parse.h"
-
 
 #ifdef USE_IN_LIBIO
 /* This code is for use in libio.  */
 # include <libioP.h>
-# define PUTC(C, F)	_IO_putc_unlocked (C, F)
-# define vfprintf	_IO_vfprintf
 # define FILE		_IO_FILE
 # undef va_list
 # define va_list	_IO_va_list
-# undef	BUFSIZ
+# undef BUFSIZ
 # define BUFSIZ		_IO_BUFSIZ
-# define ARGCHECK(S, Format)						      \
+# define ARGCHECK(S, Format) \
   do									      \
     {									      \
       /* Check file argument for consistence.  */			      \
@@ -120,11 +62,54 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
 	}								      \
     } while (0)
 # define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
+
+# ifndef COMPILE_WPRINTF
+#  define vfprintf	_IO_vfprintf
+#  define CHAR_T	char
+#  define UCHAR_T	unsigned char
+#  define INT_T		int
+#  define L_(Str)	Str
+#  define ISDIGIT(Ch)	isdigit (Ch)
+#  define ISASCII(Ch)	isascii (Ch)
+#  define MBRLEN(Cp, L, St) mbrlen (Cp, L, St)
+
+#  define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
+#  define PAD(Padchar) \
+  if (width > 0)							      \
+    done += _IO_padn (s, (Padchar), width)
+#  define PUTC(C, F)	_IO_putc_unlocked (C, F)
+#  define ORIENT	if (_IO_fwide (s, -1) != -1) return -1
+# else
+# include "_itowa.h"
+
+#  define vfprintf	_IO_vfwprintf
+#  define CHAR_T	wchar_t
+/* This is a hack!!!  There should be a type uwchar_t.  */
+#  define UCHAR_T	unsigned int /* uwchar_t */
+#  define INT_T		wint_t
+#  define L_(Str)	L##Str
+#  define ISDIGIT(Ch)	iswdigit (Ch)
+#  define ISASCII(Ch)	(((unsigned int) (Ch) & ~0x7f) == 0)
+#  define MBRLEN(Cp, L, St) wcslen ((const wchar_t *) (Cp))
+
+#  define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
+#  define PAD(Padchar) \
+  if (width > 0)							      \
+    done += _IO_wpadn (s, (Padchar), width)
+#  define PUTC(C, F)	_IO_putwc_unlocked (C, F)
+#  define ORIENT	if (_IO_fwide (s, 1) != 1) return -1
+
+#  define _itoa(Val, Buf, Base, Case) _itowa (Val, (wchar_t *) Buf, Base, Case)
+#  define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, (wchar_t *) Buf, \
+							Base, Case)
+#  undef EOF
+#  define EOF WEOF
+# endif
 #else /* ! USE_IN_LIBIO */
 /* This code is for use in the GNU C library.  */
 # include <stdio.h>
 # define PUT(F, S, N)	fwrite (S, 1, N, F)
-# define ARGCHECK(S, Format)						      \
+# define ARGCHECK(S, Format) \
   do									      \
     {									      \
       /* Check file argument for consistence.  */			      \
@@ -153,11 +138,14 @@ extern void __flockfile (FILE *);
 extern void __funlockfile (FILE *);
 #endif /* USE_IN_LIBIO */
 
+/* Include the shared code for parsing the format string.  */
+#include "printf-parse.h"
+
 
 #define	outchar(Ch)							      \
   do									      \
     {									      \
-      register const int outc = (Ch);					      \
+      register const INT_T outc = (Ch);					      \
       if (PUTC (outc, s) == EOF)					      \
 	{								      \
 	  done = -1;							      \
@@ -199,7 +187,7 @@ extern void __funlockfile (FILE *);
 
 
 /* Global variables.  */
-static const char null[] = "(null)";
+static const CHAR_T null[] = L_("(null)");
 
 
 /* Helper function to provide temporary buffering for unbuffered streams.  */
@@ -211,7 +199,8 @@ static int printf_unknown __P ((FILE *, const struct printf_info *,
 				const void *const *));
 
 /* Group digits of number string.  */
-static char *group_number __P ((CHAR_T *, CHAR_T *, const CHAR_T *, wchar_t))
+static UCHAR_T *group_number __P ((UCHAR_T *, UCHAR_T *, const char *,
+				   wchar_t))
      internal_function;
 
 
@@ -238,11 +227,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   const UCHAR_T *end_of_spec;
 
   /* Buffer intermediate results.  */
-  char work_buffer[1000];
-  char *workend;
+  UCHAR_T work_buffer[1000];
+  UCHAR_T *workend;
 
   /* State for restartable multibyte character handling functions.  */
+#ifndef COMPILE_WPRINTF
   mbstate_t mbstate;
+#endif
 
   /* We have to save the original argument pointer.  */
   va_list ap_save;
@@ -505,7 +496,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	 now process the wanted format specifier.  */			      \
     LABEL (form_percent):						      \
       /* Write a literal "%".  */					      \
-      outchar ('%');							      \
+      outchar (L_('%'));						      \
       break;								      \
 									      \
     LABEL (form_integer):						      \
@@ -588,7 +579,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	  else								      \
 	    /* We have to take care for the '0' flag.  If a precision	      \
 	       is given it must be ignored.  */				      \
-	    pad = ' ';							      \
+	    pad = L_(' ');						      \
 									      \
 	  /* If the precision is 0 and the number is 0 nothing has to	      \
 	     be written for the number, except for the 'o' format in	      \
@@ -597,13 +588,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    {								      \
 	      string = workend;						      \
 	      if (base == 8 && alt)					      \
-		*string-- = '0';					      \
+		*string-- = L_('0');					      \
 	    }								      \
 	  else								      \
 	    {								      \
 	      /* Put the number in WORK.  */				      \
-	      string = _itoa (number.longlong, workend + 1, base,	      \
-			      spec == 'X');				      \
+	      string = (UCHAR_T *) _itoa (number.longlong, workend + 1, base, \
+					  spec == L_('X'));		      \
 	      string -= 1;						      \
 	      if (group && grouping)					      \
 		string = group_number (string, workend, grouping,	      \
@@ -642,7 +633,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	  else								      \
 	    /* We have to take care for the '0' flag.  If a precision	      \
 	       is given it must be ignored.  */				      \
-	    pad = ' ';							      \
+	    pad = L_(' ');						      \
 									      \
 	  /* If the precision is 0 and the number is 0 nothing has to	      \
 	     be written for the number, except for the 'o' format in	      \
@@ -651,13 +642,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    {								      \
 	      string = workend;						      \
 	      if (base == 8 && alt)					      \
-		*string-- = '0';					      \
+		*string-- = L_('0');					      \
 	    }								      \
 	  else								      \
 	    {								      \
 	      /* Put the number in WORK.  */				      \
-	      string = _itoa_word (number.word, workend + 1, base,	      \
-				   spec == 'X');			      \
+	      string = (UCHAR_T *) _itoa_word (number.word, workend + 1,      \
+					       base, spec == L_('X'));	      \
 	      string -= 1;						      \
 	      if (group && grouping)					      \
 		string = group_number (string, workend, grouping,	      \
@@ -670,10 +661,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       if (prec > 0)							      \
 	/* Add zeros to the precision.  */				      \
 	while (prec-- > 0)						      \
-	  *string-- = '0';						      \
+	  *string-- = L_('0');						      \
       else if (number.word != 0 && alt && base == 8)			      \
 	/* Add octal marker.  */					      \
-	*string-- = '0';						      \
+	*string-- = L_('0');						      \
 									      \
       if (!left)							      \
 	{								      \
@@ -686,41 +677,41 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	  if (is_negative || showsign || space)				      \
 	    --width;							      \
 									      \
-	  if (pad == '0')						      \
+	  if (pad == L_('0'))						      \
 	    {								      \
 	      while (width-- > 0)					      \
-		*string-- = '0';					      \
+		*string-- = L_('0');					      \
 									      \
 	      if (number.word != 0 && alt && base == 16)		      \
 		{							      \
 		  *string-- = spec;					      \
-		  *string-- = '0';					      \
+		  *string-- = L_('0');					      \
 		}							      \
 									      \
 	      if (is_negative)						      \
-		*string-- = '-';					      \
+		*string-- = L_('-');					      \
 	      else if (showsign)					      \
-		*string-- = '+';					      \
+		*string-- = L_('+');					      \
 	      else if (space)						      \
-		*string-- = ' ';					      \
+		*string-- = L_(' ');					      \
 	    }								      \
 	  else								      \
 	    {								      \
 	      if (number.word != 0 && alt && base == 16)		      \
 		{							      \
 		  *string-- = spec;					      \
-		  *string-- = '0';					      \
+		  *string-- = L_('0');					      \
 		}							      \
 									      \
 	      if (is_negative)						      \
-		*string-- = '-';					      \
+		*string-- = L_('-');					      \
 	      else if (showsign)					      \
-		*string-- = '+';					      \
+		*string-- = L_('+');					      \
 	      else if (space)						      \
-		*string-- = ' ';					      \
+		*string-- = L_(' ');					      \
 									      \
 	      while (width-- > 0)					      \
-		*string-- = ' ';					      \
+		*string-- = L_(' ');					      \
 	    }								      \
 									      \
 	  outstring (string + 1, workend - string);			      \
@@ -732,20 +723,20 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	  if (number.word != 0 && alt && base == 16)			      \
 	    {								      \
 	      *string-- = spec;						      \
-	      *string-- = '0';						      \
+	      *string-- = L_('0');					      \
 	    }								      \
 									      \
 	  if (is_negative)						      \
-	    *string-- = '-';						      \
+	    *string-- = L_('-');					      \
 	  else if (showsign)						      \
-	    *string-- = '+';						      \
+	    *string-- = L_('+');					      \
 	  else if (space)						      \
-	    *string-- = ' ';						      \
+	    *string-- = L_(' ');					      \
 									      \
 	  width -= workend - string;					      \
 	  outstring (string + 1, workend - string);			      \
 									      \
-	  PAD (' ');							      \
+	  PAD (L_(' '));						      \
 	  break;							      \
 	}								      \
 									      \
@@ -771,7 +762,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 					showsign: showsign,		      \
 					group: group,			      \
 					pad: pad,			      \
-					extra: 0 };			      \
+					extra: 0,			      \
+					wide: sizeof (CHAR_T) != 1 };	      \
 									      \
 	    if (is_long_double)						      \
 	      the_arg.pa_long_double = va_arg (ap, long double);	      \
@@ -821,7 +813,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 					showsign: showsign,		      \
 					group: group,			      \
 					pad: pad,			      \
-					extra: 0 };			      \
+					extra: 0,			      \
+					wide: sizeof (CHAR_T) != 1 };	      \
 									      \
 	    if (is_long_double)						      \
 	      the_arg.pa_long_double = va_arg (ap, long double);	      \
@@ -849,6 +842,178 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       }									      \
       break;								      \
 									      \
+    LABEL (form_pointer):						      \
+      /* Generic pointer.  */						      \
+      {									      \
+	const void *ptr;						      \
+	if (fspec == NULL)						      \
+	  ptr = va_arg (ap, void *);					      \
+	else								      \
+	  ptr = args_value[fspec->data_arg].pa_pointer;			      \
+	if (ptr != NULL)						      \
+	  {								      \
+	    /* If the pointer is not NULL, write it as a %#x spec.  */	      \
+	    base = 16;							      \
+	    number.word = (unsigned long int) ptr;			      \
+	    is_negative = 0;						      \
+	    alt = 1;							      \
+	    group = 0;							      \
+	    spec = 'x';							      \
+	    goto LABEL (number);					      \
+	  }								      \
+	else								      \
+	  {								      \
+	    /* Write "(nil)" for a nil pointer.  */			      \
+	    string = (UCHAR_T *) L_("(nil)");				      \
+	    /* Make sure the full string "(nil)" is printed.  */	      \
+	    if (prec < 5)						      \
+	      prec = 5;							      \
+	    is_long = 0;	/* This is no wide-char string.  */	      \
+	    goto LABEL (print_string);					      \
+	  }								      \
+      }									      \
+      /* NOTREACHED */							      \
+									      \
+    LABEL (form_number):						      \
+      /* Answer the count of characters written.  */			      \
+      if (fspec == NULL)						      \
+	{								      \
+	  if (is_longlong)						      \
+	    *(long long int *) va_arg (ap, void *) = done;		      \
+	  else if (is_long_num)						      \
+	    *(long int *) va_arg (ap, void *) = done;			      \
+	  else if (!is_short)						      \
+	    *(int *) va_arg (ap, void *) = done;			      \
+	  else								      \
+	    *(short int *) va_arg (ap, void *) = done;			      \
+	}								      \
+      else								      \
+	if (is_longlong)						      \
+	  *(long long int *) args_value[fspec->data_arg].pa_pointer = done;   \
+	else if (is_long_num)						      \
+	  *(long int *) args_value[fspec->data_arg].pa_pointer = done;	      \
+	else if (!is_short)						      \
+	  *(int *) args_value[fspec->data_arg].pa_pointer = done;	      \
+	else								      \
+	  *(short int *) args_value[fspec->data_arg].pa_pointer = done;	      \
+      break;								      \
+									      \
+    LABEL (form_strerror):						      \
+      /* Print description of error ERRNO.  */				      \
+      string =								      \
+	(UCHAR_T *) __strerror_r (save_errno, (char *) work_buffer,	      \
+				  sizeof work_buffer);			      \
+      is_long = 0;		/* This is no wide-char string.  */	      \
+      goto LABEL (print_string)
+
+#ifdef COMPILE_WPRINTF
+# define process_string_arg(fspec) \
+    LABEL (form_character):						      \
+      /* Character.  */							      \
+      if (is_long)							      \
+	goto LABEL (form_wcharacter);					      \
+      --width;	/* Account for the character itself.  */		      \
+      if (!left)							      \
+	PAD (L' ');							      \
+      if (fspec == NULL)						      \
+	outchar (btowc ((unsigned char) va_arg (ap, int))); /* Promoted.  */  \
+      else								      \
+	outchar (btowc ((unsigned char) args_value[fspec->data_arg].pa_char));\
+      if (left)								      \
+	PAD (L' ');							      \
+      break;								      \
+									      \
+    LABEL (form_wcharacter):						      \
+      {									      \
+	/* Wide character.  */						      \
+	--width;							      \
+	if (!left)							      \
+	  PAD (L' ');							      \
+        if (fspec == NULL)						      \
+	  outchar (va_arg (ap, wint_t));				      \
+	else								      \
+	  outchar (args_value[fspec->data_arg].pa_wchar);		      \
+	if (left)							      \
+	  PAD (L' ');							      \
+      }									      \
+      break;								      \
+									      \
+    LABEL (form_string):						      \
+      {									      \
+	size_t len;							      \
+									      \
+	/* The string argument could in fact be `char *' or `wchar_t *'.      \
+	   But this should not make a difference here.  */		      \
+	if (fspec == NULL)						      \
+	  string = (UCHAR_T *) va_arg (ap, const wchar_t *);		      \
+	else								      \
+	  string = (UCHAR_T *) args_value[fspec->data_arg].pa_wstring;	      \
+									      \
+	/* Entry point for printing other strings.  */			      \
+      LABEL (print_string):						      \
+									      \
+	if (string == NULL)						      \
+	  {								      \
+	    /* Write "(null)" if there's space.  */			      \
+	    if (prec == -1						      \
+		|| prec >= (int) (sizeof (null) / sizeof (null[0])) - 1)      \
+	      {								      \
+		string = (UCHAR_T *) null;				      \
+		len = (sizeof (null) / sizeof (null[0])) - 1;		      \
+	      }								      \
+	    else							      \
+	      {								      \
+		string = (UCHAR_T *) L"";				      \
+		len = 0;						      \
+	      }								      \
+	  }								      \
+	else if (!is_long && spec != L_('S'))				      \
+	  {								      \
+	    /* This is complicated.  We have to transform the multibyte	      \
+	       string into a wide character string.  */			      \
+	    const char *mbs = (const char *) string;			      \
+	    mbstate_t mbstate;						      \
+									      \
+	    len = prec == -1 ? strnlen (mbs, prec) : strlen (mbs);	      \
+									      \
+	    /* Allocate dynamically an array which definitely is long	      \
+	       enough for the wide character version.  */		      \
+	    string = (UCHAR_T *) alloca ((len + 1) * sizeof (wchar_t));	      \
+									      \
+	    memset (&mbstate, '\0', sizeof (mbstate_t));		      \
+	    len = __mbsrtowcs ((wchar_t *) string, &mbs, len + 1, &mbstate);  \
+	    if (len == (size_t) -1)					      \
+	      {								      \
+		/* Illegal multibyte character.  */			      \
+		done = -1;						      \
+		goto all_done;						      \
+	      }								      \
+	  }								      \
+	else								      \
+	  {								      \
+	    if (prec != -1)						      \
+	      /* Search for the end of the string, but don't search past      \
+		 the length specified by the precision.  */		      \
+	      len = __wcsnlen ((wchar_t *) string, prec);		      \
+	    else							      \
+	      len = __wcslen ((wchar_t *) string);			      \
+	  }								      \
+									      \
+	if ((width -= len) < 0)						      \
+	  {								      \
+	    outstring (string, len);					      \
+	    break;							      \
+	  }								      \
+									      \
+	if (!left)							      \
+	  PAD (L' ');							      \
+	outstring (string, len);					      \
+	if (left)							      \
+	  PAD (L' ');							      \
+      }									      \
+      break;
+#else
+# define process_string_arg(fspec) \
     LABEL (form_character):						      \
       /* Character.  */							      \
       if (is_long)							      \
@@ -917,7 +1082,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    if (prec != -1)						      \
 	      /* Search for the end of the string, but don't search past      \
 		 the length specified by the precision.  */		      \
-	      len = strnlen (string, prec);				      \
+	      len = __strnlen (string, prec);				      \
 	    else							      \
 	      len = strlen (string);					      \
 	  }								      \
@@ -939,7 +1104,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    s2 = (const wchar_t *) string;				      \
 	    string = alloca (len + 1);					      \
 	    (void) __wcsrtombs (string, &s2, len + 1, &mbstate);	      \
-	    if (prec < len)						      \
+	    if (prec > 0 && prec < len)					      \
 	      len = prec;						      \
 	  }								      \
 									      \
@@ -955,75 +1120,23 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	if (left)							      \
 	  PAD (' ');							      \
       }									      \
-      break;								      \
-									      \
-    LABEL (form_pointer):						      \
-      /* Generic pointer.  */						      \
-      {									      \
-	const void *ptr;						      \
-	if (fspec == NULL)						      \
-	  ptr = va_arg (ap, void *);					      \
-	else								      \
-	  ptr = args_value[fspec->data_arg].pa_pointer;			      \
-	if (ptr != NULL)						      \
-	  {								      \
-	    /* If the pointer is not NULL, write it as a %#x spec.  */	      \
-	    base = 16;							      \
-	    number.word = (unsigned long int) ptr;			      \
-	    is_negative = 0;						      \
-	    alt = 1;							      \
-	    group = 0;							      \
-	    spec = 'x';							      \
-	    goto LABEL (number);					      \
-	  }								      \
-	else								      \
-	  {								      \
-	    /* Write "(nil)" for a nil pointer.  */			      \
-	    string = (char *) "(nil)";					      \
-	    /* Make sure the full string "(nil)" is printed.  */	      \
-	    if (prec < 5)						      \
-	      prec = 5;							      \
-	    is_long = 0;	/* This is no wide-char string.  */	      \
-	    goto LABEL (print_string);					      \
-	  }								      \
-      }									      \
-      /* NOTREACHED */							      \
-									      \
-    LABEL (form_number):						      \
-      /* Answer the count of characters written.  */			      \
-      if (fspec == NULL)						      \
-	{								      \
-	  if (is_longlong)						      \
-	    *(long long int *) va_arg (ap, void *) = done;		      \
-	  else if (is_long_num)						      \
-	    *(long int *) va_arg (ap, void *) = done;			      \
-	  else if (!is_short)						      \
-	    *(int *) va_arg (ap, void *) = done;			      \
-	  else								      \
-	    *(short int *) va_arg (ap, void *) = done;			      \
-	}								      \
-      else								      \
-	if (is_longlong)						      \
-	  *(long long int *) args_value[fspec->data_arg].pa_pointer = done;   \
-	else if (is_long_num)						      \
-	  *(long int *) args_value[fspec->data_arg].pa_pointer = done;	      \
-	else if (!is_short)						      \
-	  *(int *) args_value[fspec->data_arg].pa_pointer = done;	      \
-	else								      \
-	  *(short int *) args_value[fspec->data_arg].pa_pointer = done;	      \
-      break;								      \
-									      \
-    LABEL (form_strerror):						      \
-      /* Print description of error ERRNO.  */				      \
-      string =								      \
-	(char *) __strerror_r (save_errno, work_buffer, sizeof work_buffer);  \
-      is_long = 0;		/* This is no wide-char string.  */	      \
-      goto LABEL (print_string)
+      break;
+#endif
 
+  /* Orient the stream.  */
+#ifdef ORIENT
+  ORIENT;
+#endif
 
   /* Sanity check of arguments.  */
   ARGCHECK (s, format);
 
+  /* Check for correct orientation.  */
+  if (_IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)
+      != (sizeof (CHAR_T) == 1 ? -1 : 1))
+    /* The stream is already oriented otherwise.  */
+    return EOF;
+
   if (UNBUFFERED_P (s))
     /* Use a helper function which will allocate a local temporary buffer
        for the stream and then call us again.  */
@@ -1041,11 +1154,16 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 #endif
   nspecs_done = 0;
 
+#ifdef COMPILE_WPRINTF
+  /* Find the first format specifier.  */
+  f = lead_str_end = find_spec ((const UCHAR_T *) format);
+#else
   /* Put state for processing format string in initial state.  */
   memset (&mbstate, '\0', sizeof (mbstate_t));
 
   /* Find the first format specifier.  */
   f = lead_str_end = find_spec (format, &mbstate);
+#endif
 
   /* Lock stream.  */
 #ifdef USE_IN_LIBIO
@@ -1081,7 +1199,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       } number;
       int base;
       union printf_arg the_arg;
-      char *string;	/* Pointer to argument string.  */
+      UCHAR_T *string;	/* Pointer to argument string.  */
       int alt = 0;	/* Alternate format.  */
       int space = 0;	/* Use space prefix if no sign is needed.  */
       int left = 0;	/* Left-justify output.  */
@@ -1093,10 +1211,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       int is_char = 0;	/* Argument is promoted (unsigned) char.  */
       int width = 0;	/* Width of output; 0 means none specified.  */
       int prec = -1;	/* Precision of output; -1 means none specified.  */
-      char pad = ' ';	/* Padding character.  */
+      UCHAR_T pad = L_(' ');/* Padding character.  */
       CHAR_T spec;
 
-      workend = &work_buffer[sizeof (work_buffer) - 1];
+      workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T) - 1];
 
       /* Get current character in format string.  */
       JUMP (*++f, step0_jumps);
@@ -1172,10 +1290,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    left = 1;
 	  }
 
-	if (width + 32 >= sizeof (work_buffer))
+	if (width + 32 >= sizeof (work_buffer) / sizeof (work_buffer[0]))
 	  /* We have to use a special buffer.  The "32" is just a safe
 	     bet for all the output which is not counted in the width.  */
-	  workend = alloca (width + 32) + (width + 31);
+	  workend = ((UCHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
+		     + (width + 31));
       }
       JUMP (*f, step1_jumps);
 
@@ -1183,10 +1302,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
     LABEL (width):
       width = read_int (&f);
 
-      if (width + 32 >= sizeof (work_buffer))
+      if (width + 32 >= sizeof (work_buffer) / sizeof (work_buffer[0]))
 	/* We have to use a special buffer.  The "32" is just a safe
 	   bet for all the output which is not counted in the width.  */
-	workend = alloca (width + 32) + (width + 31);
+	workend = ((UCHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
+		   + (width + 31));
       if (*f == L_('$'))
 	/* Oh, oh.  The argument comes from a positional parameter.  */
 	goto do_positional;
@@ -1213,7 +1333,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	prec = read_int (&f);
       else
 	prec = 0;
-      if (prec > width && prec + 32 > sizeof (work_buffer))
+      if (prec > width
+	  && prec + 32 > sizeof (work_buffer) / sizeof (work_buffer[0]))
 	workend = alloca (spec + 32) + (spec + 31);
       JUMP (*f, step2_jumps);
 
@@ -1258,6 +1379,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       while (1)
 	{
 	  process_arg (((struct printf_spec *) NULL));
+	  process_string_arg (((struct printf_spec *) NULL));
 
 	LABEL (form_unknown):
 	  if (spec == L_('\0'))
@@ -1276,7 +1398,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       ++nspecs_done;
 
       /* Look for next format specifier.  */
+#ifdef COMPILE_WPRINTF
+      f = find_spec ((end_of_spec = ++f));
+#else
       f = find_spec ((end_of_spec = ++f), &mbstate);
+#endif
 
       /* Write the following constant string.  */
       outstring (end_of_spec, f - end_of_spec);
@@ -1301,7 +1427,7 @@ do_positional:
        attributes.  */
     size_t nargs = 0;
     int *args_type;
-    union printf_arg *args_value;
+    union printf_arg *args_value = NULL;
 
     /* Positional parameters refer to arguments directly.  This could
        also determine the maximum number of arguments.  Track the
@@ -1329,7 +1455,7 @@ do_positional:
 	  grouping = NULL;
       }
 
-    for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
+    for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt)
       {
 	if (nspecs >= nspecs_max)
 	  {
@@ -1356,8 +1482,12 @@ do_positional:
 	  }
 
 	/* Parse the format specifier.  */
+#ifdef COMPILE_WPRINTF
+	nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
+#else
 	nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg,
 				 &mbstate);
+#endif
       }
 
     /* Determine the number of arguments the format string consumes.  */
@@ -1449,7 +1579,7 @@ do_positional:
 	} number;
 	int base;
 	union printf_arg the_arg;
-	char *string;	/* Pointer to argument string.  */
+	UCHAR_T *string;	/* Pointer to argument string.  */
 
 	/* Fill variables from values in struct.  */
 	int alt = specs[nspecs_done].info.alt;
@@ -1498,8 +1628,10 @@ do_positional:
 	  }
 
 	/* Maybe the buffer is too small.  */
-	if (MAX (prec, width) + 32 > sizeof (work_buffer))
-	  workend = alloca (MAX (prec, width) + 32) + (MAX (prec, width) + 31);
+	if (MAX (prec, width) + 32 > sizeof (work_buffer) / sizeof (UCHAR_T))
+	  workend = ((UCHAR_T *) alloca ((MAX (prec, width) + 32)
+					 * sizeof (UCHAR_T))
+		     + (MAX (prec, width) + 31));
 
 	/* Process format specifiers.  */
 	while (1)
@@ -1507,6 +1639,7 @@ do_positional:
 	    JUMP (spec, step4_jumps);
 
 	    process_arg ((&specs[nspecs_done]));
+	    process_string_arg ((&specs[nspecs_done]));
 
 	  LABEL (form_unknown):
 	    {
@@ -1564,21 +1697,6 @@ all_done:
 
   return done;
 }
-
-#ifdef USE_IN_LIBIO
-# undef vfprintf
-# ifdef strong_alias
-/* This is for glibc.  */
-strong_alias (_IO_vfprintf, vfprintf);
-# else
-#  if defined __ELF__ || defined __GNU_LIBRARY__
-#   include <gnu-stabs.h>
-#   ifdef weak_alias
-weak_alias (_IO_vfprintf, vfprintf);
-#   endif
-#  endif
-# endif
-#endif
 
 /* Handle an unknown format specifier.  This prints out a canonicalized
    representation of the format spec itself.  */
@@ -1588,24 +1706,25 @@ printf_unknown (FILE *s, const struct printf_info *info,
 
 {
   int done = 0;
-  char work_buffer[MAX (info->width, info->spec) + 32];
-  char *const workend = &work_buffer[sizeof (work_buffer) - 1];
-  register char *w;
+  CHAR_T work_buffer[MAX (info->width, info->spec) + 32];
+  CHAR_T *const workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)
+				      - 1];
+  register CHAR_T *w;
 
-  outchar ('%');
+  outchar (L_('%'));
 
   if (info->alt)
-    outchar ('#');
+    outchar (L_('#'));
   if (info->group)
-    outchar ('\'');
+    outchar (L_('\''));
   if (info->showsign)
-    outchar ('+');
+    outchar (L_('+'));
   else if (info->space)
-    outchar (' ');
+    outchar (L_(' '));
   if (info->left)
-    outchar ('-');
+    outchar (L_('-'));
   if (info->pad == '0')
-    outchar ('0');
+    outchar (L_('0'));
 
   if (info->width != 0)
     {
@@ -1622,7 +1741,7 @@ printf_unknown (FILE *s, const struct printf_info *info,
 	outchar (*w++);
     }
 
-  if (info->spec != '\0')
+  if (info->spec != L_('\0'))
     outchar (info->spec);
 
  all_done:
@@ -1631,13 +1750,13 @@ printf_unknown (FILE *s, const struct printf_info *info,
 
 /* Group the digits according to the grouping rules of the current locale.
    The interpretation of GROUPING is as in `struct lconv' from <locale.h>.  */
-static char *
+static UCHAR_T *
 internal_function
-group_number (CHAR_T *w, CHAR_T *rear_ptr, const CHAR_T *grouping,
+group_number (UCHAR_T *w, UCHAR_T *rear_ptr, const char *grouping,
 	      wchar_t thousands_sep)
 {
   int len;
-  char *src, *s;
+  UCHAR_T *src, *s;
 
   /* We treat all negative values like CHAR_MAX.  */
 
@@ -1648,8 +1767,9 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const CHAR_T *grouping,
   len = *grouping;
 
   /* Copy existing string so that nothing gets overwritten.  */
-  src = (char *) alloca (rear_ptr - w);
-  s = (char *) __mempcpy (src, w + 1, rear_ptr - w) - 1;
+  src = (UCHAR_T *) alloca ((rear_ptr - w) * sizeof (UCHAR_T));
+  s = (UCHAR_T *) __mempcpy (src, w + 1,
+			     (rear_ptr - w) * sizeof (UCHAR_T)) - 1;
   w = rear_ptr;
 
   /* Process all characters in the string.  */
@@ -1699,12 +1819,22 @@ static int
 _IO_helper_overflow (_IO_FILE *s, int c)
 {
   _IO_FILE *target = ((struct helper_file*) s)->_put_stream;
+#ifdef COMPILE_WPRINTF
+  int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base;
+  if (used)
+    {
+      _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base,
+				      used);
+      s->_wide_data->_IO_write_ptr -= written;
+    }
+#else
   int used = s->_IO_write_ptr - s->_IO_write_base;
   if (used)
     {
       _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
       s->_IO_write_ptr -= written;
     }
+#endif
   return PUTC (c, s);
 }
 
@@ -1735,16 +1865,18 @@ internal_function
 buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
 		   _IO_va_list args)
 {
-  char buf[_IO_BUFSIZ];
+  CHAR_T buf[_IO_BUFSIZ];
   struct helper_file helper;
   register _IO_FILE *hp = (_IO_FILE *) &helper;
   int result, to_flush;
 
   /* Initialize helper.  */
   helper._put_stream = s;
-  hp->_IO_write_base = buf;
-  hp->_IO_write_ptr = buf;
-  hp->_IO_write_end = buf + sizeof buf;
+#ifdef COMPILE_WPRINTF
+  _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T));
+#else
+  _IO_setp (hp, buf, buf + sizeof buf);
+#endif
   hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
 #if _IO_JUMPS_OFFSET
   hp->_vtable_offset = 0;
@@ -1756,14 +1888,24 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
   _IO_JUMPS (hp) = (struct _IO_jump_t *) &_IO_helper_jumps;
 
   /* Now print to helper instead.  */
-  result = _IO_vfprintf (hp, format, args);
+  result = vfprintf (hp, format, args);
 
   /* Now flush anything from the helper to the S. */
+#ifdef COMPILE_WPRINTF
+  if ((to_flush = (hp->_wide_data->_IO_write_ptr
+		   - hp->_wide_data->_IO_write_base)) > 0)
+    {
+      if ((int) _IO_sputn (s, hp->_wide_data->_IO_write_base, to_flush)
+	  != to_flush)
+	return -1;
+    }
+#else
   if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
     {
       if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
 	return -1;
     }
+#endif
 
   return result;
 }
@@ -1826,3 +1968,26 @@ __wprintf_pad (FILE *s, wchar_t pad, size_t count)
 }
 #undef PADSIZE
 #endif /* USE_IN_LIBIO */
+
+#ifdef USE_IN_LIBIO
+# undef vfprintf
+# ifdef strong_alias
+/* This is for glibc.  */
+#  ifdef COMPILE_WPRINTF
+strong_alias (_IO_vfwprintf, vfwprintf);
+#  else
+strong_alias (_IO_vfprintf, vfprintf);
+#  endif
+# else
+#  if defined __ELF__ || defined __GNU_LIBRARY__
+#   include <gnu-stabs.h>
+#   ifdef weak_alias
+#    ifdef COMPILE_WPRINTF
+weak_alias (_IO_vfwprintf, vfwprintf);
+#    else
+weak_alias (_IO_vfprintf, vfprintf);
+#    endif
+#   endif
+#  endif
+# endif
+#endif
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 0339edbeca..5caf616be3 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -16,6 +16,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <ctype.h>
@@ -69,13 +70,56 @@
 
 # undef va_list
 # define va_list	_IO_va_list
-# define ungetc(c, s)	((void) ((int) c == EOF				      \
+
+# ifdef COMPILE_WPRINTF
+#  define ungetc(c, s)	((void) ((int) c == WEOF			      \
+				 || (--read_in,				      \
+				     _IO_sputbackwc (s, (unsigned char) c))))
+#  define inchar()	(c == EOF ? EOF					      \
+			 : ((c = _IO_getwc_unlocked (s)),		      \
+			    (void) (c != EOF && ++read_in), c))
+
+#  define MEMCPY(d, s, n) wmemcpy (d, s, n)
+#  define ISSPACE(Ch)	  iswspace (Ch)
+#  define ISDIGIT(Ch)	  iswdigit (Ch)
+#  define ISXDIGIT(Ch)	  iswxdigit (Ch)
+#  define UNGETC(Ch, S)   ungetwc (Ch, S)
+#  define TOLOWER(Ch)	  towlower (Ch)
+#  define ORIENT	  if (_IO_fwide (s, 1) != 1) return EOF
+#  define __strtoll_internal	__wcstoll_internal
+#  define __strtoull_internal	__wcstoull_internal
+#  define __strtol_internal	__wcstol_internal
+#  define __strtoul_internal	__wcstoul_internal
+#  define __strtold_internal	__wcstold_internal
+#  define __strtod_internal	__wcstod_internal
+#  define __strtof_internal	__wcstof_internal
+
+#  define L_(Str)	  L##Str
+#  define CHAR_T	  wchar_t
+#  define UCHAR_T	  unsigned int
+#  define WINT_T	  wint_t
+# else
+#  define ungetc(c, s)	((void) ((int) c == EOF				      \
 				 || (--read_in,				      \
 				     _IO_sputbackc (s, (unsigned char) c))))
-# define inchar()	(c == EOF ? EOF					      \
+#  define inchar()	(c == EOF ? EOF					      \
 			 : ((c = _IO_getc_unlocked (s)),		      \
 			    (void) (c != EOF && ++read_in), c))
-# define encode_error()	do {						      \
+#  define MEMCPY(d, s, n) memcpy (d, s, n)
+#  define ISSPACE(Ch)	  isspace (Ch)
+#  define ISDIGIT(Ch)	  isdigit (Ch)
+#  define ISXDIGIT(Ch)	  isxdigit (Ch)
+#  define UNGETC(Ch, S)   ungetc (Ch, S)
+#  define TOLOWER(Ch)	  tolower (Ch)
+#  define ORIENT	  if (_IO_fwide (s, -1) != -1) return EOF
+
+#  define L_(Str)	  Str
+#  define CHAR_T	  char
+#  define UCHAR_T	  unsigned char
+#  define WINT_T	  int
+# endif
+
+# define encode_error() do {						      \
 			  if (errp != NULL) *errp |= 4;			      \
 			  _IO_funlockfile (s);				      \
 			  __libc_cleanup_end (0);			      \
@@ -94,7 +138,7 @@
 			  __libc_cleanup_end (0);			      \
 			  return done ?: EOF;				      \
 			} while (0)
-# define memory_error()	do {						      \
+# define memory_error() do {						      \
 			  _IO_funlockfile (s);				      \
 			  __set_errno (ENOMEM);				      \
 			  __libc_cleanup_end (0);			      \
@@ -180,30 +224,39 @@
    FORMAT, using the argument list in ARG.
    Return the number of assignments made, or -1 for an input error.  */
 #ifdef USE_IN_LIBIO
+# ifdef COMPILE_WPRINTF
+int
+_IO_vfwscanf (s, format, argptr, errp)
+     _IO_FILE *s;
+     const wchar_t *format;
+     _IO_va_list argptr;
+     int *errp;
+# else
 int
 _IO_vfscanf (s, format, argptr, errp)
      _IO_FILE *s;
      const char *format;
      _IO_va_list argptr;
      int *errp;
+# endif
 #else
 int
 __vfscanf (FILE *s, const char *format, va_list argptr)
 #endif
 {
   va_list arg;
-  register const char *f = format;
-  register unsigned char fc;	/* Current character of the format.  */
+  register const CHAR_T *f = format;
+  register UCHAR_T fc;	/* Current character of the format.  */
   register size_t done = 0;	/* Assignments done.  */
   register size_t read_in = 0;	/* Chars read in.  */
-  register int c = 0;		/* Last char read.  */
+  register WINT_T c = 0;	/* Last char read.  */
   register int width;		/* Maximum field width.  */
   register int flags;		/* Modifiers for current format element.  */
 
   /* Status for reading F-P nums.  */
   char got_dot, got_e, negative;
   /* If a [...] is a [^...].  */
-  char not_in;
+  CHAR_T not_in;
 #define exp_char not_in
   /* Base for integral numbers.  */
   int base;
@@ -236,8 +289,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
   /* Nonzero if we are reading a pointer.  */
   int read_pointer;
   /* Workspace.  */
-  char *tw;			/* Temporary pointer.  */
-  char *wp = NULL;		/* Workspace.  */
+  CHAR_T *tw;			/* Temporary pointer.  */
+  CHAR_T *wp = NULL;		/* Workspace.  */
   size_t wpmax = 0;		/* Maximal size of workspace.  */
   size_t wpsize;		/* Currently used bytes in workspace.  */
 #define ADDW(Ch)							    \
@@ -245,11 +298,11 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
     {									    \
       if (wpsize == wpmax)						    \
 	{								    \
-	  char *old = wp;						    \
+	  CHAR_T *old = wp;						    \
 	  wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax;	    \
-	  wp = (char *) alloca (wpmax);					    \
+	  wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t));		    \
 	  if (old != NULL)						    \
-	    memcpy (wp, old, wpsize);					    \
+	    MEMCPY (wp, old, wpsize);					    \
 	}								    \
       wp[wpsize++] = (Ch);						    \
     }									    \
@@ -261,6 +314,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
   arg = (va_list) argptr;
 #endif
 
+#ifdef ORIENT
+  ORIENT;
+#endif
+
   ARGCHECK (s, format);
 
   /* Figure out the decimal point character.  */
@@ -280,8 +337,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
   LOCK_STREAM (s);
 
 
+#ifndef COMPILE_WPRINTF
   /* From now on we use `state' to convert the format string.  */
   memset (&state, '\0', sizeof (state));
+#endif
 
   /* Run through the format string.  */
   while (*f != '\0')
@@ -320,6 +379,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 # endif
 #endif
 
+#ifndef COMPILE_WPRINTF
       if (!isascii (*f))
 	{
 	  /* Non-ASCII, may be a multibyte.  */
@@ -341,12 +401,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      continue;
 	    }
 	}
+#endif
 
       fc = *f++;
       if (fc != '%')
 	{
 	  /* Remember to skip spaces.  */
-	  if (isspace (fc))
+	  if (ISSPACE (fc))
 	    {
 	      skip_space = 1;
 	      continue;
@@ -363,7 +424,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	     string.  Now it's time to skip all leading white space.  */
 	  if (skip_space)
 	    {
-	      while (isspace (c))
+	      while (ISSPACE (c))
 		if (inchar () == EOF && errno == EINTR)
 		  conv_error ();
 	      skip_space = 0;
@@ -371,7 +432,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 
 	  if (c != fc)
 	    {
-	      ungetc (c, s);
+	      UNGETC (c, s);
 	      conv_error ();
 	    }
 
@@ -391,12 +452,12 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
       wpsize = 0;
 
       /* Check for a positional parameter specification.  */
-      if (isdigit (*f))
+      if (ISDIGIT (*f))
 	{
-	  argpos = *f++ - '0';
-	  while (isdigit (*f))
-	    argpos = argpos * 10 + (*f++ - '0');
-	  if (*f == '$')
+	  argpos = *f++ - L_('0');
+	  while (ISDIGIT (*f))
+	    argpos = argpos * 10 + (*f++ - L_('0'));
+	  if (*f == L_('$'))
 	    ++f;
 	  else
 	    {
@@ -409,27 +470,27 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	}
 
       /* Check for the assignment-suppressing and the number grouping flag.  */
-      while (*f == '*' || *f == '\'')
+      while (*f == L_('*') || *f == L_('\''))
 	switch (*f++)
 	  {
-	  case '*':
+	  case L_('*'):
 	    flags |= SUPPRESS;
 	    break;
-	  case '\'':
+	  case L_('\''):
 	    flags |= GROUP;
 	    break;
 	  }
 
       /* We have seen width. */
-      if (isdigit (*f))
+      if (ISDIGIT (*f))
 	flags |= WIDTH;
 
       /* Find the maximum field width.  */
       width = 0;
-      while (isdigit (*f))
+      while (ISDIGIT (*f))
 	{
 	  width *= 10;
-	  width += *f++ - '0';
+	  width += *f++ - L_('0');
 	}
     got_width:
       if (width == 0)
@@ -438,9 +499,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
       /* Check for type modifiers.  */
       switch (*f++)
 	{
-	case 'h':
+	case L_('h'):
 	  /* ints are short ints or chars.  */
-	  if (*f == 'h')
+	  if (*f == L_('h'))
 	    {
 	      ++f;
 	      flags |= CHAR;
@@ -448,8 +509,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  else
 	    flags |= SHORT;
 	  break;
-	case 'l':
-	  if (*f == 'l')
+	case L_('l'):
+	  if (*f == L_('l'))
 	    {
 	      /* A double `l' is equivalent to an `L'.  */
 	      ++f;
@@ -459,15 +520,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    /* ints are long ints.  */
 	    flags |= LONG;
 	  break;
-	case 'q':
-	case 'L':
+	case L_('q'):
+	case L_('L'):
 	  /* doubles are long doubles, and ints are long long ints.  */
 	  flags |= LONGDBL | LONG;
 	  break;
-	case 'a':
+	case L_('a'):
 	  /* The `a' is used as a flag only if followed by `s', `S' or
 	     `['.  */
-	  if (*f != 's' && *f != 'S' && *f != '[')
+	  if (*f != L_('s') && *f != L_('S') && *f != L_('['))
 	    {
 	      --f;
 	      break;
@@ -476,19 +537,19 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	     arg and fill it in with a malloc'd pointer.  */
 	  flags |= MALLOC;
 	  break;
-	case 'z':
+	case L_('z'):
 	  if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
 	    flags |= LONGDBL;
 	  else if (sizeof (size_t) > sizeof (unsigned int))
 	    flags |= LONG;
 	  break;
-	case 'j':
+	case L_('j'):
 	  if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
 	    flags |= LONGDBL;
 	  else if (sizeof (uintmax_t) > sizeof (unsigned int))
 	    flags |= LONG;
 	  break;
-	case 't':
+	case L_('t'):
 	  if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
 	    flags |= LONGDBL;
 	  else if (sizeof (ptrdiff_t) > sizeof (int))
@@ -501,12 +562,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	}
 
       /* End of the format string?  */
-      if (*f == '\0')
+      if (*f == L_('\0'))
 	conv_error ();
 
       /* Find the conversion specifier.  */
       fc = *f++;
-      if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
+      if (skip_space || (fc != L_('[') && fc != L_('c')
+			 && fc != L_('C') && fc != L_('n')))
 	{
 	  /* Eat whitespace.  */
 	  int save_errno = errno;
@@ -514,15 +576,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  do
 	    if (inchar () == EOF && errno == EINTR)
 	      input_error ();
-	  while (isspace (c));
+	  while (ISSPACE (c));
 	  errno = save_errno;
-	  ungetc (c, s);
+	  UNGETC (c, s);
 	  skip_space = 0;
 	}
 
       switch (fc)
 	{
-	case '%':	/* Must match a literal '%'.  */
+	case L_('%'):	/* Must match a literal '%'.  */
 	  c = inchar ();
 	  if (c == EOF)
 	    input_error ();
@@ -533,7 +595,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 	  break;
 
-	case 'n':	/* Answer number of assignments done.  */
+	case L_('n'):	/* Answer number of assignments done.  */
 	  /* Corrigendum 1 to ISO C 1990 describes the allowed flags
 	     with the 'n' conversion specifier.  */
 	  if (!(flags & SUPPRESS))
@@ -581,7 +643,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 	  break;
 
-	case 'c':	/* Match characters.  */
+	case L_('c'):	/* Match characters.  */
 	  if ((flags & LONG) == 0)
 	    {
 	      if (!(flags & SUPPRESS))
@@ -598,6 +660,26 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      if (width == -1)
 		width = 1;
 
+#ifdef COMPILE_WPRINTF
+	      /* We have to convert the wide character(s) into multibyte
+		 characters and store the result.  */
+	      memset (&state, '\0', sizeof (state));
+
+	      do
+		{
+		  size_t n;
+
+		  n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
+		  if (n == (size_t) -1)
+		    /* No valid wide character.  */
+		    input_error ();
+
+		  /* Increment the output pointer.  Even if we don't
+		     write anything.  */
+		  str += n;
+		}
+	      while (--width > 0 && inchar () != EOF);
+#else
 	      if (!(flags & SUPPRESS))
 		{
 		  do
@@ -606,6 +688,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 		}
 	      else
 		while (--width > 0 && inchar () != EOF);
+#endif
 
 	      if (!(flags & SUPPRESS))
 		++done;
@@ -613,238 +696,448 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      break;
 	    }
 	  /* FALLTHROUGH */
-	case 'C':
-	  /* Get UTF-8 encoded wide character.  Here we assume (as in
-	     other parts of the libc) that we only have to handle
-	     UTF-8.  */
+	case L_('C'):
+	  if (!(flags & SUPPRESS))
+	    {
+	      wstr = ARG (wchar_t *);
+	      if (str == NULL)
+		conv_error ();
+	    }
+
+	  c = inchar ();
+	  if (c == EOF)
+	    input_error ();
+
+#ifdef COMPILE_WPRINTF
+	  /* Just store the incoming wide characters.  */
+	  if (!(flags & SUPPRESS))
+	    {
+	      do
+		*wstr++ = c;
+	      while (--width > 0 && inchar () != EOF);
+	    }
+	  else
+	    while (--width > 0 && inchar () != EOF);
+#else
 	  {
-	    wint_t val;
-	    size_t cnt = 0;
-	    int first = 1;
+	    /* We have to convert the multibyte input sequence to wide
+	       characters.  */
+	    char buf[MB_LEN_MAX];
+	    mbstate_t cstate;
 
-	    if (!(flags & SUPPRESS))
-	      {
-		wstr = ARG (wchar_t *);
-		if (str == NULL)
-		  conv_error ();
-	      }
+	    memset (&cstate, '\0', sizeof (cstate));
 
 	    do
 	      {
-#define NEXT_WIDE_CHAR(First)						      \
-		c = inchar ();						      \
-		if (c == EOF)						      \
-		  {							      \
-		    /* EOF is only an error for the first character.  */      \
-		    if (First)						      \
-		      input_error ();					      \
-		    else						      \
-		      break;						      \
-		  }							      \
-		val = c;						      \
-		if (val >= 0x80)					      \
-		  {							      \
-		    if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)	      \
-		      encode_error ();					      \
-		    if ((c & 0xe0) == 0xc0)				      \
-		      {							      \
-			/* We expect two bytes.  */			      \
-			cnt = 1;					      \
-			val &= 0x1f;					      \
-		      }							      \
-		    else if ((c & 0xf0) == 0xe0)			      \
-		      {							      \
-			/* We expect three bytes.  */			      \
-			cnt = 2;					      \
-			val &= 0x0f;					      \
-		      }							      \
-		    else if ((c & 0xf8) == 0xf0)			      \
-		      {							      \
-			/* We expect four bytes.  */			      \
-			cnt = 3;					      \
-			val &= 0x07;					      \
-		      }							      \
-		    else if ((c & 0xfc) == 0xf8)			      \
-		      {							      \
-			/* We expect five bytes.  */			      \
-			cnt = 4;					      \
-			val &= 0x03;					      \
-		      }							      \
-		    else						      \
-		      {							      \
-			/* We expect six bytes.  */			      \
-			cnt = 5;					      \
-			val &= 0x01;					      \
-		      }							      \
-		    							      \
-		    do							      \
-		      {							      \
-			c = inchar ();					      \
-			if (c == EOF					      \
-			    || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)      \
-			  encode_error ();				      \
-			val <<= 6;					      \
-			val |= c & 0x3f;				      \
-		      }							      \
-		    while (--cnt > 0);					      \
-		  }							      \
-									      \
-		if (!(flags & SUPPRESS))				      \
-		  *wstr++ = val;					      \
-		First = 0
-
-		NEXT_WIDE_CHAR (first);
-	      }
-	    while (--width > 0);
+		size_t cnt;
 
-	    if (!(flags & SUPPRESS))
-	      ++done;
+		/* This is what we present the mbrtowc function first.  */
+		buf[0] = c;
+		cnt = 1;
+
+		while (1)
+		  {
+		    size_t n;
+
+		    n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
+				   buf, cnt, &cstate);
+
+		    if (n == (size_t) -2)
+		      {
+			/* Possibly correct character, just not enough
+			   input.  */
+			assert (cnt < MB_CUR_MAX);
+
+			if (inchar () == EOF)
+			  encode_error ();
+
+			buf[cnt++] = c;
+			continue;
+		      }
+
+		    if (n != cnt)
+		      encode_error ();
+
+		    /* We have a match.  */
+		    break;
+		  }
+
+		/* Advance the result pointer.  */
+		++wstr;
+	      }
+	    while (--width > 0 && inchar () != EOF);
 	  }
-	  break;
+#endif
 
-	case 's':		/* Read a string.  */
-	  if (flags & LONG)
-	    /* We have to process a wide character string.  */
-	    goto wide_char_string;
+	  if (!(flags & SUPPRESS))
+	    ++done;
 
+	  break;
+
+	case L_('s'):		/* Read a string.  */
+	  if (!(flags & LONG))
+	    {
 #define STRING_ARG(Str, Type)						      \
-	  if (!(flags & SUPPRESS))					      \
-	    {								      \
-	      if (flags & MALLOC)					      \
+	      do if (!(flags & SUPPRESS))				      \
 		{							      \
-		  /* The string is to be stored in a malloc'd buffer.  */     \
-		  strptr = ARG (char **);				      \
-		  if (strptr == NULL)					      \
+		  if (flags & MALLOC)					      \
+		    {							      \
+		      /* The string is to be stored in a malloc'd buffer.  */ \
+		      strptr = ARG (char **);				      \
+		      if (strptr == NULL)				      \
+			conv_error ();					      \
+		      /* Allocate an initial buffer.  */		      \
+		      strsize = 100;					      \
+		      *strptr = (char *) malloc (strsize * sizeof (Type));    \
+		      Str = (Type *) *strptr;				      \
+		    }							      \
+		  else							      \
+		    Str = ARG (Type *);					      \
+		  if (Str == NULL)					      \
 		    conv_error ();					      \
-		  /* Allocate an initial buffer.  */			      \
-		  strsize = 100;					      \
-		  *strptr = malloc (strsize * sizeof (Type));		      \
-		  Str = (Type *) *strptr;				      \
-		}							      \
-	      else							      \
-		Str = ARG (Type *);					      \
-	      if (Str == NULL)						      \
-		conv_error ();						      \
-	    }
-	  STRING_ARG (str, char);
+		} while (0)
+	      STRING_ARG (str, char);
 
-	  c = inchar ();
-	  if (c == EOF)
-	    input_error ();
+	      c = inchar ();
+	      if (c == EOF)
+		input_error ();
 
-	  do
-	    {
-	      if (isspace (c))
+#ifdef COMPILE_WPRINTF
+	      memset (&state, '\0', sizeof (state));
+#endif
+
+	      do
 		{
-		  ungetc (c, s);
-		  break;
-		}
-#define	STRING_ADD_CHAR(Str, c, Type)					      \
-	      if (!(flags & SUPPRESS))					      \
-		{							      \
-		  *Str++ = c;						      \
-		  if ((flags & MALLOC) && (char *) Str == *strptr + strsize)  \
-		    {							      \
-		      /* Enlarge the buffer.  */			      \
-		      Str = realloc (*strptr, strsize * 2 * sizeof (Type));   \
-		      if (Str == NULL)					      \
-			{						      \
-			  /* Can't allocate that much.  Last-ditch effort.  */\
-			  Str = realloc (*strptr,			      \
-					 (strsize + 1) * sizeof (Type));      \
-			  if (Str == NULL)				      \
-			    {						      \
-			      /* We lose.  Oh well.			      \
-				 Terminate the string and stop converting,    \
-				 so at least we don't skip any input.  */     \
-			      ((Type *) (*strptr))[strsize] = '\0';	      \
-			      ++done;					      \
-			      conv_error ();				      \
-			    }						      \
-			  else						      \
-			    {						      \
-			      *strptr = (char *) Str;			      \
-			      Str = ((Type *) *strptr) + strsize;	      \
-			      ++strsize;				      \
-			    }						      \
-			}						      \
-		      else						      \
-			{						      \
-			  *strptr = (char *) Str;			      \
-			  Str = ((Type *) *strptr) + strsize;		      \
-			  strsize *= 2;					      \
-			}						      \
-		    }							      \
+		  if (ISSPACE (c))
+		    {
+		      UNGETC (c, s);
+		      break;
+		    }
+
+#ifdef COMPILE_WPRINTF
+		  /* This is quite complicated.  We have to convert the
+		     wide characters into multibyte characters and then
+		     store them.  */
+		  {
+		    size_t n;
+
+		    if (!(flags & SUPPRESS) && (flags & MALLOC)
+			&& str + MB_CUR_MAX >= *strptr + strsize)
+		      {
+			/* We have to enlarge the buffer if the `a' flag
+			   was given.  */
+			str = (char *) realloc (*strptr, strsize * 2);
+			if (str == NULL)
+			  {
+			    /* Can't allocate that much.  Last-ditch
+			       effort.  */
+			    str = (char *) realloc (*strptr, strsize + 1);
+			    if (str == NULL)
+			      {
+				/* We lose.  Oh well.  Terminate the
+				   string and stop converting,
+				   so at least we don't skip any input.  */
+				((char *) (*strptr))[strsize - 1] = '\0';
+				++done;
+				conv_error ();
+			      }
+			    else
+			      {
+				*strptr = (char *) str;
+				str += strsize;
+				++strsize;
+			      }
+			  }
+			else
+			  {
+			    *strptr = (char *) str;
+			    str += strsize;
+			    strsize *= 2;
+			  }
+		      }
+
+		    n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
+		    if (n == (size_t) -1)
+		      encode_error ();
+
+		    assert (n <= MB_CUR_MAX);
+		    str += n;
+		  }
+#else
+		  /* This is easy.  */
+		  if (!(flags & SUPPRESS))
+		    {
+		      *str++ = c;
+		      if ((flags & MALLOC)
+			  && (char *) str == *strptr + strsize)
+			{
+			  /* Enlarge the buffer.  */
+			  str = (char *) realloc (*strptr, 2 * strsize);
+			  if (str == NULL)
+			    {
+			      /* Can't allocate that much.  Last-ditch
+				 effort.  */
+			      str = (char *) realloc (*strptr, strsize + 1);
+			      if (str == NULL)
+				{
+				  /* We lose.  Oh well.  Terminate the
+				     string and stop converting,
+				     so at least we don't skip any input.  */
+				  ((char *) (*strptr))[strsize - 1] = '\0';
+				  ++done;
+				  conv_error ();
+				}
+			      else
+				{
+				  *strptr = (char *) str;
+				  str += strsize;
+				  ++strsize;
+				}
+			    }
+			  else
+			    {
+			      *strptr = (char *) str;
+			      str += strsize;
+			      strsize *= 2;
+			    }
+			}
+		    }
+#endif
 		}
-	      STRING_ADD_CHAR (str, c, char);
-	    } while ((width <= 0 || --width > 0) && inchar () != EOF);
+	      while ((width <= 0 || --width > 0) && inchar () != EOF);
 
-	  if (!(flags & SUPPRESS))
-	    {
-	      *str = '\0';
-	      ++done;
+	      if (!(flags & SUPPRESS))
+		{
+#ifdef COMPILE_WPRINTF
+		  /* We have to emit the code to get into the intial
+		     state.  */
+		  char buf[MB_LEN_MAX];
+		  size_t n = wcrtomb (buf, L'\0', &state);
+		  if (n > 0 && (flags & MALLOC)
+		      && str + n >= *strptr + strsize)
+		    {
+		      /* Enlarge the buffer.  */
+		      str = (char *) realloc (*strptr,
+					      (str + n + 1) - *strptr);
+		      if (str == NULL)
+			{
+			  /* We lose.  Oh well.  Terminate the string
+			     and stop converting, so at least we don't
+			     skip any input.  */
+			  ((char *) (*strptr))[strsize - 1] = '\0';
+			  ++done;
+			  conv_error ();
+			}
+		      else
+			{
+			  *strptr = (char *) str;
+			  str = ((char *) *strptr) + strsize;
+			  strsize = (str + n + 1) - *strptr;
+			}
+		    }
+
+		  str = __mempcpy (str, buf, n);
+#endif
+		  *str = '\0';
+
+		  if ((flags & MALLOC) && str - *strptr != strsize)
+		    {
+		      char *cp = (char *) realloc (*strptr, str - *strptr);
+		      if (cp != NULL)
+			*strptr = cp;
+		    }
+
+		  ++done;
+		}
+	      break;
 	    }
-	  break;
+	  /* FALLTHROUGH */
 
-	case 'S':
-	  /* Wide character string.  */
-	wide_char_string:
+	case L_('S'):
 	  {
-	    wint_t val;
-	    int first = 1;
+#ifndef COMPILE_WPRINTF
+	    mbstate_t cstate;
+#endif
+
+	    /* Wide character string.  */
 	    STRING_ARG (wstr, wchar_t);
 
+	    c = inchar ();
+	    if (c == EOF)
+	      input_error ();
+
+#ifndef COMPILE_WPRINTF
+	    memset (&cstate, '\0', sizeof (cstate));
+#endif
+
 	    do
 	      {
-		size_t cnt = 0;
-		NEXT_WIDE_CHAR (first);
-
-		if (__iswspace (val))
+		if (ISSPACE (c))
 		  {
-		    /* XXX We would have to push back the whole wide char
-		       with possibly many bytes.  But since scanf does
-		       not make a difference for white space characters
-		       we can simply push back a simple <SP> which is
-		       guaranteed to be in the [:space:] class.  */
-		    ungetc (' ', s);
+		    UNGETC (c, s);
 		    break;
 		  }
 
-		STRING_ADD_CHAR (wstr, val, wchar_t);
-		first = 0;
+#ifdef COMPILE_WPRINTF
+		/* This is easy.  */
+		if (!(flags & SUPPRESS))
+		  {
+		    *wstr++ = c;
+		    if ((flags & MALLOC)
+			&& wstr == (wchar_t *) *strptr + strsize)
+		      {
+			/* Enlarge the buffer.  */
+			wstr = (wchar_t *) realloc (*strptr,
+						    (2 * strsize)
+						    * sizeof (wchar_t));
+			if (wstr == NULL)
+			  {
+			    /* Can't allocate that much.  Last-ditch
+                               effort.  */
+			    wstr = (wchar_t *) realloc (*strptr,
+							(strsize
+							 + sizeof (wchar_t)));
+			    if (wstr == NULL)
+			      {
+				/* We lose.  Oh well.  Terminate the string
+				   and stop converting, so at least we don't
+				   skip any input.  */
+				((wchar_t *) (*strptr))[strsize - 1] = L'\0';
+				++done;
+				conv_error ();
+			      }
+			    else
+			      {
+				*strptr = (char *) wstr;
+				wstr += strsize;
+				++strsize;
+			      }
+			  }
+			else
+			  {
+			    *strptr = (char *) wstr;
+			    wstr += strsize;
+			    strsize *= 2;
+			  }
+		      }
+		  }
+#else
+		{
+		  char buf[MB_LEN_MAX];
+		  size_t cnt;
+
+		  buf[0] = c;
+		  cnt = 1;
+
+		  while (1)
+		    {
+		      size_t n;
+
+		      n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
+				     buf, cnt, &cstate);
+
+		      if (n == (size_t) -2)
+			{
+			  /* Possibly correct character, just not enough
+			     input.  */
+			  assert (cnt < MB_CUR_MAX);
+
+			  if (inchar () == EOF)
+			    encode_error ();
+
+			  buf[cnt++] = c;
+			  continue;
+			}
+
+		      if (n != cnt)
+			encode_error ();
+
+		      /* We have a match.  */
+		      break;
+		    }
+
+		  if (!(flags & SUPPRESS) && (flags & MALLOC)
+		      && wstr == (wchar_t *) *strptr + strsize)
+		    {
+		      /* Enlarge the buffer.  */
+		      wstr = (wchar_t *) realloc (*strptr,
+						  (2 * strsize
+						   * sizeof (wchar_t)));
+		      if (wstr == NULL)
+			{
+			  /* Can't allocate that much.  Last-ditch effort.  */
+			  wstr = (wchar_t *) realloc (*strptr,
+						      ((strsize + 1)
+						       * sizeof (wchar_t)));
+			  if (wstr == NULL)
+			    {
+			      /* We lose.  Oh well.  Terminate the
+				 string and stop converting, so at
+				 least we don't skip any input.  */
+			      ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
+			      ++done;
+			      conv_error ();
+			    }
+			  else
+			    {
+			      *strptr = (char *) wstr;
+			      wstr += strsize;
+			      ++strsize;
+			    }
+			}
+		      else
+			{
+			  *strptr = (char *) wstr;
+			  wstr += strsize;
+			  strsize *= 2;
+			}
+		    }
+		}
+#endif
 	      }
-	    while (width <= 0 || --width > 0);
+	    while ((width <= 0 || --width > 0) && inchar () != EOF);
 
 	    if (!(flags & SUPPRESS))
 	      {
-		*wstr = L'\0';
+		*wstr++ = L'\0';
+
+		if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
+		  {
+		    wchar_t *cp = (wchar_t *) realloc (*strptr,
+						       ((wstr
+							 - (wchar_t *) *strptr)
+							* sizeof(wchar_t)));
+		    if (cp != NULL)
+		      *strptr = (char *) cp;
+		  }
+
 		++done;
 	      }
 	  }
 	  break;
 
-	case 'x':	/* Hexadecimal integer.  */
-	case 'X':	/* Ditto.  */
+	case L_('x'):	/* Hexadecimal integer.  */
+	case L_('X'):	/* Ditto.  */
 	  base = 16;
 	  number_signed = 0;
 	  goto number;
 
-	case 'o':	/* Octal integer.  */
+	case L_('o'):	/* Octal integer.  */
 	  base = 8;
 	  number_signed = 0;
 	  goto number;
 
-	case 'u':	/* Unsigned decimal integer.  */
+	case L_('u'):	/* Unsigned decimal integer.  */
 	  base = 10;
 	  number_signed = 0;
 	  goto number;
 
-	case 'd':	/* Signed decimal integer.  */
+	case L_('d'):	/* Signed decimal integer.  */
 	  base = 10;
 	  number_signed = 1;
 	  goto number;
 
-	case 'i':	/* Generic number.  */
+	case L_('i'):	/* Generic number.  */
 	  base = 0;
 	  number_signed = 1;
 
@@ -854,7 +1147,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    input_error ();
 
 	  /* Check for a sign.  */
-	  if (c == '-' || c == '+')
+	  if (c == L_('-') || c == L_('+'))
 	    {
 	      ADDW (c);
 	      if (width > 0)
@@ -863,7 +1156,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 
 	  /* Look for a leading indication of base.  */
-	  if (width != 0 && c == '0')
+	  if (width != 0 && c == L_('0'))
 	    {
 	      if (width > 0)
 		--width;
@@ -871,7 +1164,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      ADDW (c);
 	      c = inchar ();
 
-	      if (width != 0 && _tolower (c) == 'x')
+	      if (width != 0 && TOLOWER (c) == L_('x'))
 		{
 		  if (base == 0)
 		    base = 16;
@@ -892,8 +1185,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  /* Read the number into workspace.  */
 	  while (c != EOF && width != 0)
 	    {
-	      if (base == 16 ? !isxdigit (c) :
-		  ((!isdigit (c) || c - '0' >= base) &&
+	      if (base == 16 ? !ISXDIGIT (c) :
+		  ((!ISDIGIT (c) || c - L_('0') >= base) &&
 		   !((flags & GROUP) && base == 10 && c == thousands)))
 		break;
 	      ADDW (c);
@@ -904,34 +1197,34 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 
 	  if (wpsize == 0 ||
-	      (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
+	      (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
 	    {
 	      /* There was no number.  If we are supposed to read a pointer
 		 we must recognize "(nil)" as well.  */
 	      if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
 		  && c == '('
-		  && _tolower (inchar ()) == 'n'
-		  && _tolower (inchar ()) == 'i'
-		  && _tolower (inchar ()) == 'l'
-		  && inchar () == ')')
+		  && TOLOWER (inchar ()) == L_('n')
+		  && TOLOWER (inchar ()) == L_('i')
+		  && TOLOWER (inchar ()) == L_('l')
+		  && inchar () == L_(')'))
 		/* We must produce the value of a NULL pointer.  A single
 		   '0' digit is enough.  */
-		ADDW ('0');
+		ADDW (L_('0'));
 	      else
 		{
 		  /* The last read character is not part of the number
 		     anymore.  */
-		  ungetc (c, s);
+		  UNGETC (c, s);
 
 		  conv_error ();
 		}
 	    }
 	  else
 	    /* The just read character is not part of the number anymore.  */
-	    ungetc (c, s);
+	    UNGETC (c, s);
 
 	  /* Convert the number.  */
-	  ADDW ('\0');
+	  ADDW (L_('\0'));
 	  if (need_longlong && (flags & LONGDBL))
 	    {
 	      if (number_signed)
@@ -982,28 +1275,28 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 	  break;
 
-	case 'e':	/* Floating-point numbers.  */
-	case 'E':
-	case 'f':
-	case 'g':
-	case 'G':
-	case 'a':
-	case 'A':
+	case L_('e'):	/* Floating-point numbers.  */
+	case L_('E'):
+	case L_('f'):
+	case L_('g'):
+	case L_('G'):
+	case L_('a'):
+	case L_('A'):
 	  c = inchar ();
 	  if (c == EOF)
 	    input_error ();
 
 	  /* Check for a sign.  */
-	  if (c == '-' || c == '+')
+	  if (c == L_('-') || c == L_('+'))
 	    {
-	      negative = c == '-';
+	      negative = c == L_('-');
 	      if (inchar () == EOF)
 		/* EOF is only an input error before we read any chars.  */
 		conv_error ();
-	      if (! isdigit (c) && c != decimal)
+	      if (! ISDIGIT (c) && c != decimal)
 		{
 		  /* This is no valid number.  */
-		  ungetc (c, s);
+		  UNGETC (c, s);
 		  input_error ();
 		}
 	      if (width > 0)
@@ -1013,69 +1306,69 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    negative = 0;
 
 	  /* Take care for the special arguments "nan" and "inf".  */
-	  if (_tolower (c) == 'n')
+	  if (TOLOWER (c) == L_('n'))
 	    {
 	      /* Maybe "nan".  */
 	      ADDW (c);
-	      if (inchar () == EOF || _tolower (c) != 'a')
+	      if (inchar () == EOF || TOLOWER (c) != L_('a'))
 		input_error ();
 	      ADDW (c);
-	      if (inchar () == EOF || _tolower (c) != 'n')
+	      if (inchar () == EOF || TOLOWER (c) != L_('n'))
 		input_error ();
 	      ADDW (c);
 	      /* It is "nan".  */
 	      goto scan_float;
 	    }
-	  else if (_tolower (c) == 'i')
+	  else if (TOLOWER (c) == L_('i'))
 	    {
 	      /* Maybe "inf" or "infinity".  */
 	      ADDW (c);
-	      if (inchar () == EOF || _tolower (c) != 'n')
+	      if (inchar () == EOF || TOLOWER (c) != L_('n'))
 		input_error ();
 	      ADDW (c);
-	      if (inchar () == EOF || _tolower (c) != 'f')
+	      if (inchar () == EOF || TOLOWER (c) != L_('f'))
 		input_error ();
 	      ADDW (c);
 	      /* It is as least "inf".  */
 	      if (inchar () != EOF)
 		{
-		  if (_tolower (c) == 'i')
+		  if (TOLOWER (c) == L_('i'))
 		    {
 		      /* Now we have to read the rest as well.  */
 		      ADDW (c);
-		      if (inchar () == EOF || _tolower (c) != 'n')
+		      if (inchar () == EOF || TOLOWER (c) != L_('n'))
 			input_error ();
 		      ADDW (c);
-		      if (inchar () == EOF || _tolower (c) != 'i')
+		      if (inchar () == EOF || TOLOWER (c) != L_('i'))
 			input_error ();
 		      ADDW (c);
-		      if (inchar () == EOF || _tolower (c) != 't')
+		      if (inchar () == EOF || TOLOWER (c) != L_('t'))
 			input_error ();
 		      ADDW (c);
-		      if (inchar () == EOF || _tolower (c) != 'y')
+		      if (inchar () == EOF || TOLOWER (c) != L_('y'))
 			input_error ();
 		      ADDW (c);
 		    }
 		  else
 		    /* Never mind.  */
-		    ungetc (c, s);
+		    UNGETC (c, s);
 		}
 	      goto scan_float;
 	    }
 
 	  is_hexa = 0;
-	  exp_char = 'e';
-	  if (c == '0')
+	  exp_char = L_('e');
+	  if (c == L_('0'))
 	    {
 	      ADDW (c);
 	      c = inchar ();
-	      if (_tolower (c) == 'x')
+	      if (TOLOWER (c) == L_('x'))
 		{
 		  /* It is a number in hexadecimal format.  */
 		  ADDW (c);
 
 		  is_hexa = 1;
-		  exp_char = 'p';
+		  exp_char = L_('p');
 
 		  /* Grouping is not allowed.  */
 		  flags &= ~GROUP;
@@ -1086,14 +1379,14 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  got_dot = got_e = 0;
 	  do
 	    {
-	      if (isdigit (c))
+	      if (ISDIGIT (c))
 		ADDW (c);
-	      else if (!got_e && is_hexa && isxdigit (c))
+	      else if (!got_e && is_hexa && ISXDIGIT (c))
 		ADDW (c);
 	      else if (got_e && wp[wpsize - 1] == exp_char
-		       && (c == '-' || c == '+'))
+		       && (c == L_('-') || c == L_('+')))
 		ADDW (c);
-	      else if (wpsize > 0 && !got_e && _tolower (c) == exp_char)
+	      else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
 		{
 		  ADDW (exp_char);
 		  got_e = got_dot = 1;
@@ -1109,7 +1402,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 		{
 		  /* The last read character is not part of the number
 		     anymore.  */
-		  ungetc (c, s);
+		  UNGETC (c, s);
 		  break;
 		}
 	      if (width > 0)
@@ -1125,7 +1418,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 
 	scan_float:
 	  /* Convert the number.  */
-	  ADDW ('\0');
+	  ADDW (L_('\0'));
 	  if (flags & LONGDBL)
 	    {
 	      long double d = __strtold_internal (wp, &tw, flags & GROUP);
@@ -1152,22 +1445,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    ++done;
 	  break;
 
-	case '[':	/* Character class.  */
+	case L_('['):	/* Character class.  */
 	  if (flags & LONG)
-	    {
-	      STRING_ARG (wstr, wchar_t);
-	      c = '\0';		/* This is to keep gcc quiet.  */
-	    }
+	    STRING_ARG (wstr, wchar_t);
 	  else
-	    {
-	      STRING_ARG (str, char);
+	    STRING_ARG (str, char);
 
-	      c = inchar ();
-	      if (c == EOF)
-		input_error ();
-	    }
-
-	  if (*f == '^')
+	  if (*f == L_('^'))
 	    {
 	      ++f;
 	      not_in = 1;
@@ -1175,6 +1459,29 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  else
 	    not_in = 0;
 
+	  if (width < 0)
+	    /* There is no width given so there is also no limit on the
+	       number of characters we read.  Therefore we set width to
+	       a very high value to make the algorithm easier.  */
+	    width = INT_MAX;
+
+#ifdef COMPILE_WPRINTF
+	  /* Find the beginning and the end of the scanlist.  We are not
+	     creating a lookup table since it would have to be too large.
+	     Instead we search each time through the string.  This is not
+	     a constant lookup time but who uses this feature deserves to
+	     be punished.  */
+	  tw = (wchar_t *) f;	/* Marks the beginning.  */
+
+	  if (*f == ']' || *f == '-')
+	    ++f;
+
+	  while ((fc = *f++) != L'\0' && fc != L']');
+
+	  if (fc == L'\0')
+	    conv_error ();
+	  wp = (wchar_t *) f - 1;
+#else
 	  /* Fill WP with byte flags indexed by character.
 	     We will use this flag map for matching input characters.  */
 	  if (wpmax < UCHAR_MAX)
@@ -1182,7 +1489,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      wpmax = UCHAR_MAX;
 	      wp = (char *) alloca (wpmax);
 	    }
-	  memset (wp, 0, UCHAR_MAX);
+	  memset (wp, '\0', UCHAR_MAX);
 
 	  fc = *f;
 	  if (fc == ']' || fc == '-')
@@ -1194,85 +1501,433 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      ++f;
 	    }
 
+	  tw = (char *) f;
 	  while ((fc = *f++) != '\0' && fc != ']')
-	    {
-	      if (fc == '-' && *f != '\0' && *f != ']' &&
-		  (unsigned char) f[-2] <= (unsigned char) *f)
-		{
-		  /* Add all characters from the one before the '-'
-		     up to (but not including) the next format char.  */
-		  for (fc = f[-2]; fc < *f; ++fc)
-		    wp[fc] = 1;
-		}
-	      else
-		/* Add the character to the flag map.  */
-		wp[fc] = 1;
-	    }
+	    if (fc == '-' && *f != '\0' && *f != ']' && f - 2 != tw
+		&& (unsigned char) f[-2] <= (unsigned char) *f)
+	      {
+		/* Add all characters from the one before the '-'
+		   up to (but not including) the next format char.  */
+		for (fc = f[-2]; fc < *f; ++fc)
+		  wp[fc] = 1;
+	      }
+	    else
+	      /* Add the character to the flag map.  */
+	      wp[fc] = 1;
+
 	  if (fc == '\0')
-	    {
-	      if (!(flags & LONG))
-		ungetc (c, s);
-	      conv_error();
-	    }
+	    conv_error();
+#endif
 
 	  if (flags & LONG)
 	    {
-	      wint_t val;
-	      int first = 1;
+	      size_t now = read_in;
+#ifdef COMPILE_WPRINTF
+	      do
+		{
+		  wchar_t *runp;
+
+		  if (inchar () == WEOF)
+		    break;
+
+		  /* Test whether it's in the scanlist.  */
+		  runp = tw;
+		  while (runp < wp)
+		    {
+		      if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
+			  && runp != tw
+			  && (unsigned int) runp[-1] <= (unsigned int) runp[1])
+			{
+			  /* Match against all characters in between the
+			     first and last character of the sequence.  */
+			  wchar_t wc;
+
+			  for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
+			    if (wc == c)
+			      break;
+
+			  if (wc == runp[1] && !not_in)
+			    break;
+			  if (wc == runp[1] && not_in)
+			    {
+			      /* The current character is not in the
+                                 scanset.  */
+			      ungetwc (c, s);
+			      goto out;
+			    }
+			}
+		      else
+			{
+			  if (*runp == runp[1] && !not_in)
+			    break;
+			  if (*runp != runp[1] && not_in)
+			    {
+			      ungetwc (c ,s);
+			      goto out;
+			    }
+			}
+
+		      ++runp;
+		    }
+
+		  if (!(flags & SUPPRESS))
+		    {
+		      *wstr++ = c;
+
+		      if ((flags & MALLOC)
+			  && wstr == (wchar_t *) *strptr + strsize)
+			{
+			  /* Enlarge the buffer.  */
+			  wstr = (wchar_t *) realloc (*strptr,
+						      (2 * strsize)
+						      * sizeof (wchar_t));
+			  if (wstr == NULL)
+			    {
+			      /* Can't allocate that much.  Last-ditch
+				 effort.  */
+			      wstr = (wchar_t *)
+				realloc (*strptr, (strsize
+						   + sizeof (wchar_t)));
+			      if (wstr == NULL)
+				{
+				  /* We lose.  Oh well.  Terminate the string
+				     and stop converting, so at least we don't
+				     skip any input.  */
+				  ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
+				  ++done;
+				  conv_error ();
+				}
+			      else
+				{
+				  *strptr = (char *) wstr;
+				  wstr += strsize;
+				  ++strsize;
+				}
+			    }
+			  else
+			    {
+			      *strptr = (char *) wstr;
+			      wstr += strsize;
+			      strsize *= 2;
+			    }
+			}
+		    }
+		}
+	      while (--width > 0);
+	    out:
+#else
+	      char buf[MB_LEN_MAX];
+	      size_t cnt = 0;
+	      mbstate_t cstate;
+
+	      memset (&cstate, '\0', sizeof (cstate));
 
 	      do
 		{
-		  size_t cnt = 0;
-		  NEXT_WIDE_CHAR (first);
-		  if (val <= 255 && wp[val] == not_in)
+		again:
+		  if (inchar () == EOF)
+		    break;
+
+		  if (wp[c] == not_in)
 		    {
-		      ungetc (val, s);
+		      ungetc (c, s);
 		      break;
 		    }
-		  STRING_ADD_CHAR (wstr, val, wchar_t);
-		  if (width > 0)
-		    --width;
-		  first = 0;
+
+		  /* This is easy.  */
+		  if (!(flags & SUPPRESS))
+		    {
+		      size_t n;
+
+		      /* Convert it into a wide character.  */
+		      n = __mbrtowc (wstr, buf, cnt, &cstate);
+
+		      if (n == (size_t) -2)
+			{
+			  /* Possibly correct character, just not enough
+			     input.  */
+			  assert (cnt < MB_CUR_MAX);
+			  goto again;
+			}
+
+		      if (n != cnt)
+			encode_error ();
+
+		      ++wstr;
+		      if ((flags & MALLOC)
+			  && wstr == (wchar_t *) *strptr + strsize)
+			{
+			  /* Enlarge the buffer.  */
+			  wstr = (wchar_t *) realloc (*strptr,
+						      (2 * strsize
+						       * sizeof (wchar_t)));
+			  if (wstr == NULL)
+			    {
+			      /* Can't allocate that much.  Last-ditch
+				 effort.  */
+			      wstr = (wchar_t *)
+				realloc (*strptr, ((strsize + 1)
+						   * sizeof (wchar_t)));
+			      if (wstr == NULL)
+				{
+				  /* We lose.  Oh well.  Terminate the
+				     string and stop converting,
+				     so at least we don't skip any input.  */
+				  ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
+				  ++done;
+				  conv_error ();
+				}
+			      else
+				{
+				  *strptr = (char *) wstr;
+				  wstr += strsize;
+				  ++strsize;
+				}
+			    }
+			  else
+			    {
+			      *strptr = (char *) wstr;
+			      wstr += strsize;
+			      strsize *= 2;
+			    }
+			}
+		    }
 		}
-	      while (width != 0);
+	      while (--width > 0);
+
+	      if (cnt != 0)
+		/* We stopped in the middle of recognizing another
+		   character.  That's a problem.  */
+		encode_error ();
+#endif
 
-	      if (first)
+	      if (now == read_in)
+		/* We haven't succesfully read any character.  */
 		conv_error ();
 
 	      if (!(flags & SUPPRESS))
 		{
-		  *wstr = L'\0';
+		  *wstr++ = L'\0';
+
+		  if ((flags & MALLOC)
+		      && wstr - (wchar_t *) *strptr != strsize)
+		    {
+		      wchar_t *cp = (wchar_t *)
+			realloc (*strptr, ((wstr - (wchar_t *) *strptr)
+					   * sizeof(wchar_t)));
+		      if (cp != NULL)
+			*strptr = (char *) cp;
+		    }
+
 		  ++done;
 		}
 	    }
 	  else
 	    {
-	      num.ul = read_in - 1; /* -1 because we already read one char.  */
+	      size_t now = read_in;
+#ifdef COMPILE_WPRINTF
+
+	      memset (&state, '\0', sizeof (state));
+
+	      do
+		{
+		  wchar_t *runp;
+		  size_t n;
+
+		  if (inchar () == WEOF)
+		    break;
+
+		  /* Test whether it's in the scanlist.  */
+		  runp = tw;
+		  while (runp < wp)
+		    {
+		      if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
+			  && runp != tw
+			  && (unsigned int) runp[-1] <= (unsigned int) runp[1])
+			{
+			  /* Match against all characters in between the
+			     first and last character of the sequence.  */
+			  wchar_t wc;
+
+			  for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
+			    if (wc == c)
+			      break;
+
+			  if (wc == runp[1] && !not_in)
+			    break;
+			  if (wc == runp[1] && not_in)
+			    {
+			      /* The current character is not in the
+                                 scanset.  */
+			      ungetwc (c, s);
+			      goto out2;
+			    }
+			}
+		      else
+			{
+			  if (*runp == runp[1] && !not_in)
+			    break;
+			  if (*runp != runp[1] && not_in)
+			    {
+			      ungetwc (c ,s);
+			      goto out2;
+			    }
+			}
+
+		      ++runp;
+		    }
+
+		  if (!(flags & SUPPRESS))
+		    {
+		      if ((flags & MALLOC)
+			  && str + MB_CUR_MAX >= *strptr + strsize)
+			{
+			  /* Enlarge the buffer.  */
+			  str = (char *) realloc (*strptr, 2 * strsize);
+			  if (str == NULL)
+			    {
+			      /* Can't allocate that much.  Last-ditch
+				 effort.  */
+			      str = (char *) realloc (*strptr, strsize + 1);
+			      if (str == NULL)
+				{
+				  /* We lose.  Oh well.  Terminate the string
+				     and stop converting, so at least we don't
+				     skip any input.  */
+				  (*strptr)[strsize - 1] = '\0';
+				  ++done;
+				  conv_error ();
+				}
+			      else
+				{
+				  *strptr = str;
+				  str += strsize;
+				  ++strsize;
+				}
+			    }
+			  else
+			    {
+			      *strptr = str;
+			      str += strsize;
+			      strsize *= 2;
+			    }
+			}
+		    }
+
+		  n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
+		  if (n == (size_t) -1)
+		    encode_error ();
+
+		  assert (n <= MB_CUR_MAX);
+		  str += n;
+		}
+	      while (--width > 0);
+	    out2:
+#else
 	      do
 		{
+		  if (inchar () == EOF)
+		    break;
+
 		  if (wp[c] == not_in)
 		    {
 		      ungetc (c, s);
 		      break;
 		    }
-		  STRING_ADD_CHAR (str, c, char);
-		  if (width > 0)
-		    --width;
+
+		  /* This is easy.  */
+		  if (!(flags & SUPPRESS))
+		    {
+		      *str++ = c;
+		      if ((flags & MALLOC)
+			  && (char *) str == *strptr + strsize)
+			{
+			  /* Enlarge the buffer.  */
+			  str = (char *) realloc (*strptr, 2 * strsize);
+			  if (str == NULL)
+			    {
+			      /* Can't allocate that much.  Last-ditch
+				 effort.  */
+			      str = (char *) realloc (*strptr, strsize + 1);
+			      if (str == NULL)
+				{
+				  /* We lose.  Oh well.  Terminate the
+				     string and stop converting,
+				     so at least we don't skip any input.  */
+				  ((char *) (*strptr))[strsize - 1] = '\0';
+				  ++done;
+				  conv_error ();
+				}
+			      else
+				{
+				  *strptr = (char *) str;
+				  str += strsize;
+				  ++strsize;
+				}
+			    }
+			  else
+			    {
+			      *strptr = (char *) str;
+			      str += strsize;
+			      strsize *= 2;
+			    }
+			}
+		    }
 		}
-	      while (width != 0 && inchar () != EOF);
+	      while (--width > 0);
+#endif
 
-	      if (read_in == num.ul)
+	      if (now == read_in)
+		/* We haven't succesfully read any character.  */
 		conv_error ();
 
 	      if (!(flags & SUPPRESS))
 		{
+#ifdef COMPILE_WPRINTF
+		  /* We have to emit the code to get into the intial
+		     state.  */
+		  char buf[MB_LEN_MAX];
+		  size_t n = wcrtomb (buf, L'\0', &state);
+		  if (n > 0 && (flags & MALLOC)
+		      && str + n >= *strptr + strsize)
+		    {
+		      /* Enlarge the buffer.  */
+		      str = (char *) realloc (*strptr,
+					      (str + n + 1) - *strptr);
+		      if (str == NULL)
+			{
+			  /* We lose.  Oh well.  Terminate the string
+			     and stop converting, so at least we don't
+			     skip any input.  */
+			  ((char *) (*strptr))[strsize - 1] = '\0';
+			  ++done;
+			  conv_error ();
+			}
+		      else
+			{
+			  *strptr = (char *) str;
+			  str = ((char *) *strptr) + strsize;
+			  strsize = (str + n + 1) - *strptr;
+			}
+		    }
+
+		  str = __mempcpy (str, buf, n);
+#endif
 		  *str = '\0';
+
+		  if ((flags & MALLOC) && str - *strptr != strsize)
+		    {
+		      char *cp = (char *) realloc (*strptr, str - *strptr);
+		      if (cp != NULL)
+			*strptr = cp;
+		    }
+
 		  ++done;
 		}
 	    }
 	  break;
 
-	case 'p':	/* Generic pointer.  */
+	case L_('p'):	/* Generic pointer.  */
 	  base = 16;
 	  /* A PTR must be the same size as a `long int'.  */
 	  flags &= ~(SHORT|LONGDBL);
@@ -1305,11 +1960,23 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 }
 
 #ifdef USE_IN_LIBIO
+# ifdef COMPILE_WPRINTF
+int
+__vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
+{
+  return _IO_vfwscanf (s, format, argptr, NULL);
+}
+# else
 int
 __vfscanf (FILE *s, const char *format, va_list argptr)
 {
   return _IO_vfscanf (s, format, argptr, NULL);
 }
+# endif
 #endif
 
+#ifdef COMPILE_WPRINTF
+weak_alias (__vfwscanf, vfwscanf)
+#else
 weak_alias (__vfscanf, vfscanf)
+#endif
diff --git a/stdio-common/vfwprintf.c b/stdio-common/vfwprintf.c
new file mode 100644
index 0000000000..2c3cd06fad
--- /dev/null
+++ b/stdio-common/vfwprintf.c
@@ -0,0 +1,3 @@
+#include <wctype.h>
+#define COMPILE_WPRINTF	1
+#include "vfprintf.c"
diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf.c
new file mode 100644
index 0000000000..62220bdccc
--- /dev/null
+++ b/stdio-common/vfwscanf.c
@@ -0,0 +1,2 @@
+#define COMPILE_WPRINTF	1
+#include "vfscanf.c"
diff --git a/stdlib/mblen.c b/stdlib/mblen.c
index 9d8d0ccc5a..3a9755bcea 100644
--- a/stdlib/mblen.c
+++ b/stdlib/mblen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 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
@@ -40,7 +40,7 @@ mblen (const char *s, size_t n)
       /* Make sure we use the correct value.  */
       update_conversion_ptrs ();
 
-      result = __wcsmbs_gconv_fcts.towc->stateful;
+      result = __wcsmbs_gconv_fcts.towc->__stateful;
     }
   else if (*s == '\0')
     /* According to the ISO C 89 standard this is the expected behaviour.
diff --git a/stdlib/mbtowc.c b/stdlib/mbtowc.c
index 938d54750c..a8df154b75 100644
--- a/stdlib/mbtowc.c
+++ b/stdlib/mbtowc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 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
@@ -46,7 +46,7 @@ mbtowc (wchar_t *pwc, const char *s, size_t n)
       /* Make sure we use the correct value.  */
       update_conversion_ptrs ();
 
-      result = __wcsmbs_gconv_fcts.towc->stateful;
+      result = __wcsmbs_gconv_fcts.towc->__stateful;
     }
   else if (*s == '\0')
     {
diff --git a/stdlib/strfmon.c b/stdlib/strfmon.c
index 187e33fe37..7041994eca 100644
--- a/stdlib/strfmon.c
+++ b/stdlib/strfmon.c
@@ -1,5 +1,5 @@
 /* Formatting a monetary value according to the current locale.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>
    and Jochen Hein <Jochen.Hein@informatik.TU-Clausthal.de>, 1996.
@@ -454,6 +454,7 @@ __strfmon_l (char *s, size_t maxsize, __locale_t loc, const char *format, ...)
       info.group = group;
       info.pad = pad;
       info.extra = 1;		/* This means use values from LC_MONETARY.  */
+      info.wide = 0;
 
       ptr = &fpnum;
       done = __printf_fp ((FILE *) &f, &info, &ptr);
diff --git a/stdlib/wctomb.c b/stdlib/wctomb.c
index b7132e02c4..2df8b998d5 100644
--- a/stdlib/wctomb.c
+++ b/stdlib/wctomb.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 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
@@ -42,7 +42,7 @@ wctomb (char *s, wchar_t wchar)
       /* Make sure we use the correct value.  */
       update_conversion_ptrs ();
 
-      return __wcsmbs_gconv_fcts.tomb->stateful;
+      return __wcsmbs_gconv_fcts.tomb->__stateful;
     }
 
   return __wcrtomb (s, wchar, &__no_r_state);
diff --git a/sysdeps/generic/_G_config.h b/sysdeps/generic/_G_config.h
index d63b0d71a6..04bc4ed644 100644
--- a/sysdeps/generic/_G_config.h
+++ b/sysdeps/generic/_G_config.h
@@ -21,8 +21,16 @@
 typedef unsigned int wint_t;
 #endif
 #define _G_size_t	size_t
-#define _G_fpos_t	__off_t
-#define _G_fpos64_t	__off_t
+typedef struct
+{
+  __off_t __pos;
+  __mbstate_t __state;
+} _G_fpos_t;
+typedef struct
+{
+  __off64_t __pos;
+  __mbstate_t __state;
+} _G_fpos64_t;
 #define _G_ssize_t	__ssize_t
 #define _G_off_t	__off_t
 #define _G_off64_t	__off_t
@@ -31,6 +39,12 @@ typedef unsigned int wint_t;
 #define _G_wchar_t	wchar_t
 #define _G_wint_t	wint_t
 #define _G_stat64	stat
+#include <gconv.h>
+typedef struct
+{
+  __gconv_t __cd;
+  struct __gconv_step_data __data;
+} _G_iconv_t;
 
 typedef int _G_int16_t __attribute__ ((__mode__ (__HI__)));
 typedef int _G_int32_t __attribute__ ((__mode__ (__SI__)));
diff --git a/sysdeps/generic/printf_fphex.c b/sysdeps/generic/printf_fphex.c
index b30622080c..9e9fd07dfc 100644
--- a/sysdeps/generic/printf_fphex.c
+++ b/sysdeps/generic/printf_fphex.c
@@ -38,11 +38,12 @@
 #ifdef USE_IN_LIBIO
 # include <libioP.h>
 # define PUT(f, s, n) _IO_sputn (f, s, n)
-# define PAD(f, c, n) _IO_padn (f, c, n)
+# define PAD(f, c, n) (wide  ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
 /* We use this file GNU C library and GNU I/O library.	So make
    names equal.	 */
 # undef putc
-# define putc(c, f) _IO_putc_unlocked (c, f)
+# define putc(c, f) (wide \
+		     ? _IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
 # define size_t     _IO_size_t
 # define FILE	     _IO_FILE
 #else	/* ! USE_IN_LIBIO */
@@ -132,6 +133,9 @@ __printf_fphex (FILE *fp,
   /* Number of characters written.  */
   int done = 0;
 
+  /* Nonzero if this is output on a wide character stream.  */
+  int wide = info->wide;
+
 
   /* Figure out the decimal point character.  */
   if (info->extra == 0)
diff --git a/sysdeps/unix/sysv/linux/_G_config.h b/sysdeps/unix/sysv/linux/_G_config.h
index e829a73106..edd29ea3f6 100644
--- a/sysdeps/unix/sysv/linux/_G_config.h
+++ b/sysdeps/unix/sysv/linux/_G_config.h
@@ -20,9 +20,19 @@
 # define _WINT_T
 typedef unsigned int wint_t;
 #endif
+#define __need_mbstate_t
+#include <wchar.h>
 #define _G_size_t	size_t
-#define _G_fpos_t	__off_t
-#define _G_fpos64_t	__off64_t
+typedef struct
+{
+  __off_t __pos;
+  __mbstate_t __state;
+} _G_fpos_t;
+typedef struct
+{
+  __off64_t __pos;
+  __mbstate_t __state;
+} _G_fpos64_t;
 #define _G_ssize_t	__ssize_t
 #define _G_off_t	__off_t
 #define _G_off64_t	__off64_t
@@ -31,6 +41,16 @@ typedef unsigned int wint_t;
 #define _G_wchar_t	wchar_t
 #define _G_wint_t	wint_t
 #define _G_stat64	stat64
+#include <gconv.h>
+typedef union
+{
+  struct __gconv_info __cd;
+  struct
+  {
+    struct __gconv_info __cd;
+    struct __gconv_step_data __data;
+  } __combined;
+} _G_iconv_t;
 
 typedef int _G_int16_t __attribute__ ((__mode__ (__HI__)));
 typedef int _G_int32_t __attribute__ ((__mode__ (__SI__)));
diff --git a/time/Makefile b/time/Makefile
index 08b783fa30..c0cbb91a1d 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -28,9 +28,9 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    gettimeofday settimeofday adjtime tzset	 \
 	    tzfile getitimer setitimer			 \
 	    stime dysize timegm ftime			 \
-	    strptime getdate
+	    strptime getdate wcsftime
 
-tests	:= test_time clocktest tst-posixtz tst-strptime
+tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime
 
 include ../Rules
 
diff --git a/time/Versions b/time/Versions
index e117a4acd4..ed6429edec 100644
--- a/time/Versions
+++ b/time/Versions
@@ -46,4 +46,8 @@ libc {
     # g*
     getdate; getdate_r; getitimer;
   }
+  GLIBC_2.2 {
+    # w*
+    wcsftime;
+  }
 }
diff --git a/time/strftime.c b/time/strftime.c
index bb19babc34..60c8123afa 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,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
@@ -83,22 +83,41 @@ extern char *tzname[];
 # include <stddef.h>
 # include <stdlib.h>
 # include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-#  define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
 #endif
 
-#ifdef _LIBC
-# define MEMPCPY(d, s, n) __mempcpy (d, s, n)
+#ifdef COMPILE_WIDE
+# define CHAR_T wchar_t
+# define UCHAR_T unsigned int
+# define L_(Str) L##Str
+# define NLW(Sym) _NL_W##Sym
+
+# define MEMCPY(d, s, n) wmemcpy (d, s, n)
+# define STRLEN(s) wcslen (s)
+
 #else
-# ifndef HAVE_MEMPCPY
-#  define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define L_(Str) Str
+# define NLW(Sym) Sym
+
+# if !defined STDC_HEADERS && !defined HAVE_MEMCPY
+#  define MEMCPY(d, s, n) bcopy ((s), (d), (n))
+# else
+#  define MEMCPY(d, s, n) memcpy ((d), (s), (n))
+# endif
+# define STRLEN(s) strlen (s)
+
+# ifdef _LIBC
+#  define MEMPCPY(d, s, n) __mempcpy (d, s, n)
+# else
+#  ifndef HAVE_MEMPCPY
+#   define MEMPCPY(d, s, n) ((void *) ((char *) memcpy (d, s, n) + (n)))
+#  endif
 # endif
 #endif
 
 #ifndef __P
-# if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
 #  define __P(args) args
 # else
 #  define __P(args) ()
@@ -187,10 +206,16 @@ my_strftime_localtime_r (t, tp)
    introduce additional dependencies.  */
 /* The SGI compiler reportedly barfs on the trailing null
    if we use a string constant as the initializer.  28 June 1997, rms.  */
-static const char spaces[16] = /* "                " */
-  { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
-static const char zeroes[16] = /* "0000000000000000" */
-  { '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0' };
+static const CHAR_T spaces[16] = /* "                " */
+{
+  L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),
+  L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' '),L_(' ')
+};
+static const CHAR_T zeroes[16] = /* "0000000000000000" */
+{
+  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')
+};
 
 # define memset_space(P, Len) \
   do {									      \
@@ -199,7 +224,7 @@ static const char zeroes[16] = /* "0000000000000000" */
     do									      \
       {									      \
 	int _this = _len > 16 ? 16 : _len;				      \
-	(P) = MEMPCPY ((P), spaces, _this);				      \
+	(P) = MEMPCPY ((P), spaces, _this * sizeof (CHAR_T));		      \
 	_len -= _this;							      \
       }									      \
     while (_len > 0);							      \
@@ -212,14 +237,19 @@ static const char zeroes[16] = /* "0000000000000000" */
     do									      \
       {									      \
 	int _this = _len > 16 ? 16 : _len;				      \
-	(P) = MEMPCPY ((P), zeroes, _this);				      \
+	(P) = MEMPCPY ((P), zeroes, _this * sizeof (CHAR_T));		      \
 	_len -= _this;							      \
       }									      \
     while (_len > 0);							      \
   } while (0)
 #else
-# define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
-# define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
+# ifdef COMPILE_WIDE
+#  define memset_space(P, Len) (wmemset ((P), L' ', (Len)), (P) += (Len))
+#  define memset_zero(P, Len) (wmemset ((P), L'0', (Len)), (P) += (Len))
+# else
+#  define memset_space(P, Len) (memset ((P), ' ', (Len)), (P) += (Len))
+#  define memset_zero(P, Len) (memset ((P), '0', (Len)), (P) += (Len))
+# endif
 #endif
 
 #define add(n, f)							      \
@@ -234,7 +264,7 @@ static const char zeroes[16] = /* "0000000000000000" */
 	{								      \
 	  if (_delta > 0)						      \
 	    {								      \
-	      if (pad == '0')						      \
+	      if (pad == L_('0'))					      \
 		memset_zero (p, _delta);				      \
 	      else							      \
 		memset_space (p, _delta);				      \
@@ -252,46 +282,64 @@ static const char zeroes[16] = /* "0000000000000000" */
 	 else if (to_uppcase)						      \
 	   memcpy_uppcase (p, (s), _n);					      \
 	 else								      \
-	   memcpy ((PTR) p, (PTR) (s), _n))
-
+	   MEMCPY ((PTR) p, (PTR) (s), _n))
+
+#ifdef COMPILE_WIDE
+# define widen(os, ws, l) \
+  {									      \
+    mbstate_t __st;							      \
+    const char *__s = os;						      \
+    memset (&__st, '\0', sizeof (__st));				      \
+    l = __mbsrtowcs (NULL, &__s, 0, &__st);				      \
+    ws = alloca ((l + 1) * sizeof (wchar_t));				      \
+    (void) __mbsrtowcs (ws, &__s, l, &__st);				      \
+  }
+#endif
 
 
-#ifdef _LIBC
-# define TOUPPER(Ch) toupper (Ch)
-# define TOLOWER(Ch) tolower (Ch)
+#ifdef COMPILE_WIDE
+# define TOUPPER(Ch) towupper (Ch)
+# define TOLOWER(Ch) towlower (Ch)
 #else
-# define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
-# define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+# ifdef _LIBC
+#  define TOUPPER(Ch) toupper (Ch)
+#  define TOLOWER(Ch) tolower (Ch)
+# else
+#  define TOUPPER(Ch) (islower (Ch) ? toupper (Ch) : (Ch))
+#  define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+# endif
 #endif
 /* We don't use `isdigit' here since the locale dependent
    interpretation is not what we want here.  We only need to accept
    the arabic digits in the ASCII range.  One day there is perhaps a
    more reliable way to accept other sets of digits.  */
-#define ISDIGIT(Ch) ((unsigned int) (Ch) - '0' <= 9)
+#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9)
 
-static char *memcpy_lowcase __P ((char *dest, const char *src, size_t len));
+static CHAR_T *memcpy_lowcase __P ((CHAR_T *dest, const CHAR_T *src,
+				    size_t len));
 
-static char *
+static CHAR_T *
 memcpy_lowcase (dest, src, len)
-     char *dest;
-     const char *src;
+     CHAR_T *dest;
+     const CHAR_T *src;
      size_t len;
 {
   while (len-- > 0)
-    dest[len] = TOLOWER ((unsigned char) src[len]);
+    dest[len] = TOLOWER ((UCHAR_T) src[len]);
   return dest;
 }
 
-static char *memcpy_uppcase __P ((char *dest, const char *src, size_t len));
+static CHAR_T *memcpy_uppcase __P ((CHAR_T *dest, const CHAR_T *src,
+				    size_t len));
 
-static char *
+static CHAR_T *
 memcpy_uppcase (dest, src, len)
-     char *dest;
-     const char *src;
+     CHAR_T *dest;
+     const CHAR_T *src;
      size_t len;
 {
   while (len-- > 0)
-    dest[len] = TOUPPER ((unsigned char) src[len]);
+    dest[len] = TOUPPER ((UCHAR_T) src[len]);
   return dest;
 }
 
@@ -352,15 +400,16 @@ iso_week_days (yday, wday)
 
 
 #if !(defined _NL_CURRENT || HAVE_STRFTIME)
-static char const weekday_name[][10] =
+static CHAR_T const weekday_name[][10] =
   {
-    "Sunday", "Monday", "Tuesday", "Wednesday",
-    "Thursday", "Friday", "Saturday"
+    L_("Sunday"), L_("Monday"), L_("Tuesday"), L_("Wednesday"),
+    L_("Thursday"), L_("Friday"), L_("Saturday")
   };
-static char const month_name[][10] =
+static CHAR_T const month_name[][10] =
   {
-    "January", "February", "March", "April", "May", "June",
-    "July", "August", "September", "October", "November", "December"
+    L_("January"), L_("February"), L_("March"), L_("April"), L_("May"),
+    L_("June"), L_("July"), L_("August"), L_("September"), L_("October"),
+    L_("November"), L_("December")
   };
 #endif
 
@@ -371,7 +420,11 @@ static char const month_name[][10] =
 # define ut_argument_spec int ut;
 # define ut_argument_spec_iso , int ut
 #else
-# define my_strftime strftime
+# ifdef COMPILE_WIDE
+#  define my_strftime wcsftime
+# else
+#  define my_strftime strftime
+# endif
 # define ut_argument
 # define ut_argument_spec
 # define ut_argument_spec_iso
@@ -386,9 +439,9 @@ static char const month_name[][10] =
 			        const struct tm * ut_argument_spec_iso));
   size_t
   my_strftime (s, maxsize, format, tp ut_argument)
-      char *s;
+      CHAR_T *s;
       size_t maxsize;
-      const char *format;
+      const CHAR_T *format;
       const struct tm *tp;
       ut_argument_spec
   {
@@ -410,9 +463,9 @@ static char const month_name[][10] =
    written, use NULL for S and (size_t) UINT_MAX for MAXSIZE.  */
 size_t
 my_strftime (s, maxsize, format, tp ut_argument)
-      char *s;
+      CHAR_T *s;
       size_t maxsize;
-      const char *format;
+      const CHAR_T *format;
       const struct tm *tp;
       ut_argument_spec
 {
@@ -424,22 +477,28 @@ my_strftime (s, maxsize, format, tp ut_argument)
      might be generated by a strptime() call that initialized
      only a few elements.  Dereference the pointers only if the format
      requires this.  Then it is ok to fail if the pointers are invalid.  */
-# define a_wkday _NL_CURRENT (LC_TIME, ABDAY_1 + tp->tm_wday)
-# define f_wkday _NL_CURRENT (LC_TIME, DAY_1 + tp->tm_wday)
-# define a_month _NL_CURRENT (LC_TIME, ABMON_1 + tp->tm_mon)
-# define f_month _NL_CURRENT (LC_TIME, MON_1 + tp->tm_mon)
-# define ampm _NL_CURRENT (LC_TIME, tp->tm_hour > 11 ? PM_STR : AM_STR)
-
-# define aw_len strlen (a_wkday)
-# define am_len strlen (a_month)
-# define ap_len strlen (ampm)
+# define a_wkday \
+  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
+# define f_wkday \
+  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
+# define a_month \
+  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
+# define f_month \
+  ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
+# define ampm \
+  ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11		      \
+				 ? NLW(PM_STR) : NLW(AM_STR)))
+
+# define aw_len STRLEN (a_wkday)
+# define am_len STRLEN (a_month)
+# define ap_len STRLEN (ampm)
 #else
 # if !HAVE_STRFTIME
 # define f_wkday (weekday_name[tp->tm_wday])
 # define f_month (month_name[tp->tm_mon])
 # define a_wkday f_wkday
 # define a_month f_month
-# define ampm ("AMPM" + 2 * (tp->tm_hour > 11))
+# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
 
   size_t aw_len = 3;
   size_t am_len = 3;
@@ -448,8 +507,8 @@ my_strftime (s, maxsize, format, tp ut_argument)
 #endif
   const char *zone;
   size_t i = 0;
-  char *p = s;
-  const char *f;
+  CHAR_T *p = s;
+  const CHAR_T *f;
 
   zone = NULL;
 #if HAVE_TM_ZONE
@@ -491,42 +550,44 @@ my_strftime (s, maxsize, format, tp ut_argument)
       int digits;		/* Max digits for numeric format.  */
       int number_value; 	/* Numeric value to be printed.  */
       int negative_number;	/* 1 if the number is negative.  */
-      const char *subfmt;
-      char *bufp;
-      char buf[1 + (sizeof (int) < sizeof (time_t)
-		    ? INT_STRLEN_BOUND (time_t)
-		    : INT_STRLEN_BOUND (int))];
+      const CHAR_T *subfmt;
+      CHAR_T *bufp;
+      CHAR_T buf[1 + (sizeof (int) < sizeof (time_t)
+		      ? INT_STRLEN_BOUND (time_t)
+		      : INT_STRLEN_BOUND (int))];
       int width = -1;
       int to_lowcase = 0;
       int to_uppcase = 0;
       int change_case = 0;
       int format_char;
 
-#if DO_MULTIBYTE
-
-       switch (*f)
+#if DO_MULTIBYTE && !defined COMPILE_WIDE
+      switch (*f)
 	{
-	case '%':
+	case L_('%'):
 	  break;
 
-	case '\a': case '\b': case '\t': case '\n':
-	case '\v': case '\f': case '\r':
-	case ' ': case '!': case '"': case '#': case '&': case'\'':
-	case '(': case ')': case '*': case '+': case ',': case '-':
-	case '.': case '/': case '0': case '1': case '2': case '3':
-	case '4': case '5': case '6': case '7': case '8': case '9':
-	case ':': case ';': case '<': case '=': case '>': case '?':
-	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
-	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
-	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-	case 'Y': case 'Z': case '[': case'\\': case ']': case '^':
-	case '_': case 'a': case 'b': case 'c': case 'd': case 'e':
-	case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
-	case 'l': case 'm': case 'n': case 'o': case 'p': case 'q':
-	case 'r': case 's': case 't': case 'u': case 'v': case 'w':
-	case 'x': case 'y': case 'z': case '{': case '|': case '}':
-	case '~':
+	case L_('\a'): case L_('\b'): case L_('\t'): case L_('\n'):
+	case L_('\v'): case L_('\f'): case L_('\r'):
+	case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'):
+	case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'):
+	case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'):
+	case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'):
+	case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'):
+	case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'):
+	case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'):
+	case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'):
+	case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'):
+	case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'):
+	case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'):
+	case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'):
+	case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'):
+	case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
+	case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
+	case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
+	case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
+	case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
+	case L_('~'):
 	  /* The C Standard requires these 98 characters (plus '%') to
 	     be in the basic execution character set.  None of these
 	     characters can start a multibyte sequence, so they need
@@ -572,9 +633,10 @@ my_strftime (s, maxsize, format, tp ut_argument)
 
 #else /* ! DO_MULTIBYTE */
 
-      /* Either multibyte encodings are not supported, or they are
-	 safe for formats, so any non-'%' byte can be copied through.  */
-      if (*f != '%')
+      /* Either multibyte encodings are not supported, they are
+	 safe for formats, so any non-'%' byte can be copied through,
+	 or this is the wide character version.  */
+      if (*f != L_('%'))
 	{
 	  add (1, *p = *f);
 	  continue;
@@ -588,17 +650,17 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  switch (*++f)
 	    {
 	      /* This influences the number formats.  */
-	    case '_':
-	    case '-':
-	    case '0':
+	    case L_('_'):
+	    case L_('-'):
+	    case L_('0'):
 	      pad = *f;
 	      continue;
 
 	      /* This changes textual output.  */
-	    case '^':
+	    case L_('^'):
 	      to_uppcase = 1;
 	      continue;
-	    case '#':
+	    case L_('#'):
 	      change_case = 1;
 	      continue;
 
@@ -615,7 +677,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  do
 	    {
 	      width *= 10;
-	      width += *f - '0';
+	      width += *f - L_('0');
 	      ++f;
 	    }
 	  while (ISDIGIT (*f));
@@ -624,8 +686,8 @@ my_strftime (s, maxsize, format, tp ut_argument)
       /* Check for modifiers.  */
       switch (*f)
 	{
-	case 'E':
-	case 'O':
+	case L_('E'):
+	case L_('O'):
 	  modifier = *f++;
 	  break;
 
@@ -645,13 +707,13 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  digits = width == -1 ? d : width;				      \
 	  number_value = v; goto do_number_spacepad
 
-	case '%':
+	case L_('%'):
 	  if (modifier != 0)
 	    goto bad_format;
 	  add (1, *p = *f);
 	  break;
 
-	case 'a':
+	case L_('a'):
 	  if (modifier != 0)
 	    goto bad_format;
 	  if (change_case)
@@ -675,14 +737,14 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	      to_lowcase = 0;
 	    }
 #if defined _NL_CURRENT || !HAVE_STRFTIME
-	  cpy (strlen (f_wkday), f_wkday);
+	  cpy (STRLEN (f_wkday), f_wkday);
 	  break;
 #else
 	  goto underlying_strftime;
 #endif
 
-	case 'b':
-	case 'h':		/* POSIX.2 extension.  */
+	case L_('b'):
+	case L_('h'):		/* POSIX.2 extension.  */
 	  if (modifier != 0)
 	    goto bad_format;
 #if defined _NL_CURRENT || !HAVE_STRFTIME
@@ -692,7 +754,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  goto underlying_strftime;
 #endif
 
-	case 'B':
+	case L_('B'):
 	  if (modifier != 0)
 	    goto bad_format;
 	  if (change_case)
@@ -701,37 +763,39 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	      to_lowcase = 0;
 	    }
 #if defined _NL_CURRENT || !HAVE_STRFTIME
-	  cpy (strlen (f_month), f_month);
+	  cpy (STRLEN (f_month), f_month);
 	  break;
 #else
 	  goto underlying_strftime;
 #endif
 
-	case 'c':
-	  if (modifier == 'O')
+	case L_('c'):
+	  if (modifier == L_('O'))
 	    goto bad_format;
 #ifdef _NL_CURRENT
 	  if (! (modifier == 'E'
-		 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT)) != '\0'))
-	    subfmt = _NL_CURRENT (LC_TIME, D_T_FMT);
+		 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
+							NLW(ERA_D_T_FMT)))
+		     != '\0')))
+	    subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT));
 #else
 # if HAVE_STRFTIME
 	  goto underlying_strftime;
 # else
-	  subfmt = "%a %b %e %H:%M:%S %Y";
+	  subfmt = L_("%a %b %e %H:%M:%S %Y");
 # endif
 #endif
 
 	subformat:
 	  {
-	    char *old_start = p;
+	    CHAR_T *old_start = p;
 	    size_t len = my_strftime (NULL, (size_t) -1, subfmt, tp);
 	    add (len, my_strftime (p, maxsize - i, subfmt, tp));
 
 	    if (to_uppcase)
 	      while (old_start < p)
 		{
-		  *old_start = TOUPPER ((unsigned char) *old_start);
+		  *old_start = TOUPPER ((UCHAR_T) *old_start);
 		  ++old_start;
 		}
 	  }
@@ -759,17 +823,26 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  break;
 #endif
 
-	case 'C':		/* POSIX.2 extension.  */
-	  if (modifier == 'O')
+	case L_('C'):		/* POSIX.2 extension.  */
+	  if (modifier == L_('O'))
 	    goto bad_format;
-	  if (modifier == 'E')
+	  if (modifier == L_('E'))
 	    {
 #if HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp);
 	      if (era)
 		{
+# ifdef COMPILE_WIDE
+		  /* XXX For the time being there is no equivalent to
+		     _nl_get_era_entry to get a wide character variant.  */
+		  wchar_t *ws;
+		  size_t len;
+		  widen (era->name_fmt, ws, len);
+		  cpy (len, ws);
+# else
 		  size_t len = strlen (era->name_fmt);
 		  cpy (len, era->name_fmt);
+# endif
 		  break;
 		}
 #else
@@ -784,13 +857,15 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	    DO_NUMBER (1, year / 100 - (year % 100 < 0));
 	  }
 
-	case 'x':
-	  if (modifier == 'O')
+	case L_('x'):
+	  if (modifier == L_('O'))
 	    goto bad_format;
 #ifdef _NL_CURRENT
-	  if (! (modifier == 'E'
-		 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_D_FMT)) != '\0'))
-	    subfmt = _NL_CURRENT (LC_TIME, D_FMT);
+	  if (! (modifier == L_('E')
+		 && (*(subfmt = (CHAR_T *)_NL_CURRENT (LC_TIME,
+						       NLW(ERA_D_FMT)))
+		     != L_('\0'))))
+	    subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT));
 	  goto subformat;
 #else
 # if HAVE_STRFTIME
@@ -799,20 +874,20 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  /* Fall through.  */
 # endif
 #endif
-	case 'D':		/* POSIX.2 extension.  */
+	case L_('D'):		/* POSIX.2 extension.  */
 	  if (modifier != 0)
 	    goto bad_format;
-	  subfmt = "%m/%d/%y";
+	  subfmt = L_("%m/%d/%y");
 	  goto subformat;
 
-	case 'd':
-	  if (modifier == 'E')
+	case L_('d'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, tp->tm_mday);
 
-	case 'e':		/* POSIX.2 extension.  */
-	  if (modifier == 'E')
+	case L_('e'):		/* POSIX.2 extension.  */
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER_SPACEPAD (2, tp->tm_mday);
@@ -822,22 +897,32 @@ my_strftime (s, maxsize, format, tp ut_argument)
 
 	do_number_spacepad:
 	  /* Force `_' flag unless overwritten by `0' flag.  */
-	  if (pad != '0')
-	    pad = '_';
+	  if (pad != L_('0'))
+	    pad = L_('_');
 
 	do_number:
 	  /* Format the number according to the MODIFIER flag.  */
 
-	  if (modifier == 'O' && 0 <= number_value)
+	  if (modifier == L_('O') && 0 <= number_value)
 	    {
 #ifdef _NL_CURRENT
 	      /* Get the locale specific alternate representation of
 		 the number NUMBER_VALUE.  If none exist NULL is returned.  */
+# ifdef COMPILE_WIDE
+	      const char *ncp = _nl_get_alt_digit (number_value);
+	      wchar_t *cp = NULL;
+	      if (ncp != NULL)
+		{
+		  size_t len;
+		  widen (ncp, cp, len);
+		}
+# else
 	      const char *cp = _nl_get_alt_digit (number_value);
+# endif
 
 	      if (cp != NULL)
 		{
-		  size_t digitlen = strlen (cp);
+		  size_t digitlen = STRLEN (cp);
 		  if (digitlen != 0)
 		    {
 		      cpy (digitlen, cp);
@@ -853,103 +938,104 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  {
 	    unsigned int u = number_value;
 
-	    bufp = buf + sizeof (buf);
+	    bufp = buf + sizeof (buf) / sizeof (buf[0]);
 	    negative_number = number_value < 0;
 
 	    if (negative_number)
 	      u = -u;
 
 	    do
-	      *--bufp = u % 10 + '0';
+	      *--bufp = u % 10 + L_('0');
 	    while ((u /= 10) != 0);
   	  }
 
 	do_number_sign_and_padding:
 	  if (negative_number)
-	    *--bufp = '-';
+	    *--bufp = L_('-');
 
-	  if (pad != '-')
+	  if (pad != L_('-'))
 	    {
-	      int padding = digits - (buf + sizeof (buf) - bufp);
+	      int padding = digits - (buf + (sizeof (buf) / sizeof (buf[0]))
+				      - bufp);
 
-	      if (pad == '_')
+	      if (pad == L_('_'))
 		{
 		  while (0 < padding--)
-		    *--bufp = ' ';
+		    *--bufp = L_(' ');
 		}
 	      else
 		{
 		  bufp += negative_number;
 		  while (0 < padding--)
-		    *--bufp = '0';
+		    *--bufp = L_('0');
 		  if (negative_number)
-		    *--bufp = '-';
+		    *--bufp = L_('-');
 		}
 	    }
 
-	  cpy (buf + sizeof (buf) - bufp, bufp);
+	  cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
 	  break;
 
-	case 'F':
+	case L_('F'):
 	  if (modifier != 0)
 	    goto bad_format;
-	  subfmt = "%Y-%m-%d";
+	  subfmt = L_("%Y-%m-%d");
 	  goto subformat;
 
-	case 'H':
-	  if (modifier == 'E')
+	case L_('H'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, tp->tm_hour);
 
-	case 'I':
-	  if (modifier == 'E')
+	case L_('I'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, hour12);
 
-	case 'k':		/* GNU extension.  */
-	  if (modifier == 'E')
+	case L_('k'):		/* GNU extension.  */
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER_SPACEPAD (2, tp->tm_hour);
 
-	case 'l':		/* GNU extension.  */
-	  if (modifier == 'E')
+	case L_('l'):		/* GNU extension.  */
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER_SPACEPAD (2, hour12);
 
-	case 'j':
-	  if (modifier == 'E')
+	case L_('j'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (3, 1 + tp->tm_yday);
 
-	case 'M':
-	  if (modifier == 'E')
+	case L_('M'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, tp->tm_min);
 
-	case 'm':
-	  if (modifier == 'E')
+	case L_('m'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, tp->tm_mon + 1);
 
-	case 'n':		/* POSIX.2 extension.  */
-	  add (1, *p = '\n');
+	case L_('n'):		/* POSIX.2 extension.  */
+	  add (1, *p = L_('\n'));
 	  break;
 
-	case 'P':
+	case L_('P'):
 	  to_lowcase = 1;
 #if !defined _NL_CURRENT && HAVE_STRFTIME
-	  format_char = 'p';
+	  format_char = L_('p');
 #endif
 	  /* FALLTHROUGH */
 
-	case 'p':
+	case L_('p'):
 	  if (change_case)
 	    {
 	      to_uppcase = 0;
@@ -962,24 +1048,25 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  goto underlying_strftime;
 #endif
 
-	case 'R':		/* GNU extension.  */
-	  subfmt = "%H:%M";
+	case L_('R'):		/* GNU extension.  */
+	  subfmt = L_("%H:%M");
 	  goto subformat;
 
-	case 'r':		/* POSIX.2 extension.  */
+	case L_('r'):		/* POSIX.2 extension.  */
 #ifdef _NL_CURRENT
-	  if (*(subfmt = _NL_CURRENT (LC_TIME, T_FMT_AMPM)) == '\0')
+	  if (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
+						 NLW(T_FMT_AMPM))) == L_('\0'))
 #endif
-	    subfmt = "%I:%M:%S %p";
+	    subfmt = L_("%I:%M:%S %p");
 	  goto subformat;
 
-	case 'S':
-	  if (modifier == 'E')
+	case L_('S'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, tp->tm_sec);
 
-	case 's':		/* GNU extension.  */
+	case L_('s'):		/* GNU extension.  */
   	  {
 	    struct tm ltm;
 	    time_t t;
@@ -990,7 +1077,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	    /* Generate string value for T using time_t arithmetic;
 	       this works even if sizeof (long) < sizeof (time_t).  */
 
-	    bufp = buf + sizeof (buf);
+	    bufp = buf + sizeof (buf) / sizeof (buf[0]);
 	    negative_number = t < 0;
 
 	    do
@@ -1010,7 +1097,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 		      }
 		  }
 
-		*--bufp = d + '0';
+		*--bufp = d + L_('0');
 	      }
 	    while (t != 0);
 
@@ -1018,13 +1105,15 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	    goto do_number_sign_and_padding;
 	  }
 
-	case 'X':
-	  if (modifier == 'O')
+	case L_('X'):
+	  if (modifier == L_('O'))
 	    goto bad_format;
 #ifdef _NL_CURRENT
-	  if (! (modifier == 'E'
-		 && *(subfmt = _NL_CURRENT (LC_TIME, ERA_T_FMT)) != '\0'))
-	    subfmt = _NL_CURRENT (LC_TIME, T_FMT);
+	  if (! (modifier == L_('E')
+		 && (*(subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME,
+							NLW(ERA_T_FMT)))
+		     != L_('\0'))))
+	    subfmt = (CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT));
 	  goto subformat;
 #else
 # if HAVE_STRFTIME
@@ -1033,27 +1122,27 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  /* Fall through.  */
 # endif
 #endif
-	case 'T':		/* POSIX.2 extension.  */
-	  subfmt = "%H:%M:%S";
+	case L_('T'):		/* POSIX.2 extension.  */
+	  subfmt = L_("%H:%M:%S");
 	  goto subformat;
 
-	case 't':		/* POSIX.2 extension.  */
-	  add (1, *p = '\t');
+	case L_('t'):		/* POSIX.2 extension.  */
+	  add (1, *p = L_('\t'));
 	  break;
 
-	case 'u':		/* POSIX.2 extension.  */
+	case L_('u'):		/* POSIX.2 extension.  */
 	  DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1);
 
-	case 'U':
-	  if (modifier == 'E')
+	case L_('U'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7);
 
-	case 'V':
-	case 'g':		/* GNU extension.  */
-	case 'G':		/* GNU extension.  */
-	  if (modifier == 'E')
+	case L_('V'):
+	case L_('g'):		/* GNU extension.  */
+	case L_('G'):		/* GNU extension.  */
+	  if (modifier == L_('E'))
 	    goto bad_format;
 	  {
 	    int year = tp->tm_year + TM_YEAR_BASE;
@@ -1080,10 +1169,10 @@ my_strftime (s, maxsize, format, tp ut_argument)
 
 	    switch (*f)
 	      {
-	      case 'g':
+	      case L_('g'):
 		DO_NUMBER (2, (year % 100 + 100) % 100);
 
-	      case 'G':
+	      case L_('G'):
 		DO_NUMBER (1, year);
 
 	      default:
@@ -1091,26 +1180,36 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	      }
 	  }
 
-	case 'W':
-	  if (modifier == 'E')
+	case L_('W'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7);
 
-	case 'w':
-	  if (modifier == 'E')
+	case L_('w'):
+	  if (modifier == L_('E'))
 	    goto bad_format;
 
 	  DO_NUMBER (1, tp->tm_wday);
 
-	case 'Y':
+	case L_('Y'):
 	  if (modifier == 'E')
 	    {
 #if HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp);
 	      if (era)
 		{
+# ifdef COMPILE_WIDE
+		  /* XXX For the time being there is no wide character
+		     equivalent or _nl_get_era_entry.  */
+		  const char *ncp = strchr (era->name_fmt, '\0') + 1;
+		  size_t len;
+		  wchar_t *s;
+		  widen (ncp, s, len);
+		  subfmt = s;
+# else
 		  subfmt = strchr (era->name_fmt, '\0') + 1;
+# endif
 		  goto subformat;
 		}
 #else
@@ -1119,13 +1218,13 @@ my_strftime (s, maxsize, format, tp ut_argument)
 # endif
 #endif
 	    }
-	  if (modifier == 'O')
+	  if (modifier == L_('O'))
 	    goto bad_format;
 	  else
 	    DO_NUMBER (1, tp->tm_year + TM_YEAR_BASE);
 
-	case 'y':
-	  if (modifier == 'E')
+	case L_('y'):
+	  if (modifier == L_('E'))
 	    {
 #if HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp);
@@ -1143,7 +1242,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	    }
 	  DO_NUMBER (2, (tp->tm_year % 100 + 100) % 100);
 
-	case 'Z':
+	case L_('Z'):
 	  if (change_case)
 	    {
 	      to_uppcase = 0;
@@ -1158,10 +1257,21 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	  if (! zone)
 	    zone = "";		/* POSIX.2 requires the empty string here.  */
 
+#ifdef COMPILE_WIDE
+	  {
+	    /* The zone string is always given in multibyte form.  We have
+	       to transform it first.  */
+	    wchar_t *wczone;
+	    size_t len;
+	    widen (zone, wczone, len);
+	    cpy (len, wczone);
+	  }
+#else
 	  cpy (strlen (zone), zone);
+#endif
 	  break;
 
-	case 'z':		/* GNU extension.  */
+	case L_('z'):		/* GNU extension.  */
 	  if (tp->tm_isdst < 0)
 	    break;
 
@@ -1207,17 +1317,17 @@ my_strftime (s, maxsize, format, tp ut_argument)
 
 	    if (diff < 0)
 	      {
-		add (1, *p = '-');
+		add (1, *p = L_('-'));
 		diff = -diff;
 	      }
 	    else
-	      add (1, *p = '+');
+	      add (1, *p = L_('+'));
 
 	    diff /= 60;
 	    DO_NUMBER (4, (diff / 60) * 100 + diff % 60);
 	  }
 
-	case '\0':		/* GNU extension: % at end of format.  */
+	case L_('\0'):		/* GNU extension: % at end of format.  */
 	    --f;
 	    /* Fall through.  */
 	default:
@@ -1227,7 +1337,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 	bad_format:
 	  {
 	    int flen;
-	    for (flen = 1; f[1 - flen] != '%'; flen++)
+	    for (flen = 1; f[1 - flen] != L_('%'); flen++)
 	      continue;
 	    cpy (flen, &f[1 - flen]);
 	  }
@@ -1236,7 +1346,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
     }
 
   if (p && maxsize != 0)
-    *p = '\0';
+    *p = L_('\0');
   return i;
 }
 
diff --git a/time/tst_wcsftime.c b/time/tst_wcsftime.c
new file mode 100644
index 0000000000..3f6f0d9f77
--- /dev/null
+++ b/time/tst_wcsftime.c
@@ -0,0 +1,28 @@
+#include <time.h>
+#include <wchar.h>
+
+int
+main (int argc, char *argv[])
+{
+  wchar_t buf[200];
+  time_t t;
+  struct tm *tp;
+  int result = 0;
+  size_t n;
+
+  time (&t);
+  tp = gmtime (&t);
+
+  n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]),
+		L"%H:%M:%S  %Y-%m-%d\n", tp);
+  if (n != 21)
+    result = 1;
+
+  wprintf (L"It is now %ls", buf);
+
+  wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A\n", tp);
+
+  wprintf (L"The weekday is %ls", buf);
+
+  return result;
+}
diff --git a/time/wcsftime.c b/time/wcsftime.c
new file mode 100644
index 0000000000..17bb53ede6
--- /dev/null
+++ b/time/wcsftime.c
@@ -0,0 +1,4 @@
+#include <wctype.h>
+#include <wchar.h>
+#define COMPILE_WIDE	1
+#include "strftime.c"
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index fa5dbef0a6..f1dc651877 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1996, 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
@@ -26,10 +26,10 @@ distribute := wcwidth.h wcsmbsload.h
 
 routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
 	    wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
-	    wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy \
+	    wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \
 	    btowc wctob mbsinit \
 	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
-	    mbsnrtowcs wcsnrtombs wcsnlen \
+	    mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
 	    wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \
 	    wcstol_l wcstoul_l wcstoll_l wcstoull_l \
 	    wcstod_l wcstold_l wcstof_l \
diff --git a/wcsmbs/Versions b/wcsmbs/Versions
index 54195bad73..d0ba267756 100644
--- a/wcsmbs/Versions
+++ b/wcsmbs/Versions
@@ -20,4 +20,8 @@ libc {
     wcscasecmp; wcsncasecmp; wcsnlen; wcstoll;
     wcstoimax; wcstoumax; wcstoull; wcswcs; wmemrtombs; wmemrtowcs;
   }
+  GLIBC_2.2 {
+    # w*
+    wcschrnul; wmempcpy;
+  }
 }
diff --git a/wcsmbs/btowc.c b/wcsmbs/btowc.c
index 1c6332ee8c..bec0d48841 100644
--- a/wcsmbs/btowc.c
+++ b/wcsmbs/btowc.c
@@ -30,7 +30,7 @@ __btowc (c)
      int c;
 {
   wchar_t result;
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   unsigned char inbuf[1];
   const unsigned char *inptr = inbuf;
   size_t dummy;
@@ -42,12 +42,12 @@ __btowc (c)
     return WEOF;
 
   /* Tell where we want the result.  */
-  data.outbuf = (unsigned char *) &result;
-  data.outbufend = data.outbuf + sizeof (wchar_t);
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = &data.__state;
+  data.__outbuf = (unsigned char *) &result;
+  data.__outbufend = data.__outbuf + sizeof (wchar_t);
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = &data.__state;
 
   /* Make sure we start in the initial state.  */
   memset (&data.__state, '\0', sizeof (mbstate_t));
@@ -58,11 +58,11 @@ __btowc (c)
   /* Create the input string.  */
   inbuf[0] = c;
 
-  status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc, &data,
-					     &inptr, inptr + 1, &dummy, 0);
+  status = (*__wcsmbs_gconv_fcts.towc->__fct) (__wcsmbs_gconv_fcts.towc, &data,
+					       &inptr, inptr + 1, &dummy, 0);
   /* The conversion failed.  */
-  if (status != GCONV_OK && status != GCONV_FULL_OUTPUT
-      && status != GCONV_EMPTY_INPUT)
+  if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+      && status != __GCONV_EMPTY_INPUT)
     result = WEOF;
 
   return result;
diff --git a/wcsmbs/mbrtowc.c b/wcsmbs/mbrtowc.c
index 78ff2a22dd..a68b0f2f79 100644
--- a/wcsmbs/mbrtowc.c
+++ b/wcsmbs/mbrtowc.c
@@ -35,7 +35,7 @@ size_t
 __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
 {
   wchar_t buf[1];
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   int status;
   size_t result;
   size_t dummy;
@@ -43,18 +43,18 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
   char *outbuf = (char *) (pwc ?: buf);
 
   /* Tell where we want the result.  */
-  data.outbuf = outbuf;
-  data.outbufend = outbuf + sizeof (wchar_t);
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__outbuf = outbuf;
+  data.__outbufend = outbuf + sizeof (wchar_t);
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   /* A first special case is if S is NULL.  This means put PS in the
      initial state.  */
   if (s == NULL)
     {
-      data.outbuf = (char *) buf;
+      data.__outbuf = (char *) buf;
       s = "";
       n = 1;
     }
@@ -64,27 +64,27 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
 
   /* Do a normal conversion.  */
   inbuf = (const unsigned char *) s;
-  status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc,
-					     &data, &inbuf, inbuf + n,
-					     &dummy, 0);
+  status = (*__wcsmbs_gconv_fcts.towc->__fct) (__wcsmbs_gconv_fcts.towc,
+					       &data, &inbuf, inbuf + n,
+					       &dummy, 0);
 
   /* There must not be any problems with the conversion but illegal input
      characters.  The output buffer must be large enough, otherwise the
      definition of MB_CUR_MAX is not correct.  All the other possible
      errors also must not happen.  */
-  assert (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT
-	  || status == GCONV_FULL_OUTPUT);
+  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
 
-  if (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-      || status == GCONV_FULL_OUTPUT)
+  if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+      || status == __GCONV_FULL_OUTPUT)
     {
-      if (data.outbuf != (unsigned char *) outbuf
+      if (data.__outbuf != (unsigned char *) outbuf
 	  && *(wchar_t *) outbuf == L'\0')
 	{
 	  /* The converted character is the NUL character.  */
-	  assert (__mbsinit (data.statep));
+	  assert (__mbsinit (data.__statep));
 	  result = 0;
 	}
       else
@@ -92,7 +92,7 @@ __mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
     }
   else
     {
-      result = status == GCONV_INCOMPLETE_INPUT ? (size_t) -2 : (size_t) -1;
+      result = status == __GCONV_INCOMPLETE_INPUT ? (size_t) -2 : (size_t) -1;
       __set_errno (EILSEQ);
     }
 
diff --git a/wcsmbs/mbsnrtowcs.c b/wcsmbs/mbsnrtowcs.c
index cb2d41c4c8..b58a467854 100644
--- a/wcsmbs/mbsnrtowcs.c
+++ b/wcsmbs/mbsnrtowcs.c
@@ -45,15 +45,16 @@ __mbsnrtowcs (dst, src, nmc, len, ps)
      mbstate_t *ps;
 {
   const unsigned char *srcend;
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   size_t result = 0;
   int status;
+  struct __gconv_step *towc;
 
   /* Tell where we want the result.  */
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   if (nmc == 0)
     return 0;
@@ -62,25 +63,27 @@ __mbsnrtowcs (dst, src, nmc, len, ps)
   /* Make sure we use the correct function.  */
   update_conversion_ptrs ();
 
+  /* Get the structure with the function pointers.  */
+  towc = __wcsmbs_gconv_fcts.towc;
+
   /* We have to handle DST == NULL special.  */
   if (dst == NULL)
     {
       wchar_t buf[64];		/* Just an arbitrary size.  */
       const unsigned char *inbuf = *src;
 
-      data.outbufend = (char *) buf + sizeof (buf);
+      data.__outbufend = (char *) buf + sizeof (buf);
       do
 	{
-	  data.outbuf = (char *) buf;
+	  data.__outbuf = (char *) buf;
 
-	  status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc,
-						     &data, &inbuf, srcend,
-						     &result, 0);
+	  status = (*towc->__fct) (__wcsmbs_gconv_fcts.towc, &data, &inbuf,
+				   srcend, &result, 0);
 	}
-      while (status == GCONV_FULL_OUTPUT);
+      while (status == __GCONV_FULL_OUTPUT);
 
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT)
-	  && ((wchar_t *) data.outbuf)[-1] == L'\0')
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
+	  && ((wchar_t *) data.__outbuf)[-1] == L'\0')
 	/* Don't count the NUL character in.  */
 	--result;
     }
@@ -89,21 +92,20 @@ __mbsnrtowcs (dst, src, nmc, len, ps)
       /* This code is based on the safe assumption that all internal
 	 multi-byte encodings use the NUL byte only to mark the end
 	 of the string.  */
-      data.outbuf = (unsigned char *) dst;
-      data.outbufend = data.outbuf + len * sizeof (wchar_t);
+      data.__outbuf = (unsigned char *) dst;
+      data.__outbufend = data.__outbuf + len * sizeof (wchar_t);
 
-      status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc,
-						 &data,
-						 (const unsigned char **) src,
-						 srcend, &result, 0);
+      status = (*towc->__fct) (__wcsmbs_gconv_fcts.towc, &data,
+			       (const unsigned char **) src, srcend,
+			       &result, 0);
 
       /* We have to determine whether the last character converted
 	 is the NUL character.  */
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT)
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
 	  && ((wchar_t *) dst)[result - 1] == L'\0')
 	{
 	  assert (result > 0);
-	  assert (__mbsinit (data.statep));
+	  assert (__mbsinit (data.__statep));
 	  *src = NULL;
 	  --result;
 	}
@@ -111,12 +113,13 @@ __mbsnrtowcs (dst, src, nmc, len, ps)
 
   /* There must not be any problems with the conversion but illegal input
      characters.  */
-  assert (status == GCONV_OK || status != GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT || status == GCONV_FULL_OUTPUT);
+  assert (status == __GCONV_OK || status != __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
 
-  if (status != GCONV_OK && status != GCONV_FULL_OUTPUT
-      && status != GCONV_EMPTY_INPUT)
+  if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+      && status != __GCONV_EMPTY_INPUT)
     {
       result = (size_t) -1;
       __set_errno (EILSEQ);
diff --git a/wcsmbs/mbsrtowcs.c b/wcsmbs/mbsrtowcs.c
index 84b7a3883b..f69247ff85 100644
--- a/wcsmbs/mbsrtowcs.c
+++ b/wcsmbs/mbsrtowcs.c
@@ -41,19 +41,23 @@ __mbsrtowcs (dst, src, len, ps)
      size_t len;
      mbstate_t *ps;
 {
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   size_t result = 0;
   int status;
+  struct __gconv_step *towc;
 
   /* Tell where we want the result.  */
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   /* Make sure we use the correct function.  */
   update_conversion_ptrs ();
 
+  /* Get the structure with the function pointers.  */
+  towc = __wcsmbs_gconv_fcts.towc;
+
   /* We have to handle DST == NULL special.  */
   if (dst == NULL)
     {
@@ -61,21 +65,20 @@ __mbsrtowcs (dst, src, len, ps)
       const unsigned char *inbuf = (const unsigned char *) *src;
       const unsigned char *srcend = inbuf + strlen (inbuf) + 1;
 
-      data.outbufend = (char *) buf + sizeof (buf);
+      data.__outbufend = (char *) buf + sizeof (buf);
       do
 	{
-	  data.outbuf = (char *) buf;
+	  data.__outbuf = (char *) buf;
 
-	  status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc,
-						     &data, &inbuf, srcend,
-						     &result, 0);
+	  status = (*towc->__fct) (__wcsmbs_gconv_fcts.towc, &data, &inbuf,
+				   srcend, &result, 0);
 	}
-      while (status == GCONV_FULL_OUTPUT);
+      while (status == __GCONV_FULL_OUTPUT);
 
-      if (status == GCONV_OK || status == GCONV_EMPTY_INPUT)
+      if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
 	{
 	  /* There better should be a NUL wide char at the end.  */
-	  assert (((wchar_t *) data.outbuf)[-1] == L'\0');
+	  assert (((wchar_t *) data.__outbuf)[-1] == L'\0');
 	  /* Don't count the NUL character in.  */
 	  --result;
 	}
@@ -91,21 +94,20 @@ __mbsrtowcs (dst, src, len, ps)
 					+ __strnlen (*src, len * MB_CUR_MAX)
 					+ 1);
 
-      data.outbuf = (unsigned char *) dst;
-      data.outbufend = data.outbuf + len * sizeof (wchar_t);
+      data.__outbuf = (unsigned char *) dst;
+      data.__outbufend = data.__outbuf + len * sizeof (wchar_t);
 
-      status = (*__wcsmbs_gconv_fcts.towc->fct) (__wcsmbs_gconv_fcts.towc,
-						 &data,
-						 (const unsigned char **) src,
-						 srcend, &result, 0);
+      status = (*towc->__fct) (__wcsmbs_gconv_fcts.towc, &data,
+			       (const unsigned char **) src, srcend,
+			       &result, 0);
 
       /* We have to determine whether the last character converted
 	 is the NUL character.  */
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT)
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
 	  && ((wchar_t *) dst)[result - 1] == L'\0')
 	{
 	  assert (result > 0);
-	  assert (__mbsinit (data.statep));
+	  assert (__mbsinit (data.__statep));
 	  *src = NULL;
 	  --result;
 	}
@@ -113,12 +115,13 @@ __mbsrtowcs (dst, src, len, ps)
 
   /* There must not be any problems with the conversion but illegal input
      characters.  */
-  assert (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT || status == GCONV_FULL_OUTPUT);
+  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
 
-  if (status != GCONV_OK && status != GCONV_FULL_OUTPUT
-      && status != GCONV_EMPTY_INPUT)
+  if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+      && status != __GCONV_EMPTY_INPUT)
     {
       result = (size_t) -1;
       __set_errno (EILSEQ);
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index fddb3d626c..8be3f10c2d 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 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
@@ -22,19 +22,24 @@
  */
 
 #ifndef _WCHAR_H
-#define _WCHAR_H 1
 
-#include <features.h>
+#ifndef __need_mbstate_t
+# define _WCHAR_H 1
+# include <features.h>
+#endif
 
+#ifdef _WCHAR_H
 /* Get FILE definition.  */
-#define __need_FILE
-#include <stdio.h>
+# define __need_FILE
+# include <stdio.h>
+# include <stdarg.h>
 
 /* Get size_t, wchar_t, wint_t and NULL from <stddef.h>.  */
-#define __need_size_t
-#define __need_wchar_t
+# define __need_size_t
+# define __need_wchar_t
+# define __need_NULL
+#endif
 #define __need_wint_t
-#define __need_NULL
 #include <stddef.h>
 
 /* We try to get wint_t from <stddef.h>, but not all GCC versions define it
@@ -49,12 +54,24 @@ typedef unsigned int wint_t;
 #endif
 
 
+#ifndef __mbstate_t_defined
+# define __mbstate_t_defined	1
 /* Conversion state information.  */
 typedef struct
 {
   int count;		/* Number of bytes needed for the current character. */
   wint_t value;		/* Value so far.  */
-} mbstate_t;
+} __mbstate_t;
+#endif
+#undef __need_mbstate_t
+
+
+/* The rest of the file is only used if used if __need_mbstate_t is not
+   defined.  */
+#ifdef _WCHAR_H
+
+/* Public type.  */
+typedef __mbstate_t mbstate_t;
 
 #ifndef WCHAR_MIN
 /* These constants might also be defined in <inttypes.h>.  */
@@ -150,6 +167,12 @@ extern wchar_t *wcschr __P ((__const wchar_t *__wcs, wchar_t __wc));
 /* Find the last occurrence of WC in WCS.  */
 extern wchar_t *wcsrchr __P ((__const wchar_t *__wcs, wchar_t __wc));
 
+#ifdef __USE_GNU
+/* This funciton is similar to `wcschr'.  But it returns a pointer to
+   the closing NUL wide character in case C is not found in S.  */
+extern wchar_t *wcschrnul __P ((__const wchar_t *__s, wchar_t __wc));
+#endif
+
 /* Return the length of the initial segmet of WCS which
    consists entirely of wide characters not in REJECT.  */
 extern size_t wcscspn __P ((__const wchar_t *__wcs,
@@ -204,6 +227,13 @@ extern wchar_t *wmemmove __P ((wchar_t *__s1, __const wchar_t *__s2,
 /* Set N wide characters of S to C.  */
 extern wchar_t *wmemset __P ((wchar_t *__s, wchar_t __c, size_t __n));
 
+#ifdef __USE_GNU
+/* Copy N wide characters of SRC to DEST and return pointer to following
+   wide character.  */
+extern wchar_t *wmempcpy __P ((wchar_t *__restrict __s1,
+			       __const wchar_t *__restrict __s2, size_t __n));
+#endif
+
 
 /* Determine whether C constitutes a valid (one-byte) multibyte
    character.  */
@@ -488,6 +518,137 @@ extern wchar_t *wcpncpy __P ((wchar_t *__dest, __const wchar_t *__src,
 #endif	/* use GNU */
 
 
+/* Wide character I/O functions.  */
+
+/* Select orientation for stream.  */
+extern int fwide __P ((FILE *__fp, int __mode));
+
+
+/* Write formatted output to STREAM.  */
+extern int fwprintf __P ((FILE *__restrict __stream,
+			  __const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wprintf__, 2, 3))) */;
+/* Write formatted output to stdout.  */
+extern int wprintf __P ((__const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wprintf__, 1, 2))) */;
+/* Write formatted output of at most N characters to S.  */
+extern int swprintf __P ((wchar_t *__restrict __s, size_t __n,
+			  __const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */;
+
+/* Write formatted output to S from argument list ARG.  */
+extern int vfwprintf __P ((FILE *__restrict __s,
+			   __const wchar_t *__restrict __format,
+			   va_list __arg))
+     /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */;
+/* Write formatted output to stdout from argument list ARG.  */
+extern int vwprintf __P ((__const wchar_t *__restrict __format,
+			  va_list __arg))
+     /* __attribute__ ((__format__ (__wprintf__, 1, 0))) */;
+/* Write formatted output of at most N character to S from argument
+   list ARG.  */
+extern int vswprintf __P ((wchar_t *__restrict __s, size_t __n,
+			   __const wchar_t *__restrict __format,
+			   va_list __arg))
+     /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */;
+
+
+/* Read formatted input from STREAM.  */
+extern int fwscanf __P ((FILE *__restrict __stream,
+			 __const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */;
+/* Read formatted input from stdin.  */
+extern int wscanf __P ((__const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wscanf__, 1, 2))) */;
+/* Read formatted input from S.  */
+extern int swscanf __P ((__const wchar_t *__restrict __s,
+			 __const wchar_t *__restrict __format, ...))
+     /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */;
+
+/* Read formatted input from S into argument list ARG.  */
+extern int vfwscanf __P ((FILE *__restrict __s,
+			  __const wchar_t *__restrict __format, va_list __arg))
+     /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */;
+/* Read formatted input from stdin into argument list ARG.  */
+extern int vwscanf __P ((__const wchar_t *__restrict __format, va_list __arg))
+     /* __attribute__ ((__format__ (__wscanf__, 1, 0))) */;
+/* Read formatted input from S into argument list ARG.  */
+extern int vswscanf __P ((__const wchar_t *__restrict __s,
+			  __const wchar_t *__restrict __format, va_list __arg))
+     /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */;
+
+
+/* Read a character from STREAM.  */
+extern wint_t fgetwc __P ((FILE *__stream));
+extern wint_t getwc __P ((FILE *__stream));
+
+/* Read a character from stdin.  */
+extern wint_t getwchar __P ((void));
+
+#ifdef __USE_GNU
+/* These are defined to be equivalent to the `char' functions defined
+   in POSIX.1:1996.  */
+extern wint_t getwc_unlocked __P ((FILE *__stream));
+extern wint_t getwchar_unlocked __P ((void));
+
+/* This is the wide character version of a GNU extension.  */
+extern wint_t fgetwc_unlocked __P ((FILE *__stream));
+#endif /* Use POSIX or MISC.  */
+
+
+/* Write a character to STREAM.  */
+extern wint_t fputwc __P ((wint_t __wc, FILE *__stream));
+extern wint_t putwc __P ((wint_t __wc, FILE *__stream));
+
+/* Write a character to stdout.  */
+extern wint_t putwchar __P ((wint_t __wc));
+
+#ifdef __USE_GNU
+/* Faster version when locking is not necessary.  */
+extern wint_t fputwc_unlocked __P ((wint_t __wc, FILE *__stream));
+
+/* These are defined to be equivalent to the `char' functions defined
+   in POSIX.1:1996.  */
+extern wint_t putwc_unlocked __P ((wint_t __wc, FILE *__stream));
+extern wint_t putwchar_unlocked __P ((wint_t __wc));
+#endif
+
+
+/* Get a newline-terminated wide character string of finite length
+   from STREAM.  */
+extern wchar_t *fgetws __P ((wchar_t *__restrict __ws, int __n,
+			     FILE *__restrict __stream));
+
+#ifdef __USE_GNU
+/* This function does the same as `fgetws' but does not lock the stream.  */
+extern wchar_t *fgetws_unlocked __P ((wchar_t *__restrict __ws, int __n,
+				      FILE *__restrict __stream));
+#endif
+
+
+/* Write a string to STREAM.  */
+extern int fputws __P ((__const wchar_t *__restrict __ws,
+			FILE *__restrict __stream));
+
+#ifdef __USE_GNU
+/* This function does the same as `fputws' but does not lock the stream.  */
+extern int fputws_unlocked __P ((__const wchar_t *__restrict __ws,
+				 FILE *__restrict __stream));
+#endif
+
+
+/* Push a character back onto the input buffer of STREAM.  */
+extern wint_t ungetwc __P ((wint_t __wc, FILE *__stream));
+
+
+/* Format TP into S according to FORMAT.
+   Write no more than MAXSIZE wide characters and return the number
+   of wide characters written, or 0 if it would exceed MAXSIZE.  */
+extern size_t wcsftime __P ((wchar_t *__restrict __s, size_t __maxsize,
+			     __const wchar_t *__restrict __format,
+			     __const struct tm *__restrict __tp));
+
+
 /* The X/Open standard demands that most of the functions defined in
    the <wctype.h> header must also appear here.  This is probably
    because some X/Open members wrote their implementation before the
@@ -501,4 +662,6 @@ extern wchar_t *wcpncpy __P ((wchar_t *__dest, __const wchar_t *__src,
 
 __END_DECLS
 
+#endif	/* _WCHAR_H defined */
+
 #endif /* wchar.h  */
diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c
index b546c7a9d3..91daf4d94c 100644
--- a/wcsmbs/wcrtomb.c
+++ b/wcsmbs/wcrtomb.c
@@ -37,24 +37,24 @@ size_t
 __wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
 {
   char buf[MB_CUR_MAX];
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   int status;
   size_t result;
   size_t dummy;
 
   /* Tell where we want the result.  */
-  data.outbuf = s;
-  data.outbufend = s + MB_CUR_MAX;
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__outbuf = s;
+  data.__outbufend = s + MB_CUR_MAX;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   /* A first special case is if S is NULL.  This means put PS in the
      initial state.  */
   if (s == NULL)
     {
-      data.outbuf = buf;
+      data.__outbuf = buf;
       wc = L'\0';
     }
 
@@ -66,35 +66,36 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
      by a NUL byte.  */
   if (wc == L'\0')
     {
-      status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						 &data, NULL, NULL, &dummy, 1);
+      status = (*__wcsmbs_gconv_fcts.tomb->__fct) (__wcsmbs_gconv_fcts.tomb,
+						   &data, NULL, NULL,
+						   &dummy, 1);
 
-      if (status == GCONV_OK || status == GCONV_EMPTY_INPUT)
-	*data.outbuf++ = '\0';
+      if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
+	*data.__outbuf++ = '\0';
     }
   else
     {
       /* Do a normal conversion.  */
       const unsigned char *inbuf = (const unsigned char *) &wc;
 
-      status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						 &data, &inbuf,
-						 inbuf + sizeof (wchar_t),
-						 &dummy, 0);
+      status = (*__wcsmbs_gconv_fcts.tomb->__fct) (__wcsmbs_gconv_fcts.tomb,
+						   &data, &inbuf,
+						   inbuf + sizeof (wchar_t),
+						   &dummy, 0);
     }
 
   /* There must not be any problems with the conversion but illegal input
      characters.  The output buffer must be large enough, otherwise the
      definition of MB_CUR_MAX is not correct.  All the other possible
      errors also must not happen.  */
-  assert (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT
-	  || status == GCONV_FULL_OUTPUT);
-
-  if (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-      || status == GCONV_FULL_OUTPUT)
-    result = data.outbuf - (unsigned char *) s;
+  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
+
+  if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+      || status == __GCONV_FULL_OUTPUT)
+    result = data.__outbuf - (unsigned char *) s;
   else
     {
       result = (size_t) -1;
diff --git a/wcsmbs/wcschrnul.c b/wcsmbs/wcschrnul.c
new file mode 100644
index 0000000000..2ea9b2ccc2
--- /dev/null
+++ b/wcsmbs/wcschrnul.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1995, 1996, 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 <wchar.h>
+
+
+/* Find the first occurrence of WC in WCS.  */
+wchar_t *
+__wcschrnul (wcs, wc)
+     register const wchar_t *wcs;
+     register const wchar_t wc;
+{
+  while (*wcs != L'\0')
+    if (*wcs == wc)
+      break;
+    else
+      ++wcs;
+
+  return wcs;
+}
+weak_alias (__wcschrnul, wcschrnul)
diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c
index b16aa6c500..b02acad68d 100644
--- a/wcsmbs/wcsmbsload.c
+++ b/wcsmbs/wcsmbsload.c
@@ -36,64 +36,76 @@ const struct locale_data *__wcsmbs_last_locale = &_nl_C_LC_CTYPE;
 
 
 /* These are the descriptions for the default conversion functions.  */
-static struct gconv_step to_wc =
+static struct __gconv_step to_wc =
 {
-  shlib_handle: NULL,
-  modname: NULL,
-  counter: INT_MAX,
-  from_name: "ANSI_X3.4-1968//",
-  to_name: "INTERNAL",
-  fct: __gconv_transform_ascii_internal,
-  init_fct: NULL,
-  end_fct: NULL,
-  min_needed_from: 1,
-  max_needed_from: 1,
-  min_needed_to: 4,
-  max_needed_to: 4,
-  stateful: 0,
-  data: NULL
+  .__shlib_handle = NULL,
+  .__modname = NULL,
+  .__counter = INT_MAX,
+  .__from_name = "ANSI_X3.4-1968//",
+  .__to_name = "INTERNAL",
+  .__fct = __gconv_transform_ascii_internal,
+  .__init_fct = NULL,
+  .__end_fct = NULL,
+  .__min_needed_from = 1,
+  .__max_needed_from = 1,
+  .__min_needed_to = 4,
+  .__max_needed_to = 4,
+  .__stateful = 0,
+  .__data = NULL
 };
 
-static struct gconv_step to_mb =
+static struct __gconv_step to_mb =
 {
-  shlib_handle: NULL,
-  modname: NULL,
-  counter: INT_MAX,
-  from_name: "INTERNAL",
-  to_name: "ANSI_X3.4-1968//",
-  fct: __gconv_transform_internal_ascii,
-  init_fct: NULL,
-  end_fct: NULL,
-  min_needed_from: 4,
-  max_needed_from: 4,
-  min_needed_to: 1,
-  max_needed_to: 1,
-  stateful: 0,
-  data: NULL
+  .__shlib_handle = NULL,
+  .__modname = NULL,
+  .__counter = INT_MAX,
+  .__from_name = "INTERNAL",
+  .__to_name = "ANSI_X3.4-1968//",
+  .__fct = __gconv_transform_internal_ascii,
+  .__init_fct = NULL,
+  .__end_fct = NULL,
+  .__min_needed_from = 4,
+  .__max_needed_from = 4,
+  .__min_needed_to = 1,
+  .__max_needed_to = 1,
+  .__stateful = 0,
+  .__data = NULL
 };
 
 
 /* For the default locale we only have to handle ANSI_X3.4-1968.  */
 struct gconv_fcts __wcsmbs_gconv_fcts =
 {
-  towc: &to_wc,
-  tomb: &to_mb
+  .towc = &to_wc,
+  .tomb = &to_mb
 };
 
 
-static inline struct gconv_step *
+static inline struct __gconv_step *
 getfct (const char *to, const char *from)
 {
   size_t nsteps;
-  struct gconv_step *result;
+  struct __gconv_step *result;
+  size_t nstateful;
+  size_t cnt;
 
-  if (__gconv_find_transform (to, from, &result, &nsteps) != GCONV_OK)
+  if (__gconv_find_transform (to, from, &result, &nsteps) != __GCONV_OK)
     /* Loading the conversion step is not possible.  */
     return NULL;
 
-  /* We must only have one step in this conversion.  */
-  if (nsteps != 1)
-    return NULL;
+  /* Count the number of stateful conversions.  Since we will only
+     have one 'mbstate_t' object available we can only deal with one
+     stateful conversion.  */
+  nstateful = 0;
+  for (cnt = 0; cnt < nsteps; ++cnt)
+    if (result[cnt].__stateful)
+      ++nstateful;
+  if (nstateful > 1)
+    {
+      /* We cannot handle this case.  */
+      __gconv_close_transform (result, nsteps);
+      result = NULL;
+    }
 
   return result;
 }
@@ -148,14 +160,15 @@ getfct (const char *to, const char *from)
   })
 
 
+/* We must modify global data.  */
+__libc_lock_define_initialized (static, lock)
+
+
 /* Load conversion functions for the currently selected locale.  */
 void
 internal_function
 __wcsmbs_load_conv (const struct locale_data *new_category)
 {
-  /* We must modify global data.  */
-  __libc_lock_define_initialized (static, lock)
-
   /* Acquire the lock.  */
   __libc_lock_lock (lock);
 
@@ -174,6 +187,12 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	  /* We must find the real functions.  */
 	  const char *charset_name;
 	  const char *complete_name;
+	  struct __gconv_step *new_towc;
+	  struct __gconv_step *new_tomb;
+
+	  /* Free the old conversions.  */
+	  __gconv_close_transform (__wcsmbs_gconv_fcts.tomb, 1);
+	  __gconv_close_transform (__wcsmbs_gconv_fcts.towc, 1);
 
 	  /* Get name of charset of the locale.  We first examine
 	     whether we have a character set mentioned in the locale
@@ -188,15 +207,23 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
              complete lookup.  */
 	  complete_name = norm_add_slashes (charset_name);
 
-	  __wcsmbs_gconv_fcts.tomb = getfct (complete_name, "INTERNAL");
-	  __wcsmbs_gconv_fcts.towc = getfct ("INTERNAL", complete_name);
+	  new_towc = getfct ("INTERNAL", complete_name);
+	  if (new_towc != NULL)
+	    new_tomb = getfct (complete_name, "INTERNAL");
 
 	  /* If any of the conversion functions is not available we don't
 	     use any since this would mean we cannot convert back and
 	     forth.*/
-	  if (__wcsmbs_gconv_fcts.towc == NULL
-	      || __wcsmbs_gconv_fcts.tomb == NULL)
-	    goto failed;
+	  if (new_towc == NULL || new_tomb == NULL)
+	    {
+	      if (new_towc != NULL)
+		__gconv_close_transform (new_towc, 1);
+
+	      goto failed;
+	    }
+
+	  __wcsmbs_gconv_fcts.tomb = new_tomb;
+	  __wcsmbs_gconv_fcts.towc = new_towc;
 	}
 
       /* Set last-used variable for current locale.  */
@@ -205,3 +232,24 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 
   __libc_lock_unlock (lock);
 }
+
+
+/* Clone the current conversion function set.  */
+void
+internal_function
+__wcsmbs_clone_conv (struct gconv_fcts *copy)
+{
+  /* Make sure the data structures remain the same until we are finished.  */
+  __libc_lock_lock (lock);
+
+  /* Copy the data.  */
+  *copy = __wcsmbs_gconv_fcts;
+
+  /* Now increment the usage counters.  */
+  if (copy->towc->__shlib_handle != NULL)
+    ++copy->towc->__counter;
+  if (copy->tomb->__shlib_handle != NULL)
+    ++copy->tomb->__counter;
+
+  __libc_lock_unlock (lock);
+}
diff --git a/wcsmbs/wcsmbsload.h b/wcsmbs/wcsmbsload.h
index df0ba7b796..a3652d22ac 100644
--- a/wcsmbs/wcsmbsload.h
+++ b/wcsmbs/wcsmbsload.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -25,8 +25,8 @@
 /* Contains pointers to the used functions in the `gconv' modules.  */
 struct gconv_fcts
   {
-    struct gconv_step *towc;
-    struct gconv_step *tomb;
+    struct __gconv_step *towc;
+    struct __gconv_step *tomb;
   };
 
 /* Set of currently active conversion functions.  */
@@ -41,6 +41,10 @@ extern const struct locale_data *__wcsmbs_last_locale;
 extern void __wcsmbs_load_conv (const struct locale_data *new_category)
      internal_function;
 
+/* Clone the current `__wcsmbs_load_conv' value.  */
+extern void __wcsmbs_clone_conv (struct gconv_fcts *copy)
+     internal_function;
+
 
 /* Check whether the LC_CTYPE locale changed since the last call.
    Update the pointers appropriately.  */
diff --git a/wcsmbs/wcsnrtombs.c b/wcsmbs/wcsnrtombs.c
index f93d404eb1..fb86992aea 100644
--- a/wcsmbs/wcsnrtombs.c
+++ b/wcsmbs/wcsnrtombs.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
    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
@@ -43,16 +43,17 @@ __wcsnrtombs (dst, src, nwc, len, ps)
      size_t len;
      mbstate_t *ps;
 {
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   const wchar_t *srcend;
   int status;
   size_t result;
+  struct __gconv_step *tomb;
 
   /* Tell where we want the result.  */
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   if (nwc == 0)
     return 0;
@@ -61,6 +62,9 @@ __wcsnrtombs (dst, src, nwc, len, ps)
   /* Make sure we use the correct function.  */
   update_conversion_ptrs ();
 
+  /* Get the structure with the function pointers.  */
+  tomb = __wcsmbs_gconv_fcts.tomb;
+
   /* We have to handle DST == NULL special.  */
   if (dst == NULL)
     {
@@ -69,25 +73,23 @@ __wcsnrtombs (dst, src, nwc, len, ps)
       size_t dummy;
 
       result = 0;
-      data.outbufend = buf + sizeof (buf);
+      data.__outbufend = buf + sizeof (buf);
 
       do
 	{
-	  data.outbuf = buf;
+	  data.__outbuf = buf;
 
-	  status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						     &data,
-						     (const unsigned char **) &inbuf,
-						     (const unsigned char *) srcend,
-						     &dummy, 0);
+	  status = (*tomb->__fct) (__wcsmbs_gconv_fcts.tomb, &data,
+				   (const unsigned char **) &inbuf,
+				   (const unsigned char *) srcend, &dummy, 0);
 
 	  /* Count the number of bytes.  */
-	  result += data.outbuf - buf;
+	  result += data.__outbuf - buf;
 	}
-      while (status == GCONV_FULL_OUTPUT);
+      while (status == __GCONV_FULL_OUTPUT);
 
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT)
-	  && data.outbuf[-1] == '\0')
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
+	  && data.__outbuf[-1] == '\0')
 	/* Don't count the NUL character in.  */
 	--result;
     }
@@ -98,25 +100,23 @@ __wcsnrtombs (dst, src, nwc, len, ps)
 	 of the string.  */
       size_t dummy;
 
-      data.outbuf = dst;
-      data.outbufend = dst + len;
+      data.__outbuf = dst;
+      data.__outbufend = dst + len;
 
-      status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						 &data,
-						 (const unsigned char **) src,
-						 (const unsigned char *) srcend,
-						 &dummy, 0);
+      status = (*tomb->__fct) (__wcsmbs_gconv_fcts.tomb, &data,
+			       (const unsigned char **) src,
+			       (const unsigned char *) srcend, &dummy, 0);
 
       /* Count the number of bytes.  */
-      result = data.outbuf - (unsigned char *) dst;
+      result = data.__outbuf - (unsigned char *) dst;
 
       /* We have to determine whether the last character converted
 	 is the NUL character.  */
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT)
-	  && data.outbuf[-1] == '\0')
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
+	  && data.__outbuf[-1] == '\0')
 	{
-	  assert (data.outbuf != (unsigned char *) dst);
-	  assert (__mbsinit (data.statep));
+	  assert (data.__outbuf != (unsigned char *) dst);
+	  assert (__mbsinit (data.__statep));
 	  *src = NULL;
 	  --result;
 	}
@@ -124,12 +124,13 @@ __wcsnrtombs (dst, src, nwc, len, ps)
 
   /* There must not be any problems with the conversion but illegal input
      characters.  */
-  assert (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT || status == GCONV_FULL_OUTPUT);
+  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
 
-  if (status != GCONV_OK && status != GCONV_FULL_OUTPUT
-      && status != GCONV_EMPTY_INPUT)
+  if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+      && status != __GCONV_EMPTY_INPUT)
     {
       result = (size_t) -1;
       __set_errno (EILSEQ);
diff --git a/wcsmbs/wcsrtombs.c b/wcsmbs/wcsrtombs.c
index 02575992d6..5ab84814a0 100644
--- a/wcsmbs/wcsrtombs.c
+++ b/wcsmbs/wcsrtombs.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
    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
@@ -40,19 +40,23 @@ __wcsrtombs (dst, src, len, ps)
      size_t len;
      mbstate_t *ps;
 {
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   int status;
   size_t result;
+  struct __gconv_step *tomb;
 
   /* Tell where we want the result.  */
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = ps ?: &state;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = ps ?: &state;
 
   /* Make sure we use the correct function.  */
   update_conversion_ptrs ();
 
+  /* Get the structure with the function pointers.  */
+  tomb = __wcsmbs_gconv_fcts.tomb;
+
   /* We have to handle DST == NULL special.  */
   if (dst == NULL)
     {
@@ -62,27 +66,25 @@ __wcsrtombs (dst, src, len, ps)
       size_t dummy;
 
       result = 0;
-      data.outbufend = buf + sizeof (buf);
+      data.__outbufend = buf + sizeof (buf);
 
       do
 	{
-	  data.outbuf = buf;
+	  data.__outbuf = buf;
 
-	  status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						     &data,
-						     (const unsigned char **) &inbuf,
-						     (const unsigned char *) srcend,
-						     &dummy, 0);
+	  status = (*tomb->__fct) (__wcsmbs_gconv_fcts.tomb, &data,
+				   (const unsigned char **) &inbuf,
+				   (const unsigned char *) srcend, &dummy, 0);
 
 	  /* Count the number of bytes.  */
-	  result += data.outbuf - buf;
+	  result += data.__outbuf - buf;
 	}
-      while (status == GCONV_FULL_OUTPUT);
+      while (status == __GCONV_FULL_OUTPUT);
 
-      if (status == GCONV_OK || status == GCONV_EMPTY_INPUT)
+      if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT)
 	{
 	  /* There better should be a NUL byte at the end.  */
-	  assert (data.outbuf[-1] == '\0');
+	  assert (data.__outbuf[-1] == '\0');
 	  /* Don't count the NUL character in.  */
 	  --result;
 	}
@@ -95,26 +97,24 @@ __wcsrtombs (dst, src, len, ps)
       const wchar_t *srcend = *src + __wcsnlen (*src, len * MB_CUR_MAX) + 1;
       size_t dummy;
 
-      data.outbuf = dst;
-      data.outbufend = dst + len;
+      data.__outbuf = dst;
+      data.__outbufend = dst + len;
 
-      status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb,
-						 &data,
-						 (const unsigned char **) src,
-						 (const unsigned char *) srcend,
-						 &dummy, 0);
+      status = (*tomb->__fct) (__wcsmbs_gconv_fcts.tomb, &data,
+			       (const unsigned char **) src,
+			       (const unsigned char *) srcend, &dummy, 0);
 
       /* Count the number of bytes.  */
-      result = data.outbuf - (unsigned char *) dst;
+      result = data.__outbuf - (unsigned char *) dst;
 
       /* We have to determine whether the last character converted
 	 is the NUL character.  */
-      if ((status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	   || status == GCONV_FULL_OUTPUT)
-	  && data.outbuf[-1] == '\0')
+      if ((status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	   || status == __GCONV_FULL_OUTPUT)
+	  && data.__outbuf[-1] == '\0')
 	{
-	  assert (data.outbuf != (unsigned char *) dst);
-	  assert (__mbsinit (data.statep));
+	  assert (data.__outbuf != (unsigned char *) dst);
+	  assert (__mbsinit (data.__statep));
 	  *src = NULL;
 	  --result;
 	}
@@ -122,12 +122,13 @@ __wcsrtombs (dst, src, len, ps)
 
   /* There must not be any problems with the conversion but illegal input
      characters.  */
-  assert (status == GCONV_OK || status == GCONV_EMPTY_INPUT
-	  || status == GCONV_ILLEGAL_INPUT
-	  || status == GCONV_INCOMPLETE_INPUT || status == GCONV_FULL_OUTPUT);
+  assert (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
+	  || status == __GCONV_ILLEGAL_INPUT
+	  || status == __GCONV_INCOMPLETE_INPUT
+	  || status == __GCONV_FULL_OUTPUT);
 
-  if (status != GCONV_OK && status != GCONV_FULL_OUTPUT
-      && status != GCONV_EMPTY_INPUT)
+  if (status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+      && status != __GCONV_EMPTY_INPUT)
     {
       result = (size_t) -1;
       __set_errno (EILSEQ);
diff --git a/wcsmbs/wctob.c b/wcsmbs/wctob.c
index 0fba46ad72..565cbead4c 100644
--- a/wcsmbs/wctob.c
+++ b/wcsmbs/wctob.c
@@ -29,19 +29,19 @@ wctob (c)
      wint_t c;
 {
   char buf[MB_LEN_MAX];
-  struct gconv_step_data data;
+  struct __gconv_step_data data;
   wchar_t inbuf[1];
   wchar_t *inptr = inbuf;
   size_t dummy;
   int status;
 
   /* Tell where we want the result.  */
-  data.outbuf = buf;
-  data.outbufend = buf + MB_LEN_MAX;
-  data.invocation_counter = 0;
-  data.internal_use = 1;
-  data.is_last = 1;
-  data.statep = &data.__state;
+  data.__outbuf = buf;
+  data.__outbufend = buf + MB_LEN_MAX;
+  data.__invocation_counter = 0;
+  data.__internal_use = 1;
+  data.__is_last = 1;
+  data.__statep = &data.__state;
 
   /* Make sure we start in the initial state.  */
   memset (&data.__state, '\0', sizeof (mbstate_t));
@@ -52,14 +52,14 @@ wctob (c)
   /* Create the input string.  */
   inbuf[0] = c;
 
-  status = (*__wcsmbs_gconv_fcts.tomb->fct) (__wcsmbs_gconv_fcts.tomb, &data,
-					     (const unsigned char **) &inptr,
-					     (const unsigned char *) &inbuf[1],
-					     &dummy, 0);
+  status = (*__wcsmbs_gconv_fcts.tomb->__fct) (__wcsmbs_gconv_fcts.tomb, &data,
+					       (const unsigned char **) &inptr,
+					       (const unsigned char *) &inbuf[1],
+					       &dummy, 0);
   /* The conversion failed or the output is too long.  */
-  if ((status != GCONV_OK && status != GCONV_FULL_OUTPUT
-       && status != GCONV_EMPTY_INPUT)
-      || data.outbuf != (unsigned char *) (buf + 1))
+  if ((status != __GCONV_OK && status != __GCONV_FULL_OUTPUT
+       && status != __GCONV_EMPTY_INPUT)
+      || data.__outbuf != (unsigned char *) (buf + 1))
     return EOF;
 
   return buf[0];
diff --git a/wcsmbs/wmemcpy.c b/wcsmbs/wmemcpy.c
index 6133a5a48d..8530a71457 100644
--- a/wcsmbs/wmemcpy.c
+++ b/wcsmbs/wmemcpy.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
 
    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
@@ -22,10 +22,11 @@
 
 
 wchar_t *
-wmemcpy (s1, s2, n)
+__wmemcpy (s1, s2, n)
      wchar_t *s1;
      const wchar_t *s2;
      size_t n;
 {
   return (wchar_t *) memcpy ((char *) s1, (char *) s2, n * sizeof (wchar_t));
 }
+weak_alias (__wmemcpy, wmemcpy)
diff --git a/wcsmbs/wmemmove.c b/wcsmbs/wmemmove.c
index fc4cead656..5d41601750 100644
--- a/wcsmbs/wmemmove.c
+++ b/wcsmbs/wmemmove.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
@@ -22,10 +22,11 @@
 
 
 wchar_t *
-wmemmove (s1, s2, n)
+__wmemmove (s1, s2, n)
      wchar_t *s1;
      const wchar_t *s2;
      size_t n;
 {
   return (wchar_t *) memmove ((char *) s1, (char *) s2, n * sizeof (wchar_t));
 }
+weak_alias (__wmemmove, wmemmove)
diff --git a/wcsmbs/wmempcpy.c b/wcsmbs/wmempcpy.c
new file mode 100644
index 0000000000..46cb9585c9
--- /dev/null
+++ b/wcsmbs/wmempcpy.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.org>, 1999.
+
+   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 <wchar.h>
+#include <string.h>
+
+
+wchar_t *
+__wmempcpy (s1, s2, n)
+     wchar_t *s1;
+     const wchar_t *s2;
+     size_t n;
+{
+  return (wchar_t *) __mempcpy ((char *) s1, (char *) s2,
+				n * sizeof (wchar_t));
+}
+weak_alias (__wmempcpy, wmempcpy)