about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-04-03 16:31:49 +0000
committerRoland McGrath <roland@gnu.org>1996-04-03 16:31:49 +0000
commit299a95b9f048679f1288512b0a6ab6ca16dd9d7c (patch)
tree4788a62ee8f131887e5817e8daa3339084dbe764
parent30de3b18a526acc837957865129b7fa6d8ac91d1 (diff)
downloadglibc-299a95b9f048679f1288512b0a6ab6ca16dd9d7c.tar.gz
glibc-299a95b9f048679f1288512b0a6ab6ca16dd9d7c.tar.xz
glibc-299a95b9f048679f1288512b0a6ab6ca16dd9d7c.zip
Tue Apr 2 21:27:01 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
	* posix/glob.c (glob_pattern_p): Avoid scanning past eos if
	the pattern ends with a backslash and quoting is enabled.
	* posix/fnmatch.c (fnmatch): Likewise; return FNM_NOMATCH for such
 	patterns.
-rw-r--r--ChangeLog7
-rw-r--r--MakeTAGS4
-rw-r--r--Makerules4
-rw-r--r--locale/Makefile5
-rw-r--r--locale/programs/config.h3
-rw-r--r--locale/programs/ctypedump.c163
-rw-r--r--locale/programs/locale.c188
-rw-r--r--po/header.pot14
-rw-r--r--posix/fnmatch.c17
-rw-r--r--posix/glob.c2
-rw-r--r--setjmp/setjmp.h2
-rw-r--r--stdio-common/_itoa.c6
-rw-r--r--stdio-common/_itoa.h29
-rw-r--r--stdio-common/printf-parse.h135
-rw-r--r--stdio-common/printf-prs.c52
-rw-r--r--stdio-common/printf.h9
-rw-r--r--stdio-common/tst-printf.c17
-rw-r--r--stdio-common/vfprintf.c1710
-rw-r--r--stdlib/strtod.c20
-rw-r--r--sysdeps/generic/setenv.c5
-rw-r--r--wcsmbs/Makefile11
-rw-r--r--wcsmbs/mbsadvance.c38
-rw-r--r--wcsmbs/mbscat.c56
-rw-r--r--wcsmbs/mbschr.c60
-rw-r--r--wcsmbs/mbscpy.c47
-rw-r--r--wcsmbs/mbsdup.c51
-rw-r--r--wcsmbs/mbslen.c45
-rw-r--r--wcsmbs/mbsncat.c61
-rw-r--r--wcsmbs/mbsncmp.c68
-rw-r--r--wcsmbs/mbsncpy.c55
-rw-r--r--wcsmbs/mbsrchr.c61
-rw-r--r--wcsmbs/mbstomb.c42
-rw-r--r--wcsmbs/mbstr.h69
-rw-r--r--wcsmbs/wcscat.c9
-rw-r--r--wcsmbs/wcschr.c8
-rw-r--r--wcsmbs/wcscmp.c11
-rw-r--r--wcsmbs/wcscpy.c9
-rw-r--r--wcsmbs/wcscspn.c9
-rw-r--r--wcsmbs/wcsdup.c7
-rw-r--r--wcsmbs/wcslen.c7
-rw-r--r--wcsmbs/wcsncat.c11
-rw-r--r--wcsmbs/wcsncmp.c11
-rw-r--r--wcsmbs/wcsncpy.c13
-rw-r--r--wcsmbs/wcspbrk.c9
-rw-r--r--wcsmbs/wcsrchr.c9
-rw-r--r--wcsmbs/wcsspn.c9
-rw-r--r--wcsmbs/wcstok.c43
-rw-r--r--wcsmbs/wcstr.h84
-rw-r--r--wcsmbs/wcswcs.c97
49 files changed, 1507 insertions, 1895 deletions
diff --git a/ChangeLog b/ChangeLog
index f8c952fa76..ac276db283 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Tue Apr  2 21:27:01 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* posix/glob.c (glob_pattern_p): Avoid scanning past eos if
+	the pattern ends with a backslash and quoting is enabled.
+	* posix/fnmatch.c (fnmatch): Likewise; return FNM_NOMATCH for such
+ 	patterns.
+
 Mon Apr  1 13:34:55 1996  Roland McGrath  <roland@whiz-bang.gnu.ai.mit.edu>
 
 	* stdio-common/tst-printf.c (main): Add new test case.
diff --git a/MakeTAGS b/MakeTAGS
index a9baba65e8..7aaf0ac7da 100644
--- a/MakeTAGS
+++ b/MakeTAGS
@@ -165,7 +165,9 @@ $P/subdirs.pot: $(subdirs:%=$P/%.pot)
 # Combine all the messages into the final sorted template translation file.
 $P/SYS_libc.pot: $(all-pot)
 	@rm -f $@.new
-	$(XGETTEXT) -d - -n -s --omit-header $^ > $@.new
+	sed -e 's/VERSION/$(version)/' -e "s/DATE/`date +'%Y-%m-%d %k:%M'`" \
+	    po/header.pot > $@.new
+	$(XGETTEXT) -d - -n -s --omit-header $^ >> $@.new
 	mv -f $@.new $@
 	test ! -d CVS || cvs ci -m'Regenerated from source files' $@
 
diff --git a/Makerules b/Makerules
index 296e811432..d7e82d9082 100644
--- a/Makerules
+++ b/Makerules
@@ -610,8 +610,12 @@ cd $(@D); $(BUILD_CC) $(BUILD_CFLAGS) $(<:$(common-objpfx)%=%) -o $(@F)
 endef
 
 # We always want to use configuration definitions.
+ifdef objdir
 # This is always used in $(common-objdir), so we use no directory name.
 BUILD_CFLAGS = -include config.h
+else
+BUILD_CFLAGS = -include $(..)config.h
+endif
 
 # Support the GNU standard name for this target.
 .PHONY: check
diff --git a/locale/Makefile b/locale/Makefile
index 675052aa03..0a30cd27d3 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -31,8 +31,8 @@ distribute	= localeinfo.h categories.def \
 routines	= setlocale loadlocale localeconv nl_langinfo
 categories	= ctype messages monetary numeric time collate
 aux		= $(categories:%=lc-%) $(categories:%=C-%) SYS_libc
-others		= localedef# locale
-install-bin	= localedef# locale
+others		= localedef locale
+install-bin	= localedef locale
 extra-objs	= $(localedef-modules:=.o) $(locale-modules:=.o) \
 		  $(lib-modules:=.o)
 
@@ -41,7 +41,6 @@ vpath %.h programs
 
 localedef-modules	:= $(categories:%=ld-%) charmap charset linereader \
 			   locfile stringtrans
-locale-modules		:= ctypedump
 lib-modules		:= simple-hash xmalloc xstrdup
 
 
diff --git a/locale/programs/config.h b/locale/programs/config.h
index 64054657cb..4aa406d755 100644
--- a/locale/programs/config.h
+++ b/locale/programs/config.h
@@ -27,7 +27,6 @@ typedef int wint_t;
 typedef unsigned short int u16_t;
 
 
-
-int euidaccess (__const char *__name, int __type);
+#include_next <config.h>
 
 #endif
diff --git a/locale/programs/ctypedump.c b/locale/programs/ctypedump.c
deleted file mode 100644
index 2a6753495e..0000000000
--- a/locale/programs/ctypedump.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Copyright (C) 1995, 1996 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
-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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <ctype.h>
-#include <endian.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <netinet/in.h>        /* Just for htons() */
-
-/*#include "localedef.h"*/
-#include "localeinfo.h"
-
-
-/* FIXME: these values should be part of the LC_CTYPE information.  */
-#define mb_cur_max 1
-#define mb_cur_min 1
-
-
-#define SWAP32(v)							     \
-	((u32_t) (((((u32_t) (v)) & 0x000000ff) << 24)			     \
-		| ((((u32_t) (v)) & 0x0000ff00) << 8)			     \
-		| ((((u32_t) (v)) & 0x00ff0000) >> 8)			     \
-		| ((((u32_t) (v)) & 0xff000000) >> 24)))
-
-
-
-static inline void
-print_short_in_char (unsigned short val)
-{
-  const unsigned char *p = (const unsigned char *) &val;
-  printf ("\"\\%03o\\%03o\"", p[0], p[1]);
-}
-
-
-static inline void
-print_int_in_char (unsigned int val)
-{
-  const unsigned char *p = (const unsigned char *) &val;
-  printf ("\"\\%03o\\%03o\\%03o\\%03o\"", p[0], p[1], p[2], p[3]);
-}
-
-
-int
-ctype_output (void)
-{
-  int ch;
-  int result = 0;
-  const char *locname = (getenv ("LC_ALL") ?: getenv ("LC_CTYPE") ?:
-			 getenv ("LANG") ?: "POSIX");
-
-  puts ("#include <endian.h>\n");
-
-  if (mb_cur_max == 1)
-    {
-      printf ("const char _nl_%s_LC_CTYPE_class[] = \n", locname);
-      for (ch = -128; ch < (1 << (8 * MB_CUR_MAX)); ++ch)
-        {
-	  if (((ch + 128) % 6) == 0)
-	    printf ("  /* 0x%02x */ ", ch < 0 ? 256 + ch : ch);
-	  print_short_in_char (htons (__ctype_b [ch < 0 ? 256 + ch : ch]));
-	  fputc (((ch + 128) % 6) == 5 ? '\n' : ' ', stdout);
-        }
-      puts (";");
-    }
-
-  printf ("#if BYTE_ORDER == %s\n",
-	  BYTE_ORDER == LITTLE_ENDIAN ? "LITTLE_ENDIAN" : "BIG_ENDIAN");
-
-  if (mb_cur_max == 1)
-    {
-      printf ("const char _nl_%s_LC_CTYPE_toupper[] = \n", locname);
-      for (ch = -128; ch < (1 << (8 * MB_CUR_MAX)); ++ch)
-        {
-	  if (((ch + 128) % 3) == 0)
-	    printf ("  /* 0x%02x */ ", ch < 0 ? 256 + ch : ch);
-	  print_int_in_char (__ctype_toupper[ch < 0 ? 256 + ch : ch]);
-	  fputc (((ch + 128) % 3) == 2 ? '\n' : ' ', stdout);
-        }
-      puts (";");
-
-      printf ("const char _nl_%s_LC_CTYPE_tolower[] = \n", locname);
-      for (ch = -128; ch < (1 << (8 * MB_CUR_MAX)); ++ch)
-        {
-	  if (((ch + 128) % 3) == 0)
-	    printf ("  /* 0x%02x */ ", ch < 0 ? 256 + ch : ch);
-	  print_int_in_char (__ctype_tolower[ch < 0 ? 256 + ch : ch]);
-	  fputc (((ch + 128) % 3) == 2 ? '\n' : ' ', stdout);
-        }
-      puts (";");
-    }
-  else
-    /* not implemented */;
-
-  printf ("#elif BYTE_ORDER == %s\n",
-          BYTE_ORDER == LITTLE_ENDIAN ? "BIG_ENDIAN" : "LITTLE_ENDIAN");
-
-  if (mb_cur_max == 1)
-    {
-      printf ("const char _nl_%s_LC_CTYPE_toupper[] = \n", locname);
-      for (ch = -128; ch < (1 << (8 * MB_CUR_MAX)); ++ch)
-        {
-	  if (((ch + 128) % 3) == 0)
-	    printf ("  /* 0x%02x */ ", ch < 0 ? 256 + ch : ch);
-	  print_int_in_char (SWAP32 (__ctype_toupper[ch < 0 ? 256 + ch : ch]));
-	  fputc (((ch + 128) % 3) == 2 ? '\n' : ' ', stdout);
-        }
-      puts (";");
-
-      printf ("const char _nl_%s_LC_CTYPE_tolower[] = \n", locname);
-      for (ch = -128; ch < (1 << (8 * MB_CUR_MAX)); ++ch)
-        {
-	  if (((ch + 128) % 3) == 0)
-	    printf ("  /* 0x%02x */ ", ch < 0 ? 256 + ch : ch);
-	  print_int_in_char (SWAP32 (__ctype_tolower[ch < 0 ? 256 + ch : ch]));
-	  fputc (((ch + 128) % 3) == 2 ? '\n' : ' ', stdout);
-        }
-      puts (";");
-    }
-  else
-    /* not implemented */;
-
-  puts ("#else\n#error \"BYTE_ORDER\" BYTE_ORDER \" not handled.\"\n#endif\n");
-
-  printf("const struct locale_data _nl_%s_LC_CTYPE = \n\
-{\n\
-  NULL, 0, /* no file mapped */\n\
-  5,\n\
-  {\n\
-    _nl_C_LC_CTYPE_class,\n\
-#ifdef BYTE_ORDER == LITTLE_ENDIAN\n\
-    NULL, NULL,\n\
-#endif\n\
-    _nl_C_LC_CTYPE_toupper,\n\
-    _nl_C_LC_CTYPE_tolower,\n\
-#ifdef BYTE_ORDER == BIG_ENDIAN\n\
-    NULL, NULL,\n\
-#endif\n\
-  }\n\
-};\n", locname);
-
-  return result;
-}
-
-/*
- * Local Variables:
- *  mode:c
- *  c-basic-offset:2
- * End:
- */
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index 4e4ff83a37..8254289598 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -15,7 +15,12 @@ License along with the GNU C Library; see the file COPYING.LIB.  If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include <dirent.h>
+#include <error.h>
 #include <getopt.h>
 #include <langinfo.h>
 #include <libintl.h>
@@ -26,13 +31,9 @@ Cambridge, MA 02139, USA.  */
 #include <unistd.h>
 #include <errno.h>
 
-/*#include "localedef.h"*/
 #include "localeinfo.h"
 
 
-/* If set dump C code describing the current locale.  */
-static int do_dump;
-
 /* If set print the name of the category.  */
 static int show_category_name;
 
@@ -45,7 +46,6 @@ static const struct option long_options[] =
   { "all-locales", no_argument, NULL, 'a' },
   { "category-name", no_argument, &show_category_name, 1 },
   { "charmaps", no_argument, NULL, 'm' },
-  { "dump", no_argument, &do_dump, 1 },
   { "help", no_argument, NULL, 'h' },
   { "keyword-name", no_argument, &show_keyword_name, 1 },
   { "version", no_argument, NULL, 'v' },
@@ -65,35 +65,48 @@ static const struct option long_options[] =
 #define CTYPE_TOUPPER_EL 0
 #define CTYPE_TOLOWER_EL 0
 
-/* XXX Hack */
-struct cat_item
+/* Definition of the data structure which represents a category and its
+   items.  */
+struct category
 {
-  int item_id;
+  int cat_id;
   const char *name;
-  enum { std, opt } status;
-  enum value_type value_type;
-  int min;
-  int max;
+  size_t number;
+  struct cat_item
+  {
+    int item_id;
+    const char *name;
+    enum { std, opt } status;
+    enum value_type value_type;
+    int min;
+    int max;
+  } *item_desc;
 };
 
+/* Simple helper macro.  */
+#define NELEMS(arr) ((sizeof (arr)) / (sizeof (arr[0])))
+
+/* For some tricky stuff.  */
+#define NO_PAREN(Item, More...) Item, ## More
 
 /* We have all categories defined in `categories.def'.  Now construct
    the description and data structure used for all categories.  */
+#define DEFINE_ELEMENT(Item, More...) { Item, ## More },
 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out)      \
     static struct cat_item category##_desc[] =				      \
       {									      \
         NO_PAREN items							      \
       };
 
-#include "locale/aux/categories.def"
+#include "categories.def"
 #undef DEFINE_CATEGORY
 
 static struct category category[] =
   {
 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out)      \
     { _NL_NUM_##category, name, NELEMS (category##_desc) - 1,                 \
-      category##_desc, NULL, NULL, NULL, out },
-#include "locale/aux/categories.def"
+      category##_desc },
+#include "categories.def"
 #undef DEFINE_CATEGORY
   };
 #define NCATEGORIES NELEMS (category)
@@ -105,7 +118,6 @@ static void write_locales (void);
 static void write_charmaps (void);
 static void show_locale_vars (void);
 static void show_info (const char *name);
-static void dump_category (const char *name);
 
 
 int
@@ -118,7 +130,6 @@ main (int argc, char *argv[])
   int do_charmaps = 0;
 
   /* Set initial values for global varaibles.  */
-  do_dump = 0;
   show_category_name = 0;
   show_keyword_name = 0;
 
@@ -170,20 +181,6 @@ main (int argc, char *argv[])
   if (do_help)
     usage (EXIT_SUCCESS);
 
-  /* Dump C code.  */
-  if (do_dump)
-    {
-      printf ("\
-/* Generated by GNU %s %s.  */\n\
-\n\
-#include \"localeinfo.h\"\n", program_invocation_name, VERSION);
-
-      while (optind < argc)
-	dump_category (argv[optind++]);
-
-      exit (EXIT_SUCCESS);
-    }
-
   /* `-a' requests the names of all available locales.  */
   if (do_all != 0)
     {
@@ -235,8 +232,6 @@ Mandatory arguments to long options are mandatory for short options too.\n\
   -c, --category-name   write names of selected categories\n\
   -k, --keyword-name    write names of selected keywords\n\
 \n\
-      --dump            dump C code describing the current locale\n\
-                        (this code can be used in the C library)\n\
 "), program_invocation_name);
 
   exit (status);
@@ -389,6 +384,12 @@ show_info (const char *name)
 	    printf ("%d", cnt == 0 || *val == CHAR_MAX ? -1 : *val);
 	  }
 	  break;
+	case word:
+	  {
+	    unsigned int val = (unsigned int) nl_langinfo (item->item_id);
+	    printf ("%d", val);
+	  }
+	  break;
 	default:
 	}
       putchar ('\n');
@@ -398,13 +399,6 @@ show_info (const char *name)
     {
       size_t item_no;
 
-      if (category[cat_no].outfct != NULL)
-	/* Categories which need special handling of the output are
-	   not written.  This is especially for LC_CTYPE and LC_COLLATE.
-	   It does not make sense to have this large number of cryptic
-	   characters displayed.  */
-	continue;
-
       if (strcmp (name, category[cat_no].name) == 0)
 	/* Print the whole category.  */
 	{
@@ -428,117 +422,3 @@ show_info (const char *name)
 	  }
     }
 }
-
-
-static void
-dump_category (const char *name)
-{
-  char *locname;
-  size_t cat_no, item_no, nstrings;
-
-  for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
-    if (strcmp (name, category[cat_no].name) == 0)
-      break;
-
-  if (cat_no >= NCATEGORIES)
-    return;
-
-  /* The NAME specifies a correct locale category.  */
-  if (category[cat_no].outfct != NULL)
-    {
-      category[cat_no].outfct ();
-      return;
-    }
-
-  locname = (getenv ("LC_ALL") ?: getenv (name) ?:
-	     getenv ("LANG") ?: (char *) "POSIX");
-
-  /* Determine the number of strings in advance.  */
-  nstrings = 0;
-  for (item_no = 0; item_no < category[cat_no].number; ++item_no)
-    switch (category[cat_no].item_desc[item_no].value_type)
-      {
-      case string:
-      case byte:
-      case bytearray:
-	++nstrings;
-	break;
-      case stringarray:
-	nstrings += category[cat_no].item_desc[item_no].max;
-      default:
-      }
-
-  printf ("\nconst struct locale_data _nl_%s_%s =\n{\n"
-	  "  NULL, 0, /* no file mapped */\n  %Zu,\n  {\n",
-	  locname, name, nstrings);
-
-  for (item_no = 0; item_no < category[cat_no].number; ++item_no)
-    switch (category[cat_no].item_desc[item_no].value_type)
-      {
-      case string:
-	{
-	  const char *val = nl_langinfo (
-	    category[cat_no].item_desc[item_no].item_id);
-
-	  if (val != NULL)
-	    printf ("    \"%s\",\n", val);
-	  else
-	    puts ("    NULL,");
-	}
-	break;
-      case stringarray:
-	{
-	  const char *val;
-	  int cnt;
-
-	  for (cnt = 0; cnt < category[cat_no].item_desc[item_no].max; ++cnt)
-	    {
-	      val = nl_langinfo (
-		category[cat_no].item_desc[item_no].item_id + cnt);
-
-	      if (val != NULL)
-		printf ("    \"%s\",\n", val);
-	      else
-                puts ("    NULL,");
-	    }
-	}
-	break;
-      case byte:
-	{
-	  const char *val = nl_langinfo (
-	    category[cat_no].item_desc[item_no].item_id);
-
-	  if (val != NULL)
-	    printf ("    \"\\%o\",\n",
-		    *(unsigned char *) val ? : UCHAR_MAX);
-	  else
-	    puts ("    NULL,");
-	}
-	break;
-      case bytearray:
-	{
-	  const char *bytes = nl_langinfo (
-	    category[cat_no].item_desc[item_no].item_id);
-
-	  if (bytes != NULL)
-	    {
-	      fputs ("    \"", stdout);
-	      if (*bytes != '\0')
-		do
-		  printf ("\\%o", *(unsigned char *) bytes++);
-		while (*bytes != '\0');
-	      else
-		printf ("\\%o", UCHAR_MAX);
-
-	      puts ("\",");
-	    }
-	  else
-	    puts ("    NULL,");
-	}
-	break;
-      default:
-	break;
-      }
-
-  puts ("  }\n};");
-}
diff --git a/po/header.pot b/po/header.pot
new file mode 100644
index 0000000000..c8d0c8a9d2
--- /dev/null
+++ b/po/header.pot
@@ -0,0 +1,14 @@
+# GNU libc message catalog of translations
+# Copyright (C) 1996 Free Software Foundation, Inc.
+# Automatically generated; contact <bug-glibc@prep.ai.mit.edu>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: libc VERSION\n"
+"PO-Revision-Date: DATE\n"
+"Last-Translator: GNU libc maintainers <bug-glibc@prep.ai.mit.edu>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
diff --git a/posix/fnmatch.c b/posix/fnmatch.c
index 1ddea80961..08c1c9448e 100644
--- a/posix/fnmatch.c
+++ b/posix/fnmatch.c
@@ -78,6 +78,9 @@ fnmatch (pattern, string, flags)
 	  if (!(flags & FNM_NOESCAPE))
 	    {
 	      c = *p++;
+	      if (c == '\0')
+		/* Trailing \ loses.  */
+		return FNM_NOMATCH;
 	      c = FOLD (c);
 	    }
 	  if (FOLD (*n) != c)
@@ -129,7 +132,11 @@ fnmatch (pattern, string, flags)
 		register char cstart = c, cend = c;
 
 		if (!(flags & FNM_NOESCAPE) && c == '\\')
-		  cstart = cend = *p++;
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    cstart = cend = *p++;
+		  }
 
 		cstart = cend = FOLD (cstart);
 
@@ -176,8 +183,12 @@ fnmatch (pattern, string, flags)
 
 		c = *p++;
 		if (!(flags & FNM_NOESCAPE) && c == '\\')
-		  /* XXX 1003.2d11 is unclear if this is right.  */
-		  ++p;
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    /* XXX 1003.2d11 is unclear if this is right.  */
+		    ++p;
+		  }
 	      }
 	    if (not)
 	      return FNM_NOMATCH;
diff --git a/posix/glob.c b/posix/glob.c
index eea126d800..1a00af6f3f 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -699,7 +699,7 @@ glob_pattern_p (pattern, quote)
 	return 1;
 
       case '\\':
-	if (quote)
+	if (quote && p[1] != '\0')
 	  ++p;
 	break;
 
diff --git a/setjmp/setjmp.h b/setjmp/setjmp.h
index 12b05f1033..1cd5bbd36d 100644
--- a/setjmp/setjmp.h
+++ b/setjmp/setjmp.h
@@ -32,7 +32,7 @@ __BEGIN_DECLS
 #include <sigset.h>		/* Get `__sigset_t'.  */
 
 /* Calling environment, plus possibly a saved signal mask.  */
-typedef struct __jmp_buf	/* C++ doesn't like tagless structs.  */
+typedef struct __jmp_buf_tag	/* C++ doesn't like tagless structs.  */
   {
     /* NOTE: The machine-dependent definitions of `__sigsetjmp'
        assume that a `jmp_buf' begins with a `__jmp_buf'.
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index caa8179624..38d5367ba2 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -1,5 +1,5 @@
 /* Internal function for converting integers to ASCII.
-Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+Copyright (C) 1994, 1995, 1996 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.ai.mit.edu>.
@@ -159,10 +159,10 @@ static const struct base_table_t base_table[] =
 };
 
 /* Lower-case digits.  */
-static const char _itoa_lower_digits[]
+const char _itoa_lower_digits[]
 	= "0123456789abcdefghijklmnopqrstuvwxyz";
 /* Upper-case digits.  */
-static const char _itoa_upper_digits[]
+const char _itoa_upper_digits[]
 	= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
 
diff --git a/stdio-common/_itoa.h b/stdio-common/_itoa.h
index ab3d1d1d3a..75f5f85892 100644
--- a/stdio-common/_itoa.h
+++ b/stdio-common/_itoa.h
@@ -1,5 +1,5 @@
 /* Internal function for converting integers to ASCII.
-Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+Copyright (C) 1994, 1995, 1996 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,4 +29,31 @@ Cambridge, MA 02139, USA.  */
 extern char *_itoa __P ((unsigned long long int value, char *buflim,
 			 unsigned int base, int upper_case));
 
+static inline char *_itoa_word (unsigned long value, char *buflim,
+				unsigned int base, int upper_case)
+{
+  extern const char _itoa_upper_digits[], _itoa_lower_digits[];
+  const char *digits = upper_case ? _itoa_upper_digits : _itoa_lower_digits;
+  char *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	/* itoa.h */
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index 9abbdba187..a7960e6003 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -1,5 +1,5 @@
 /* Internal header for parsing printf format strings.
-Copyright (C) 1995 Free Software Foundation, Inc.
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of th GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -73,14 +73,14 @@ union printf_arg
 /* Read a simple integer from a string and update the string pointer.
    It is assumed that the first character is a digit.  */
 static inline unsigned int
-read_int (const char * *pstr)
+read_int (const UCHAR_T * *pstr)
 {
-  unsigned int retval = **pstr - '0';
+  unsigned int retval = **pstr - L_('0');
 
-  while (isdigit (*++(*pstr)))
+  while (ISDIGIT (*++(*pstr)))
     {
       retval *= 10;
-      retval += **pstr - '0';
+      retval += **pstr - L_('0');
     }
 
   return retval;
@@ -91,13 +91,13 @@ read_int (const char * *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)
+find_spec (const char *format, mbstate_t *ps)
 {
   while (*format != '\0' && *format != '%')
     {
       int len;
 
-      if (isascii (*format) || (len = mblen (format, MB_CUR_MAX)) <= 0)
+      if (isascii (*format) || (len = mbrlen (format, MB_CUR_MAX, ps)) <= 0)
 	++format;
       else
 	format += len;
@@ -116,8 +116,8 @@ extern printf_arginfo_function **__printf_arginfo_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
-parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
-		size_t *max_ref_arg)
+parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec,
+		size_t *max_ref_arg, mbstate_t *ps)
 {
   unsigned int n;
   size_t nargs = 0;
@@ -135,13 +135,13 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
   spec->info.pad = ' ';
 
   /* Test for positional argument.  */
-  if (isdigit (*format))
+  if (ISDIGIT (*format))
     {
-      const char *begin = format;
+      const UCHAR_T *begin = format;
 
       n = read_int (&format);
 
-      if (n > 0 && *format == '$')
+      if (n > 0 && *format == L_('$'))
 	/* Is positional parameter.  */
 	{
 	  ++format;		/* Skip the '$'.  */
@@ -155,32 +155,32 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
     }
 
   /* Check for spec modifiers.  */
-  while (*format == ' ' || *format == '+' || *format == '-' ||
-	 *format == '#' || *format == '0' || *format == '\'')
+  while (*format == L_(' ') || *format == L_('+') || *format == L_('-') ||
+	 *format == L_('#') || *format == L_('0') || *format == L_('\''))
     switch (*format++)
       {
-      case ' ':
+      case L_(' '):
 	/* Output a space in place of a sign, when there is no sign.  */
 	spec->info.space = 1;
 	break;
-      case '+':
+      case L_('+'):
 	/* Always output + or - for numbers.  */
 	spec->info.showsign = 1;
 	break;
-      case '-':
+      case L_('-'):
 	/* Left-justify things.  */
 	spec->info.left = 1;
 	break;
-      case '#':
+      case L_('#'):
 	/* Use the "alternate form":
 	   Hex has 0x or 0X, FP always has a decimal point.  */
 	spec->info.alt = 1;
 	break;
-      case '0':
+      case L_('0'):
 	/* Pad with 0s.  */
 	spec->info.pad = '0';
 	break;
-      case '\'':
+      case L_('\''):
 	/* Show grouping in numbers if the locale information
 	   indicates any.  */
 	spec->info.group = 1;
@@ -192,18 +192,18 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
   /* Get the field width.  */
   spec->width_arg = -1;
   spec->info.width = 0;
-  if (*format == '*')
+  if (*format == L_('*'))
     {
       /* The field width is given in an argument.
 	 A negative field width indicates left justification.  */
-      const char *begin = ++format;
+      const UCHAR_T *begin = ++format;
 
-      if (isdigit (*format))
+      if (ISDIGIT (*format))
 	{
 	  /* The width argument might be found in a positional parameter.  */
 	  n = read_int (&format);
 
-	  if (n > 0 && *format == '$')
+	  if (n > 0 && *format == L_('$'))
 	    {
 	      spec->width_arg = n - 1;
 	      *max_ref_arg = MAX (*max_ref_arg, n);
@@ -219,7 +219,7 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
 	  format = begin;	/* Step back and reread.  */
 	}
     }
-  else if (isdigit (*format))
+  else if (ISDIGIT (*format))
     /* Constant width specification.  */
     spec->info.width = read_int (&format);
 
@@ -227,19 +227,19 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
   spec->prec_arg = -1;
   /* -1 means none given; 0 means explicit 0.  */
   spec->info.prec = -1;
-  if (*format == '.')
+  if (*format == L_('.'))
     {
       ++format;
-      if (*format == '*')
+      if (*format == L_('*'))
 	{
 	  /* The precision is given in an argument.  */
-	  const char *begin = ++format;
+	  const UCHAR_T *begin = ++format;
 
-	  if (isdigit (*format))
+	  if (ISDIGIT (*format))
 	    {
 	      n = read_int (&format);
 
-	      if (n > 0 && *format == '$')
+	      if (n > 0 && *format == L_('$'))
 		{
 		  spec->prec_arg = n - 1;
 		  *max_ref_arg = MAX (*max_ref_arg, n);
@@ -255,7 +255,7 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
 	      format = begin;
 	    }
 	}
-      else if (isdigit (*format))
+      else if (ISDIGIT (*format))
 	spec->info.prec = read_int (&format);
       else
 	/* "%.?" is treated like "%.0?".  */
@@ -268,40 +268,41 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
   spec->info.is_short = 0;
   spec->info.is_long = 0;
 
-  while (*format == 'h' || *format == 'l' || *format == 'L' ||
-	 *format == 'Z' || *format == 'q')
+  if (*format == L_('h') || *format == L_('l') || *format == L_('L') ||
+      *format == L_('Z') || *format == L_('q'))
     switch (*format++)
       {
-      case 'h':
+      case L_('h'):
 	/* int's are short int's.  */
 	spec->info.is_short = 1;
 	break;
-      case 'l':
-	if (spec->info.is_long)
-	  /* A double `l' is equivalent to an `L'.  */
-	  spec->info.is_longlong = 1;
-	else
-	  /* int's are long int's.  */
-	  spec->info.is_long = 1;
-	break;
-      case 'L':
+      case L_('l'):
+	/* int's are long int's.  */
+	spec->info.is_long = 1;
+	if (*format != L_('l'))
+	  break;
+	++format;
+	/* FALLTHROUGH */
+      case L_('L'):
 	/* double's are long double's, and int's are long long int's.  */
+      case L_('q'):
+	/* 4.4 uses this for long long.  */
 	spec->info.is_long_double = 1;
 	break;
-      case 'Z':
+      case L_('Z'):
 	/* int's are size_t's.  */
 	assert (sizeof(size_t) <= sizeof(unsigned long long int));
 	spec->info.is_longlong = sizeof(size_t) > sizeof(unsigned long int);
 	spec->info.is_long = sizeof(size_t) > sizeof(unsigned int);
 	break;
-      case 'q':
-	/* 4.4 uses this for long long.  */
-	spec->info.is_longlong = 1;
-	break;
       }
 
   /* Get the format specification.  */
-  spec->info.spec = *format++;
+#ifdef THIS_IS_INCOMPATIBLE_WITH_LINUX_LIBC
+  spec->info.spec = (wchar_t) *format++;
+#else
+  spec->info.spec = (char) *format++;
+#endif
   if (__printf_arginfo_table != NULL &&
       __printf_arginfo_table[spec->info.spec] != NULL)
     /* We don't try to get the types for all arguments if the format
@@ -315,12 +316,12 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
 
       switch (spec->info.spec)
 	{
-	case 'i':
-	case 'd':
-	case 'u':
-	case 'o':
-	case 'X':
-	case 'x':
+	case L'i':
+	case L'd':
+	case L'u':
+	case L'o':
+	case L'X':
+	case L'x':
 	  if (spec->info.is_longlong)
 	    spec->data_arg_type = PA_INT|PA_FLAG_LONG_LONG;
 	  else if (spec->info.is_long)
@@ -330,30 +331,30 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
 	  else
 	    spec->data_arg_type = PA_INT;
 	  break;
-	case 'e':
-	case 'E':
-	case 'f':
-	case 'g':
-	case 'G':
+	case L'e':
+	case L'E':
+	case L'f':
+	case L'g':
+	case L'G':
 	  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 'c':
+	case L'c':
 	  spec->data_arg_type = PA_CHAR;
 	  break;
-	case 's':
+	case L's':
 	  spec->data_arg_type = PA_STRING;
 	  break;
-	case 'p':
+	case L'p':
 	  spec->data_arg_type = PA_POINTER;
 	  break;
-	case 'n':
+	case L'n':
 	  spec->data_arg_type = PA_INT|PA_FLAG_PTR;
 	  break;
 
-	case 'm':
+	case L'm':
 	default:
 	  /* An unknown spec will consume no args.  */
 	  spec->ndata_args = 0;
@@ -370,14 +371,14 @@ parse_one_spec (const char *format, size_t posn, struct printf_spec *spec,
 	}
     }
 
-  if (spec->info.spec == '\0')
+  if (spec->info.spec == L'\0')
     /* Format ended before this spec was complete.  */
     spec->end_of_fmt = spec->next_fmt = format - 1;
   else
     {
       /* Find the next format spec.  */
       spec->end_of_fmt = format;
-      spec->next_fmt = find_spec (format);
+      spec->next_fmt = find_spec (format, ps);
     }
 
   return nargs;
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
index 811a9cb7eb..d0756de7d4 100644
--- a/stdio-common/printf-prs.c
+++ b/stdio-common/printf-prs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1995, 1996 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
@@ -20,6 +20,50 @@ Cambridge, MA 02139, USA.  */
 #include <printf.h>
 #include <stdlib.h>
 #include <string.h>
+#include <wchar.h>
+
+#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)							      \
+    { if (__printf_pad (s, Padchar, width) == -1)			      \
+	return -1; else done += width; }
+# 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)							      \
+    { if (__wprintf_pad (s, Padchar, width) == -1)			      \
+	return -1; else done += width; }
+# endif
+#endif
 
 #include "printf-parse.h"
 
@@ -33,15 +77,17 @@ parse_printf_format (fmt, n, argtypes)
   size_t nargs;			/* Number of arguments.  */
   size_t max_ref_arg;		/* Highest index used in a positional arg.  */
   struct printf_spec spec;
+  mbstate_t mbstate;
 
   nargs = 0;
   max_ref_arg = 0;
+  mbstate = 0;
 
   /* Search for format specifications.  */
-  for (fmt = find_spec (fmt); *fmt != '\0'; fmt = spec.next_fmt)
+  for (fmt = find_spec (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt)
     {
       /* Parse this spec.  */
-      nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg);
+      nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg, &mbstate);
 
       /* If the width is determined by an argument this is an int.  */
       if (spec.width_arg != -1 && spec.width_arg < n)
diff --git a/stdio-common/printf.h b/stdio-common/printf.h
index df7747ec38..6e90154cde 100644
--- a/stdio-common/printf.h
+++ b/stdio-common/printf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 95, 96 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,6 +26,7 @@ __BEGIN_DECLS
 #define	__need_FILE
 #include <stdio.h>
 #define	__need_size_t
+#define __need_wchar_t
 #include <stddef.h>
 
 
@@ -33,7 +34,11 @@ struct printf_info
 {
   int prec;			/* Precision.  */
   int width;			/* Width.  */
-  unsigned char spec;		/* Format letter.  */
+#ifdef THIS_IS_INCOMPATIBLE_WITH_LINUX_LIBC
+  wchar_t spec;			/* Format letter.  */
+#else
+  char spec;			/* Format letter.  */
+#endif
   unsigned int is_long_double:1;/* L flag.  */
   unsigned int is_short:1;	/* h flag.  */
   unsigned int is_long:1;	/* l flag.  */
diff --git a/stdio-common/tst-printf.c b/stdio-common/tst-printf.c
index c177da18b2..12212b87b2 100644
--- a/stdio-common/tst-printf.c
+++ b/stdio-common/tst-printf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 1995, 1996 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
@@ -188,7 +188,7 @@ I am ready for my first lesson today.";
   {
     double d = FLT_MIN;
     int niter = 17;
-    
+
     while (niter-- != 0)
       printf ("%.17e\n", d / 2);
     fflush (stdout);
@@ -233,7 +233,18 @@ I am ready for my first lesson today.";
   rfg1 ();
   rfg2 ();
 
-  exit(EXIT_SUCCESS);
+  {
+    char buf[200];
+    int result;
+
+    sprintf(buf,"%*s%*s%*s",-1,"one",-20,"two",-30,"three");
+
+    result = strcmp (buf,
+		     "onetwo                 three                         ");
+
+    puts (result != 0 ? "Test failed!" : "Test ok.");
+    return result != 0;
+  }
 }
 
 rfg1 ()
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index d6b9f9a092..26b31a6ed2 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -13,128 +13,162 @@ 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 #include <ctype.h>
-#include <errno.h>
-#include <float.h>
 #include <limits.h>
-#include <math.h>
 #include <printf.h>
 #include <stdarg.h>
 #include <stdlib.h>
-#include <string.h>
-#include <printf.h>
-#include <stddef.h>
+#include <wchar.h>
 #include "_itoa.h"
 #include "../locale/localeinfo.h"
 
+/* This code is shared between the standard stdio implementation found
+   in GNU C library and the libio implementation originally found in
+   GNU libg++.
+
+   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)							      \
+    { if (__printf_pad (s, Padchar, width) == -1)			      \
+	return -1; else done += width; }
+# 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)							      \
+    { if (__wprintf_pad (s, Padchar, width) == -1)			      \
+	return -1; else done += width; }
+# endif
+#endif
+
 /* Include the shared code for parsing the format string.  */
 #include "printf-parse.h"
 
 
-/* This function from the GNU C library is also used in libio.
-   To compile for use in libio, compile with -DUSE_IN_LIBIO.  */
-
 #ifdef USE_IN_LIBIO
 /* This code is for use in libio.  */
-#include <libioP.h>
-#define PUT(f, s, n)	_IO_sputn (f, s, n)
-#define PAD(padchar)							      \
-  if (specs[cnt].info.width > 0)					      \
-    done += _IO_padn (s, padchar, specs[cnt].info.width)
-#define PUTC(c, f)	_IO_putc (c, f)
-#define vfprintf	_IO_vfprintf
-#define size_t		_IO_size_t
-#define FILE		_IO_FILE
-#define va_list		_IO_va_list
-#undef	BUFSIZ
-#define BUFSIZ		_IO_BUFSIZ
-#define ARGCHECK(s, format)						      \
+# include <libioP.h>
+# define PUTC(C, F)	_IO_putc (C, F)
+# define vfprintf	_IO_vfprintf
+# define size_t		_IO_size_t
+# define FILE		_IO_FILE
+# define va_list	_IO_va_list
+# undef	BUFSIZ
+# define BUFSIZ		_IO_BUFSIZ
+# define ARGCHECK(S, Format)						      \
   do									      \
     {									      \
       /* Check file argument for consistence.  */			      \
-      CHECK_FILE (s, -1);						      \
-      if (s->_flags & _IO_NO_WRITES || format == NULL)			      \
+      CHECK_FILE (S, -1);						      \
+      if (S->_flags & _IO_NO_WRITES || Format == NULL)			      \
 	{								      \
 	  MAYBE_SET_EINVAL;						      \
 	  return -1;							      \
 	}								      \
     } while (0)
-#define UNBUFFERED_P(s)	((s)->_IO_file_flags & _IO_UNBUFFERED)
+# define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
 #else /* ! USE_IN_LIBIO */
 /* This code is for use in the GNU C library.  */
-#include <stdio.h>
-#define PUTC(c, f)	putc (c, f)
-#define PUT(f, s, n)	fwrite (s, 1, n, f)
-ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
-#define PAD(padchar)							      \
-  if (specs[cnt].info.width > 0)					      \
-    { if (__printf_pad (s, padchar, specs[cnt].info.width) == -1)	      \
-	return -1; else done += specs[cnt].info.width; }
-#define ARGCHECK(s, format) \
+# include <stdio.h>
+# define PUT(F, S, N)	fwrite (S, 1, N, F)
+# define ARGCHECK(S, Format)						      \
   do									      \
     {									      \
       /* Check file argument for consistence.  */			      \
-      if (!__validfp(s) || !s->__mode.__write || format == NULL)	      \
+      if (!__validfp(S) || !S->__mode.__write || Format == NULL)	      \
 	{								      \
 	  errno = EINVAL;						      \
 	  return -1;							      \
 	}								      \
-      if (!s->__seen)							      \
+      if (!S->__seen)							      \
 	{								      \
-	  if (__flshfp (s, EOF) == EOF)					      \
+	  if (__flshfp (S, EOF) == EOF)					      \
 	    return -1;							      \
 	}								      \
-    } while (0)
-#define UNBUFFERED_P(s)	((s)->__buffer == NULL)
+    }									      \
+   while (0)
+# define UNBUFFERED_P(s) ((s)->__buffer == NULL)
 #endif /* USE_IN_LIBIO */
 
 
-#define	outchar(x)							      \
+#define	outchar(Ch)							      \
   do									      \
     {									      \
-      register const int outc = (x);					      \
+      register const int outc = (Ch);					      \
       if (PUTC (outc, s) == EOF)					      \
 	return -1;							      \
       else								      \
 	++done;								      \
-    } while (0)
+    }									      \
+  while (0)
 
-#define outstring(string, len)						      \
+#define outstring(String, Len)						      \
   do									      \
     {									      \
-      if (len > 20)							      \
-	{								      \
-	  if (PUT (s, string, len) != len)				      \
-	    return -1;							      \
-	  done += len;							      \
-	}								      \
-      else								      \
-	{								      \
-	  register const char *cp = string;				      \
-	  register int l = len;						      \
-	  while (l-- > 0)						      \
-	    outchar (*cp++);						      \
-	}								      \
-    } while (0)
+      if (PUT (s, String, Len) != Len)					      \
+	return -1;							      \
+      done += Len;							      \
+    }									      \
+  while (0)
 
-/* Helper function to provide temporary buffering for unbuffered streams.  */
-static int buffered_vfprintf __P ((FILE *stream, const char *fmt, va_list));
+/* For handling long_double and longlong we use the same flag.  */
+#ifndef is_longlong
+# define is_longlong is_long_double
+#endif
+
+
+/* Global variables.  */
+static const char null[] = "(null)";
 
-static printf_function printf_unknown;
 
-extern printf_function **__printf_function_table;
+/* Helper function to provide temporary buffering for unbuffered streams.  */
+static int buffered_vfprintf __P ((FILE *stream, const CHAR_T *fmt, va_list));
+
+/* Handle unknown format specifier.  */
+static int printf_unknown __P ((FILE *, const struct printf_info *,
+				const void *const *));
 
-static char *group_number __P ((char *, char *, const char *, wchar_t));
+/* Group digits of number string.  */
+static char *group_number __P ((CHAR_T *, CHAR_T *, const CHAR_T *, wchar_t));
 
 
+/* The function itself.  */
 int
-vfprintf (s, format, ap)
-    register FILE *s;
-    const char *format;
-    va_list ap;
+vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 {
   /* The character used as thousands separator.  */
   wchar_t thousands_sep;
@@ -142,35 +176,613 @@ vfprintf (s, format, ap)
   /* The string describing the size of groups of digits.  */
   const char *grouping;
 
-  /* Array with information about the needed arguments.  This has to be
-     dynamically extendable.  */
-  size_t nspecs;
-  size_t nspecs_max;
-  struct printf_spec *specs;
+  /* Place to accumulate the result.  */
+  int done;
 
-  /* The number of arguments the format string requests.  This will
-     determine the size of the array needed to store the argument
-     attributes.  */
-  size_t nargs;
-  int *args_type;
-  union printf_arg *args_value;
-
-  /* Positional parameters refer to arguments directly.  This could also
-     determine the maximum number of arguments.  Track the maximum number.  */
-  size_t max_ref_arg;
+  /* Current character in format string.  */
+  const UCHAR_T *f;
 
   /* End of leading constant string.  */
-  const char *lead_str_end;
+  const UCHAR_T *lead_str_end;
+
+  /* Points to next format specifier.  */
+  const UCHAR_T *end_of_spec;
+
+  /* Buffer intermediate results.  */
+  char work_buffer[1000];
+#define workend (&work_buffer[sizeof (work_buffer) - 1])
+
+  /* State for restartable multibyte character handling functions.  */
+  mbstate_t mbstate;
+
+  /* We have to save the original argument pointer.  */
+  va_list ap_save;
 
-  /* Number of characters written.  */
-  register size_t done = 0;
+  /* Count number of specifiers we already processed.  */
+  int nspecs_done;
+
+
+  /* This table maps a character into a number representing a
+     class.  In each step there is a destination label for each
+     class.  */
+  static const int jump_table[] =
+  {
+    /* ' ' */  1,            0,            0, /* '#' */  4,
+	       0, /* '%' */ 14,            0, /* '\''*/  6,
+	       0,            0, /* '*' */  7, /* '+' */  2,
+	       0, /* '-' */  3, /* '.' */  9,            0,
+    /* '0' */  5, /* '1' */  8, /* '2' */  8, /* '3' */  8,
+    /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,
+    /* '8' */  8, /* '9' */  8,            0,            0,
+	       0,            0,            0,            0,
+	       0,            0,            0,            0,
+	       0, /* 'E' */ 19,            0, /* 'G' */ 19,
+	       0,            0,            0,            0,
+    /* 'L' */ 12,            0,            0,            0,
+	       0,            0,            0,            0,
+	       0,            0,            0,            0,
+    /* 'X' */ 18,            0, /* 'Z' */ 13,            0,
+	       0,            0,            0,            0,
+	       0,            0,            0, /* 'c' */ 20,
+    /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
+    /* 'h' */ 10, /* 'i' */ 15,            0,            0,
+    /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
+    /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
+	       0, /* 'u' */ 16,            0,            0,
+    /* 'x' */ 18
+  };
+
+#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < ' ' || (Ch) > 'x')
+#define CHAR_CLASS(Ch) (jump_table[(int) (Ch) - ' '])
+#define JUMP(ChExpr, table)						      \
+      do								      \
+	{								      \
+	  const void *ptr;						      \
+	  spec = (ChExpr);						      \
+	  ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)		      \
+	    : table[CHAR_CLASS (spec)];					      \
+	  goto *ptr;							      \
+	}								      \
+      while (0)
+
+#define STEP0_3_TABLE							      \
+    /* Step 0: at the beginning.  */					      \
+    static const void *step0_jumps[25] =				      \
+    {									      \
+      REF (form_unknown),						      \
+      REF (flag_space),		/* for ' ' */				      \
+      REF (flag_plus),		/* for '+' */				      \
+      REF (flag_minus),		/* for '-' */				      \
+      REF (flag_hash),		/* for '<hash>' */			      \
+      REF (flag_zero),		/* for '0' */				      \
+      REF (flag_quote),		/* for '\'' */				      \
+      REF (width_asterics),	/* for '*' */				      \
+      REF (width),		/* for '1'...'9' */			      \
+      REF (precision),		/* for '.' */				      \
+      REF (mod_half),		/* for 'h' */				      \
+      REF (mod_long),		/* for 'l' */				      \
+      REF (mod_longlong),	/* for 'L', 'q' */			      \
+      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (form_percent),	/* for '%' */				      \
+      REF (form_integer),	/* for 'd', 'i' */			      \
+      REF (form_unsigned),	/* for 'u' */				      \
+      REF (form_octal),		/* for 'o' */				      \
+      REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_float),		/* for 'E', 'e', 'f', 'G', 'g' */	      \
+      REF (form_character),	/* for 'c' */				      \
+      REF (form_string),	/* for 's' */				      \
+      REF (form_pointer),	/* for 'p' */				      \
+      REF (form_number),	/* for 'n' */				      \
+      REF (form_strerror)	/* for 'm' */				      \
+    };									      \
+    /* Step 1: after processing width.  */				      \
+    static const void *step1_jumps[25] =				      \
+    {									      \
+      REF (form_unknown),						      \
+      REF (form_unknown),	/* for ' ' */				      \
+      REF (form_unknown),	/* for '+' */				      \
+      REF (form_unknown),	/* for '-' */				      \
+      REF (form_unknown),	/* for '<hash>' */			      \
+      REF (form_unknown),	/* for '0' */				      \
+      REF (form_unknown),	/* for '\'' */				      \
+      REF (form_unknown),	/* for '*' */				      \
+      REF (form_unknown),	/* for '1'...'9' */			      \
+      REF (precision),		/* for '.' */				      \
+      REF (mod_half),		/* for 'h' */				      \
+      REF (mod_long),		/* for 'l' */				      \
+      REF (mod_longlong),	/* for 'L', 'q' */			      \
+      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (form_percent),	/* for '%' */				      \
+      REF (form_integer),	/* for 'd', 'i' */			      \
+      REF (form_unsigned),	/* for 'u' */				      \
+      REF (form_octal),		/* for 'o' */				      \
+      REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_float),		/* for 'E', 'e', 'f', 'G', 'g' */	      \
+      REF (form_character),	/* for 'c' */				      \
+      REF (form_string),	/* for 's' */				      \
+      REF (form_pointer),	/* for 'p' */				      \
+      REF (form_number),	/* for 'n' */				      \
+      REF (form_strerror)	/* for 'm' */				      \
+    };									      \
+    /* Step 2: after processing precision.  */				      \
+    static const void *step2_jumps[25] =				      \
+    {									      \
+      REF (form_unknown),						      \
+      REF (form_unknown),	/* for ' ' */				      \
+      REF (form_unknown),	/* for '+' */				      \
+      REF (form_unknown),	/* for '-' */				      \
+      REF (form_unknown),	/* for '<hash>' */			      \
+      REF (form_unknown),	/* for '0' */				      \
+      REF (form_unknown),	/* for '\'' */				      \
+      REF (form_unknown),	/* for '*' */				      \
+      REF (form_unknown),	/* for '1'...'9' */			      \
+      REF (form_unknown),	/* for '.' */				      \
+      REF (mod_half),		/* for 'h' */				      \
+      REF (mod_long),		/* for 'l' */				      \
+      REF (mod_longlong),	/* for 'L', 'q' */			      \
+      REF (mod_size_t),		/* for 'Z' */				      \
+      REF (form_percent),	/* for '%' */				      \
+      REF (form_integer),	/* for 'd', 'i' */			      \
+      REF (form_unsigned),	/* for 'u' */				      \
+      REF (form_octal),		/* for 'o' */				      \
+      REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_float),		/* for 'E', 'e', 'f', 'G', 'g' */	      \
+      REF (form_character),	/* for 'c' */				      \
+      REF (form_string),	/* for 's' */				      \
+      REF (form_pointer),	/* for 'p' */				      \
+      REF (form_number),	/* for 'n' */				      \
+      REF (form_strerror)	/* for 'm' */				      \
+    };									      \
+    /* Step 3: after processing first 'l' modifier.  */			      \
+    static const void *step3_jumps[25] =				      \
+    {									      \
+      REF (form_unknown),						      \
+      REF (form_unknown),	/* for ' ' */				      \
+      REF (form_unknown),	/* for '+' */				      \
+      REF (form_unknown),	/* for '-' */				      \
+      REF (form_unknown),	/* for '<hash>' */			      \
+      REF (form_unknown),	/* for '0' */				      \
+      REF (form_unknown),	/* for '\'' */				      \
+      REF (form_unknown),	/* for '*' */				      \
+      REF (form_unknown),	/* for '1'...'9' */			      \
+      REF (form_unknown),	/* for '.' */				      \
+      REF (form_unknown),	/* for 'h' */				      \
+      REF (mod_longlong),	/* for 'l' */				      \
+      REF (form_unknown),	/* for 'L', 'q' */			      \
+      REF (form_unknown),	/* for 'Z' */				      \
+      REF (form_percent),	/* for '%' */				      \
+      REF (form_integer),	/* for 'd', 'i' */			      \
+      REF (form_unsigned),	/* for 'u' */				      \
+      REF (form_octal),		/* for 'o' */				      \
+      REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_float),		/* for 'E', 'e', 'f', 'G', 'g' */	      \
+      REF (form_character),	/* for 'c' */				      \
+      REF (form_string),	/* for 's' */				      \
+      REF (form_pointer),	/* for 'p' */				      \
+      REF (form_number),	/* for 'n' */				      \
+      REF (form_strerror)	/* for 'm' */				      \
+    }
 
-  /* Running pointer through format string.  */
-  const char *f;
+#define STEP4_TABLE							      \
+    /* Step 4: processing format specifier.  */				      \
+    static const void *step4_jumps[25] =				      \
+    {									      \
+      REF (form_unknown),						      \
+      REF (form_unknown),	/* for ' ' */				      \
+      REF (form_unknown),	/* for '+' */				      \
+      REF (form_unknown),	/* for '-' */				      \
+      REF (form_unknown),	/* for '<hash>' */			      \
+      REF (form_unknown),	/* for '0' */				      \
+      REF (form_unknown),	/* for '\'' */				      \
+      REF (form_unknown),	/* for '*' */				      \
+      REF (form_unknown),	/* for '1'...'9' */			      \
+      REF (form_unknown),	/* for '.' */				      \
+      REF (form_unknown),	/* for 'h' */				      \
+      REF (form_unknown),	/* for 'l' */				      \
+      REF (form_unknown),	/* for 'L', 'q' */			      \
+      REF (form_unknown),	/* for 'Z' */				      \
+      REF (form_percent),	/* for '%' */				      \
+      REF (form_integer),	/* for 'd', 'i' */			      \
+      REF (form_unsigned),	/* for 'u' */				      \
+      REF (form_octal),		/* for 'o' */				      \
+      REF (form_hexa),		/* for 'X', 'x' */			      \
+      REF (form_float),		/* for 'E', 'e', 'f', 'G', 'g' */	      \
+      REF (form_character),	/* for 'c' */				      \
+      REF (form_string),	/* for 's' */				      \
+      REF (form_pointer),	/* for 'p' */				      \
+      REF (form_number),	/* for 'n' */				      \
+      REF (form_strerror)	/* for 'm' */				      \
+    }
 
-  /* Just a counter.  */
-  int cnt;
 
+#define process_arg(fspec)						      \
+      /* Start real work.  We know about all flag and modifiers and	      \
+	 now process the wanted format specifier.  */			      \
+    LABEL (form_percent):						      \
+      /* Write a literal "%".  */					      \
+      outchar ('%');							      \
+      break;								      \
+									      \
+    LABEL (form_integer):						      \
+      /* Signed decimal integer.  */					      \
+      base = 10;							      \
+									      \
+      if (is_longlong)							      \
+	{								      \
+	  long long int signed_number;					      \
+									      \
+	  signed_number = va_arg (ap, long long int);			      \
+									      \
+	  is_negative = signed_number < 0;				      \
+	  number.longlong = is_negative ? (- signed_number) : signed_number;  \
+									      \
+	  goto LABEL (longlong_number);					      \
+	}								      \
+      else								      \
+	{								      \
+	  long int signed_number;					      \
+									      \
+	  if (is_long)							      \
+	    signed_number = va_arg (ap, long int);			      \
+	  else	/* `short int' will be promoted to `int'.  */		      \
+	    signed_number = va_arg (ap, int);				      \
+									      \
+	  is_negative = signed_number < 0;				      \
+	  number.word = is_negative ? (- signed_number) : signed_number;      \
+									      \
+	  goto LABEL (number);						      \
+	}								      \
+      /* NOTREACHED */							      \
+									      \
+    LABEL (form_unsigned):						      \
+      /* Unsigned decimal integer.  */					      \
+      base = 10;							      \
+      goto LABEL (unsigned_number);					      \
+      /* NOTREACHED */							      \
+									      \
+    LABEL (form_octal):							      \
+      /* Unsigned octal integer.  */					      \
+      base = 8;								      \
+      goto LABEL (unsigned_number);					      \
+      /* NOTREACHED */							      \
+									      \
+    LABEL (form_hexa):							      \
+      /* Unsigned hexadecimal integer.  */				      \
+      base = 16;							      \
+									      \
+    LABEL (unsigned_number):	  /* Unsigned number of base BASE.  */	      \
+									      \
+      /* ANSI specifies the `+' and ` ' flags only for signed		      \
+	 conversions.  */						      \
+      is_negative = 0;							      \
+      showsign = 0;							      \
+      space = 0;							      \
+									      \
+      if (is_longlong)							      \
+	{								      \
+	  number.longlong = va_arg (ap, unsigned long long int);	      \
+									      \
+	LABEL (longlong_number):					      \
+	  if (prec < 0)							      \
+	    /* Supply a default precision if none was given.  */	      \
+	    prec = 1;							      \
+	  else								      \
+	    /* We have to take care for the '0' flag.  If a precision	      \
+	       is given it must be ignored.  */				      \
+	    pad = ' ';							      \
+									      \
+	  /* If the precision is 0 and the number is 0 nothing has to	      \
+	     be written for the number.  */				      \
+	  if (prec == 0 && number.longlong == 0)			      \
+	    string = workend;						      \
+	  else								      \
+	    {								      \
+	      /* Put the number in WORK.  */				      \
+	      string = _itoa (number.longlong, workend + 1, base,	      \
+			      spec == 'X');				      \
+	      string -= 1;						      \
+	      if (group && grouping)					      \
+		string = group_number (string, workend, grouping,	      \
+				       thousands_sep);			      \
+	    }								      \
+	  /* Simply further test for num != 0.  */			      \
+	  number.word = number.longlong != 0;				      \
+	}								      \
+      else								      \
+	{								      \
+	  if (is_long)							      \
+	    number.word = va_arg (ap, unsigned long int);		      \
+	  else								      \
+	    number.word = va_arg (ap, unsigned int); /* Promoted.  */	      \
+									      \
+	LABEL (number):							      \
+	  if (prec < 0)							      \
+	    /* Supply a default precision if none was given.  */	      \
+	    prec = 1;							      \
+	  else								      \
+	    /* We have to take care for the '0' flag.  If a precision	      \
+	       is given it must be ignored.  */				      \
+	    pad = ' ';							      \
+									      \
+	  /* If the precision is 0 and the number is 0 nothing has to	      \
+	     be written for the number.  */				      \
+	  if (prec == 0 && number.word == 0)				      \
+	    string = workend;						      \
+	  else								      \
+	    {								      \
+	      /* Put the number in WORK.  */				      \
+	      string = _itoa_word (number.word, workend + 1, base,	      \
+				   spec == 'X');			      \
+	      string -= 1;						      \
+	      if (group && grouping)					      \
+		string = group_number (string, workend, grouping,	      \
+				       thousands_sep);			      \
+	    }								      \
+	}								      \
+									      \
+      prec -= workend - string;						      \
+									      \
+      if (prec > 0)							      \
+	/* Add zeros to the precision.  */				      \
+	while (prec-- > 0)						      \
+	  *string-- = '0';						      \
+      else if (number.word != 0 && alt && base == 8)			      \
+	/* Add octal marker.  */					      \
+	*string-- = '0';						      \
+									      \
+      if (!left)							      \
+	{								      \
+	  width -= workend - string;					      \
+									      \
+	  if (number.word != 0 && alt && base == 16)			      \
+	    /* Account for 0X hex marker.  */				      \
+	    width -= 2;							      \
+									      \
+	  if (is_negative || showsign || space)				      \
+	    --width;							      \
+									      \
+	  if (pad == '0')						      \
+	    {								      \
+	      while (width-- > 0)					      \
+		*string-- = '0';					      \
+									      \
+	      if (number.word != 0 && alt && base == 16)		      \
+		{							      \
+		  *string-- = spec;					      \
+		  *string-- = '0';					      \
+		}							      \
+									      \
+	      if (is_negative)						      \
+		*string-- = '-';					      \
+	      else if (showsign)					      \
+		*string-- = '+';					      \
+	      else if (space)						      \
+		*string-- = ' ';					      \
+	    }								      \
+	  else								      \
+	    {								      \
+	      if (number.word != 0 && alt && base == 16)		      \
+		{							      \
+		  *string-- = spec;					      \
+		  *string-- = '0';					      \
+		}							      \
+									      \
+	      if (is_negative)						      \
+		*string-- = '-';					      \
+	      else if (showsign)					      \
+		*string-- = '+';					      \
+	      else if (space)						      \
+		*string-- = ' ';					      \
+									      \
+	      while (width-- > 0)					      \
+		*string-- = ' ';					      \
+	    }								      \
+									      \
+	  outstring (string + 1, workend - string);			      \
+									      \
+	  break;							      \
+	}								      \
+      else								      \
+	{								      \
+	  if (number.word != 0 && alt && base == 16)			      \
+	    {								      \
+	      *string-- = spec;						      \
+	      *string-- = '0';						      \
+	    }								      \
+									      \
+	  if (is_negative)						      \
+	    *string-- = '-';						      \
+	  else if (showsign)						      \
+	    *string-- = '+';						      \
+	  else if (space)						      \
+	    *string-- = ' ';						      \
+									      \
+	  width -= workend - string;					      \
+	  outstring (string + 1, workend - string);			      \
+									      \
+	  PAD (' ');							      \
+	  break;							      \
+	}								      \
+									      \
+    LABEL (form_float):							      \
+      {									      \
+	/* Floating-point number.  This is handled by printf_fp.c.  */	      \
+	extern int __printf_fp __P ((FILE *, const struct printf_info *,      \
+				     const void **const));		      \
+	const void *ptr;						      \
+	int function_done;						      \
+									      \
+	if (is_long_double)						      \
+	  the_arg.pa_long_double = va_arg (ap, long double);		      \
+	else								      \
+	  the_arg.pa_double = va_arg (ap, double);			      \
+									      \
+	ptr = (const void *) &the_arg;					      \
+									      \
+	if (fspec == NULL)						      \
+	  {								      \
+	    struct printf_info info = { prec: prec,			      \
+					width: width,			      \
+					spec: spec,			      \
+					is_long_double: is_long_double,	      \
+					is_short: is_short,		      \
+					is_long: is_long,		      \
+					alt: alt,			      \
+					space: space,			      \
+					left: left,			      \
+					showsign: showsign,		      \
+					group: group,			      \
+					pad: pad };			      \
+									      \
+	    function_done = __printf_fp (s, &info, &ptr);		      \
+	  }								      \
+	else								      \
+	  function_done = __printf_fp (s, &fspec->info, &ptr);		      \
+									      \
+	if (function_done < 0)						      \
+	  /* Error in print handler.  */				      \
+	  return -1;							      \
+									      \
+	done += function_done;						      \
+      }									      \
+      break;								      \
+									      \
+    LABEL (form_character):						      \
+      /* Character.  */							      \
+      --width;	/* Account for the character itself.  */		      \
+      if (!left)							      \
+	PAD (' ');							      \
+      outchar ((unsigned char) va_arg (ap, int));	/* Promoted.  */      \
+      if (left)								      \
+	PAD (' ');							      \
+      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.  */		      \
+	string = (char *) va_arg (ap, const char *);			      \
+									      \
+	/* 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) - 1)		      \
+	      {								      \
+		string = (char *) null;					      \
+		len = sizeof (null) - 1;				      \
+	      }								      \
+	    else							      \
+	      {								      \
+		string = (char *) "";					      \
+		len = 0;						      \
+	      }								      \
+	  }								      \
+	else if (!is_long)						      \
+	  {								      \
+	    if (prec != -1)						      \
+	      {								      \
+		/* Search for the end of the string, but don't search past    \
+		   the length specified by the precision.  */		      \
+		const char *end = memchr (string, '\0', prec);		      \
+		if (end)						      \
+		  len = end - string;					      \
+		else							      \
+		  len = prec;						      \
+	      }								      \
+	    else							      \
+	      len = strlen (string);					      \
+	  }								      \
+	else								      \
+	  {								      \
+	    const wchar_t *s2 = (const wchar_t *) string;		      \
+	    mbstate_t mbstate = 0;					      \
+									      \
+	    len = wcsrtombs (NULL, &s2, prec != -1 ? prec : UINT_MAX,	      \
+			     &mbstate);					      \
+	    if (len == (size_t) -1)					      \
+	      /* Illegal wide-character string.  */			      \
+	      return -1;						      \
+									      \
+	    s2 = (const wchar_t *) string;				      \
+	    mbstate = 0;						      \
+	    string = alloca (len + 1);					      \
+	    (void) wcsrtombs (string, &s2, prec != -1 ? prec : UINT_MAX,      \
+			      &mbstate);				      \
+	  }								      \
+									      \
+	if ((width -= len) < 0)						      \
+	  {								      \
+	    outstring (string, len);					      \
+	    break;							      \
+	  }								      \
+									      \
+	if (!left)							      \
+	  PAD (' ');							      \
+	outstring (string, len);					      \
+	if (left)							      \
+	  PAD (' ');							      \
+      }									      \
+      break;								      \
+									      \
+    LABEL (form_pointer):						      \
+      /* Generic pointer.  */						      \
+      {									      \
+	const void *ptr;						      \
+	ptr = va_arg (ap, void *);					      \
+	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 (is_longlong)							      \
+	*(long long int *) va_arg (ap, void *) = done;			      \
+      else if (is_long)							      \
+	*(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;			      \
+      break;								      \
+									      \
+    LABEL (form_strerror):						      \
+      /* Print description of error ERRNO.  */				      \
+      {									      \
+	extern char *_strerror_internal __P ((int, char *buf, size_t));	      \
+									      \
+	string = (char *)						      \
+	  _strerror_internal (errno, work_buffer, sizeof work_buffer);	      \
+      }									      \
+      is_long = 0;		/* This is no wide-char string.  */	      \
+      goto LABEL (print_string)
+
+
+  /* Sanity check of arguments.  */
   ARGCHECK (s, format);
 
   if (UNBUFFERED_P (s))
@@ -178,101 +790,326 @@ vfprintf (s, format, ap)
        for the stream and then call us again.  */
     return buffered_vfprintf (s, format, ap);
 
-  /* Reset multibyte characters to their initial state.  */
-  (void) mblen ((char *) NULL, 0);
+  /* Initialize local variables.  */
+  done = 0;
+  grouping = (const char *) -1;
+  mbstate = 0;
+  ap_save = ap;
+  nspecs_done = 0;
 
-  /* Figure out the thousands separator character.  */
-  if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
-              strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
-    thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
-  grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-  if (*grouping == '\0' || *grouping == CHAR_MAX || thousands_sep == L'\0')
-    grouping = NULL;
+  /* Find the first format specifier.  */
+  f = lead_str_end = find_spec (format, &mbstate);
 
-  nspecs_max = 32;		/* A more or less arbitrary start value.  */
-  specs = alloca (nspecs_max * sizeof (struct printf_spec));
-  nspecs = 0;
-  nargs = 0;
-  max_ref_arg = 0;
+  /* Write the literal text before the first format.  */
+  outstring ((const UCHAR_T *) format,
+	     lead_str_end - (const UCHAR_T *) format);
 
-  /* Find the first format specifier.  */
-  lead_str_end = find_spec (format);
+  /* If we only have to print a simple string, return now.  */
+  if (*f == L_('\0'))
+    return done;
 
-  for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
+  /* Process whole format string.  */
+  do
     {
-      if (nspecs >= nspecs_max)
+#define REF(Name) &&do_##Name
+#define LABEL(Name) do_##Name
+      STEP0_3_TABLE;
+      STEP4_TABLE;
+
+      int is_negative;	/* Flag for negative number.  */
+      union
+      {
+	unsigned long long int longlong;
+	unsigned long int word;
+      } number;
+      int base;
+      union printf_arg the_arg;
+      char *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.  */
+      int showsign = 0;	/* Always begin with plus or minus sign.  */
+      int group = 0;	/* Print numbers according grouping rules.  */
+      int is_long_double = 0; /* Argument is long double/ long long int.  */
+      int is_short = 0;	/* Argument is long int.  */
+      int is_long = 0;	/* Argument is short int.  */
+      int width = 0;	/* Width of output; 0 means none specified.  */
+      int prec = -1;	/* Precision of output; -1 means none specified.  */
+      char pad = ' ';	/* Padding character.  */
+      CHAR_T spec;
+
+      /* Get current character in format string.  */
+      JUMP (*++f, step0_jumps);
+
+      /* ' ' flag.  */
+    LABEL (flag_space):
+      space = 1;
+      JUMP (*++f, step0_jumps);
+
+      /* '+' flag.  */
+    LABEL (flag_plus):
+      showsign = 1;
+      JUMP (*++f, step0_jumps);
+
+      /* The '-' flag.  */
+    LABEL (flag_minus):
+      left = 1;
+      pad = L_(' ');
+      JUMP (*++f, step0_jumps);
+
+      /* The '#' flag.  */
+    LABEL (flag_hash):
+      alt = 1;
+      JUMP (*++f, step0_jumps);
+
+      /* The '0' flag.  */
+    LABEL (flag_zero):
+      if (!left)
+	pad = L_('0');
+      JUMP (*++f, step0_jumps);
+
+      /* The '\'' flag.  */
+    LABEL (flag_quote):
+      group = 1;
+
+      /* XXX Completely wrong.  Use wctob.  */
+      if (grouping == (const char *) -1)
 	{
-	  /* Extend the array of format specifiers.  */
-	  struct printf_spec *old = specs;
-
-	  nspecs_max *= 2;
-	  specs = alloca (nspecs_max * sizeof (struct printf_spec));
-	  if (specs == &old[nspecs])
-	    /* Stack grows up, OLD was the last thing allocated; extend it.  */
-	    nspecs_max += nspecs_max / 2;
-	  else
-	    {
-	      /* Copy the old array's elements to the new space.  */
-	      memcpy (specs, old, nspecs * sizeof (struct printf_spec));
-	      if (old == &specs[nspecs])
-		/* Stack grows down, OLD was just below the new SPECS.
-		   We can use that space when the new space runs out.  */
-		nspecs_max += nspecs_max / 2;
-	    }
+	  /* Figure out the thousands separator character.  */
+	  if (mbtowc (&thousands_sep,
+		      _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
+		      strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
+	    thousands_sep = (wchar_t)
+	      *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+	  grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+	  if (*grouping == '\0' || *grouping == CHAR_MAX
+	      || thousands_sep == L'\0')
+	    grouping = NULL;
 	}
+      JUMP (*++f, step0_jumps);
 
-      /* Parse the format specifier.  */
-      nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg);
-    }
+      /* Get width from argument.  */
+    LABEL (width_asterics):
+      {
+	const UCHAR_T *tmp;	/* Temporary value.  */
 
-  /* Determine the number of arguments the format string consumes.  */
-  nargs = MAX (nargs, max_ref_arg);
+	tmp = ++f;
+	if (ISDIGIT (*tmp) && read_int (&tmp) && *tmp == L_('$'))
+	  /* The width comes from an positional parameter.  */
+	  goto do_positional;
 
-  /* Allocate memory for the argument descriptions.  */
-  args_type = alloca (nargs * sizeof (int));
-  memset (args_type, 0, nargs * sizeof (int));
-  args_value = alloca (nargs * sizeof (union printf_arg));
+	width = va_arg (ap, int);
 
-  /* XXX Could do sanity check here: If any element in ARGS_TYPE is
-     still zero after this loop, format is invalid.  For now we simply
-     use 0 as the value.  */
+	/* Negative width means left justified.  */
+	if (width < 0)
+	  {
+	    width = -width;
+	    pad = L_(' ');
+	    left = 1;
+	  }
+      }
+      JUMP (*f, step1_jumps);
+
+      /* Given width in format string.  */
+    LABEL (width):
+      width = read_int (&f);
+      if (*f == L_('$'))
+	/* Oh, oh.  The argument comes from an positional parameter.  */
+	goto do_positional;
+      JUMP (*f, step1_jumps);
+
+    LABEL (precision):
+      ++f;
+      if (*f == L_('*'))
+	{
+	  const UCHAR_T *tmp;	/* Temporary value.  */
 
-  /* Fill in the types of all the arguments.  */
-  for (cnt = 0; cnt < nspecs; ++cnt)
-    {
-      /* If the width is determined by an argument this is an int.  */
-      if (specs[cnt].width_arg != -1)
-	args_type[specs[cnt].width_arg] = PA_INT;
+	  tmp = ++f;
+	  if (ISDIGIT (*tmp) && read_int (&tmp) > 0 && *tmp == L_('$'))
+	    /* The precision comes from an positional parameter.  */
+	    goto do_positional;
 
-      /* If the precision is determined by an argument this is an int.  */
-      if (specs[cnt].prec_arg != -1)
-	args_type[specs[cnt].prec_arg] = PA_INT;
+	  prec = va_arg (ap, int);
 
-      switch (specs[cnt].ndata_args)
+	  /* If the precision is negative the precision is omitted.  */
+	  if (prec < 0)
+	    prec = -1;
+	}
+      else if (ISDIGIT (*f))
+	prec = read_int (&f);
+      else
+	prec = 0;
+      JUMP (*f, step2_jumps);
+
+      /* Process 'h' modifier.  No other modifier is allowed to
+	 follow.  */
+    LABEL (mod_half):
+      is_short = 1;
+      JUMP (*++f, step4_jumps);
+
+      /* Process 'l' modifier.  There might another 'l' follow.  */
+    LABEL (mod_long):
+      is_long = 1;
+      JUMP (*++f, step3_jumps);
+
+      /* Process 'L', 'q', or 'll' modifier.  No other modifier is
+	 allowed to follow.  */
+    LABEL (mod_longlong):
+      is_long_double = 1;
+      JUMP (*++f, step4_jumps);
+
+    LABEL (mod_size_t):
+      is_longlong = sizeof (size_t) > sizeof (unsigned long int);
+      is_long = sizeof (size_t) > sizeof (unsigned int);
+      JUMP (*++f, step4_jumps);
+
+
+      /* Process current format.  */
+      while (1)
 	{
-	case 0:			/* No arguments.  */
-	  break;
-	case 1:			/* One argument; we already have the type.  */
-	  args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
-	  break;
-	default:
-	  /* We have more than one argument for this format spec.  We must
-	     call the arginfo function again to determine all the types.  */
-	  (void) (*__printf_arginfo_table[specs[cnt].info.spec])
-	    (&specs[cnt].info,
-	     specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
-	  break;
+	  process_arg (((struct printf_spec *) NULL));
+
+	LABEL (form_unknown):
+	  if (spec == L_('\0'))
+	    /* The format string ended before the specifier is complete.  */
+	    return -1;
+
+	  /* If we are in the fast loop force entering the complicated
+	     one.  */
+	  goto do_positional;
 	}
+
+      /* Look for next format specifier.  */
+      f = find_spec ((end_of_spec = ++f), &mbstate);
+
+      /* Write the following constant string.  */
+      outstring (end_of_spec, f - end_of_spec);
     }
+  while (*f != L_('\0'));
 
-  /* Now we know all the types and the order.  Fill in the argument values.  */
-  for (cnt = 0; cnt < nargs; ++cnt)
-    switch (args_type[cnt])
+  /* We processed the whole format without any positional parameters.  */
+  return done;
+
+  /* Here starts the more complex loop to handle positional parameters.  */
+do_positional:
+  {
+    /* Array with information about the needed arguments.  This has to
+       be dynamically extendable.  */
+    size_t nspecs = 0;
+    size_t nspecs_max = 32;	/* A more or less arbitrary start value.  */
+    struct printf_spec *specs
+      = alloca (nspecs_max * sizeof (struct printf_spec));
+
+    /* The number of arguments the format string requests.  This will
+       determine the size of the array needed to store the argument
+       attributes.  */
+    size_t nargs = 0;
+    int *args_type;
+    union printf_arg *args_value;
+
+    /* Positional parameters refer to arguments directly.  This could
+       also determine the maximum number of arguments.  Track the
+       maximum number.  */
+    size_t max_ref_arg = 0;
+
+    /* Just a counter.  */
+    int cnt;
+
+
+    if (grouping == (const char *) -1)
       {
+	/* XXX Use wctob.  But this is incompatible for now.  */
+	/* Figure out the thousands separator character.  */
+	if (mbtowc (&thousands_sep,
+		    _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
+		    strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
+	  thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+	grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+	if (*grouping == '\0' || *grouping == CHAR_MAX
+	    || thousands_sep == L'\0')
+	  grouping = NULL;
+      }
+
+    for (f = lead_str_end; *f != '\0'; f = specs[nspecs++].next_fmt)
+      {
+	if (nspecs >= nspecs_max)
+	  {
+	    /* Extend the array of format specifiers.  */
+	    struct printf_spec *old = specs;
+
+	    nspecs_max *= 2;
+	    specs = alloca (nspecs_max * sizeof (struct printf_spec));
+
+	    if (specs == &old[nspecs])
+	      /* Stack grows up, OLD was the last thing allocated;
+		 extend it.  */
+	      nspecs_max += nspecs_max / 2;
+	    else
+	      {
+		/* Copy the old array's elements to the new space.  */
+		memcpy (specs, old, nspecs * sizeof (struct printf_spec));
+		if (old == &specs[nspecs])
+		  /* Stack grows down, OLD was just below the new
+		     SPECS.  We can use that space when the new space
+		     runs out.  */
+		  nspecs_max += nspecs_max / 2;
+	      }
+	  }
+
+	/* Parse the format specifier.  */
+	nargs += parse_one_spec (f, nargs, &specs[nspecs], &max_ref_arg, NULL);
+      }
+
+    /* Determine the number of arguments the format string consumes.  */
+    nargs = MAX (nargs, max_ref_arg);
+
+    /* Allocate memory for the argument descriptions.  */
+    args_type = alloca (nargs * sizeof (int));
+    memset (args_type, 0, nargs * sizeof (int));
+    args_value = alloca (nargs * sizeof (union printf_arg));
+
+    /* XXX Could do sanity check here: If any element in ARGS_TYPE is
+       still zero after this loop, format is invalid.  For now we
+       simply use 0 as the value.  */
+
+    /* Fill in the types of all the arguments.  */
+    for (cnt = 0; cnt < nspecs; ++cnt)
+      {
+	/* If the width is determined by an argument this is an int.  */
+	if (specs[cnt].width_arg != -1)
+	  args_type[specs[cnt].width_arg] = PA_INT;
+
+	/* If the precision is determined by an argument this is an int.  */
+	if (specs[cnt].prec_arg != -1)
+	  args_type[specs[cnt].prec_arg] = PA_INT;
+
+	switch (specs[cnt].ndata_args)
+	  {
+	  case 0:		/* No arguments.  */
+	    break;
+	  case 1:		/* One argument; we already have the type.  */
+	    args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
+	    break;
+	  default:
+	    /* We have more than one argument for this format spec.
+	       We must call the arginfo function again to determine
+	       all the types.  */
+	    (void) (*__printf_arginfo_table[specs[cnt].info.spec])
+	      (&specs[cnt].info,
+	       specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
+	    break;
+	  }
+      }
+
+    /* Now we know all the types and the order.  Fill in the argument
+       values.  */
+    for (cnt = 0, ap = ap_save; cnt < nargs; ++cnt)
+      switch (args_type[cnt])
+	{
 #define T(tag, mem, type)						      \
-      case tag:								      \
-	args_value[cnt].mem = va_arg (ap, type);			      \
-	break
+	case tag:							      \
+	  args_value[cnt].mem = va_arg (ap, type);			      \
+	  break
 
 	T (PA_CHAR, pa_char, int); /* Promoted.  */
 	T (PA_INT|PA_FLAG_SHORT, pa_short_int, int); /* Promoted.  */
@@ -285,349 +1122,126 @@ vfprintf (s, format, ap)
 	T (PA_STRING, pa_string, const char *);
 	T (PA_POINTER, pa_pointer, void *);
 #undef T
-      default:
-	if ((args_type[cnt] & PA_FLAG_PTR) != 0)
-	  args_value[cnt].pa_pointer = va_arg (ap, void *);
-	else
-	  args_value[cnt].pa_long_double = 0.0;
-	break;
-      }
-
-  /* Write the literal text before the first format.  */
-  outstring (format, lead_str_end - format);
+	default:
+	  if ((args_type[cnt] & PA_FLAG_PTR) != 0)
+	    args_value[cnt].pa_pointer = va_arg (ap, void *);
+	  else
+	    args_value[cnt].pa_long_double = 0.0;
+	  break;
+	}
 
-  /* Now walk through all format specifiers and process them.  */
-  for (cnt = 0; cnt < nspecs; ++cnt)
-    {
-      printf_function *function; /* Auxiliary function to do output.  */
-      int is_neg;		/* Decimal integer is negative.  */
-      int base;			/* Base of a number to be written.  */
-      unsigned long long int num; /* Integral number to be written.  */
-      const char *str;		/* String to be written.  */
-      char errorbuf[1024];      /* Buffer sometimes used by %m.  */
-
-      if (specs[cnt].width_arg != -1)
+    /* Now walk through all format specifiers and process them.  */
+    for (; nspecs_done < nspecs; ++nspecs_done)
+      {
+#undef REF
+#define REF(Name) &&do2_##Name
+#undef LABEL
+#define LABEL(Name) do2_##Name
+	STEP4_TABLE;
+
+	int is_negative;
+	union
 	{
-	  /* Extract the field width from an argument.  */
-	  specs[cnt].info.width = args_value[specs[cnt].width_arg].pa_int;
+	  unsigned long long int longlong;
+	  unsigned long int word;
+	} number;
+	int base;
+	union printf_arg the_arg;
+	char *string;	/* Pointer to argument string.  */
+
+	/* Fill variables from values in struct.  */
+	int alt = specs[nspecs_done].info.alt;
+	int space = specs[nspecs_done].info.space;
+	int left = specs[nspecs_done].info.left;
+	int showsign = specs[nspecs_done].info.showsign;
+	int group = specs[nspecs_done].info.group;
+	int is_long_double = specs[nspecs_done].info.is_long_double;
+	int is_short = specs[nspecs_done].info.is_short;
+	int is_long = specs[nspecs_done].info.is_long;
+	int width = specs[nspecs_done].info.width;
+	int prec = specs[nspecs_done].info.prec;
+	char pad = specs[nspecs_done].info.pad;
+	CHAR_T spec = specs[nspecs_done].info.spec;
+
+	/* Fill in last information.  */
+	if (specs[nspecs_done].width_arg != -1)
+	  {
+	    /* Extract the field width from an argument.  */
+	    specs[nspecs_done].info.width =
+	      args_value[specs[nspecs_done].width_arg].pa_int;
+
+	    if (specs[nspecs_done].info.width < 0)
+	      /* If the width value is negative left justification is
+		 selected and the value is taken as being positive.  */
+	      {
+		specs[nspecs_done].info.width *= -1;
+		left = specs[nspecs_done].info.left = 1;
+	      }
+	    width = specs[nspecs_done].info.width;
+	  }
 
-	  if (specs[cnt].info.width < 0)
-	    /* If the width value is negative left justification is selected
-	       and the value is taken as being positive.  */
-	    {
-	      specs[cnt].info.width = -specs[cnt].info.width;
-	      specs[cnt].info.left = 1;
-	    }
-	}
+	if (specs[nspecs_done].prec_arg != -1)
+	  {
+	    /* Extract the precision from an argument.  */
+	    specs[nspecs_done].info.prec =
+	      args_value[specs[nspecs_done].prec_arg].pa_int;
 
-      if (specs[cnt].prec_arg != -1)
-	{
-	  /* Extract the precision from an argument.  */
-	  specs[cnt].info.prec = args_value[specs[cnt].prec_arg].pa_int;
+	    if (specs[nspecs_done].info.prec < 0)
+	      /* If the precision is negative the precision is
+		 omitted.  */
+	      specs[nspecs_done].info.prec = -1;
 
-	  if (specs[cnt].info.prec < 0)
-	    /* If the precision is negative the precision is omitted.  */
-	    specs[cnt].info.prec = -1;
-	}
+	    prec = specs[nspecs_done].info.prec;
+	  }
 
-      /* Check for a user-defined handler for this spec.  */
-      function = (__printf_function_table == NULL ? NULL :
-                  __printf_function_table[specs[cnt].info.spec]);
+	/* Process format specifiers.  */
+	while (1)
+	  {
+	    JUMP (spec, step4_jumps);
 
-      if (function != NULL)
-      use_function:		/* Built-in formats with helpers use this.  */
-	{
-	  int function_done;
-	  unsigned int i;
-	  const void *ptr[specs[cnt].ndata_args];
+	    process_arg ((&specs[nspecs_done]));
 
-	  /* Fill in an array of pointers to the argument values.  */
-	  for (i = 0; i < specs[cnt].ndata_args; ++i)
-	    ptr[i] = &args_value[specs[cnt].data_arg + i];
+	  LABEL (form_unknown):
+	    {
+	      extern printf_function **__printf_function_table;
+	      int function_done;
+	      printf_function *function;
+	      unsigned int i;
+	      const void **ptr;
 
-	  /* Call the function.  */
-	  function_done = (*function) (s, &specs[cnt].info, ptr);
+	      function =
+		(__printf_function_table == NULL ? NULL :
+		 __printf_function_table[specs[nspecs_done].info.spec]);
 
-	  /* If an error occured don't do any further work.  */
-	  if (function_done < 0)
-	    return -1;
+	      if (function == NULL)
+		function = &printf_unknown;
 
-	  done += function_done;
-	}
-      else
-	switch (specs[cnt].info.spec)
-	  {
-	  case '%':
-	    /* Write a literal "%".  */
-	    outchar ('%');
-	    break;
-	  case 'i':
-	  case 'd':
-	    {
-	      long long int signed_num;
-
-	      /* Decimal integer.  */
-	      base = 10;
-	      if (specs[cnt].info.is_longlong)
-		signed_num = args_value[specs[cnt].data_arg].pa_long_long_int;
-	      else if (specs[cnt].info.is_long)
-		signed_num = args_value[specs[cnt].data_arg].pa_long_int;
-	      else if (!specs[cnt].info.is_short)
-		signed_num = args_value[specs[cnt].data_arg].pa_int;
-	      else
-		signed_num = args_value[specs[cnt].data_arg].pa_short_int;
-
-	      is_neg = signed_num < 0;
-	      num = is_neg ? (- signed_num) : signed_num;
-	      goto number;
-	    }
+	      ptr = alloca (specs[nspecs_done].ndata_args
+			    * sizeof (const void *));
+
+	      /* Fill in an array of pointers to the argument values.  */
+	      for (i = 0; i < specs[nspecs_done].ndata_args; ++i)
+		ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
 
-	  case 'u':
-	    /* Decimal unsigned integer.  */
-            base = 10;
-            goto unsigned_number;
-
-	  case 'o':
-            /* Octal unsigned integer.  */
-            base = 8;
-            goto unsigned_number;
-
-          case 'X':
-            /* Hexadecimal unsigned integer.  */
-          case 'x':
-            /* Hex with lower-case digits.  */
-            base = 16;
-
-	  unsigned_number:
-            /* Unsigned number of base BASE.  */
-
-            if (specs[cnt].info.is_longlong)
-	      num = args_value[specs[cnt].data_arg].pa_u_long_long_int;
-            else if (specs[cnt].info.is_long)
-	      num = args_value[specs[cnt].data_arg].pa_u_long_int;
-            else if (!specs[cnt].info.is_short)
-	      num = args_value[specs[cnt].data_arg].pa_u_int;
-            else
-	      num = args_value[specs[cnt].data_arg].pa_u_short_int;
-
-            /* ANSI only specifies the `+' and
-               ` ' flags for signed conversions.  */
-            is_neg = 0;
-	    specs[cnt].info.showsign = 0;
-	    specs[cnt].info.space = 0;
-
-	  number:
-	    /* Number of base BASE.  */
-            {
-              char work[BUFSIZ];
-              char *const workend = &work[sizeof(work) - 1];
-              register char *w;
-
-              if (specs[cnt].info.prec == -1)
-		  /* Supply a default precision if none was given.  */
-		  specs[cnt].info.prec = 1;
-	      else
-		/* We have to take care for the '0' flag.  If a
-		   precision is given it must be ignored.  */
-		specs[cnt].info.pad = ' ';
-
-	      /* If the precision is 0 and the number is 0 nothing has
-		 to be written for the number.  */
-	      if (specs[cnt].info.prec == 0 && num == 0)
-		w = workend;
-	      else
-		{
-		  /* Put the number in WORK.  */
-		  w = _itoa (num, workend + 1, base,
-			     specs[cnt].info.spec == 'X');
-		  w -= 1;
-		  if (specs[cnt].info.group && grouping)
-		    w = group_number (w, workend, grouping, thousands_sep);
-		}
-              specs[cnt].info.width -= workend - w;
-              specs[cnt].info.prec -= workend - w;
-
-              if (num != 0 && specs[cnt].info.alt && base == 8
-		  && specs[cnt].info.prec <= 0)
-                {
-		  /* Add octal marker.  */
-                  *w-- = '0';
-                  --specs[cnt].info.width;
-                }
-
-              if (specs[cnt].info.prec > 0)
-                {
-		  /* Add zeros to the precision.  */
-                  specs[cnt].info.width -= specs[cnt].info.prec;
-                  while (specs[cnt].info.prec-- > 0)
-                    *w-- = '0';
-                }
-
-              if (num != 0 && specs[cnt].info.alt && base == 16)
-		/* Account for 0X hex marker.  */
-                specs[cnt].info.width -= 2;
-
-              if (is_neg || specs[cnt].info.showsign || specs[cnt].info.space)
-                --specs[cnt].info.width;
-
-              if (!specs[cnt].info.left && specs[cnt].info.pad == ' ')
-                PAD (' ');
-
-              if (is_neg)
-                outchar ('-');
-              else if (specs[cnt].info.showsign)
-                outchar ('+');
-              else if (specs[cnt].info.space)
-                outchar (' ');
-
-              if (num != 0 && specs[cnt].info.alt && base == 16)
-                {
-                  outchar ('0');
-                  outchar (specs[cnt].info.spec);
-                }
-
-              if (!specs[cnt].info.left && specs[cnt].info.pad == '0')
-                PAD ('0');
-
-              /* Write the number.  */
-              while (++w <= workend)
-                outchar (*w);
-
-              if (specs[cnt].info.left)
-                PAD (' ');
-            }
-            break;
-
-          case 'e':
-          case 'E':
-          case 'f':
-          case 'g':
-          case 'G':
-            {
-              /* Floating-point number.  This is handled by printf_fp.c.  */
-              extern printf_function __printf_fp;
-              function = __printf_fp;
-              goto use_function;
-            }
-
-          case 'c':
-            /* Character.  */
-	    --specs[cnt].info.width;/* Account for the character itself.  */
-            if (!specs[cnt].info.left)
-	      PAD (' ');
-            outchar ((unsigned char) args_value[specs[cnt].data_arg].pa_char);
-            if (specs[cnt].info.left)
-              PAD (' ');
-            break;
-
-          case 's':
-            {
-              static const char null[] = "(null)";
-              size_t len;
-
-	      str = args_value[specs[cnt].data_arg].pa_string;
-
-	    string:
-
-              if (str == NULL)
-		{
-		  /* Write "(null)" if there's space.  */
-		  if (specs[cnt].info.prec == -1
-		      || specs[cnt].info.prec >= (int) sizeof (null) - 1)
-		    {
-		      str = null;
-		      len = sizeof (null) - 1;
-		    }
-		  else
-		    {
-		      str = "";
-		      len = 0;
-		    }
-		}
-              else if (specs[cnt].info.prec != -1)
-		{
-		  /* Search for the end of the string, but don't search
-		     past the length specified by the precision.  */
-		  const char *end = memchr (str, '\0', specs[cnt].info.prec);
-		  if (end)
-		    len = end - str;
-		  else
-		    len = specs[cnt].info.prec;
-		}
-	      else
-		len = strlen (str);
-
-              specs[cnt].info.width -= len;
-
-              if (!specs[cnt].info.left)
-                PAD (' ');
-              outstring (str, len);
-              if (specs[cnt].info.left)
-                PAD (' ');
-            }
-            break;
-
-          case 'p':
-            /* Generic pointer.  */
-            {
-              const void *ptr;
-              ptr = args_value[specs[cnt].data_arg].pa_pointer;
-              if (ptr != NULL)
-                {
-                  /* If the pointer is not NULL, write it as a %#x spec.  */
-                  base = 16;
-                  num = (unsigned long long int) (unsigned long int) ptr;
-                  is_neg = 0;
-                  specs[cnt].info.alt = 1;
-		  specs[cnt].info.spec = 'x';
-                  specs[cnt].info.group = 0;
-                  goto number;
-                }
-              else
-                {
-                  /* Write "(nil)" for a nil pointer.  */
-                  str = "(nil)";
-		  /* Make sure the full string "(nil)" is printed.  */
-		  if (specs[cnt].info.prec < 5)
-		    specs[cnt].info.prec = 5;
-                  goto string;
-                }
-            }
-            break;
-
-          case 'n':
-            /* Answer the count of characters written.  */
-            if (specs[cnt].info.is_longlong)
-	      *(long long int *)
-		args_value[specs[cnt].data_arg].pa_pointer = done;
-            else if (specs[cnt].info.is_long)
-	      *(long int *)
-		args_value[specs[cnt].data_arg].pa_pointer = done;
-            else if (!specs[cnt].info.is_short)
-	      *(int *)
-		args_value[specs[cnt].data_arg].pa_pointer = done;
-            else
-	      *(short int *)
-		args_value[specs[cnt].data_arg].pa_pointer = done;
-            break;
-
-          case 'm':
-            {
-              extern char *_strerror_internal __P ((int, char *buf, size_t));
-              str = _strerror_internal (errno, errorbuf, sizeof errorbuf);
-              goto string;
-            }
-
-          default:
-            /* Unrecognized format specifier.  */
-            function = printf_unknown;
-            goto use_function;
+	      /* Call the function.  */
+	      function_done = (*function) (s, &specs[nspecs_done].info, ptr);
+
+	      /* If an error occured we don't have information about #
+		 of chars.  */
+	      if (function_done < 0)
+		return -1;
+
+	      done += function_done;
+	    }
+	    break;
 	  }
 
-      /* Write the following constant string.  */
-      outstring (specs[cnt].end_of_fmt,
-		 specs[cnt].next_fmt - specs[cnt].end_of_fmt);
-    }
+	/* Write the following constant string.  */
+	outstring (specs[nspecs_done].end_of_fmt,
+		   specs[nspecs_done].next_fmt
+		   - specs[nspecs_done].end_of_fmt);
+      }
+  }
 
   return done;
 }
@@ -636,7 +1250,7 @@ vfprintf (s, format, ap)
 # undef vfprintf
 # ifdef strong_alias
 /* This is for glibc.  */
-strong_alias (_IO_vfprintf, vfprintf)
+strong_alias (_IO_vfprintf, vfprintf);
 # else
 #  if defined __ELF__ || defined __GNU_LIBRARY__
 #   include <gnu-stabs.h>
@@ -646,20 +1260,16 @@ weak_alias (_IO_vfprintf, vfprintf);
 #  endif
 # endif
 #endif
-
-
+
 /* Handle an unknown format specifier.  This prints out a canonicalized
    representation of the format spec itself.  */
-
 static int
-printf_unknown (s, info, args)
-  FILE *s;
-  const struct printf_info *info;
-  const void *const *args;
+printf_unknown (FILE *s, const struct printf_info *info,
+		const void *const *args)
+
 {
   int done = 0;
-  char work[BUFSIZ];
-  char *const workend = &work[sizeof(work) - 1];
+  char work_buffer[BUFSIZ];
   register char *w;
 
   outchar ('%');
@@ -679,7 +1289,7 @@ printf_unknown (s, info, args)
 
   if (info->width != 0)
     {
-      w = _itoa (info->width, workend + 1, 10, 0);
+      w = _itoa_word (info->width, workend + 1, 10, 0);
       while (++w <= workend)
 	outchar (*w);
     }
@@ -687,7 +1297,7 @@ printf_unknown (s, info, args)
   if (info->prec != -1)
     {
       outchar ('.');
-      w = _itoa (info->prec, workend + 1, 10, 0);
+      w = _itoa_word (info->prec, workend + 1, 10, 0);
       while (++w <= workend)
 	outchar (*w);
     }
@@ -700,9 +1310,8 @@ printf_unknown (s, info, args)
 
 /* 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 *
-group_number (char *w, char *workend, const char *grouping,
+group_number (CHAR_T *w, CHAR_T *rear_ptr, const CHAR_T *grouping,
 	      wchar_t thousands_sep)
 {
   int len;
@@ -717,10 +1326,10 @@ group_number (char *w, char *workend, const char *grouping,
   len = *grouping;
 
   /* Copy existing string so that nothing gets overwritten.  */
-  src = (char *) alloca (workend - w);
-  memcpy (src, w + 1, workend - w);
-  s = &src[workend - w - 1];
-  w = workend;
+  src = (char *) alloca (rear_ptr - w);
+  memcpy (src, w + 1, rear_ptr - w);
+  s = &src[rear_ptr - w - 1];
+  w = rear_ptr;
 
   /* Process all characters in the string.  */
   while (s >= src)
@@ -772,32 +1381,30 @@ _IO_helper_overflow (_IO_FILE *s, int c)
 }
 
 static const struct _IO_jump_t _IO_helper_jumps =
-  {
-    JUMP_INIT_DUMMY,
-    JUMP_INIT (finish, _IO_default_finish),
-    JUMP_INIT (overflow, _IO_helper_overflow),
-    JUMP_INIT (underflow, _IO_default_underflow),
-    JUMP_INIT (uflow, _IO_default_uflow),
-    JUMP_INIT (pbackfail, _IO_default_pbackfail),
-    JUMP_INIT (xsputn, _IO_default_xsputn),
-    JUMP_INIT (xsgetn, _IO_default_xsgetn),
-    JUMP_INIT (seekoff, _IO_default_seekoff),
-    JUMP_INIT (seekpos, _IO_default_seekpos),
-    JUMP_INIT (setbuf, _IO_default_setbuf),
-    JUMP_INIT (sync, _IO_default_sync),
-    JUMP_INIT (doallocate, _IO_default_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_DUMMY,
+  JUMP_INIT (finish, _IO_default_finish),
+  JUMP_INIT (overflow, _IO_helper_overflow),
+  JUMP_INIT (underflow, _IO_default_underflow),
+  JUMP_INIT (uflow, _IO_default_uflow),
+  JUMP_INIT (pbackfail, _IO_default_pbackfail),
+  JUMP_INIT (xsputn, _IO_default_xsputn),
+  JUMP_INIT (xsgetn, _IO_default_xsgetn),
+  JUMP_INIT (seekoff, _IO_default_seekoff),
+  JUMP_INIT (seekpos, _IO_default_seekpos),
+  JUMP_INIT (setbuf, _IO_default_setbuf),
+  JUMP_INIT (sync, _IO_default_sync),
+  JUMP_INIT (doallocate, _IO_default_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)
+};
 
 static int
-buffered_vfprintf (s, format, args)
-  register _IO_FILE *s;
-  char const *format;
-  _IO_va_list args;
+buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
+		   _IO_va_list args)
 {
   char buf[_IO_BUFSIZ];
   struct helper_file helper;
@@ -828,10 +1435,7 @@ buffered_vfprintf (s, format, args)
 #else /* !USE_IN_LIBIO */
 
 static int
-buffered_vfprintf (s, format, args)
-  register FILE *s;
-  char const *format;
-  va_list args;
+buffered_vfprintf (register FILE *s, const CHAR_T *format, va_list args)
 {
   char buf[BUFSIZ];
   int result;
@@ -851,26 +1455,28 @@ buffered_vfprintf (s, format, args)
 
   return result;
 }
-
-
+
 /* Pads string with given number of a specified character.
    This code is taken from iopadn.c of the GNU I/O library.  */
 #define PADSIZE 16
-static const char blanks[PADSIZE] =
-{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
-static const char zeroes[PADSIZE] =
-{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+static const CHAR_T blanks[PADSIZE] =
+{ L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '),
+  L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' '), L_(' ') };
+static const CHAR_T 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') };
 
 ssize_t
-__printf_pad (s, pad, count)
-     FILE *s;
-     char pad;
-     size_t count;
+#ifndef COMPILE_WPRINTF
+__printf_pad (FILE *s, char pad, size_t count)
+#else
+__wprintf_pad (FILE *s, wchar_t pad, size_t count)
+#endif
 {
-  const char *padptr;
+  const CHAR_T *padptr;
   register size_t i;
 
-  padptr = pad == ' ' ? blanks : zeroes;
+  padptr = pad == L_(' ') ? blanks : zeroes;
 
   for (i = count; i >= PADSIZE; i -= PADSIZE)
     if (PUT (s, padptr, PADSIZE) != PADSIZE)
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 3818c81ecb..51dc520c01 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -481,20 +481,12 @@ INTERNAL (STRTOF) (nptr, endptr, group)
   /* Read the fractional digits.  A special case are the 'american style'
      numbers like `16.' i.e. with decimal but without trailing digits.  */
   if (c == decimal)
-    {
-      if (isdigit (cp[1]))
-	{
-	  c = *++cp;
-	  do
-	    {
-	      if (c != '0' && lead_zero == -1)
-		lead_zero = dig_no - int_no;
-	      ++dig_no;
-	      c = *++cp;
-	    }
-	  while (isdigit (c));
-	}
-    }
+    while (isdigit (c = *++cp))
+      {
+	if (c != '0' && lead_zero == -1)
+	  lead_zero = dig_no - int_no;
+	++dig_no;
+      }
 
   /* Remember start of exponent (if any).  */
   expp = cp;
diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c
index dc2e8b43f3..7bbd0acbab 100644
--- a/sysdeps/generic/setenv.c
+++ b/sysdeps/generic/setenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995, 1996 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
@@ -108,7 +108,8 @@ setenv (name, value, replace)
 }
 
 void
-unsetenv (const char *name)
+unsetenv (name)
+     const char *name;
 {
   const size_t len = strlen (name);
   char **ep;
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index 6d75c7b01f..99d9dd5010 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -21,11 +21,12 @@
 #
 subdir	:= wcsmbs
 
-headers	:= wcstr.h mbstr.h
+headers	:= wchar.h
 
-routines := mbsadvance mbscat mbschr mbscmp mbscpy mbsdup mbslen	\
-	    mbsncat mbsncmp mbsncpy mbsrchr mbstomb wcscat wcschr wcscmp\
-	    wcscpy wcscspn wcsdup wcslen wcsncat wcsncmp wcsncpy wcspbrk\
-	    wcsrchr wcsspn wcstok wcswcs
+routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
+	    wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
+	    wmemcmp wmemcpy wmemmove wmemset \
+	    btowc wctob mbsinit \
+	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs
 
 include ../Rules
diff --git a/wcsmbs/mbsadvance.c b/wcsmbs/mbsadvance.c
deleted file mode 100644
index b6649935d7..0000000000
--- a/wcsmbs/mbsadvance.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Advance pointer to multibyte string by one character.  */
-char *
-mbsadvance (mbs)
-    const char *mbs;
-{
-  int clen;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  clen = mblen (mbs, MB_CUR_MAX);
-
-  /* FIXME: when current character is illegal return same character.  */
-  return clen <= 0 ? (char *) mbs : (char *) (mbs + clen);
-}
-
diff --git a/wcsmbs/mbscat.c b/wcsmbs/mbscat.c
deleted file mode 100644
index 324cad9cc8..0000000000
--- a/wcsmbs/mbscat.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Append SRC onto DEST.  */
-char *
-mbscat (dest, src)
-    char *dest;
-    const char *src;
-{
-  const char * const d = dest;
-  size_t len = 0;
-  int clen = 0;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      dest += clen;
-      clen = mblen (dest, MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  clen = 0;
-  do
-    {
-      len += clen;
-      clen = mblen (&src[len], MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  (void) memcpy ((void *) dest, (void *) src, len);
-  dest[len] = '\0';	    /* '\0' is the multibyte representation of L'\0' */
-
-  return (char *) d;
-}
-
diff --git a/wcsmbs/mbschr.c b/wcsmbs/mbschr.c
deleted file mode 100644
index f8a7d21857..0000000000
--- a/wcsmbs/mbschr.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-#define __need_wchar_t
-#include <stddef.h>
-
-
-/* Find the first occurence of MBC in MBS.  */
-char *
-mbschr (mbs, mbc)
-    const char *mbs;
-    mbchar_t mbc;
-{
-  int clen;
-  wchar_t wc;
-  wchar_t c;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  clen = mbtowc (&wc, (char *) &mbc, MB_CUR_MAX);
-  if (clen < 0)
-    /* FIXME: search character is illegal.  */
-    return NULL;
-  else if (clen == 0)
-    wc = L'\0';
-
-  clen = 0;
-  do
-    {
-      mbs += clen;
-      clen = mbtowc (&c, mbs, MB_CUR_MAX);
-    }
-  while (clen > 0 && c != wc);
-
-  if (clen < 0 || (clen == 0 && wc != L'\0'))
-    /* FIXME: clen < 0 means illegal character in string.  */
-    return NULL;
-
-  return (char *) mbs;
-}
-
diff --git a/wcsmbs/mbscpy.c b/wcsmbs/mbscpy.c
deleted file mode 100644
index 8f354ceede..0000000000
--- a/wcsmbs/mbscpy.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Copy SRC to DEST.  */
-char *
-mbscpy (dest, src)
-    char *dest;
-    const char *src;
-{
-  size_t len = 0;
-  int clen = 0;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      len += clen;
-      clen = mblen (&src[len], MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  (void) memcpy ((void *) dest, (void *) src, len);
-  dest[len] = '\0';	    /* '\0' is the multibyte representation of L'\0' */
-
-  return dest;
-}
-
diff --git a/wcsmbs/mbsdup.c b/wcsmbs/mbsdup.c
deleted file mode 100644
index 2d196dd06d..0000000000
--- a/wcsmbs/mbsdup.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Duplicate MBS, returning an identical malloc'd string.  */
-char *
-mbsdup (mbs)
-    const char *mbs;
-{
-  size_t len = 0;
-  int clen = 0;
-  char *retval;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      len += clen;
-      clen = mblen (&mbs[len], MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  retval = (char *) malloc (len + 1);
-  if (retval != NULL)
-    {
-      (void) memcpy ((void *) retval, (void *) mbs, len);
-      retval[len] = '\0';   /* '\0' is the multibyte representation of L'\0' */
-    }
-
-  return retval;
-}
-
diff --git a/wcsmbs/mbslen.c b/wcsmbs/mbslen.c
deleted file mode 100644
index f8077d0fb9..0000000000
--- a/wcsmbs/mbslen.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Return the length of MBS.  */
-size_t
-mbslen (mbs)
-    const char *mbs;
-{
-  size_t len = 0;
-  int clen = 0;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      len += clen;
-      clen = mblen (&mbs[len], MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  /* FIXME: if string contains an illegal character the length upto this
-     character is returned.  */
-  return len;
-}
-
diff --git a/wcsmbs/mbsncat.c b/wcsmbs/mbsncat.c
deleted file mode 100644
index 3dd4df1c70..0000000000
--- a/wcsmbs/mbsncat.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Append no more than N multi-byte characters from SRC onto DEST.  */
-char *
-mbsncat (dest, src, n)
-    char *dest;
-    const char *src;
-    size_t n;
-{
-  const char * const d = dest;
-  const char * const s = src;
-  size_t len = 0;
-  int clen = 0;
-
-  if (n == 0)
-    return (char *) d;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      dest += clen;
-      clen = mblen (dest, MB_CUR_MAX);
-    }
-  while (clen > 0);
-
-  clen = 0;
-  do
-    {
-      src += clen;
-      clen = mblen (src, MB_CUR_MAX);
-    }
-  while (clen > 0 && ++len < n);
-
-  (void) memcpy ((void *) dest, (void *) s, src - s);
-  dest[src - s] = '\0';	    /* '\0' is the multibyte representation of L'\0' */
-
-  return (char *) d;
-}
-
diff --git a/wcsmbs/mbsncmp.c b/wcsmbs/mbsncmp.c
deleted file mode 100644
index 43fb527afb..0000000000
--- a/wcsmbs/mbsncmp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-#define __need_wchar_t
-/* FIXME: should be defined in stddef.h.
-!!! #define __need_uwchar_t  */
-typedef unsigned int uwchar_t;
-#include <stddef.h>
-
-
-/* Compare N characters of MBS1 and MBS2.  */
-int
-mbsncmp (mbs1, mbs2, n)
-    const char *mbs1;
-    const char *mbs2;
-    size_t n;
-{
-  size_t len = 0;
-  int clen1 = 0;
-  int clen2 = 0;
-  uwchar_t c1;
-  uwchar_t c2;
-
-  if (n == 0)
-    return 0;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      clen1 = mbtowc ((wchar_t *) &c1, mbs1, MB_CUR_MAX);
-      clen2 = mbtowc ((wchar_t *) &c2, mbs2, MB_CUR_MAX);
-
-      if (clen1 == 0)
-	return clen2 == 0 ? 0 : -1;
-      if (clen2 == 0)
-	return 1;
-      if (clen1 < 0 || clen2 < 0)
-	/* FIXME: an illegal character appears.	 What to do?  */
-	return c1 - c2;
-
-      mbs1 += clen1;
-      mbs2 += clen2;
-    }
-  while (c1 == c2 && ++len < n);
-
-  return len < n ? c1 - c2 : 0;
-}
-
diff --git a/wcsmbs/mbsncpy.c b/wcsmbs/mbsncpy.c
deleted file mode 100644
index 09aecefd03..0000000000
--- a/wcsmbs/mbsncpy.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Copy no more than N characters of SRC to DEST.  */
-char *
-mbsncpy (dest, src, n)
-    char *dest;
-    const char *src;
-    size_t n;
-{
-  const char * const s = src;
-  size_t len = 0;
-  int clen = 0;
-
-  if (n == 0)
-    {
-      dest[0] = '\0';	    /* '\0' is the multibyte representation of L'\0' */
-      return dest;
-    }
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  do
-    {
-      src += clen;
-      clen = mblen (src, MB_CUR_MAX);
-    }
-  while (clen > 0 && ++len < n);
-
-  (void) memcpy ((void *) dest, (void *) s, src - s);
-  dest[src - s] = '\0';	    /* '\0' is the multibyte representation of L'\0' */
-
-  return dest;
-}
-
diff --git a/wcsmbs/mbsrchr.c b/wcsmbs/mbsrchr.c
deleted file mode 100644
index 62fa219dd2..0000000000
--- a/wcsmbs/mbsrchr.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-#define __need_wchar_t
-#include <stddef.h>
-
-
-/* Find the last occurence of MBC in MBS.  */
-char *
-mbsrchr (mbs, mbc)
-    const char *mbs;
-    mbchar_t mbc;
-{
-  const char * retval = NULL;
-  int clen;
-  wchar_t wc;
-  wchar_t c;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  clen = mbtowc (&wc, (char *) &mbc, MB_CUR_MAX);
-  if (clen < 0)
-    /* FIXME: search character MBC is illegal.	*/
-    return NULL;
-  else if (clen == 0)
-    wc = L'\0';
-
-  clen = 0;
-  do
-    {
-      mbs += clen;
-      clen = mbtowc (&c, mbs, MB_CUR_MAX);
-    }
-  while (clen > 0 && c != wc);
-
-  if (clen < 0)
-    /* FIXME: clen < 0 means illegal character in string.  */
-    return NULL;
-
-  return (char *) (clen > 0 || (clen == 0 && wc == L'\0') ? mbs : retval);
-}
-
diff --git a/wcsmbs/mbstomb.c b/wcsmbs/mbstomb.c
deleted file mode 100644
index f593ced3cb..0000000000
--- a/wcsmbs/mbstomb.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#include <mbstr.h>
-#include <stdlib.h>
-
-
-/* Advance pointer to multibyte string by one character.  */
-mbchar_t
-mbstomb (mbs)
-    const char *mbs;
-{
-  mbchar_t retval = 0;
-  int clen;
-
-  /* Reset multibyte characters to their initial state.	 */
-  (void) mblen ((char *) NULL, 0);
-
-  clen = mblen (mbs, MB_CUR_MAX);
-
-  if (clen > 0)
-    (void) memcpy (&retval, mbs, clen);
-
-  /* FIXME: when current character is illegal return '\0'.  */
-  return retval;
-}
-
diff --git a/wcsmbs/mbstr.h b/wcsmbs/mbstr.h
deleted file mode 100644
index 7cb94bf85b..0000000000
--- a/wcsmbs/mbstr.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#ifndef _MBSTRING_H
-
-#define _MBSTRING_H 1
-#include <features.h>
-#include <limits.h>
-
-#define __need_size_t
-#include <stddef.h>
-
-__BEGIN_DECLS
-
-/* This data type should be large enough to contain MB_CUR_MAX bytes.  */
-typedef unsigned int mbchar_t;
-
-
-/* Copy SRC to DEST.  */
-extern char *mbscpy __P ((char *__dest, __const char *__src));
-/* Copy no more than N multi-byte characters of SRC to DEST.  */
-extern char *mbsncpy __P ((char *__dest, __const char *__src, size_t __n));
-
-/* Append SRC onto DEST.  */
-extern char *mbscat __P ((char *__dest, __const char *__src));
-/* Append no more than N characters from SRC onto DEST.  */
-extern char *mbsncat __P ((char *__dest, __const char *__src, size_t __n));
-
-/* Compare S1 and S2.  */
-extern int mbscmp __P ((__const char *__s1, __const char *__s2));
-/* Compare N characters of S1 and S2.  */
-extern int mbsncmp __P ((__const char *__s1, __const char *__s2, size_t __n));
-
-/* Duplicate MBS, returning an identical malloc'd string.  */
-extern char *mbsdup __P ((__const char *__s));
-
-/* Find the first occurence of MBC in MBS.  */
-extern char *mbschr __P ((__const char *__mbs, mbchar_t mbc));
-/* Find the last occurence of MBC in MBS.  */
-extern char *mbsrchr __P ((__const char *__mbs, mbchar_t mbc));
-
-/* Return the length of MBS.  */
-extern size_t mbslen __P ((__const char *__mbs));
-
-
-/* Advance pointer to multibyte string by one character.  */
-extern char *mbsadvance __P ((__const char *__mbs));
-
-/* Return first character in MBS.  */
-extern mbchar_t mbstomb __P ((__const char *__mbs));
-
-__END_DECLS
-
-#endif /* mbstring.h */
diff --git a/wcsmbs/wcscat.c b/wcsmbs/wcscat.c
index 4ff5c861e4..e142806fae 100644
--- a/wcsmbs/wcscat.c
+++ b/wcsmbs/wcscat.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,14 +17,14 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Append SRC on the end of DEST.  */
 wchar_t *
 wcscat (dest, src)
-    wchar_t *dest;
-    const wchar_t *src;
+     wchar_t *dest;
+     const wchar_t *src;
 {
   register wchar_t *s1 = dest;
   register const wchar_t *s2 = src;
diff --git a/wcsmbs/wcschr.c b/wcsmbs/wcschr.c
index 85a1801839..64af0bf456 100644
--- a/wcsmbs/wcschr.c
+++ b/wcsmbs/wcschr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 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
@@ -16,14 +16,14 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Find the first ocurrence of WC in WCS.  */
 wchar_t *
 wcschr (wcs, wc)
-    register const wchar_t *wcs;
-    register const wchar_t wc;
+     register const wchar_t *wcs;
+     register const wchar_t wc;
 {
   while (*wcs != L'\0')
     if (*wcs == wc)
diff --git a/wcsmbs/wcscmp.c b/wcsmbs/wcscmp.c
index 84ecae8553..08da116787 100644
--- a/wcsmbs/wcscmp.c
+++ b/wcsmbs/wcscmp.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,16 +17,16 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Compare S1 and S2, returning less than, equal to or
-   greater than zero if S1 is lexiographically less than,
+   greater than zero if S1 is lexicographically less than,
    equal to or greater than S2.	 */
 int
 wcscmp (s1, s2)
-    const wchar_t *s1;
-    const wchar_t *s2;
+     const wchar_t *s1;
+     const wchar_t *s2;
 {
   uwchar_t c1, c2;
 
diff --git a/wcsmbs/wcscpy.c b/wcsmbs/wcscpy.c
index a45747edf1..3aa897ec7f 100644
--- a/wcsmbs/wcscpy.c
+++ b/wcsmbs/wcscpy.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,7 +17,7 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 #define __need_ptrdiff_t
 #include <stddef.h>
@@ -25,8 +26,8 @@ Cambridge, MA 02139, USA.  */
 /* Copy SRC to DEST.  */
 wchar_t *
 wcscpy (dest, src)
-    wchar_t *dest;
-    const wchar_t *src;
+     wchar_t *dest;
+     const wchar_t *src;
 {
   wchar_t *wcp = (wchar_t *) src;
   wchar_t c;
diff --git a/wcsmbs/wcscspn.c b/wcsmbs/wcscspn.c
index 0dc4d9bc9e..7ab8f278fd 100644
--- a/wcsmbs/wcscspn.c
+++ b/wcsmbs/wcscspn.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,15 +17,15 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Return the length of the maximum initial segment
    of WCS which contains only wide-characters not in REJECT.  */
 size_t
 wcscspn (wcs, reject)
-    const wchar_t *wcs;
-    const wchar_t *reject;
+     const wchar_t *wcs;
+     const wchar_t *reject;
 {
   register size_t count = 0;
 
diff --git a/wcsmbs/wcsdup.c b/wcsmbs/wcsdup.c
index 62c64621de..c24ba96f88 100644
--- a/wcsmbs/wcsdup.c
+++ b/wcsmbs/wcsdup.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,7 +17,7 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 #include <string.h>
 #include <stdlib.h>
 
@@ -24,7 +25,7 @@ Cambridge, MA 02139, USA.  */
 /* Duplicate S, returning an identical malloc'd string.	 */
 wchar_t *
 wcsdup (s)
-    const wchar_t *s;
+     const wchar_t *s;
 {
   size_t len = (wcslen (s) + 1) * sizeof (wchar_t);
   void *new = malloc (len);
diff --git a/wcsmbs/wcslen.c b/wcsmbs/wcslen.c
index 2907cb3cc4..1ce365f8c4 100644
--- a/wcsmbs/wcslen.c
+++ b/wcsmbs/wcslen.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,13 +17,13 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Copy SRC to DEST.  */
 size_t
 wcslen (s)
-    const wchar_t *s;
+     const wchar_t *s;
 {
   size_t len = 0;
 
diff --git a/wcsmbs/wcsncat.c b/wcsmbs/wcsncat.c
index 7851d7048d..48d54603d6 100644
--- a/wcsmbs/wcsncat.c
+++ b/wcsmbs/wcsncat.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,15 +17,15 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Append no more than N wide-character of SRC onto DEST.  */
 wchar_t *
 wcsncat (dest, src, n)
-      wchar_t *dest;
-      const wchar_t *src;
-      size_t n;
+     wchar_t *dest;
+     const wchar_t *src;
+     size_t n;
 {
   wchar_t c;
   wchar_t * const s = dest;
diff --git a/wcsmbs/wcsncmp.c b/wcsmbs/wcsncmp.c
index 9f1829bc5d..3df6bfc151 100644
--- a/wcsmbs/wcsncmp.c
+++ b/wcsmbs/wcsncmp.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,7 +17,7 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Compare no more than N characters of S1 and S2,
@@ -25,9 +26,9 @@ Cambridge, MA 02139, USA.  */
    greater than S2.  */
 int
 wcsncmp (s1, s2, n)
-      const wchar_t *s1;
-      const wchar_t *s2;
-      size_t n;
+     const wchar_t *s1;
+     const wchar_t *s2;
+     size_t n;
 {
   uwchar_t c1 = L'\0';
   uwchar_t c2 = L'\0';
diff --git a/wcsmbs/wcsncpy.c b/wcsmbs/wcsncpy.c
index 740c71ecf8..180da794d7 100644
--- a/wcsmbs/wcsncpy.c
+++ b/wcsmbs/wcsncpy.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,18 +17,18 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Copy no more than N wide-characters of SRC to DEST.	*/
 wchar_t *
 wcsncpy (dest, src, n)
-      wchar_t *dest;
-      const wchar_t *src;
-      size_t n;
+     wchar_t *dest;
+     const wchar_t *src;
+     size_t n;
 {
   wchar_t c;
-  wchar_t * const s = dest;
+  wchar_t *const s = dest;
 
   --dest;
 
diff --git a/wcsmbs/wcspbrk.c b/wcsmbs/wcspbrk.c
index 83892bacb0..91c5573722 100644
--- a/wcsmbs/wcspbrk.c
+++ b/wcsmbs/wcspbrk.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,14 +17,14 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Find the first ocurrence in WCS of any wide-character in ACCEPT.  */
 wchar_t *
 wcspbrk (wcs, accept)
-      register const wchar_t *wcs;
-      register const wchar_t *accept;
+     register const wchar_t *wcs;
+     register const wchar_t *accept;
 {
   while (*wcs != L'\0')
     if (wcschr (accept, *wcs) == NULL)
diff --git a/wcsmbs/wcsrchr.c b/wcsmbs/wcsrchr.c
index 87823b3709..ae31dc4104 100644
--- a/wcsmbs/wcsrchr.c
+++ b/wcsmbs/wcsrchr.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,14 +17,14 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Find the last ocurrence of WC in WCS.  */
 wchar_t *
 wcsrchr (wcs, wc)
-    register const wchar_t *wcs;
-    register const wchar_t wc;
+     register const wchar_t *wcs;
+     register const wchar_t wc;
 {
   const wchar_t *retval = NULL;
 
diff --git a/wcsmbs/wcsspn.c b/wcsmbs/wcsspn.c
index 81a557c7b7..158e35ee97 100644
--- a/wcsmbs/wcsspn.c
+++ b/wcsmbs/wcsspn.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,15 +17,15 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 
 
 /* Return the length of the maximum initial segment
    of WCS which contains only wide-characters in ACCEPT.  */
 size_t
 wcsspn (wcs, accept)
-    const wchar_t *wcs;
-    const wchar_t *accept;
+     const wchar_t *wcs;
+     const wchar_t *accept;
 {
   register const wchar_t *p;
   register const wchar_t *a;
diff --git a/wcsmbs/wcstok.c b/wcsmbs/wcstok.c
index 191bbd5960..376fe7bfcb 100644
--- a/wcsmbs/wcstok.c
+++ b/wcsmbs/wcstok.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
+Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>
 
 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
@@ -16,52 +17,42 @@ License along with the GNU C Library; see the file COPYING.LIB.	 If
 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
 Cambridge, MA 02139, USA.  */
 
-#include <wcstr.h>
+#include <wchar.h>
 #include <errno.h>
 
 
-static wchar_t *olds = NULL;
-
-/* Parse WCS into tokens separated by characters in DELIM.
-   If WCS is NULL, the last string wcstok() was called with is
-   used.  */
+/* Parse WCS into tokens separated by characters in DELIM.  If WCS is
+   NULL, the last string wcstok() was called with is used.  */
 wchar_t *
-wcstok (wcs, delim)
-    register wchar_t *wcs;
-    register const wchar_t *delim;
+wcstok (wcs, delim, ptr)
+     register wchar_t *wcs;
+     register const wchar_t *delim;
+     register wchar_t **ptr;
 {
-  wchar_t *token;
+  wchar_t *result;
 
   if (wcs == NULL)
-    {
-      if (olds == NULL)
-	{
-	  errno = EINVAL;
-	  return NULL;
-	}
-      else
-	wcs = olds;
-    }
+    wcs = *ptr;
 
   /* Scan leading delimiters.  */
   wcs += wcsspn (wcs, delim);
   if (*wcs == L'\0')
     {
-      olds = NULL;
+      *ptr = NULL;
       return NULL;
     }
 
   /* Find the end of the token.	 */
-  token = wcs;
-  wcs = wcspbrk (token, delim);
+  result = wcs;
+  wcs = wcspbrk (result, delim);
   if (wcs == NULL)
     /* This token finishes the string.	*/
-    olds = NULL;
+    *ptr = NULL;
   else
     {
       /* Terminate the token and make OLDS point past it.  */
       *wcs = L'\0';
-      olds = wcs + 1;
+      *ptr = wcs + 1;
     }
-  return token;
+  return result;
 }
diff --git a/wcsmbs/wcstr.h b/wcsmbs/wcstr.h
deleted file mode 100644
index e9cc64ddc1..0000000000
--- a/wcsmbs/wcstr.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 1995 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, 1992 Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#ifndef _WCSTRING_H
-
-#define _WCSTRING_H 1
-#include <features.h>
-
-__BEGIN_DECLS
-
-/* Get size_t, wchar_t, uwchar_t and NULL from <stddef.h>.  */
-#define __need_size_t
-#define __need_wchar_t
-/* #define __need_uwchar_t */
-#define __need_NULL
-#include <stddef.h>
-
-/* FIXME: Should go with this or another name in stddef.h.  */
-typedef unsigned int uwchar_t;
-
-
-/* Copy SRC to DEST.  */
-extern wchar_t *wcscpy __P ((wchar_t *__dest, __const wchar_t *__src));
-/* Copy no more than N wide-characters of SRC to DEST.  */
-extern wchar_t *wcsncpy __P ((wchar_t *__dest, __const wchar_t *__src,
-			      size_t __n));
-
-/* Append SRC onto DEST.  */
-extern wchar_t *wcscat __P ((wchar_t *__dest, __const wchar_t *__src));
-/* Append no more than N wide-characters of SRC onto DEST.  */
-extern wchar_t *wcsncat __P ((wchar_t *__dest, __const wchar_t *__src,
-			      size_t __n));
-
-/* Compare S1 and S2.  */
-extern int wcscmp __P ((__const wchar_t *__s1, __const wchar_t *__s2));
-/* Compare N wide-characters of S1 and S2.  */
-extern int wcsncmp __P ((__const wchar_t *__s1, __const wchar_t *__s2,
-			 size_t __n));
-
-/* Duplicate S, returning an identical malloc'd string.  */
-extern wchar_t *wcsdup __P ((__const wchar_t *__s));
-
-/* Find the first occurence of WC in WCS.  */
-extern wchar_t *wcschr __P ((__const wchar_t *__wcs, wchar_t __wc));
-/* Find the last occurence of WC in WCS.  */
-extern wchar_t *wcsrchr __P ((__const wchar_t *__wcs, wchar_t __wc));
-
-/* 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,
-			    __const wchar_t *__reject));
-/* Return the length of the initial segmet of WCS which
-   consists entirely of wide-characters in  ACCEPT.  */
-extern size_t wcsspn __P ((__const wchar_t *__wcs, __const wchar_t *__accept));
-/* Find the first occurence in WCS of any character in ACCEPT.  */
-extern wchar_t *wcspbrk __P ((__const wchar_t *__wcs,
-			      __const wchar_t *__accept));
-/* Find the first occurence of NEEDLE in HAYSTACK.  */
-extern wchar_t *wcswcs __P ((__const wchar_t *__haystack,
-			     __const wchar_t *__needle));
-/* Divide WCS into tokens separated by characters in DELIM.  */
-extern wchar_t *wcstok __P ((wchar_t *__s, __const wchar_t *__delim));
-
-/* Return the number of wide-characters in S.  */
-extern size_t wcslen __P ((__const wchar_t *__s));
-
-__END_DECLS
-
-#endif /* wcstring.h */
diff --git a/wcsmbs/wcswcs.c b/wcsmbs/wcswcs.c
deleted file mode 100644
index 4b1f2ace54..0000000000
--- a/wcsmbs/wcswcs.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* Copyright (C) 1995 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., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-/*
- * The original strstr() file contains the following comment:
- *
- * My personal strstr() implementation that beats most other algorithms.
- * Until someone tells me otherwise, I assume that this is the
- * fastest implementation of strstr() in C.
- * I deliberately chose not to comment it.  You should have at least
- * as much fun trying to understand it, as I had to write it :-).
- *
- * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
-
-#include <wcstr.h>
-
-wchar_t *
-wcswcs (haystack, needle)
-    const wchar_t *haystack;
-    const wchar_t *needle;
-{
-  register wchar_t b, c;
-
-  if ((b = *needle) != L'\0')
-    {
-      haystack--;				/* possible ANSI violation */
-      do
-	if ((c = *++haystack) == L'\0')
-	  goto ret0;
-      while (c != b);
-
-      if (!(c = *++needle))
-	goto foundneedle;
-      ++needle;
-      goto jin;
-
-      for (;;)
-	{ 
-	  register wchar_t a;
-	  register const wchar_t *rhaystack, *rneedle;
-
-	  do
-	    {
-	      if (!(a = *++haystack))
-		goto ret0;
-	      if (a == b)
-		break;
-	      if ((a = *++haystack) == L'\0')
-		goto ret0;
-shloop:	      ;
-	    }
-	  while (a != b);
-
-jin:	  if (!(a = *++haystack))
-	    goto ret0;
-
-	  if (a != c)
-	    goto shloop;
-
-	  if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle)))
-	    do
-	      {
-		if (a == L'\0')
-		  goto foundneedle;
-		if (*++rhaystack != (a = *++needle))
-		  break;
-		if (a == L'\0')
-		  goto foundneedle;
-	      }
-	    while (*++rhaystack == (a = *++needle));
-
-	  needle=rneedle;		  /* took the register-poor approach */
-
-	  if (a == L'\0')
-	    break;
-	}
-    }
-foundneedle:
-  return (wchar_t*)haystack;
-ret0:
-  return NULL;
-}