Index: libc/stdlib/Makefile
===================================================================
--- libc/stdlib/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/stdlib/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for stdlib routines
 #
+include ../option-groups.mak
+
 subdir	:= stdlib
 
 headers	:= stdlib.h bits/stdlib.h bits/stdlib-ldbl.h			      \
@@ -28,7 +30,7 @@
 	   ucontext.h sys/ucontext.h					      \
 	   alloca.h fmtmsg.h
 
-routines	:=							      \
+routines-y	:=							      \
 	atof atoi atol atoll						      \
 	abort								      \
 	bsearch qsort msort						      \
@@ -37,7 +39,6 @@
 	quick_exit at_quick_exit cxa_at_quick_exit			      \
 	abs labs llabs							      \
 	div ldiv lldiv							      \
-	mblen mbstowcs mbtowc wcstombs wctomb				      \
 	random random_r rand rand_r					      \
 	drand48 erand48 lrand48 nrand48 mrand48 jrand48			      \
 	srand48 seed48 lcong48						      \
@@ -50,9 +51,18 @@
 	strtof_l strtod_l strtold_l					      \
 	system canonicalize						      \
 	a64l l64a							      \
-	rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg		      \
-	strtoimax strtoumax wcstoimax wcstoumax				      \
+	getsubopt xpg_basename						      \
+	strtoimax strtoumax						      \
 	getcontext setcontext makecontext swapcontext
+routines-$(OPTION_EGLIBC_LOCALE_CODE) +=				      \
+	strfmon strfmon_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) +=				      \
+	mblen mbstowcs mbtowc wcstombs wctomb				      \
+	wcstoimax wcstoumax
+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP))
+routines-y += rpmatch
+endif
+routines-$(OPTION_EGLIBC_FMTMSG) += fmtmsg
 aux =	grouping groupingwc tens_in_limb
 
 # These routines will be omitted from the libc shared object.
@@ -62,16 +72,19 @@
 
 distribute	:= exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh   \
 		   allocalim.h
-test-srcs	:= tst-fmtmsg
-tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
+test-srcs-$(OPTION_EGLIBC_FMTMSG) := tst-fmtmsg
+tests		:= tst-strtol tst-strtod testrand testsort testdiv          \
 		   test-canon test-canon2 tst-strtoll tst-environ	    \
 		   tst-xpg-basename tst-random tst-random2 tst-bsearch	    \
 		   tst-limits tst-rand48 bug-strtod tst-setcontext	    \
-		   test-a64l tst-qsort tst-system testmb2 bug-strtod2	    \
-		   tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
-		   tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2	    \
-		   tst-makecontext2 tst-strtod6 tst-unsetenv1
-
+		   test-a64l tst-qsort tst-system bug-strtod2		    \
+		   tst-atof1 tst-atof2 tst-strtod2 tst-rand48-2             \
+		   tst-makecontext tst-qsort2 tst-makecontext2 tst-strtod6  \
+		   tst-unsetenv1
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+		+= tst-strtod3 tst-strtod4 tst-strtod5 testmb2
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+		+= testmb
 include ../Makeconfig
 
 ifeq ($(build-shared),yes)
@@ -124,9 +137,11 @@
 # Run a test on the header files we use.
 tests: $(objpfx)isomac.out
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
+ifeq (y,$(OPTION_EGLIBC_FMTMSG))
 tests: $(objpfx)tst-fmtmsg.out
 endif
+# eglibc: endif
 
 $(objpfx)isomac.out: $(objpfx)isomac
 	$(dir $<)$(notdir $<) '$(CC)'  \
Index: libc/stdlib/tst-strtod.c
===================================================================
--- libc/stdlib/tst-strtod.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdlib/tst-strtod.c	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <string.h>
 #include <math.h>
+#include <gnu/option-groups.h>
 
 struct ltest
   {
@@ -174,7 +175,9 @@
 
   status |= long_dbl ();
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   status |= locale_test ();
+#endif
 
   return status ? EXIT_FAILURE : EXIT_SUCCESS;
 }
@@ -217,6 +220,7 @@
   return 0;
 }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 /* Perform a few tests in a locale with thousands separators.  */
 static int
 locale_test (void)
@@ -274,3 +278,4 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
Index: libc/stdlib/strtod_l.c
===================================================================
--- libc/stdlib/strtod_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdlib/strtod_l.c	(.../trunk)	(revision 8411)
@@ -19,6 +19,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <gnu/option-groups.h>
 #include <xlocale.h>
 
 extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
@@ -465,6 +466,7 @@
   /* Used in several places.  */
   int cnt;
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   struct locale_data *current = loc->__locales[LC_NUMERIC];
 
   if (__builtin_expect (group, 0))
@@ -503,6 +505,17 @@
   decimal_len = strlen (decimal);
   assert (decimal_len > 0);
 #endif
+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
+  /* Hard-code values from the 'C' locale.  */
+  grouping = NULL;
+#ifdef USE_WIDE_CHAR
+  decimal = L'.';
+# define decimal_len 1
+#else
+  decimal = ".";
+  decimal_len = 1;
+#endif
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 
   /* Prepare number representation.  */
   exponent = 0;
Index: libc/debug/pcprofiledump.c
===================================================================
--- libc/debug/pcprofiledump.c	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/pcprofiledump.c	(.../trunk)	(revision 8411)
@@ -201,13 +201,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -218,7 +221,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "pcprofiledump (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "pcprofiledump %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/debug/Makefile
===================================================================
--- libc/debug/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/Makefile	(.../trunk)	(revision 8411)
@@ -19,12 +19,14 @@
 #
 #	Sub-makefile for debug portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= debug
 
 headers	:= execinfo.h
 distribute = sigcontextinfo.h register-dump.h frame.h
 
-routines  = backtrace backtracesyms backtracesymsfd noophooks \
+routines  = noophooks \
 	    memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
 	    strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
 	    sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
@@ -33,18 +35,26 @@
 	    read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
 	    readlink_chk readlinkat_chk getwd_chk getcwd_chk \
 	    realpath_chk ptsname_r_chk fread_chk fread_u_chk \
-	    wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
-	    wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
-	    wcpncpy_chk \
-	    swprintf_chk vswprintf_chk wprintf_chk fwprintf_chk \
-	    vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk \
-	    confstr_chk getgroups_chk ttyname_r_chk getlogin_r_chk \
-	    gethostname_chk getdomainname_chk wcrtomb_chk mbsnrtowcs_chk \
-	    wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk \
-	    wcstombs_chk asprintf_chk vasprintf_chk dprintf_chk \
+	    confstr_chk getgroups_chk ttyname_r_chk \
+	    gethostname_chk getdomainname_chk \
+	    asprintf_chk vasprintf_chk dprintf_chk \
 	    vdprintf_chk obprintf_chk \
 	    stack_chk_fail fortify_fail \
 	    $(static-only-routines)
+routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin_r_chk
+routines-$(OPTION_EGLIBC_BACKTRACE) += backtrace backtracesyms backtracesymsfd 
+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)			\
+	 += wprintf_chk fwprintf_chk				\
+	    vwprintf_chk vfwprintf_chk fgetws_chk fgetws_u_chk
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR)				\
+	 += wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk	\
+	    wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk	\
+	    wcpncpy_chk							\
+	    swprintf_chk vswprintf_chk					\
+	    wcrtomb_chk mbsnrtowcs_chk					\
+	    wcsnrtombs_chk mbsrtowcs_chk wcsrtombs_chk mbstowcs_chk	\
+	    wcstombs_chk 
+
 static-only-routines := warning-nop stack_chk_fail_local
 
 CFLAGS-backtrace.c = -fno-omit-frame-pointer
@@ -113,9 +123,13 @@
 LDFLAGS-tst-lfschk5 = -lstdc++
 LDFLAGS-tst-lfschk6 = -lstdc++
 
-tests = backtrace-tst tst-chk1 tst-chk2 tst-chk3 \
-	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
-	tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6
+tests = test-strcpy_chk test-stpcpy_chk
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+      += tst-chk1 tst-chk2 tst-chk3 tst-lfschk1 tst-lfschk2 tst-lfschk3 
+tests-$(OPTION_EGLIBC_BACKTRACE) += backtrace-tst 
+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_EGLIBC_CXX_TESTS))
+tests += tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6
+endif
 
 extra-libs = libSegFault libpcprofile
 extra-libs-others = $(extra-libs)
@@ -147,7 +161,9 @@
 $(objpfx)catchsegv: catchsegv.sh $(common-objpfx)soversions.mk \
 		    $(common-objpfx)config.make
 	slibpfx=`echo $(slibdir)|sed 's/lib\(64\|\)$$/\\\\\\\\$$LIB/'`; \
-	sed -e 's|@VERSION@|$(version)|' -e "s|@SLIB@|$$slibpfx|" $< > $@.new
+	sed -e 's|@VERSION@|$(version)|' -e "s|@SLIB@|$$slibpfx|" \
+	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
+	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $< > $@.new
 	chmod 555 $@.new
 	mv -f $@.new $@
 
@@ -156,7 +172,9 @@
 $(objpfx)xtrace: xtrace.sh
 	rm -f $@.new
 	sed -e 's|@BASH@|$(BASH)|' -e 's|@VERSION@|$(version)|' \
-	    -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \
+	    -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' \
+	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
+	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
 	&& rm -f $@ && mv $@.new $@ && chmod +x $@
 
 # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
Index: libc/debug/catchsegv.sh
===================================================================
--- libc/debug/catchsegv.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/catchsegv.sh	(.../trunk)	(revision 8411)
@@ -35,11 +35,11 @@
       echo '  --help      print this help, then exit'
       echo '  --version   print version number, then exit'
       echo "For bug reporting instructions, please see:"
-      echo "<http://www.gnu.org/software/libc/bugs.html>."
+      echo "@REPORT_BUGS_TO@."
       exit 0
       ;;
     --v | --ve | --ver | --vers | --versi | --versio | --version)
-      echo 'catchsegv (GNU libc) @VERSION@'
+      echo 'catchsegv @PKGVERSION@@VERSION@'
       echo 'Copyright (C) 2009 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Index: libc/debug/tst-chk1.c
===================================================================
--- libc/debug/tst-chk1.c	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/tst-chk1.c	(.../trunk)	(revision 8411)
@@ -31,6 +31,7 @@
 #include <wchar.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <gnu/option-groups.h>
 
 #define obstack_chunk_alloc malloc
 #define obstack_chunk_free free
@@ -322,6 +323,7 @@
   snprintf (buf + 8, l0 + 3, "%d", num2);
   CHK_FAIL_END
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   CHK_FAIL_START
   swprintf (wbuf + 8, 3, L"%d", num1);
   CHK_FAIL_END
@@ -329,6 +331,7 @@
   CHK_FAIL_START
   swprintf (wbuf + 8, l0 + 3, L"%d", num1);
   CHK_FAIL_END
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
 # endif
 
   memcpy (buf, str1 + 2, l0 + 9);
@@ -396,6 +399,7 @@
   CHK_FAIL_END
 #endif
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
 
   /* These ops can be done without runtime checking of object size.  */
   wmemcpy (wbuf, L"abcdefghij", 10);
@@ -620,6 +624,7 @@
   CHK_FAIL_END
 #endif
 
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
 
   /* Now checks for %n protection.  */
 
@@ -1207,6 +1212,7 @@
 # endif
 #endif
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   if (setlocale (LC_ALL, "de_DE.UTF-8") != NULL)
     {
       assert (MB_CUR_MAX <= 10);
@@ -1363,6 +1369,7 @@
       puts ("cannot set locale");
       ret = 1;
     }
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
 
   fd = posix_openpt (O_RDWR);
   if (fd != -1)
Index: libc/debug/segfault.c
===================================================================
--- libc/debug/segfault.c	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/segfault.c	(.../trunk)	(revision 8411)
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <stdio-common/_itoa.h>
 #include <ldsodefs.h>
+#include <gnu/option-groups.h>
 
 #include <bp-checks.h>
 
@@ -95,6 +96,7 @@
   REGISTER_DUMP;
 #endif
 
+#if __OPTION_EGLIBC_BACKTRACE
   WRITE_STRING ("\nBacktrace:\n");
 
   /* Get the backtrace.  */
@@ -117,6 +119,7 @@
 
   /* Now generate nicely formatted output.  */
   __backtrace_symbols_fd (arr + i, cnt - i, fd);
+#endif
 
 #ifdef HAVE_PROC_SELF
   /* Now the link map.  */
Index: libc/debug/xtrace.sh
===================================================================
--- libc/debug/xtrace.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/debug/xtrace.sh	(.../trunk)	(revision 8411)
@@ -56,13 +56,13 @@
 
 "
   printf $"For bug reporting instructions, please see:
-<http://www.gnu.org/software/libc/bugs.html>.
-"
+%s.
+" "@REPORT_BUGS_TO@"
   exit 0
 }
 
 do_version() {
-  echo 'xtrace (GNU libc) @VERSION@'
+  echo 'xtrace @PKGVERSION@@VERSION@'
   printf $"Copyright (C) %s Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Index: libc/scripts/option-groups.awk
===================================================================
--- libc/scripts/option-groups.awk	(.../fsf/trunk)	(revision 0)
+++ libc/scripts/option-groups.awk	(.../trunk)	(revision 8411)
@@ -0,0 +1,57 @@
+# option-groups.awk --- generate option group header file
+# Given input files containing makefile-style assignments to variables, 
+# print out a header file that #defines an appropriate preprocessor
+# symbol for each variable left set to 'y'.
+
+BEGIN { FS="=" }
+
+# Trim spaces.
+{ gsub (/[[:blank:]]/, "") }
+
+# Skip comments.
+/^#/ { next }
+
+# Process assignments.
+NF == 2 {
+    vars[$1] = $2
+}
+
+# Print final values.
+END {
+    print "/* This file is automatically generated by scripts/option-groups.awk"
+    print "   in the EGLIBC source tree."
+    print ""
+    print "   It defines macros that indicate which EGLIBC option groups were"
+    print "   configured in 'option-groups.config' when this C library was"
+    print "   built.  For each option group named OPTION_foo, it #defines"
+    print "   __OPTION_foo to be 1 if the group is enabled, or leaves that"
+    print "   symbol undefined if the group is disabled.  */"
+    print ""
+    print "#ifndef __GNU_OPTION_GROUPS_H"
+    print "#define __GNU_OPTION_GROUPS_H"
+    print ""
+
+    # Produce a sorted list of variable names.
+    i=0
+    for (var in vars)
+        names[i++] = var
+    n = asort (names)
+
+    for (i = 1; i <= n; i++)
+    {
+        var = names[i]
+        if (var ~ /^OPTION_/)
+        {
+            if (vars[var] == "y")
+                print "#define __" var " 1"
+            else if (vars[var] == "n")
+                print "/* #undef __" var " */"
+            # Ignore variables that don't have boolean values.
+            # Ideally, this would be driven by the types given in
+            # option-groups.def.
+        }
+    }
+
+    print ""
+    print "#endif /* __GNU_OPTION_GROUPS_H */"
+}
Index: libc/scripts/cross-test-ssh.sh
===================================================================
--- libc/scripts/cross-test-ssh.sh	(.../fsf/trunk)	(revision 0)
+++ libc/scripts/cross-test-ssh.sh	(.../trunk)	(revision 8411)
@@ -0,0 +1,133 @@
+#!/usr/bin/env bash
+# usage: cross-test-ssh.sh [--ssh SSH] HOST COMMAND ...
+# Run with --help flag to get more detailed help.
+
+progname="$(basename $0)"
+env_blacklist='HOME LOGNAME MAIL PATH SHELL SHLVL SSH_CLIENT SSH_CONNECTION USER TERM TERMCAP PWD'
+
+usage="usage: ${progname} [--ssh SSH] HOST COMMAND ..."
+help="Run an EGLIBC test COMMAND on the remote machine HOST, via ssh,
+passing environment variables, preserving the current working directory,
+and respecting quoting.
+
+If the '--ssh SSH' flag is present, use SSH as the SSH command,
+instead of ordinary 'ssh'.
+
+To use this to run EGLIBC tests, invoke the tests as follows:
+
+  $ make cross-test-wrapper='ABSPATH/cross-test-ssh.sh HOST' tests
+
+where ABSPATH is the absolute path to this script, and HOST is the
+name of the machine to connect to via ssh.
+
+If you need to connect to the test machine as a different user, you
+may specify that just as you would to SSH:
+
+  $ make cross-test-wrapper='ABSPATH/cross-test-ssh.sh USER@HOST' tests
+
+Naturally, the remote user must have an appropriate public key, and
+you will want to ensure that SSH does not prompt interactively for a
+password on each connection.
+
+HOST and the build machines (on which 'make check' is being run) must
+share a filesystem; all files needed by the tests must be visible at
+the same paths on both machines.
+
+${progname} runs COMMAND in the same directory on the HOST that
+${progname} itself is run in on the build machine.
+
+The command and arguments are passed to the remote host in a way that
+avoids any further shell substitution or expansion, on the assumption
+that the shell on the build machine has already done them
+appropriately.
+
+${progname} propagates the values all environment variables through to
+the remote target, except the following:
+${env_blacklist}"
+
+ssh='ssh'
+while true; do
+    case "$1" in
+
+        "--ssh")
+            shift; ssh="$1"
+            ;;
+
+        "--help")
+            echo "$usage"
+            echo "$help"
+            exit 0
+            ;;
+
+        *)
+            break
+            ;;
+    esac
+    shift
+done
+
+if [ $# -lt 1 ]; then
+    echo "$usage" >&2
+    echo "Type '${progname} --help' for more detailed help." >&2
+    exit 1
+fi
+
+host="$1"; shift
+
+# Return all input as a properly quoted Bourne shell string.
+bourne_quote () {
+    printf '%s' '"'
+    sed -n \
+        -e '1h' \
+        -e '2,$H' \
+        -e '${g
+              s/["$\`]/\\&/g
+              p
+             }'
+    printf '%s' '"'
+}
+
+# Remove unnecessary newlines from a Bourne shell command sequence.
+remove_newlines () {
+    sed -n \
+        -e '1h' \
+        -e '2,$H' \
+        -e '${g
+              s/\([^\]\)\n/\1; /g
+              p
+             }'
+}
+
+# Unset all variables from the blacklist.  Then echo all exported
+# variables.  This should be run in a subshell.  The 'export -p'
+# command adds backslashes for environment variables which contain
+# newlines.
+blacklist_exports () {
+    local var
+    for var in ${env_blacklist}; do
+	unset $var
+    done
+    export -p
+}
+
+# Produce properly quoted Bourne shell arguments for 'env' to carry
+# over the current environment, less blacklisted variables.
+exports="$( (blacklist_exports) | sed -e 's|^declare -x |export |')"
+
+# Transform the current argument list into a properly quoted Bourne shell
+# command string.
+command="$(for word in "$@"; do
+               printf '%s' "$word" | bourne_quote
+               printf '%s' ' '
+           done)"
+
+# Add commands to set environment variables and the current directory.
+command="${exports}
+cd $PWD
+${command}"
+
+# HOST's sshd simply concatenates its arguments with spaces and
+# passes them to some shell.  We want to force the use of /bin/sh,
+# so we need to re-quote the whole command to ensure it appears as
+# the sole argument of the '-c' option.
+$ssh "$host" /bin/sh -c "$(printf '%s\n' "${command}" | bourne_quote | remove_newlines)"

Property changes on: libc/scripts/cross-test-ssh.sh
___________________________________________________________________
Added: svn:executable
   + *

Index: libc/scripts/run-with-env.sh
===================================================================
--- libc/scripts/run-with-env.sh	(.../fsf/trunk)	(revision 0)
+++ libc/scripts/run-with-env.sh	(.../trunk)	(revision 8411)
@@ -0,0 +1,24 @@
+#!/bin/sh
+# Usage: run-with-env.sh CMD ...
+# Execute commands with environment variables set at the last minute.
+# For certain environment variable whose names are of the form
+# 'EGLIBC_TEST_foo', if they are set, we set an environment variable
+# 'foo' to their value.
+#
+# This lets us run test programs via wrappers with environment
+# variable settings that would otherwise interfere with the wrapper
+# itself, like LD_PRELOAD or LD_AUDIT.
+
+if [ "${EGLIBC_TEST_LD_PRELOAD+set}" ]; then
+    export LD_PRELOAD="${EGLIBC_TEST_LD_PRELOAD}"
+fi
+
+if [ "${EGLIBC_TEST_LD_AUDIT+set}" ]; then
+    export LD_AUDIT="${EGLIBC_TEST_LD_AUDIT}"
+fi
+
+if [ "${EGLIBC_TEST_LD_LIBRARY_PATH+set}" ]; then
+    export LD_LIBRARY_PATH="${EGLIBC_TEST_LD_LIBRARY_PATH}"
+fi
+
+exec "$@"

Property changes on: libc/scripts/run-with-env.sh
___________________________________________________________________
Added: svn:executable
   + *

Index: libc/nscd/nscd.c
===================================================================
--- libc/nscd/nscd.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nscd/nscd.c	(.../trunk)	(revision 8411)
@@ -408,13 +408,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -425,7 +428,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "nscd (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "nscd %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/nscd/nis_hash.c
===================================================================
--- libc/nscd/nis_hash.c	(.../fsf/trunk)	(revision 0)
+++ libc/nscd/nis_hash.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,3 @@
+/* If OPTION_EGLIBC_NIS is disabled, nscd can't get this from libnsl.so;
+   we need our own copy.  */
+#include "../nis/nis_hash.c"
Index: libc/nscd/Makefile
===================================================================
--- libc/nscd/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/nscd/Makefile	(.../trunk)	(revision 8411)
@@ -20,11 +20,14 @@
 #
 #	Sub-makefile for nscd portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= nscd
 
-routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
+routines-$(OPTION_EGLIBC_INET) += \
+	     nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
 	    nscd_initgroups nscd_getserv_r
-aux	:= nscd_helper
+aux-$(OPTION_EGLIBC_INET) += nscd_helper
 
 include ../Makeconfig
 
@@ -36,15 +39,19 @@
 		getsrvbynm_r getsrvbypt_r servicescache \
 		dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
 		xmalloc xstrdup aicache initgrcache gai res_hconf
-
+ifneq (y,$(OPTION_EGLIBC_NIS))
+# If we haven't build libnsl.so, then we'll need to include our
+# own copy of nis_hash.
+nscd-modules += nis_hash
+endif
 ifeq ($(have-thread-library),yes)
 
 ifneq (yesyes,$(have-fpie)$(build-shared))
-others += nscd
+others-$(OPTION_EGLIBC_INET) += nscd
 endif
-install-sbin := nscd
+install-sbin-$(OPTION_EGLIBC_INET) += nscd
 
-extra-objs := $(nscd-modules:=.o)
+extra-objs-$(OPTION_EGLIBC_INET) += $(nscd-modules:=.o)
 
 endif
 
@@ -78,7 +85,8 @@
 
 distribute := nscd.h nscd-client.h dbg_log.h \
 	      $(addsuffix .c, $(filter-out xmalloc,$(all-nscd-modules))) \
-	      nscd.conf nscd.init nscd_proto.h nscd-types.h
+	      nscd.conf nscd.init nscd_proto.h nscd-types.h \
+	      nis_hash.c
 
 include ../Rules
 
@@ -123,6 +131,7 @@
 CFLAGS-getsrvbynm_r.c += $(nscd-cflags)
 CFLAGS-getsrvbypt_r.c += $(nscd-cflags)
 CFLAGS-res_hconf.c += $(nscd-cflags)
+CFLAGS-nis_hash.c += $(nscd-cflags)
 
 ifeq (yesyes,$(have-fpie)$(build-shared))
 relro-LDFLAGS += -Wl,-z,now
@@ -145,9 +154,15 @@
 $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o)
 
 ifeq ($(build-shared),yes)
-$(objpfx)nscd: $(common-objpfx)rt/librt.so $(shared-thread-library) \
-	       $(common-objpfx)nis/libnsl.so
+$(objpfx)nscd: $(common-objpfx)rt/librt.so $(shared-thread-library)
 else
-$(objpfx)nscd: $(common-objpfx)rt/librt.a $(static-thread-library) \
-	       $(common-objpfx)nis/libnsl.a
+$(objpfx)nscd: $(common-objpfx)rt/librt.a $(static-thread-library)
 endif
+
+ifeq (y,$(OPTION_EGLIBC_NIS))
+ifeq ($(build-shared),yes)
+$(objpfx)nscd: $(common-objpfx)nis/libnsl.so
+else
+$(objpfx)nscd: $(common-objpfx)nis/libnsl.a
+endif
+endif
Index: libc/wcsmbs/Makefile
===================================================================
--- libc/wcsmbs/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/wcsmbs/Makefile	(.../trunk)	(revision 8411)
@@ -20,14 +20,20 @@
 #
 #	Sub-makefile for wcsmbs portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= wcsmbs
 
 headers	:= wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h
 distribute := wcwidth.h wcsmbsload.h
 
-routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
+# These functions are used by printf_fp.c, even in the plain case; see
+# comments there for OPTION_EGLIBC_LOCALE_CODE.
+routines  := wmemcpy wmemset 
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+	  := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
 	    wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
-	    wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy wmempcpy \
+	    wmemcmp wmemmove wcpcpy wcpncpy wmempcpy \
 	    btowc wctob mbsinit \
 	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
 	    mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
@@ -39,12 +45,16 @@
 	    wcscoll_l wcsxfrm_l \
 	    wcscasecmp wcsncase wcscasecmp_l wcsncase_l \
 	    wcsmbsload mbsrtowcs_l \
-	    isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf \
 	    isoc99_swscanf isoc99_vswscanf
+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)				\
+	 += isoc99_wscanf isoc99_vwscanf isoc99_fwscanf isoc99_vfwscanf
 
-tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
-	 tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
-	 wcsatcliff
+tests := tst-wchar-h 
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+      += tst-btowc tst-mbrtowc tst-mbrtowc2 tst-wcrtomb
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+      += tst-wcstof wcsmbs-tst1 tst-wcsnlen \
+	 tst-wcpncpy tst-mbsrtowcs wcsatcliff
 
 include ../Rules
 
Index: libc/wcsmbs/wcsmbsload.c
===================================================================
--- libc/wcsmbs/wcsmbsload.c	(.../fsf/trunk)	(revision 8411)
+++ libc/wcsmbs/wcsmbsload.c	(.../trunk)	(revision 8411)
@@ -22,6 +22,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 #include <locale/localeinfo.h>
 #include <wcsmbsload.h>
@@ -144,6 +145,7 @@
   })
 
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 /* Some of the functions here must not be used while setlocale is called.  */
 __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
 
@@ -213,6 +215,17 @@
 
   __libc_rwlock_unlock (__libc_setlocale_lock);
 }
+#else
+void
+internal_function
+__wcsmbs_load_conv (struct locale_data *new_category)
+{
+  /* When OPTION_EGLIBC_LOCALE_CODE is disabled, we should never reach
+     this point: there is no way to change locales, so every locale
+     passed to get_gconv_fcts should be _nl_C_LC_CTYPE.  */
+  abort ();
+}
+#endif
 
 
 /* Clone the current conversion function set.  */
Index: libc/time/Makefile
===================================================================
--- libc/time/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/time/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for time routines
 #
+include ../option-groups.mak
+
 subdir	:= time
 
 headers	:= time.h sys/time.h sys/timeb.h bits/time.h
@@ -29,14 +31,20 @@
 	    tzfile getitimer setitimer			 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
-	    strftime wcsftime strftime_l wcsftime_l
-aux :=	    era alt_digit lc-time-cleanup
+	    strftime strftime_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR)		 \
+	 := wcsftime wcsftime_l
+aux-$(OPTION_EGLIBC_LOCALE_CODE) += alt_digit era lc-time-cleanup
 distribute := datemsk
 
-tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
-	   tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
+tests	:= test_time clocktest tst-posixtz \
+	   tst-getdate tst-mktime tst-mktime2 tst-strftime \
 	   tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \
 	   tst-strptime3 bug-getdate1
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+	+= tst-strptime tst-ftime_l
+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
+	+= tst_wcsftime
 
 include ../Rules
 
Index: libc/time/strftime_l.c
===================================================================
--- libc/time/strftime_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/time/strftime_l.c	(.../trunk)	(revision 8411)
@@ -35,6 +35,10 @@
 # include "../locale/localeinfo.h"
 #endif
 
+#ifdef _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #if defined emacs && !defined HAVE_BCOPY
 # define HAVE_MEMCPY 1
 #endif
@@ -888,7 +892,7 @@
 	    goto bad_format;
 	  if (modifier == L_('E'))
 	    {
-#if HAVE_STRUCT_ERA_ENTRY
+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 	      if (era)
 		{
@@ -961,7 +965,7 @@
 
 	  if (modifier == L_('O') && 0 <= number_value)
 	    {
-#ifdef _NL_CURRENT
+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT)
 	      /* Get the locale specific alternate representation of
 		 the number NUMBER_VALUE.  If none exist NULL is returned.  */
 	      const CHAR_T *cp = nl_get_alt_digit (number_value
@@ -1266,7 +1270,7 @@
 	case L_('Y'):
 	  if (modifier == 'E')
 	    {
-#if HAVE_STRUCT_ERA_ENTRY
+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 	      if (era)
 		{
@@ -1291,7 +1295,7 @@
 	case L_('y'):
 	  if (modifier == L_('E'))
 	    {
-#if HAVE_STRUCT_ERA_ENTRY
+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && HAVE_STRUCT_ERA_ENTRY
 	      struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG);
 	      if (era)
 		{
Index: libc/time/strptime_l.c
===================================================================
--- libc/time/strptime_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/time/strptime_l.c	(.../trunk)	(revision 8411)
@@ -29,6 +29,7 @@
 #include <stdbool.h>
 
 #ifdef _LIBC
+# include <gnu/option-groups.h>
 # include "../locale/localeinfo.h"
 #endif
 
@@ -84,7 +85,7 @@
     if (val < from || val > to)						      \
       return NULL;							      \
   } while (0)
-#ifdef _NL_CURRENT
+#if (! _LIBC || __OPTION_EGLIBC_LOCALE_CODE) && defined (_NL_CURRENT)
 # define get_alt_number(from, to, n) \
   ({									      \
      __label__ do_normal;						      \
@@ -819,6 +820,7 @@
 	      s.want_xday = 1;
 	      break;
 	    case 'C':
+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
 	      if (s.decided != raw)
 		{
 		  if (s.era_cnt >= 0)
@@ -855,10 +857,12 @@
 
 		  s.decided = raw;
 		}
+#endif
 	      /* The C locale has no era information, so use the
 		 normal representation.  */
 	      goto match_century;
  	    case 'y':
+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
 	      if (s.decided != raw)
 		{
 		  get_number(0, 9999, 4);
@@ -917,9 +921,10 @@
 
 		  s.decided = raw;
 		}
-
+#endif
 	      goto match_year_in_century;
 	    case 'Y':
+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
 	      if (s.decided != raw)
 		{
 		  num_eras = _NL_CURRENT_WORD (LC_TIME,
@@ -947,6 +952,7 @@
 
 		  s.decided = raw;
 		}
+#endif
 	      get_number (0, 9999, 4);
 	      tm->tm_year = val - 1900;
 	      s.want_century = 0;
@@ -1117,6 +1123,7 @@
 	tm->tm_year = (s.century - 19) * 100;
     }
 
+#if ! _LIBC || __OPTION_EGLIBC_LOCALE_CODE
   if (s.era_cnt != -1)
     {
       era = _nl_select_era_entry (s.era_cnt HELPER_LOCALE_ARG);
@@ -1131,6 +1138,7 @@
 	tm->tm_year = era->start_date[0];
     }
   else
+#endif
     if (s.want_era)
       {
 	/* No era found but we have seen an E modifier.  Rectify some
Index: libc/libio/iosetbuffer.c
===================================================================
--- libc/libio/iosetbuffer.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/iosetbuffer.c	(.../trunk)	(revision 8411)
@@ -40,9 +40,11 @@
   if (!buf)
     size = 0;
   (void) _IO_SETBUF (fp, buf, size);
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   if (_IO_vtable_offset (fp) == 0 && fp->_mode == 0 && _IO_CHECK_WIDE (fp))
     /* We also have to set the buffer using the wide char function.  */
     (void) _IO_WSETBUF (fp, buf, size);
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
   _IO_release_lock (fp);
 }
 INTDEF(_IO_setbuffer)
Index: libc/libio/libioP.h
===================================================================
--- libc/libio/libioP.h	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/libioP.h	(.../trunk)	(revision 8411)
@@ -36,6 +36,10 @@
 /*# include <comthread.h>*/
 #endif
 
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #include <math_ldbl_opt.h>
 
 #include "iolibio.h"
@@ -493,8 +497,20 @@
 
 
 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
+
+/* _IO_is_wide (fp) is roughly equivalent to '_IO_fwide (fp, 0) > 0',
+   except that when OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, it
+   expands to a constant, allowing the compiler to realize that it can
+   eliminate code that references wide stream handling functions.
+   This, in turn, allows us to omit them.  */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define _IO_is_wide(_f) ((_f)->_mode > 0)
+#else
+# define _IO_is_wide(_f) (0)
+#endif
+
 # define _IO_do_flush(_f) \
-  ((_f)->_mode <= 0							      \
+  (! _IO_is_wide (_f)                                                         \
    ? INTUSE(_IO_do_write)(_f, (_f)->_IO_write_base,			      \
 			  (_f)->_IO_write_ptr-(_f)->_IO_write_base)	      \
    : INTUSE(_IO_wdo_write)(_f, (_f)->_wide_data->_IO_write_base,	      \
Index: libc/libio/ioseekoff.c
===================================================================
--- libc/libio/ioseekoff.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/ioseekoff.c	(.../trunk)	(revision 8411)
@@ -62,7 +62,7 @@
 	  else
 	    abort ();
 	}
-      if (_IO_fwide (fp, 0) < 0)
+      if (! _IO_is_wide (fp))
 	INTUSE(_IO_free_backup_area) (fp);
       else
 	INTUSE(_IO_free_wbackup_area) (fp);
Index: libc/libio/iofwide.c
===================================================================
--- libc/libio/iofwide.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/iofwide.c	(.../trunk)	(revision 8411)
@@ -27,6 +27,7 @@
 
 #include <libioP.h>
 #ifdef _LIBC
+# include <gnu/option-groups.h>
 # include <dlfcn.h>
 # include <wchar.h>
 #endif
@@ -44,6 +45,8 @@
 #endif
 
 
+#if ! defined _LIBC || __OPTION_POSIX_C_LANG_WIDE_CHAR
+
 /* Prototypes of libio's codecvt functions.  */
 static enum __codecvt_result do_out (struct _IO_codecvt *codecvt,
 				     __mbstate_t *statep,
@@ -521,3 +524,26 @@
   return MB_CUR_MAX;
 #endif
 }
+
+#else
+/* OPTION_POSIX_C_LANG_WIDE_CHAR is disabled.  */
+
+#undef _IO_fwide
+int
+_IO_fwide (fp, mode)
+     _IO_FILE *fp;
+     int mode;
+{
+  /* Die helpfully if the user tries to create a wide stream; I
+     disbelieve that most users check the return value from
+     'fwide (fp, 1)'.  */
+  assert (mode <= 0);
+
+  /* We can only make streams byte-oriented, which is trivial.  */
+  if (mode < 0)
+    fp->_mode = -1;
+
+  return fp->_mode;
+}
+
+#endif
Index: libc/libio/fileops.c
===================================================================
--- libc/libio/fileops.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/fileops.c	(.../trunk)	(revision 8411)
@@ -176,7 +176,7 @@
 
   /* Free buffer. */
 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
-  if (fp->_mode > 0)
+  if (_IO_is_wide (fp))
     {
       if (_IO_have_wbackup (fp))
 	INTUSE(_IO_free_wbackup_area) (fp);
@@ -343,6 +343,7 @@
       cs = strstr (last_recognized + 1, ",ccs=");
       if (cs != NULL)
 	{
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 	  /* Yep.  Load the appropriate conversions and set the orientation
 	     to wide.  */
 	  struct gconv_fcts fcts;
@@ -407,6 +408,12 @@
 
 	  /* Set the mode now.  */
 	  result->_mode = 1;
+#else
+          /* Treat this as if we couldn't find the given character set.  */
+          (void) INTUSE(_IO_file_close_it) (fp);
+          __set_errno (EINVAL);
+          return NULL;
+#endif
 	}
     }
 #endif	/* GNU libc */
Index: libc/libio/Makefile
===================================================================
--- libc/libio/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Specific makefile for libio.
 #
+include ../option-groups.mak
+
 subdir	:= libio
 
 headers	:= stdio.h libio.h _G_config.h bits/stdio.h bits/stdio-lock.h \
@@ -26,16 +28,13 @@
 
 routines	:=							      \
 	filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen      \
-	iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc	      \
+	iofopncook iofputs iofread iofsetpos ioftell			      \
 	iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs	      \
 	ioseekoff ioseekpos iosetbuffer iosetvbuf ioungetc		      \
 	iovsprintf iovsscanf						      \
 	iofgetpos64 iofopen64 iofsetpos64				      \
-	fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
-	iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u	      \
-	putwchar putwchar_u putchar putchar_u fwprintf swprintf vwprintf      \
-	wprintf wscanf fwscanf vwscanf vswprintf iovswscanf swscanf wgenops   \
-	wstrops wfileops iofwide fwide wmemstream			      \
+	putchar putchar_u						      \
+	iofwide								      \
 									      \
 	clearerr feof ferror fileno fputc freopen fseek getc getchar	      \
 	memstream pclose putc putchar rewind setbuf setlinebuf vasprintf      \
@@ -46,19 +45,42 @@
 	__fpurge __fpending __fsetlocking				      \
 									      \
 	libc_fatal fmemopen
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) +=				      \
+	wfiledoalloc							      \
+	iowpadn								      \
+	swprintf							      \
+	vswprintf iovswscanf swscanf wgenops				      \
+	wstrops wfileops wmemstream
+routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) +=	      \
+	wdummyfileops
+routines-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) +=				      \
+	fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \
+	iofputws iofputws_u iogetwline ioungetwc putwc putwc_u		      \
+	putwchar putwchar_u fwprintf vwprintf				      \
+	wprintf wscanf fwscanf vwscanf					      \
+	fwide
 
-tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
-	tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 tst-fopenloc \
-	tst-fgetws tst-ungetwc1 tst-ungetwc2 tst-swscanf tst-sscanf	      \
-	tst-mmap-setvbuf bug-ungetwc1 bug-ungetwc2 tst-atime tst-eof          \
-	tst-freopen bug-rewind bug-rewind2 bug-ungetc bug-fseek \
-	tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush \
-	tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \
-	bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \
-	tst-memstream1 tst-memstream2 \
-	tst-wmemstream1 tst-wmemstream2 \
-	bug-memstream1 bug-wmemstream1 \
-	tst-setvbuf1 tst-popen1 tst-fgetwc
+tests = test-fmemopen tst-ext tst-ext2				\
+	tst-mmap-setvbuf tst-atime tst-eof			\
+	tst-freopen bug-ungetc bug-fseek			\
+	tst-mmap-eofsync tst-mmap-fflushsync bug-mmap-fflush	\
+	tst-mmap2-eofsync tst-mmap-offend bug-fopena+		\
+	bug-ungetc2 bug-ungetc3 bug-ungetc4			\
+	tst-memstream1 tst-memstream2				\
+	bug-memstream1 tst-popen1
+tests-$(OPTION_EGLIBC_LOCALE_CODE)				\
+     += tst-swscanf tst-fgetws tst-fopenloc tst-setvbuf1	\
+	tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2	\
+	tst-widetext 
+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO)		\
+     += bug-rewind bug-rewind2 bug-ungetwc1		\
+	bug-wfflush bug-wmemstream1 tst-fopenloc2	\
+	tst_getwc					\
+	tst_putwc tst_wprintf tst_wprintf2 tst_wscanf tst-fgetwc
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR)			\
+     += tst_swprintf tst_swscanf			\
+	tst-sscanf					\
+	tst-wmemstream1 tst-wmemstream2
 test-srcs = test-freopen
 
 all: # Make this the default target; it will be defined in Rules.
@@ -172,15 +194,17 @@
 
 include ../Rules
 
-ifeq (no,$(cross-compiling))
-tests: $(objpfx)test-freopen.out $(objpfx)tst-fopenloc.check
-endif
-
+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
+tests: $(objpfx)test-freopen.out
 $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
 	$(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)'	\
 	$(common-objpfx)libio/
+endif
 
+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+tests: $(objpfx)tst-fopenloc.check
 $(objpfx)tst-fopenloc.check: $(objpfx)tst-fopenloc.out
 	cmp ../iconvdata/testdata/ISO-8859-1..UTF8 $(objpfx)tst-fopenloc.out \
 	  > $@
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-fopenloc.mtrace >> $@
+endif
Index: libc/libio/ioseekpos.c
===================================================================
--- libc/libio/ioseekpos.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/ioseekpos.c	(.../trunk)	(revision 8411)
@@ -36,7 +36,7 @@
   /* If we have a backup buffer, get rid of it, since the __seekoff
      callback may not know to do the right thing about it.
      This may be over-kill, but it'll do for now. TODO */
-  if (_IO_fwide (fp, 0) <= 0)
+  if (! _IO_is_wide (fp))
     {
       if (_IO_have_backup (fp))
 	INTUSE(_IO_free_backup_area) (fp);
Index: libc/libio/wdummyfileops.c
===================================================================
--- libc/libio/wdummyfileops.c	(.../fsf/trunk)	(revision 0)
+++ libc/libio/wdummyfileops.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,161 @@
+/* Copyright (C) 2007 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   As a special exception, if you link the code in this file with
+   files compiled with a GNU compiler to produce an executable,
+   that does not cause the resulting executable to be covered by
+   the GNU Lesser General Public License.  This exception does not
+   however invalidate any other reasons why the executable file
+   might be covered by the GNU Lesser General Public License.
+   This exception applies to code released by its copyright holders
+   in files containing the exception.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libioP.h>
+
+static void __THROW __attribute__ ((__noreturn__))
+_IO_wfile_wide_char_support_disabled (void)
+{
+  static const char errstr[]
+    = ("The application tried to use wide character I/O, but libc.so"
+       " was compiled\n"
+       "with the OPTION_POSIX_C_LANG_WIDE_CHAR option group disabled.\n");
+  __libc_write (STDERR_FILENO, errstr, sizeof (errstr) - 1);
+  abort ();
+}
+
+static void
+_IO_wfile_disabled_void_int (_IO_FILE *fp, int x)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_int_int (_IO_FILE *fp, int x)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_int_none (_IO_FILE *fp)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_size_t
+_IO_wfile_disabled_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_size_t
+_IO_wfile_disabled_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seekoff (_IO_FILE *fp, _IO_off64_t off, int dir, int mode)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seekpos (_IO_FILE *fp, _IO_off64_t pos, int flags)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_FILE *
+_IO_wfile_disabled_setbuf (_IO_FILE *fp, char *buffer, _IO_ssize_t length)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_ssize_t
+_IO_wfile_disabled_read (_IO_FILE *fp, void *buffer, _IO_ssize_t length)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_ssize_t
+_IO_wfile_disabled_write (_IO_FILE *fp, const void *buffer, _IO_ssize_t length)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static _IO_off64_t
+_IO_wfile_disabled_seek (_IO_FILE *fp, _IO_off64_t offset, int mode)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_close (_IO_FILE *fp)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_stat (_IO_FILE *fp, void *buf)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static int
+_IO_wfile_disabled_showmanyc (_IO_FILE *fp)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static void
+_IO_wfile_disabled_imbue (_IO_FILE *fp, void *locale)
+{
+  _IO_wfile_wide_char_support_disabled ();
+}
+
+static const struct _IO_jump_t _IO_wfile_jumps_disabled =
+{
+  JUMP_INIT_DUMMY,
+  JUMP_INIT(finish, _IO_wfile_disabled_void_int),
+  JUMP_INIT(overflow, _IO_wfile_disabled_int_int),
+  JUMP_INIT(underflow, _IO_wfile_disabled_int_none),
+  JUMP_INIT(uflow, _IO_wfile_disabled_int_none),
+  JUMP_INIT(pbackfail, _IO_wfile_disabled_int_int),
+  JUMP_INIT(xsputn, _IO_wfile_disabled_xsputn),
+  JUMP_INIT(xsgetn, _IO_wfile_disabled_xsgetn),
+  JUMP_INIT(seekoff, _IO_wfile_disabled_seekoff),
+  JUMP_INIT(seekpos, _IO_wfile_disabled_seekpos),
+  JUMP_INIT(setbuf, _IO_wfile_disabled_setbuf),
+  JUMP_INIT(sync, _IO_wfile_disabled_int_none),
+  JUMP_INIT(doallocate, _IO_wfile_disabled_int_none),
+  JUMP_INIT(read, _IO_wfile_disabled_read),
+  JUMP_INIT(write, _IO_wfile_disabled_write),
+  JUMP_INIT(seek, _IO_wfile_disabled_seek),
+  JUMP_INIT(close, _IO_wfile_disabled_close),
+  JUMP_INIT(stat, _IO_wfile_disabled_stat),
+  JUMP_INIT(showmanyc, _IO_wfile_disabled_showmanyc),
+  JUMP_INIT(imbue, _IO_wfile_disabled_imbue)
+};
+
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps)
+libc_hidden_data_def (_IO_wfile_jumps)
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_mmap)
+strong_alias (_IO_wfile_jumps_disabled, _IO_wfile_jumps_maybe_mmap)
Index: libc/libio/__fpurge.c
===================================================================
--- libc/libio/__fpurge.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libio/__fpurge.c	(.../trunk)	(revision 8411)
@@ -22,7 +22,7 @@
 void
 __fpurge (FILE *fp)
 {
-  if (fp->_mode > 0)
+  if (_IO_is_wide (fp))
     {
       /* Wide-char stream.  */
       if (_IO_in_backup (fp))
Index: libc/intl/dcigettext.c
===================================================================
--- libc/intl/dcigettext.c	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/dcigettext.c	(.../trunk)	(revision 8411)
@@ -79,6 +79,10 @@
 #endif
 #include "hash-string.h"
 
+#ifdef _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 /* Thread safetyness.  */
 #ifdef _LIBC
 # include <bits/libc-lock.h>
@@ -451,9 +455,11 @@
 #endif
 
 #ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
   __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
   __libc_rwlock_rdlock (__libc_setlocale_lock);
 #endif
+#endif
 
   __libc_rwlock_rdlock (_nl_state_lock);
 
@@ -472,7 +478,11 @@
   search.category = category;
 # ifdef HAVE_PER_THREAD_LOCALE
 #  ifdef _LIBC
+#   if __OPTION_EGLIBC_LOCALE_CODE
   localename = strdupa (__current_locale_name (category));
+#   else
+  localename = "C";
+#   endif
 #  endif
   search.localename = localename;
 # endif
@@ -496,7 +506,9 @@
 	retval = (char *) (*foundp)->translation;
 
 # ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
       __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
 # endif
       __libc_rwlock_unlock (_nl_state_lock);
       return retval;
@@ -613,7 +625,9 @@
 	{
 	no_translation:
 	  FREE_BLOCKS (block_list);
+#if __OPTION_EGLIBC_LOCALE_CODE
 	  __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
 	  __libc_rwlock_unlock (_nl_state_lock);
 	  __set_errno (saved_errno);
 	  return (plural == 0
@@ -727,7 +741,9 @@
 	      if (plural)
 		retval = plural_lookup (domain, n, retval, retlen);
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 	      __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
 	      __libc_rwlock_unlock (_nl_state_lock);
 	      return retval;
 	    }
@@ -1348,7 +1364,11 @@
      `LC_xxx', and `LANG'.  On some systems this can be done by the
      `setlocale' function itself.  */
 #ifdef _LIBC
+# if __OPTION_EGLIBC_LOCALE_CODE
   retval = __current_locale_name (category);
+# else
+  retval = "C";
+# endif
 #else
   retval = _nl_locale_name (category, categoryname);
 #endif
Index: libc/intl/tst-gettext2.sh
===================================================================
--- libc/intl/tst-gettext2.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/tst-gettext2.sh	(.../trunk)	(revision 8411)
@@ -21,6 +21,7 @@
 
 common_objpfx=$1
 objpfx=$2
+cross_test_wrapper=$3
 
 LC_ALL=C
 export LC_ALL
@@ -66,6 +67,7 @@
 export LOCPATH
 
 # Now run the test.
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-gettext2 > ${objpfx}tst-gettext2.out ${objpfx}domaindir &&
 cmp ${objpfx}tst-gettext2.out - <<EOF
Index: libc/intl/tst-codeset.sh
===================================================================
--- libc/intl/tst-codeset.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/tst-codeset.sh	(.../trunk)	(revision 8411)
@@ -21,6 +21,7 @@
 
 common_objpfx=$1
 objpfx=$2
+cross_test_wrapper=$3
 
 LC_ALL=C
 export LC_ALL
@@ -37,6 +38,7 @@
 LOCPATH=${common_objpfx}localedata
 export LOCPATH
 
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-codeset > ${objpfx}tst-codeset.out
 
Index: libc/intl/Makefile
===================================================================
--- libc/intl/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/Makefile	(.../trunk)	(revision 8411)
@@ -17,6 +17,7 @@
 # 02111-1307 USA.
 
 # Makefile for intl subdirectory: message handling code from GNU gettext.
+include ../option-groups.mak
 
 subdir = intl
 headers = libintl.h
@@ -61,8 +62,8 @@
 
 include ../Rules
 
-ifeq (no,$(cross-compiling))
-ifeq (yes,$(build-shared))
+# eglibc: ifeq (no,$(cross-compiling))
+ifeq (yyyes,$(OPTION_EGLIBC_LOCALES)$(OPTION_EGLIBC_LOCALE_CODE)$(build-shared))
 ifneq ($(strip $(MSGFMT)),:)
 tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out \
        $(objpfx)tst-codeset.out $(objpfx)tst-gettext3.out
@@ -78,15 +79,19 @@
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-gettext.mtrace > $@
 $(objpfx)tst-gettext.out: tst-gettext.sh $(objpfx)tst-gettext
 	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
-	  $(objpfx)tst-gettext.mtrace
+	  $(objpfx)tst-gettext.mtrace '$(cross-test-wrapper)'
 $(objpfx)tst-translit.out: tst-translit.sh $(objpfx)tst-translit
-	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
+	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
+	'$(cross-test-wrapper)'
 $(objpfx)tst-gettext2.out: tst-gettext2.sh $(objpfx)tst-gettext2
-	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
+	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
+	'$(cross-test-wrapper)'
 $(objpfx)tst-codeset.out: tst-codeset.sh $(objpfx)tst-codeset
-	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
+	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
+	'$(cross-test-wrapper)'
 $(objpfx)tst-gettext3.out: tst-gettext3.sh $(objpfx)tst-gettext3
-	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
+	$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
+	'$(cross-test-wrapper)'
 $(objpfx)tst-gettext4.out: tst-gettext4.sh $(objpfx)tst-gettext4
 	$(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)' $(common-objpfx)intl/
 $(objpfx)tst-gettext5.out: tst-gettext5.sh $(objpfx)tst-gettext5
@@ -94,7 +99,7 @@
 $(objpfx)tst-gettext6.out: tst-gettext6.sh $(objpfx)tst-gettext6
 	$(SHELL) -e $< $(common-objpfx) '$(run-program-prefix)' $(common-objpfx)intl/
 endif
-endif
+# eglibc: endif
 
 $(objpfx)msgs.h: po2test.sed ../po/de.po
 	$(make-target-directory)
Index: libc/intl/tst-translit.sh
===================================================================
--- libc/intl/tst-translit.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/tst-translit.sh	(.../trunk)	(revision 8411)
@@ -21,6 +21,7 @@
 
 common_objpfx=$1
 objpfx=$2
+cross_test_wrapper=$3
 
 LC_ALL=C
 export LC_ALL
@@ -36,6 +37,7 @@
 LOCPATH=${common_objpfx}localedata
 export LOCPATH
 
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-translit > ${objpfx}tst-translit.out ${objpfx}domaindir
 
Index: libc/intl/tst-gettext3.sh
===================================================================
--- libc/intl/tst-gettext3.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/tst-gettext3.sh	(.../trunk)	(revision 8411)
@@ -22,6 +22,7 @@
 
 common_objpfx=$1
 objpfx=$2
+cross_test_wrapper=$3
 
 LC_ALL=C
 export LC_ALL
@@ -38,6 +39,7 @@
 LOCPATH=${common_objpfx}localedata
 export LOCPATH
 
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-gettext3 > ${objpfx}tst-gettext3.out
 
Index: libc/intl/tst-gettext.sh
===================================================================
--- libc/intl/tst-gettext.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/intl/tst-gettext.sh	(.../trunk)	(revision 8411)
@@ -22,6 +22,7 @@
 common_objpfx=$1
 objpfx=$2
 malloc_trace=$3
+cross_test_wrapper=$4
 
 LC_ALL=C
 export LC_ALL
@@ -53,6 +54,7 @@
 
 # Now run the test.
 MALLOC_TRACE=$malloc_trace LOCPATH=${objpfx}localedir:$LOCPATH \
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-gettext > ${objpfx}tst-gettext.out ${objpfx}domaindir
 
Index: libc/EGLIBC.cross-building
===================================================================
--- libc/EGLIBC.cross-building	(.../fsf/trunk)	(revision 0)
+++ libc/EGLIBC.cross-building	(.../trunk)	(revision 8411)
@@ -0,0 +1,352 @@
+                                                        -*- mode: text -*-
+
+                        Cross-Compiling EGLIBC
+                  Jim Blandy <jimb@codesourcery.com>
+
+
+Introduction
+
+Most GNU tools have a simple build procedure: you run their
+'configure' script, and then you run 'make'.  Unfortunately, the
+process of cross-compiling the GNU C library is quite a bit more
+involved:
+
+1) Build a cross-compiler, with certain facilities disabled.
+
+2) Configure the C library using the compiler you built in step 1).
+   Build a few of the C run-time object files, but not the rest of the
+   library.  Install the library's header files and the run-time
+   object files, and create a dummy libc.so.
+
+3) Build a second cross-compiler, using the header files and object
+   files you installed in step 2.
+
+4) Configure, build, and install a fresh C library, using the compiler
+   built in step 3.
+
+5) Build a third cross-compiler, based on the C library built in step 4.
+
+The reason for this complexity is that, although GCC and the GNU C
+library are distributed separately, they are not actually independent
+of each other: GCC requires the C library's headers and some object
+files to compile its own libraries, while the C library depends on
+GCC's libraries.  EGLIBC includes features and bug fixes to the stock
+GNU C library that simplify this process, but the fundamental
+interdependency stands.
+
+In this document, we explain how to cross-compile an EGLIBC/GCC pair
+from source.  Our intended audience is developers who are already
+familiar with the GNU toolchain and comfortable working with
+cross-development tools.  While we do present a worked example to
+accompany the explanation, for clarity's sake we do not cover many of
+the options available to cross-toolchain users.
+
+
+Preparation
+
+EGLIBC requires recent versions of the GNU binutils, GCC, and the
+Linux kernel.  The web page <http://www.eglibc.org/prerequisites>
+documents the current requirements, and lists patches needed for
+certain target architectures.  As of this writing, EGLIBC required
+binutils 2.17, GCC 4.1, and Linux 2.6.19.1.
+
+First, let's set some variables, to simplify later commands.  We'll
+build EGLIBC and GCC for a PowerPC target, known to the Linux kernel
+as 'powerpc', and we'll do the build on an Intel Linux box:
+
+    $ build=i686-pc-linux-gnu
+    $ host=$build
+    $ target=powerpc-none-linux-gnu
+    $ linux_arch=powerpc
+
+We're using the aforementioned versions of Binutils, GCC, and Linux:
+
+    $ binutilsv=binutils-2.17
+    $ gccv=gcc-4.1.1
+    $ linuxv=linux-2.6.20
+
+We're carrying out the entire process under '~/cross-build', which
+contains unpacked source trees:
+
+    $ top=$HOME/cross-build/ppc
+    $ src=$HOME/cross-build/src
+    $ ls $src
+    binutils-2.17  gcc-4.1.1  libc  linux-2.6.20
+
+We're going to place our build directories in a subdirectory 'obj',
+we'll install the cross-development toolchain in 'tools', and we'll
+place our sysroot (containing files to be installed on the target
+system) in 'sysroot':
+
+    $ obj=$top/obj
+    $ tools=$top/tools
+    $ sysroot=$top/sysroot
+
+
+Binutils
+
+Configuring and building binutils for the target is straightforward:
+
+    $ mkdir -p $obj/binutils
+    $ cd $obj/binutils
+    $ $src/$binutilsv/configure \
+    >     --target=$target \
+    >     --prefix=$tools \
+    >     --with-sysroot=$sysroot 
+    $ make
+    $ make install
+
+
+The First GCC
+
+For our work, we need a cross-compiler targeting a PowerPC Linux
+system.  However, that configuration includes the shared library
+'libgcc_s.so', which is compiled against the EGLIBC headers (which we
+haven't installed yet) and linked against 'libc.so' (which we haven't
+built yet).
+
+Fortunately, there are configuration options for GCC which tell it not
+to build 'libgcc_s.so'.  The '--without-headers' option is supposed to
+take care of this, but its implementation is incomplete, so you must
+also configure with the '--with-newlib' option.  While '--with-newlib'
+appears to mean "Use the Newlib C library", its effect is to tell the
+GCC build machinery, "Don't assume there is a C library available."
+
+We also need to disable some of the libraries that would normally be
+built along with GCC, and specify that only the compiler for the C
+language is needed.
+
+So, we create a build directory, configure, make, and install.
+
+    $ mkdir -p $obj/gcc1
+    $ cd $obj/gcc1
+    $ $src/$gccv/configure \
+    >     --target=$target \
+    >     --prefix=$tools \
+    >     --without-headers --with-newlib \
+    >     --disable-shared --disable-threads --disable-libssp \
+    >     --disable-libgomp --disable-libmudflap \
+    >     --enable-languages=c
+    $ PATH=$tools/bin:$PATH make
+    $ PATH=$tools/bin:$PATH make install
+
+
+Linux Kernel Headers
+
+To configure EGLIBC, we also need Linux kernel headers in place.
+Fortunately, the Linux makefiles have a target that installs them for
+us.  Since the process does modify the source tree a bit, we make a
+copy first:
+
+    $ cp -r $src/$linuxv $obj/linux
+    $ cd $obj/linux
+
+Now we're ready to install the headers into the sysroot:
+
+    $ PATH=$tools/bin:$PATH \
+    > make headers_install \
+    >      ARCH=$linux_arch CROSS_COMPILE=$target- \
+    >      INSTALL_HDR_PATH=$sysroot/usr
+
+
+EGLIBC Headers and Preliminary Objects
+
+Using the cross-compiler we've just built, we can now configure EGLIBC
+well enough to install the headers and build the object files that the
+full cross-compiler will need:
+
+    $ mkdir -p $obj/eglibc-headers
+    $ cd $obj/eglibc-headers
+    $ BUILD_CC=gcc \
+    > CC=$tools/bin/$target-gcc \
+    > CXX=$tools/bin/$target-g++ \
+    > AR=$tools/bin/$target-ar \
+    > RANLIB=$tools/bin/$target-ranlib \
+    > $src/libc/configure \
+    >     --prefix=/usr \
+    >     --with-headers=$sysroot/usr/include \
+    >     --build=$build \
+    >     --host=$target \
+    >     --disable-profile --without-gd --without-cvs --enable-add-ons
+
+The option '--prefix=/usr' may look strange, but you should never
+configure EGLIBC with a prefix other than '/usr': in various places,
+EGLIBC's build system checks whether the prefix is '/usr', and does
+special handling only if that is the case.  Unless you use this
+prefix, you will get a sysroot that does not use the standard Linux
+directory layouts and cannot be used as a basis for the root
+filesystem on your target system compatibly with normal GLIBC
+installations.
+
+The '--with-headers' option tells EGLIBC where the Linux headers have
+been installed.  
+
+We can now use the 'install-headers' makefile target to install the
+headers:
+
+    $ make install-headers install_root=$sysroot \
+    >                      install-bootstrap-headers=yes
+
+The 'install_root' variable indicates where the files should actually
+be installed; its value is treated as the parent of the '--prefix'
+directory we passed to the configure script, so the headers will go in
+'$sysroot/usr/include'.  The 'install-bootstrap-headers' variable
+requests special handling for certain tricky header files.
+
+Next, there are a few object files needed to link shared libraries,
+which we build and install by hand:
+
+    $ mkdir -p $sysroot/usr/lib
+    $ make csu/subdir_lib
+    $ cp csu/crt1.o csu/crti.o csu/crtn.o $sysroot/usr/lib
+
+Finally, 'libgcc_s.so' requires a 'libc.so' to link against.  However,
+since we will never actually execute its code, it doesn't matter what
+it contains.  So, treating '/dev/null' as a C source file, we produce
+a dummy 'libc.so' in one step:
+
+    $ $tools/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null \
+    >                        -o $sysroot/usr/lib/libc.so
+
+
+The Second GCC
+
+With the EGLIBC headers and selected object files installed, we can
+now build a GCC that is capable of compiling EGLIBC.  We configure,
+build, and install the second GCC, again building only the C compiler,
+and avoiding libraries we won't use:
+
+    $ mkdir -p $obj/gcc2
+    $ cd $obj/gcc2
+    $ $src/$gccv/configure \
+    >     --target=$target \
+    >     --prefix=$tools \
+    >     --with-sysroot=$sysroot \
+    >     --disable-libssp --disable-libgomp --disable-libmudflap \
+    >     --enable-languages=c
+    $ PATH=$tools/bin:$PATH make
+    $ PATH=$tools/bin:$PATH make install
+
+
+EGLIBC, Complete
+
+With the second compiler built and installed, we're now ready for the
+full EGLIBC build:
+
+    $ mkdir -p $obj/eglibc
+    $ cd $obj/eglibc
+    $ BUILD_CC=gcc \
+    > CC=$tools/bin/$target-gcc \
+    > CXX=$tools/bin/$target-g++ \
+    > AR=$tools/bin/$target-ar \
+    > RANLIB=$tools/bin/$target-ranlib \
+    > $src/libc/configure \
+    >     --prefix=/usr \
+    >     --with-headers=$sysroot/usr/include \
+    >     --build=$build \
+    >     --host=$target \
+    >     --disable-profile --without-gd --without-cvs --enable-add-ons
+    $ PATH=$tools/bin:$PATH make
+    $ PATH=$tools/bin:$PATH make install install_root=$sysroot
+
+At this point, we have a complete EGLIBC installation in '$sysroot',
+with header files, library files, and most of the C runtime startup
+files in place.
+
+
+The Third GCC
+
+Finally, we recompile GCC against this full installation, enabling
+whatever languages and libraries we would like to use:
+
+    $ mkdir -p $obj/gcc3
+    $ cd $obj/gcc3
+    $ $src/$gccv/configure \
+    >     --target=$target \
+    >     --prefix=$tools \
+    >     --with-sysroot=$sysroot \
+    >     --enable-__cxa_atexit \
+    >     --disable-libssp --disable-libgomp --disable-libmudflap \
+    >     --enable-languages=c,c++
+    $ PATH=$tools/bin:$PATH make
+    $ PATH=$tools/bin:$PATH make install
+
+The '--enable-__cxa_atexit' option tells GCC what sort of C++
+destructor support to expect from the C library; it's required with
+EGLIBC.
+
+And since GCC's installation process isn't designed to help construct
+sysroot trees, we must manually copy certain libraries into place in
+the sysroot.
+
+    $ cp -d $tools/$target/lib/libgcc_s.so* $sysroot/lib
+    $ cp -d $tools/$target/lib/libstdc++.so* $sysroot/usr/lib
+
+
+Trying Things Out
+
+At this point, '$tools' contains a cross toolchain ready to use
+the EGLIBC installation in '$sysroot':
+
+    $ cat > hello.c <<EOF
+    > #include <stdio.h>
+    > int
+    > main (int argc, char **argv)
+    > {
+    >   puts ("Hello, world!");
+    >   return 0;
+    > }
+    > EOF
+    $ $tools/bin/$target-gcc -Wall hello.c -o hello
+    $ cat > c++-hello.cc <<EOF
+    > #include <iostream>
+    > int
+    > main (int argc, char **argv)
+    > {
+    >   std::cout << "Hello, C++ world!" << std::endl;
+    >   return 0;
+    > }
+    > EOF
+    $ $tools/bin/$target-g++ -Wall c++-hello.cc -o c++-hello
+
+
+We can use 'readelf' to verify that these are indeed executables for
+our target, using our dynamic linker:
+
+    $ $tools/bin/$target-readelf -hl hello
+    ELF Header:
+    ...
+      Type:                              EXEC (Executable file)
+      Machine:                           PowerPC
+
+    ...
+    Program Headers:
+      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
+      PHDR           0x000034 0x10000034 0x10000034 0x00100 0x00100 R E 0x4
+      INTERP         0x000134 0x10000134 0x10000134 0x0000d 0x0000d R   0x1
+          [Requesting program interpreter: /lib/ld.so.1]
+      LOAD           0x000000 0x10000000 0x10000000 0x008f0 0x008f0 R E 0x10000
+    ...
+
+Looking at the dynamic section of the installed 'libgcc_s.so', we see
+that the 'NEEDED' entry for the C library does include the '.6'
+suffix, indicating that was linked against our fully build EGLIBC, and
+not our dummy 'libc.so':
+
+    $ $tools/bin/$target-readelf -d $sysroot/lib/libgcc_s.so.1
+    Dynamic section at offset 0x1083c contains 24 entries:
+      Tag        Type                         Name/Value
+     0x00000001 (NEEDED)                     Shared library: [libc.so.6]
+     0x00000001 (NEEDED)                     Shared library: [ld.so.1]
+     0x0000000e (SONAME)                     Library soname: [libgcc_s.so.1]
+    ...
+
+
+And on the target machine, we can run our programs:
+
+    $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \
+    > ./hello
+    Hello, world!
+    $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \
+    > ./c++-hello
+    Hello, C++ world!
Index: libc/include/netdb.h
===================================================================
--- libc/include/netdb.h	(.../fsf/trunk)	(revision 8411)
+++ libc/include/netdb.h	(.../trunk)	(revision 8411)
@@ -243,6 +243,10 @@
 		       (const char *name, int af, struct hostent *host,	      \
 			char *buffer, size_t buflen, int *errnop,	      \
 			int *h_errnop);					      \
+extern enum nss_status _nss_ ## service ## _gethostbyname3_r		      \
+		       (const char *name, int af, struct hostent *result,     \
+			char *buffer, size_t buflen, int *errnop,	      \
+			int *h_errnop, int32_t *ttlp, char **canonp);         \
 extern enum nss_status _nss_ ## service ## _gethostbyname_r		      \
 		       (const char *name, struct hostent *host, char *buffer, \
 			size_t buflen, int *errnop, int *h_errnop);	      \
Index: libc/include/features.h
===================================================================
--- libc/include/features.h	(.../fsf/trunk)	(revision 8411)
+++ libc/include/features.h	(.../trunk)	(revision 8411)
@@ -309,9 +309,8 @@
 # define __USE_FORTIFY_LEVEL 0
 #endif
 
-/* We do support the IEC 559 math functionality, real and complex.  */
-#define __STDC_IEC_559__		1
-#define __STDC_IEC_559_COMPLEX__	1
+/* Define __STDC_IEC_559__ and other similar macros.  */
+#include <bits/predefs.h>
 
 /* wchar_t uses ISO 10646-1 (2nd ed., published 2000-09-15) / Unicode 3.1.  */
 #define __STDC_ISO_10646__		200009L
@@ -363,7 +362,15 @@
 # define __USE_EXTERN_INLINES	1
 #endif
 
+/* There are some functions that must be declared 'extern inline' even with
+   -Os when building LIBC, or they'll end up undefined.  */
+#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
+    && (defined _LIBC || !defined __OPTIMIZE_SIZE__) && !defined __NO_INLINE__ \
+    && defined __extern_inline
+# define __USE_EXTERN_INLINES_IN_LIBC	1
+#endif
 
+
 /* This is here only because every header file already includes this one.
    Get the definitions of all the appropriate `__stub_FUNCTION' symbols.
    <gnu/stubs.h> contains `#define __stub_FUNCTION' when FUNCTION is a stub
Index: libc/include/stubs-bootstrap.h
===================================================================
--- libc/include/stubs-bootstrap.h	(.../fsf/trunk)	(revision 0)
+++ libc/include/stubs-bootstrap.h	(.../trunk)	(revision 8411)
@@ -0,0 +1,12 @@
+/* Placeholder stubs.h file for bootstrapping.
+
+   When bootstrapping a GCC/EGLIBC pair, GCC requires that the EGLIBC
+   headers be installed, but we can't fully build EGLIBC without that
+   GCC.  So we run the command:
+
+      make install-headers install-bootstrap-headers=yes
+
+   to install the headers GCC needs, but avoid building certain
+   difficult headers.  The <gnu/stubs.h> header depends, via the
+   EGLIBC subdir 'stubs' make targets, on every .o file in EGLIBC, but
+   an empty stubs.h like this will do fine for GCC.  */
Index: libc/rt/Makefile
===================================================================
--- libc/rt/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/rt/Makefile	(.../trunk)	(revision 8411)
@@ -80,7 +80,7 @@
 $(tests:%=$(objpfx)%-bp): $(objpfx)librt_b.a $(bounded-thread-library)
 endif
 
-tst-mqueue7-ARGS = -- $(built-program-cmd)
+tst-mqueue7-ARGS = -- $(local-built-program-cmd)
 
 ifeq (yes,$(build-static-nss))
 otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \
Index: libc/config.make.in
===================================================================
--- libc/config.make.in	(.../fsf/trunk)	(revision 8411)
+++ libc/config.make.in	(.../trunk)	(revision 8411)
@@ -104,6 +104,7 @@
 CFLAGS = @CFLAGS@
 ASFLAGS-config = @ASFLAGS_config@
 AR = @AR@
+NM = @NM@
 RANLIB = @RANLIB@
 MAKEINFO = @MAKEINFO@
 AS = $(CC) -c
@@ -131,4 +132,8 @@
 # Additional libraries.
 LIBGD = @LIBGD@
 
+# Package versions and bug reporting configuration.
+PKGVERSION = @PKGVERSION@
+REPORT_BUGS_TO = @REPORT_BUGS_TO@
+
 # More variables may be inserted below by configure.
Index: libc/configure.in
===================================================================
--- libc/configure.in	(.../fsf/trunk)	(revision 8411)
+++ libc/configure.in	(.../trunk)	(revision 8411)
@@ -263,6 +263,11 @@
 	      [])
 AC_SUBST(all_warnings)
 
+ACX_PKGVERSION([EGLIBC])
+ACX_BUGURL([http://www.eglibc.org/issues/])
+AC_DEFINE_UNQUOTED([PKGVERSION], ["$PKGVERSION"], [Additional package description])
+AC_DEFINE_UNQUOTED([REPORT_BUGS_TO], ["$REPORT_BUGS_TO"], [Bug reporting address])
+
 AC_ARG_ENABLE([multi-arch],
 	      AC_HELP_STRING([--enable-multi-arch],
 			     [enable single DSO with optimizations for multiple architectures]),
@@ -894,13 +899,15 @@
 LIBC_PROG_BINUTILS
 AC_SUBST(MIG)dnl Needed by sysdeps/mach/configure.in
 
-# Accept binutils 2.13 or newer.
+# Accept binutils 2.17 or newer.
 AC_CHECK_PROG_VER(AS, $AS, --version,
 		  [GNU assembler.* \([0-9]*\.[0-9.]*\)],
-		  [2.1[3-9]*], AS=: critic_missing="$critic_missing as")
+		  [2.1[7-9]* | 2.[2-9][0-9]* | [3-9].*],
+                  AS=: critic_missing="$critic_missing as")
 AC_CHECK_PROG_VER(LD, $LD, --version,
 		  [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)],
-		  [2.1[3-9]*], LD=: critic_missing="$critic_missing ld")
+		  [2.1[7-9]* | 2.[2-9][0-9]* | [3-9].*],
+                  LD=: critic_missing="$critic_missing ld")
 
 # We need the physical current working directory.  We cannot use the
 # "pwd -P" shell builtin since that's not portable.  Instead we try to
@@ -914,8 +921,9 @@
 
 # These programs are version sensitive.
 AC_CHECK_TOOL_PREFIX
+# We require GCC 4.1 or later.
 AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
-  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
+  [version [egcygnustpi-]*\([0-9.]*\)], [4.[1-9]* | [5-9].*],
   critic_missing="$critic_missing gcc")
 AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
@@ -1656,20 +1664,11 @@
   rm -f conftest*])
   AC_SUBST(libc_cv_z_execstack)
 
-  AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl
-  cat > conftest.c <<EOF
-int foo;
-main () { return 0;}
-EOF
-  if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -pie -fpie
-			      -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD])
-  then
-    libc_cv_fpie=yes
-  else
-    libc_cv_fpie=no
-  fi
-  rm -f conftest*])
-
+  dnl A build-and-link test for this fails during a bootstrap build,
+  dnl since we haven't yet built startup files needed for the link.
+  dnl However, we require versions of GCC and binutils that are new
+  dnl enough that -fpie should always work.
+  libc_cv_fpie=yes
   AC_SUBST(libc_cv_fpie)
 
   AC_CACHE_CHECK(for --hash-style option,
Index: libc/localedata/tst-rpmatch.sh
===================================================================
--- libc/localedata/tst-rpmatch.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/localedata/tst-rpmatch.sh	(.../trunk)	(revision 8411)
@@ -25,9 +25,12 @@
 rc=0
 while IFS=\& read locale string result dummy; do
     if [ "$locale" != "#" ]; then
+        # If tst_rpmatch includes a cross-testing wrapper based on a
+        # program like ssh, it may steal input from the while loop, so
+        # redirect its stdin from /dev/null.
 	LOCPATH=${common_objpfx}localedata \
 	GCONV_PATH=${common_objpfx}/iconvdata \
-	${tst_rpmatch} $locale $string $result \
+	${tst_rpmatch} $locale $string $result < /dev/null \
 	|| { echo "$locale $string $result  FAILED"; exit 1; }
     fi
 done <<EOF
Index: libc/localedata/Makefile
===================================================================
--- libc/localedata/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/localedata/Makefile	(.../trunk)	(revision 8411)
@@ -22,15 +22,26 @@
 
 all: # Make this the default target; it will be defined in Rules.
 
+include ../option-groups.mak
+
 # List with all available character set descriptions.
-charmaps := $(filter-out $(addprefix charmaps/, CVS RCS SCCS %~), \
-				     $(wildcard charmaps/[A-I]*) \
-				     $(wildcard charmaps/[J-Z]*))
+all-charmaps := $(filter-out $(addprefix charmaps/, CVS RCS SCCS %~), \
+					 $(wildcard charmaps/[A-I]*) \
+					 $(wildcard charmaps/[J-Z]*))
 
 # List with all available character set descriptions.
-locales := $(filter-out $(addprefix locales/, CVS RCS SCCS %~), \
-				    $(wildcard locales/*))
+all-locales := $(filter-out $(addprefix locales/, CVS RCS SCCS %~), \
+			    $(wildcard locales/*))
 
+# If the EGLIBC_LOCALES option group is not enabled, trim the
+# list of charmap and locale source files.
+ifeq ($(OPTION_EGLIBC_LOCALES),y)
+charmaps := $(all-charmaps)
+locales  := $(all-locales)
+else
+charmaps := 
+locales  := locales/POSIX
+endif
 
 subdir-dirs = tests-mbwc
 vpath %.c tests-mbwc
@@ -61,7 +72,7 @@
 		  $(addprefix tstfmon_,$(fmon-tests))			\
 
 distribute := CHECKSUMS README SUPPORTED ChangeLog			\
-	      $(charmaps) $(locales)					\
+	      $(all-charmaps) $(all-locales)				\
 	      tst-rpmatch.sh tst-locale.sh tst-fmon.sh sort-test.sh	\
 	      tst-fmon.data $(test-input-data) $(ld-test-srcs)		\
 	      th_TH.in cs_CZ.in tst-mbswcs.sh tst-trans.sh tst-ctype.sh \
@@ -76,7 +87,7 @@
 # Get $(inst_i18ndir) defined.
 include ../Makeconfig
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl            \
 		     tst_iswctype tst_iswdigit tst_iswgraph            \
 		     tst_iswlower tst_iswprint tst_iswpunct            \
@@ -92,15 +103,19 @@
 		     tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans      \
 		     tst_wctype tst_wcwidth
 
-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
+# Since these tests build their own locale files, they're not
+# dependent on the OPTION_EGLIBC_LOCALES option group.  But they do
+# need the locale functions to be present.
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+     += $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
 	tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
 	tst-strfmon1 tst-sscanf tst-strptime
-ifeq (yes,$(build-shared))
+ifeq (yesy,$(build-shared)$(OPTION_EGLIBC_LOCALE_CODE))
 ifneq (no,$(PERL))
 tests: $(objpfx)mtrace-tst-leaks
 endif
 endif
-endif
+# eglibc: endif
 
 # Files to install.
 install-others := $(addprefix $(inst_i18ndir)/, \
@@ -128,10 +143,10 @@
 CFLAGS-tst-trans.c = -Wno-format
 
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 # We have to generate locales
 LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 \
-	   en_US.ISO-8859-1 ja_JP.EUC-JP da_DK.ISO-8859-1 \
+	   en_US.ISO-8859-1 en_US.UTF-8 ja_JP.EUC-JP da_DK.ISO-8859-1 \
 	   hr_HR.ISO-8859-2 sv_SE.ISO-8859-1 ja_JP.SJIS fr_FR.ISO-8859-1 \
 	   vi_VN.TCVN5712-1 nb_NO.ISO-8859-1 nn_NO.ISO-8859-1 \
 	   tr_TR.UTF-8 cs_CZ.UTF-8 zh_TW.EUC-TW fa_IR.UTF-8 fr_FR.UTF-8 \
@@ -148,15 +163,24 @@
 $(addprefix $(objpfx),$(CTYPE_FILES)): %: \
   gen-locale.sh $(common-objpfx)locale/localedef Makefile \
   $(addprefix charmaps/,$(CHARMAPS)) $(addprefix locales/,$(LOCALE_SRCS))
-	@$(SHELL) -e gen-locale.sh $(common-objpfx) '$(built-program-cmd)' $@
+	@$(SHELL) -e gen-locale.sh $(common-objpfx)	\
+		 '$(if $(cross-localedef), 		\
+		       $(cross-localedef),		\
+		       $(built-program-cmd))'		\
+		 $@
 
 $(addsuffix .out,$(addprefix $(objpfx),$(tests))): %: \
   $(addprefix $(objpfx),$(CTYPE_FILES))
 
+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
 tests: $(objpfx)sort-test.out $(objpfx)tst-fmon.out $(objpfx)tst-locale.out \
        $(objpfx)tst-rpmatch.out $(objpfx)tst-trans.out \
-       $(objpfx)tst-mbswcs.out $(objpfx)tst-ctype.out $(objpfx)tst-wctype.out \
+       $(objpfx)tst-mbswcs.out $(objpfx)tst-ctype.out \
        $(objpfx)tst-langinfo.out $(objpfx)tst-numeric.out
+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
+tests: $(objpfx)tst-wctype.out
+endif
+endif
 
 $(objpfx)sort-test.out: sort-test.sh $(objpfx)collate-test $(objpfx)xfrm-test \
 		       $(test-input-data) $(addprefix $(objpfx),$(CTYPE_FILES))
@@ -201,10 +225,15 @@
 	$(SHELL) -e $< $(common-objpfx) '$(built-program-cmd)'
 $(objpfx)tst-digits.out: $(objpfx)tst-locale.out
 $(objpfx)tst-mbswcs6.out: $(addprefix $(objpfx),$(CTYPE_FILES))
-endif
+# eglibc: endif
 
 include SUPPORTED
 
+# Only install locale data if OPTION_EGLIBC_LOCALES is selected.
+ifneq ($(OPTION_EGLIBC_LOCALES),y)
+SUPPORTED-LOCALES :=
+endif
+
 INSTALL-SUPPORTED-LOCALES=$(addprefix install-, $(SUPPORTED-LOCALES))
 
 # Sometimes the whole collection of locale files should be installed.
Index: libc/localedata/tst-fmon.sh
===================================================================
--- libc/localedata/tst-fmon.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/localedata/tst-fmon.sh	(.../trunk)	(revision 8411)
@@ -32,10 +32,13 @@
 for cns in `cd ./tst-fmon-locales && ls tstfmon_*`; do
     cn=tst-fmon-locales/$cns
     fn=charmaps/ISO-8859-1
+    # If run_program_prefix includes a cross-testing wrapper based on a
+    # program like ssh, it may steal input from the while loop, so
+    # redirect its stdin from /dev/null.
     I18NPATH=. GCONV_PATH=${common_objpfx}iconvdata \
     LOCPATH=${common_objpfx}localedata LC_ALL=C LANGUAGE=C \
     ${run_program_prefix} ${common_objpfx}locale/localedef \
-    --quiet -i $cn -f $fn ${common_objpfx}localedata/$cns
+    --quiet -i $cn -f $fn ${common_objpfx}localedata/$cns < /dev/null
 done
 
 # Run the tests.
@@ -45,10 +48,13 @@
     case "$locale" in '#'*) continue ;; esac
     if [ -n "$format" ]; then
 	expect=`echo "$expect" | sed 's/^\"\(.*\)\"$/\1/'`
+        # If run_program_prefix includes a cross-testing wrapper based on a
+        # program like ssh, it may steal input from the while loop, so
+        # redirect its stdin from /dev/null.
 	LOCPATH=${common_objpfx}localedata \
 	GCONV_PATH=${common_objpfx}/iconvdata \
 	${run_program_prefix} ${common_objpfx}localedata/tst-fmon \
-	"$locale" "$format" "$value" "$expect" ||
+	"$locale" "$format" "$value" "$expect" < /dev/null ||
 	errcode=$?
     fi
 done < $datafile
Index: libc/localedata/tst-numeric.sh
===================================================================
--- libc/localedata/tst-numeric.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/localedata/tst-numeric.sh	(.../trunk)	(revision 8411)
@@ -30,10 +30,13 @@
 while IFS="	" read locale format value expect; do
     case "$locale" in '#'*) continue ;; esac
     if [ -n "$format" ]; then
+        # If run_program_prefix includes a cross-testing wrapper based
+        # on a program like ssh, it may steal input from the while
+        # loop, so redirect its stdin from /dev/null.
 	if LOCPATH=${common_objpfx}localedata \
 	    GCONV_PATH=${common_objpfx}/iconvdata \
 	    ${run_program_prefix} ${common_objpfx}localedata/tst-numeric \
-	    "$locale" "$format" "$value" "$expect"
+	    "$locale" "$format" "$value" "$expect" < /dev/null
 	then
 	    echo "Locale: \"${locale}\" Format: \"${format}\"" \
 		 "Value: \"${value}\" Expect: \"${expect}\"  passed"
Index: libc/localedata/tst-wctype.sh
===================================================================
--- libc/localedata/tst-wctype.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/localedata/tst-wctype.sh	(.../trunk)	(revision 8411)
@@ -20,12 +20,11 @@
 # 02111-1307 USA.
 
 common_objpfx=$1
-run_program_prefix=$2
+tst_wctype=$2
 
 # Run the test program.
 LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}iconvdata \
-LC_ALL=ja_JP.EUC-JP ${run_program_prefix} \
-  ${common_objpfx}localedata/tst-wctype < tst-wctype.input \
+LC_ALL=ja_JP.EUC-JP ${tst_wctype} < tst-wctype.input \
     > ${common_objpfx}localedata/tst-wctype.out
 
 exit $?
Index: libc/sysdeps/powerpc/fpu/fpu_control.h
===================================================================
--- libc/sysdeps/powerpc/fpu/fpu_control.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/powerpc/fpu/fpu_control.h	(.../trunk)	(revision 8411)
@@ -1,5 +1,5 @@
 /* FPU control word definitions.  PowerPC version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 2004, 2006 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,12 +20,63 @@
 #ifndef _FPU_CONTROL_H
 #define _FPU_CONTROL_H
 
+#ifdef _SOFT_FLOAT
+
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT  0x00000000 /* Default value.  */
+typedef unsigned int fpu_control_t;
+#define _FPU_GETCW(cw) 0
+#define _FPU_SETCW(cw) do { } while (0)
+extern fpu_control_t __fpu_control;
+
+#elif defined __NO_FPRS__ /* E500 */
+
 /* rounding control */
 #define _FPU_RC_NEAREST 0x00   /* RECOMMENDED */
 #define _FPU_RC_DOWN    0x03
 #define _FPU_RC_UP      0x02
 #define _FPU_RC_ZERO    0x01
 
+/* masking of interrupts */
+#define _FPU_MASK_ZM  0x10 /* zero divide */
+#define _FPU_MASK_OM  0x40 /* overflow */
+#define _FPU_MASK_UM  0x80 /* underflow */
+#define _FPU_MASK_XM  0x40 /* inexact */
+#define _FPU_MASK_IM  0x20 /* invalid operation */
+
+#define _FPU_RESERVED 0xff3fff7f /* These bits are reserved are not changed. */
+
+/* The fdlibm code requires no interrupts for exceptions.  */
+#define _FPU_DEFAULT  0x00000000 /* Default value.  */
+
+/* IEEE:  same as above, but (some) exceptions;
+   we leave the 'inexact' exception off.
+ */
+#define _FPU_IEEE     0x000003c0
+
+/* Type of the control word.  */
+typedef unsigned int fpu_control_t;
+
+/* Macros for accessing the hardware control word.  */
+#define _FPU_GETCW(__cw) ({ \
+  unsigned int env; \
+  asm volatile ("mfspefscr %0" : "=r" (env)); \
+  (__cw) = env; })
+#define _FPU_SETCW(__cw) ({ \
+  unsigned int env = __cw; \
+  asm volatile ("mtspefscr %0" : : "r" (env)); })
+
+/* Default control word set at startup.  */
+extern fpu_control_t __fpu_control;
+
+#else /* PowerPC 6xx floating-point.  */
+
+/* rounding control */
+#define _FPU_RC_NEAREST 0x00   /* RECOMMENDED */
+#define _FPU_RC_DOWN    0x03
+#define _FPU_RC_UP      0x02
+#define _FPU_RC_ZERO    0x01
+
 #define _FPU_MASK_NI  0x04 /* non-ieee mode */
 
 /* masking of interrupts */
@@ -66,4 +117,6 @@
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;
 
+#endif
+
 #endif /* _FPU_CONTROL_H */
Index: libc/sysdeps/powerpc/fpu/bits/fenvinline.h
===================================================================
--- libc/sysdeps/powerpc/fpu/bits/fenvinline.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/powerpc/fpu/bits/fenvinline.h	(.../trunk)	(revision 8411)
@@ -18,7 +18,8 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES
+#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ \
+  && !defined __NO_MATH_INLINES
 
 /* Inline definition for fegetround.  */
 # define fegetround() \
@@ -58,4 +59,4 @@
       : 0)								      \
    : (feclearexcept) (__excepts))
 
-#endif /* __GNUC__ && !_SOFT_FLOAT */
+#endif /* __GNUC__ && !__NO_FPRS__ */
Index: libc/sysdeps/powerpc/fpu/bits/mathinline.h
===================================================================
--- libc/sysdeps/powerpc/fpu/bits/mathinline.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/powerpc/fpu/bits/mathinline.h	(.../trunk)	(revision 8411)
@@ -28,7 +28,7 @@
 # define __MATH_INLINE __extern_inline
 #endif  /* __cplusplus */
 
-#if defined __GNUC__ && !defined _SOFT_FLOAT
+#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__
 
 #ifdef __USE_ISOC99
 # if !__GNUC_PREREQ (2,97)
@@ -129,4 +129,4 @@
 
 #endif /* __USE_ISOC99 */
 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
-#endif /* __GNUC__ && !_SOFT_FLOAT */
+#endif /* __GNUC__ && !__NO_FPRS__ */
Index: libc/sysdeps/powerpc/bits/fenv.h
===================================================================
--- libc/sysdeps/powerpc/bits/fenv.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/powerpc/bits/fenv.h	(.../trunk)	(revision 8411)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2004, 2006,2008 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,8 +20,68 @@
 # error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
 #endif
 
+#if defined __NO_FPRS__ && !defined _SOFT_FLOAT /* E500 */
 
 /* Define bits representing the exception.  We use the bit positions of
+   the appropriate bits in the SPEFSCR...  */
+enum
+  {
+    FE_INEXACT = 1 << (63 - 42),
+#define FE_INEXACT	FE_INEXACT
+    FE_INVALID = 1 << (63 - 43),
+#define FE_INVALID	FE_INVALID
+    FE_DIVBYZERO = 1 << (63 - 44),
+#define FE_DIVBYZERO	FE_DIVBYZERO
+    FE_UNDERFLOW = 1 << (63 - 45),
+#define FE_UNDERFLOW	FE_UNDERFLOW
+    FE_OVERFLOW = 1 << (63 - 46)
+#define FE_OVERFLOW	FE_OVERFLOW
+  };
+
+#define FE_ALL_EXCEPT \
+	(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
+
+/* The E500 support all of the four defined rounding modes.  We use
+   the bit pattern in the SPEFSCR as the values for the appropriate
+   macros.  */
+enum
+  {
+    FE_TONEAREST = 0,
+#define FE_TONEAREST	FE_TONEAREST
+    FE_TOWARDZERO = 1,
+#define FE_TOWARDZERO	FE_TOWARDZERO
+    FE_UPWARD = 2,
+#define FE_UPWARD	FE_UPWARD
+    FE_DOWNWARD = 3
+#define FE_DOWNWARD	FE_DOWNWARD
+  };
+
+/* Type representing exception flags.  */
+typedef unsigned int fexcept_t;
+
+typedef double fenv_t;
+
+/* If the default argument is used we use this value.  */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV	(&__fe_dfl_env)
+
+#ifdef __USE_GNU
+/* Floating-point environment where all exceptions are enabled.  Note that
+   this is not sufficient to give you SIGFPE.  */
+extern const fenv_t __fe_enabled_env;
+# define FE_ENABLED_ENV	(&__fe_enabled_env)
+
+/* Floating-point environment with all exceptions enabled.  Note that
+   just evaluating this value will set the processor into 'FPU
+   exceptions imprecise recoverable' mode, which may cause a significant
+   performance penalty (but have no other visible effect).  */
+extern const fenv_t *__fe_nomask_env (void);
+# define FE_NOMASK_ENV	(__fe_nomask_env ())
+#endif
+
+#else /* PowerPC 6xx floating-point.  */
+
+/* Define bits representing the exception.  We use the bit positions of
    the appropriate bits in the FPSCR...  */
 enum
   {
@@ -158,3 +218,5 @@
 __END_DECLS
 
 #endif
+
+#endif
Index: libc/sysdeps/powerpc/bits/mathdef.h
===================================================================
--- libc/sysdeps/powerpc/bits/mathdef.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/powerpc/bits/mathdef.h	(.../trunk)	(revision 8411)
@@ -31,32 +31,10 @@
 #if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
 # define _MATH_H_MATHDEF	1
 
-# ifdef __GNUC__
-#  if __STDC__ == 1
-
-/* In GNU or ANSI mode, gcc leaves `float' expressions as-is.  */
-typedef float float_t;		/* `float' expressions are evaluated as
-				   `float'.  */
-typedef double double_t;	/* `double' expressions are evaluated as
-				   `double'.  */
-
-#  else
-
-/* For `gcc -traditional', `float' expressions are evaluated as `double'. */
-typedef double float_t;		/* `float' expressions are evaluated as
-				   `double'.  */
-typedef double double_t;	/* `double' expressions are evaluated as
-				   `double'.  */
-
-#  endif
-# else
-
-/* Wild guess at types for float_t and double_t. */
-typedef double float_t;
+/* PowerPC has both `float' and `double' arithmetic.  */
+typedef float float_t;
 typedef double double_t;
 
-# endif
-
 /* The values returned by `ilogb' for 0 and NaN respectively.  */
 # define FP_ILOGB0	(-2147483647)
 # define FP_ILOGBNAN	(2147483647)
Index: libc/sysdeps/unix/sysv/linux/lddlibc4.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/lddlibc4.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/lddlibc4.c	(.../trunk)	(revision 8411)
@@ -60,12 +60,12 @@
     {
       printf (gettext ("Usage: lddlibc4 FILE\n\n"));
       printf (gettext ("For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO);
       return 0;
     }
   else if (strcmp (argv[1], "--version") == 0)
     {
-      printf ("lddlibc4 (GNU %s) %s\n", PACKAGE, VERSION);
+      printf ("lddlibc4 %s%s\n", PKGVERSION, VERSION);
       printf (gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/sysdeps/unix/sysv/linux/i386/sysdep.h
===================================================================
--- libc/sysdeps/unix/sysv/linux/i386/sysdep.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/i386/sysdep.h	(.../trunk)	(revision 8411)
@@ -29,6 +29,10 @@
 #include <dl-sysdep.h>
 #include <tls.h>
 
+#if defined __i686 && defined __ASSEMBLER__
+#undef __i686
+#define __i686 __i686
+#endif
 
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
Index: libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
===================================================================
--- libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S	(.../trunk)	(revision 8411)
@@ -249,6 +249,10 @@
 	lfd	fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __SETCONTEXT_EXTRA
+	__SETCONTEXT_EXTRA
+#endif
+
 	/* Restore LR and CCR, and set CTR to the NIP value */
 	lwz	r3,_UC_GREGS+(PT_LNK*4)(r31)
 	lwz	r4,_UC_GREGS+(PT_NIP*4)(r31)
Index: libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
===================================================================
--- libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S	(.../trunk)	(revision 8411)
@@ -271,6 +271,10 @@
 # endif /* __CONTEXT_ENABLE_VRS */
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __GETCONTEXT_EXTRA
+	__GETCONTEXT_EXTRA
+#endif
+
 /* Restore ucontext (parm1) from stack.  */
 	lwz	r12,_FRAME_PARM_SAVE1(r1)
 	li	r4,0
@@ -475,6 +479,10 @@
 	lfd	fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __SETCONTEXT_EXTRA
+	__SETCONTEXT_EXTRA
+#endif
+
 	/* Restore LR and CCR, and set CTR to the NIP value */
 	lwz	r3,_UC_GREGS+(PT_LNK*4)(r31)
 	lwz	r4,_UC_GREGS+(PT_NIP*4)(r31)
Index: libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
===================================================================
--- libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S	(.../trunk)	(revision 8411)
@@ -267,6 +267,11 @@
 2: /* L(no_vec): */
 # endif
 #endif
+
+#ifdef __GETCONTEXT_EXTRA
+	__GETCONTEXT_EXTRA
+#endif
+
 /* We need to set up parms and call sigprocmask which will clobber
    volatile registers. So before the call we need to retrieve the
    original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
Index: libc/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c	(.../trunk)	(revision 8411)
@@ -27,9 +27,21 @@
 /* Scan the Aux Vector for the "Data Cache Block Size" entry.  If found
    verify that the static extern __cache_line_size is defined by checking
    for not NULL.  If it is defined then assign the cache block size
-   value to __cache_line_size.  */
+   value to __cache_line_size.  This is used by memset to
+   optimize setting to zero.  We have to detect 8xx processors, which
+   have buggy dcbz implementations that cannot report page faults
+   correctly.  That requires reading SPR, which is a privileged
+   operation.  Fortunately 2.2.18 and later emulates PowerPC mfspr
+   reads from the PVR register.   */
 #define DL_PLATFORM_AUXV						      \
       case AT_DCACHEBSIZE:						      \
+	if (__LINUX_KERNEL_VERSION >= 0x020218)				      \
+	  {								      \
+	    unsigned pvr = 0;						      \
+	    asm ("mfspr %0, 287" : "=r" (pvr));				      \
+	    if ((pvr & 0xffff0000) == 0x00500000)			      \
+	      break;							      \
+	  }								      \
 	__cache_line_size = av->a_un.a_val;				      \
 	break;
 
Index: libc/sysdeps/unix/sysv/linux/powerpc/libc-start.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/powerpc/libc-start.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/powerpc/libc-start.c	(.../trunk)	(revision 8411)
@@ -80,11 +80,24 @@
       rtld_fini = NULL;
     }
 
-  /* Initialize the __cache_line_size variable from the aux vector.  */
+  /* Initialize the __cache_line_size variable from the aux vector.
+     This is used by memset to optimize setting to zero.  We have to
+     detect 8xx processors, which have buggy dcbz implementations that
+     cannot report page faults correctly.  That requires reading SPR,
+     which is a privileged operation.  Fortunately 2.2.18 and later
+     emulates PowerPC mfspr reads from the PVR register.  */
   for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
     switch (av->a_type)
       {
       case AT_DCACHEBSIZE:
+	if (__LINUX_KERNEL_VERSION >= 0x020218)
+	  {
+	    unsigned pvr = 0;
+	    
+	    asm ("mfspr %0, 287" : "=r" (pvr) :);
+	    if ((pvr & 0xffff0000) == 0x00500000)
+	      break;
+	  }
 	__cache_line_size = av->a_un.a_val;
 	break;
       }
Index: libc/sysdeps/unix/sysv/linux/getcwd.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/getcwd.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/getcwd.c	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/param.h>
 
 #include <sysdep.h>
 #include <sys/syscall.h>
Index: libc/sysdeps/unix/sysv/linux/Makefile
===================================================================
--- libc/sysdeps/unix/sysv/linux/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/Makefile	(.../trunk)	(revision 8411)
@@ -16,6 +16,7 @@
 		   setfsuid setfsgid makedev epoll_pwait signalfd \
 		   eventfd eventfd_read eventfd_write
 
+
 CFLAGS-gethostid.c = -fexceptions
 
 sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
@@ -28,7 +29,7 @@
 		  bits/a.out.h sys/inotify.h sys/signalfd.h sys/eventfd.h \
 		  sys/timerfd.h
 
-install-others += $(inst_includedir)/bits/syscall.h
+install-headers-nosubdir: $(inst_includedir)/bits/syscall.h
 
 tests += tst-clone
 
Index: libc/sysdeps/unix/sysv/linux/libc_fatal.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/libc_fatal.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/libc_fatal.c	(.../trunk)	(revision 8411)
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <sys/syslog.h>
 #include <execinfo.h>
+#include <gnu/option-groups.h>
 
 /* Abort with an error message.  */
 #include <not-cancel.h>
@@ -143,6 +144,7 @@
 
   if (do_abort)
     {
+#if __OPTION_EGLIBC_BACKTRACE
       if (do_abort > 1 && written)
 	{
 	  void *addrs[64];
@@ -165,6 +167,7 @@
 	      close_not_cancel_no_status (fd2);
 	    }
 	}
+#endif /* __OPTION_EGLIBC_BACKTRACE */
 
       /* Terminate the process.  */
       abort ();
Index: libc/sysdeps/unix/sysv/linux/gethostid.c
===================================================================
--- libc/sysdeps/unix/sysv/linux/gethostid.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/unix/sysv/linux/gethostid.c	(.../trunk)	(revision 8411)
@@ -23,6 +23,7 @@
 #include <unistd.h>
 #include <netdb.h>
 #include <not-cancel.h>
+#include <gnu/option-groups.h>
 
 #define HOSTIDFILE "/etc/hostid"
 
@@ -91,6 +92,7 @@
 	return id;
     }
 
+#if __OPTION_EGLIBC_INET
   /* Getting from the file was not successful.  An intelligent guess for
      a unique number of a host is its IP address.  Return this.  */
   if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0')
@@ -117,5 +119,9 @@
   /* For the return value to be not exactly the IP address we do some
      bit fiddling.  */
   return (int32_t) (in.s_addr << 16 | in.s_addr >> 16);
+#else
+  /* Return an arbitrary value.  */
+  return 0;
+#endif
 }
 #endif
Index: libc/sysdeps/gnu/Makefile
===================================================================
--- libc/sysdeps/gnu/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/gnu/Makefile	(.../trunk)	(revision 8411)
@@ -62,7 +62,8 @@
 endif
 
 ifeq ($(subdir),login)
-sysdep_routines += setutxent getutxent endutxent getutxid getutxline \
+sysdep_routines-$(OPTION_EGLIBC_UTMPX) \
+		+= setutxent getutxent endutxent getutxid getutxline \
                    pututxline utmpxname updwtmpx getutmpx getutmp
 
 sysdep_headers += utmpx.h bits/utmpx.h
Index: libc/sysdeps/ieee754/ldbl-opt/Makefile
===================================================================
--- libc/sysdeps/ieee754/ldbl-opt/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/ieee754/ldbl-opt/Makefile	(.../trunk)	(revision 8411)
@@ -11,19 +11,18 @@
 routines += math_ldbl_opt nldbl-compat
 
 extra-libs += libnldbl
-libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \
+libnldbl-calls = asprintf dprintf fprintf fscanf iovfscanf \
 		 obstack_printf obstack_vprintf printf scanf snprintf \
-		 sprintf sscanf swprintf swscanf vasprintf vdprintf vfprintf \
-		 vfscanf vfwprintf vfwscanf vprintf vscanf vsnprintf \
-		 vsprintf vsscanf vswprintf vswscanf vwprintf vwscanf \
-		 wprintf wscanf printf_fp printf_size \
-		 fprintf_chk fwprintf_chk printf_chk snprintf_chk sprintf_chk \
-		 swprintf_chk vfprintf_chk vfwprintf_chk vprintf_chk \
-		 vsnprintf_chk vsprintf_chk vswprintf_chk vwprintf_chk \
-		 wprintf_chk asprintf_chk vasprintf_chk dprintf_chk \
+		 sprintf sscanf vasprintf vdprintf vfprintf \
+		 vfscanf vprintf vscanf vsnprintf \
+		 vsprintf vsscanf \
+		 printf_fp printf_size \
+		 fprintf_chk printf_chk snprintf_chk sprintf_chk \
+		 vfprintf_chk vprintf_chk \
+		 vsnprintf_chk vsprintf_chk \
+		 asprintf_chk vasprintf_chk dprintf_chk \
 		 vdprintf_chk obstack_printf_chk obstack_vprintf_chk \
 		 syslog syslog_chk vsyslog vsyslog_chk \
-		 strfmon strfmon_l \
 		 strtold strtold_l strtoldint wcstold wcstold_l wcstoldint \
 		 qecvt qfcvt qgcvt qecvt_r qfcvt_r \
 		 isinf isnan finite signbit scalb log2 lgamma_r ceil \
@@ -38,9 +37,15 @@
 		 casinh cexp clog cproj csin csinh csqrt ctan ctanh cpow \
 		 cabs carg cimag creal clog10 \
 		 isoc99_scanf isoc99_fscanf isoc99_sscanf \
-		 isoc99_vscanf isoc99_vfscanf isoc99_vsscanf \
+		 isoc99_vscanf isoc99_vfscanf isoc99_vsscanf
+libnldbl-calls-$(OPTION_EGLIBC_LOCALE_CODE) += strfmon strfmon_l
+libnldbl-calls-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += fwprintf fwscanf \
+		 swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf \
+		 vwprintf vwscanf wprintf wscanf fwprintf_chk swprintf_chk \
+		 vfwprintf_chk vswprintf_chk vwprintf_chk wprintf_chk \
 		 isoc99_wscanf isoc99_fwscanf isoc99_swscanf \
 		 isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf
+libnldbl-calls += $(libnldbl-calls-y)
 libnldbl-routines = $(libnldbl-calls:%=nldbl-%)
 libnldbl-inhibit-o = $(object-suffixes)
 libnldbl-static-only-routines = $(libnldbl-routines)
Index: libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
===================================================================
--- libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.c	(.../trunk)	(revision 8411)
@@ -34,20 +34,14 @@
 libc_hidden_proto (__nldbl_vsscanf)
 libc_hidden_proto (__nldbl_vsprintf)
 libc_hidden_proto (__nldbl_vfscanf)
-libc_hidden_proto (__nldbl_vfwscanf)
 libc_hidden_proto (__nldbl_vdprintf)
-libc_hidden_proto (__nldbl_vswscanf)
-libc_hidden_proto (__nldbl_vfwprintf)
-libc_hidden_proto (__nldbl_vswprintf)
 libc_hidden_proto (__nldbl_vsnprintf)
 libc_hidden_proto (__nldbl_vasprintf)
 libc_hidden_proto (__nldbl_obstack_vprintf)
-libc_hidden_proto (__nldbl___vfwprintf_chk)
 libc_hidden_proto (__nldbl___vsnprintf_chk)
 libc_hidden_proto (__nldbl___vfprintf_chk)
 libc_hidden_proto (__nldbl___vsyslog_chk)
 libc_hidden_proto (__nldbl___vsprintf_chk)
-libc_hidden_proto (__nldbl___vswprintf_chk)
 libc_hidden_proto (__nldbl___vasprintf_chk)
 libc_hidden_proto (__nldbl___vdprintf_chk)
 libc_hidden_proto (__nldbl___obstack_vprintf_chk)
@@ -55,8 +49,17 @@
 libc_hidden_proto (__nldbl___vstrfmon_l)
 libc_hidden_proto (__nldbl___isoc99_vsscanf)
 libc_hidden_proto (__nldbl___isoc99_vfscanf)
+
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+libc_hidden_proto (__nldbl_vfwscanf)
+libc_hidden_proto (__nldbl_vswscanf)
+libc_hidden_proto (__nldbl_vfwprintf)
+libc_hidden_proto (__nldbl_vswprintf)
+libc_hidden_proto (__nldbl___vfwprintf_chk)
+libc_hidden_proto (__nldbl___vswprintf_chk)
 libc_hidden_proto (__nldbl___isoc99_vswscanf)
 libc_hidden_proto (__nldbl___isoc99_vfwscanf)
+#endif
 
 static void
 __nldbl_cleanup (void *arg)
@@ -118,6 +121,7 @@
 }
 weak_alias (__nldbl_fprintf, __nldbl__IO_fprintf)
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section weak_function
 __nldbl_fwprintf (FILE *stream, const wchar_t *fmt, ...)
@@ -131,6 +135,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -227,6 +232,7 @@
   return done;
 }
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl_swprintf (wchar_t *s, size_t n, const wchar_t *fmt, ...)
@@ -240,6 +246,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section weak_function
@@ -265,6 +272,7 @@
 }
 libc_hidden_def (__nldbl_vdprintf)
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section weak_function
 __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap)
@@ -276,6 +284,7 @@
   return res;
 }
 libc_hidden_def (__nldbl_vfwprintf)
+#endif
 
 int
 attribute_compat_text_section
@@ -298,6 +307,7 @@
 libc_hidden_def (__nldbl_vsnprintf)
 weak_alias (__nldbl_vsnprintf, __nldbl___vsnprintf)
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section weak_function
 __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt,
@@ -331,6 +341,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -420,6 +431,7 @@
   return done;
 }
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap)
@@ -492,6 +504,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -507,6 +520,7 @@
   return done;
 }
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl___fwprintf_chk (FILE *stream, int flag, const wchar_t *fmt, ...)
@@ -520,6 +534,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -564,6 +579,7 @@
   return done;
 }
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl___swprintf_chk (wchar_t *s, size_t n, int flag, size_t slen,
@@ -578,6 +594,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -591,6 +608,7 @@
 }
 libc_hidden_def (__nldbl___vfprintf_chk)
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl___vfwprintf_chk (FILE *s, int flag, const wchar_t *fmt, va_list ap)
@@ -602,6 +620,7 @@
   return res;
 }
 libc_hidden_def (__nldbl___vfwprintf_chk)
+#endif
 
 int
 attribute_compat_text_section
@@ -636,6 +655,7 @@
 }
 libc_hidden_def (__nldbl___vsprintf_chk)
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl___vswprintf_chk (wchar_t *string, size_t maxlen, int flag, size_t slen,
@@ -669,6 +689,7 @@
 
   return done;
 }
+#endif
 
 int
 attribute_compat_text_section
@@ -776,6 +797,7 @@
   return ___printf_fp (fp, &info_no_ldbl, args);
 }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 ssize_t
 attribute_compat_text_section
 __nldbl_strfmon (char *s, size_t maxsize, const char *format, ...)
@@ -830,6 +852,7 @@
   return res;
 }
 libc_hidden_def (__nldbl___vstrfmon_l)
+#endif
 
 void
 attribute_compat_text_section
@@ -942,6 +965,7 @@
   return done;
 }
 
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 int
 attribute_compat_text_section
 __nldbl___isoc99_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap)
@@ -1015,6 +1039,7 @@
 
   return done;
 }
+#endif
 
 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0)
 compat_symbol (libc, __nldbl__IO_printf, _IO_printf, GLIBC_2_0);
@@ -1058,6 +1083,7 @@
 compat_symbol (libc, __nldbl___strfmon_l, __strfmon_l, GLIBC_2_1);
 #endif
 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_2)
+# ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 compat_symbol (libc, __nldbl_swprintf, swprintf, GLIBC_2_2);
 compat_symbol (libc, __nldbl_vwprintf, vwprintf, GLIBC_2_2);
 compat_symbol (libc, __nldbl_wprintf, wprintf, GLIBC_2_2);
@@ -1070,6 +1096,7 @@
 compat_symbol (libc, __nldbl_vswscanf, vswscanf, GLIBC_2_2);
 compat_symbol (libc, __nldbl_vwscanf, vwscanf, GLIBC_2_2);
 compat_symbol (libc, __nldbl_wscanf, wscanf, GLIBC_2_2);
+# endif
 #endif
 #if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3)
 compat_symbol (libc, __nldbl_strfmon_l, strfmon_l, GLIBC_2_3);
Index: libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
===================================================================
--- libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/ieee754/ldbl-opt/nldbl-compat.h	(.../trunk)	(revision 8411)
@@ -38,19 +38,15 @@
 
 NLDBL_DECL (_IO_vfscanf);
 NLDBL_DECL (vfscanf);
-NLDBL_DECL (vfwscanf);
 NLDBL_DECL (obstack_vprintf);
 NLDBL_DECL (vasprintf);
 NLDBL_DECL (dprintf);
 NLDBL_DECL (vdprintf);
 NLDBL_DECL (fprintf);
 NLDBL_DECL (vfprintf);
-NLDBL_DECL (vfwprintf);
 NLDBL_DECL (vsnprintf);
 NLDBL_DECL (vsprintf);
 NLDBL_DECL (vsscanf);
-NLDBL_DECL (vswprintf);
-NLDBL_DECL (vswscanf);
 NLDBL_DECL (__asprintf);
 NLDBL_DECL (asprintf);
 NLDBL_DECL (__printf_fp);
@@ -67,12 +63,18 @@
 NLDBL_DECL (__isoc99_vscanf);
 NLDBL_DECL (__isoc99_vfscanf);
 NLDBL_DECL (__isoc99_vsscanf);
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+NLDBL_DECL (vfwscanf);
+NLDBL_DECL (vfwprintf);
+NLDBL_DECL (vswprintf);
+NLDBL_DECL (vswscanf);
 NLDBL_DECL (__isoc99_wscanf);
 NLDBL_DECL (__isoc99_fwscanf);
 NLDBL_DECL (__isoc99_swscanf);
 NLDBL_DECL (__isoc99_vwscanf);
 NLDBL_DECL (__isoc99_vfwscanf);
 NLDBL_DECL (__isoc99_vswscanf);
+#endif
 
 /* This one does not exist in the normal interface, only
    __nldbl___vstrfmon really exists.  */
@@ -83,22 +85,23 @@
    since we don't compile with _FORTIFY_SOURCE.  */
 extern int __nldbl___vfprintf_chk (FILE *__restrict, int,
 				   const char *__restrict, _G_va_list);
-extern int __nldbl___vfwprintf_chk (FILE *__restrict, int,
-				    const wchar_t *__restrict, __gnuc_va_list);
 extern int __nldbl___vsprintf_chk (char *__restrict, int, size_t,
 				   const char *__restrict, _G_va_list) __THROW;
 extern int __nldbl___vsnprintf_chk (char *__restrict, size_t, int, size_t,
 				    const char *__restrict, _G_va_list)
   __THROW;
-extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t,
-				    const wchar_t *__restrict, __gnuc_va_list)
-  __THROW;
 extern int __nldbl___vasprintf_chk (char **, int, const char *, _G_va_list)
   __THROW;
 extern int __nldbl___vdprintf_chk (int, int, const char *, _G_va_list);
 extern int __nldbl___obstack_vprintf_chk (struct obstack *, int, const char *,
 					  _G_va_list) __THROW;
 extern void __nldbl___vsyslog_chk (int, int, const char *, va_list);
+#ifdef __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+extern int __nldbl___vfwprintf_chk (FILE *__restrict, int,
+				    const wchar_t *__restrict, __gnuc_va_list);
+extern int __nldbl___vswprintf_chk (wchar_t *__restrict, size_t, int, size_t,
+				    const wchar_t *__restrict, __gnuc_va_list)
+  __THROW;
+#endif
 
-
 #endif /* __NLDBL_COMPAT_H */
Index: libc/sysdeps/sparc/sparc64/dl-machine.h
===================================================================
--- libc/sysdeps/sparc/sparc64/dl-machine.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/sparc/sparc64/dl-machine.h	(.../trunk)	(revision 8411)
@@ -352,7 +352,7 @@
 	    {
 	      if (__builtin_expect (rela->r_addend, 0) != 0)
 		{
-                  Elf64_Addr slot = ((rela->r_offset + 0x400
+		  Elf64_Addr slot = ((rela->r_offset + l->l_addr + 0x400
 				      - (Elf64_Addr) plt)
 				     / 0x1400) * 0x1400
 				    + (Elf64_Addr) plt - 0x400;
@@ -360,20 +360,23 @@
 		  unsigned int first_ldx = *(unsigned int *)(slot + 12);
 		  Elf64_Addr ptr = slot + (first_ldx & 0xfff) + 4;
 
-		  *(Elf64_Addr *) rela->r_offset
+		  *(Elf64_Addr *) (rela->r_offset + l->l_addr)
 		    = (Elf64_Addr) plt
-		      - (slot + ((rela->r_offset - ptr) / 8) * 24 + 4);
+		      - (slot + ((rela->r_offset + l->l_addr - ptr) / 8) * 24
+			 + 4);
 		  ++rela;
 		  continue;
 		}
 
-	      *(unsigned int *) rela->r_offset
-		= 0x03000000 | (rela->r_offset - (Elf64_Addr) plt);
-	      *(unsigned int *) (rela->r_offset + 4)
-		= 0x30680000 | ((((Elf64_Addr) plt + 32
-				  - rela->r_offset - 4) >> 2) & 0x7ffff);
-	      __asm __volatile ("flush %0" : : "r" (rela->r_offset));
-	      __asm __volatile ("flush %0+4" : : "r" (rela->r_offset));
+	      *(unsigned int *) (rela->r_offset + l->l_addr)
+		= 0x03000000 | (rela->r_offset + l->l_addr - (Elf64_Addr) plt);
+	      *(unsigned int *) (rela->r_offset + l->l_addr + 4)
+		= 0x30680000 | ((((Elf64_Addr) plt + 32 - rela->r_offset
+				  - l->l_addr - 4) >> 2) & 0x7ffff);
+	      __asm __volatile ("flush %0" : : "r" (rela->r_offset
+						    + l->l_addr));
+	      __asm __volatile ("flush %0+4" : : "r" (rela->r_offset
+						      + l->l_addr));
 	      ++rela;
 	    }
 	}
Index: libc/sysdeps/sparc/sparc64/elf/configure.in
===================================================================
--- libc/sysdeps/sparc/sparc64/elf/configure.in	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/sparc/sparc64/elf/configure.in	(.../trunk)	(revision 8411)
@@ -1,50 +1,53 @@
 GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
 # Local configure fragment for sysdeps/sparc/sparc64/elf.
 
-if test "$usetls" != no; then
-# Check for support of thread-local storage handling in assembler and linker.
-AC_CACHE_CHECK(for sparc64 TLS support, libc_cv_sparc64_tls, [dnl
-changequote(,)dnl
-cat > conftest.s <<\EOF
-	.section ".tdata", "awT", @progbits
-	.globl foo
-foo:	.word	1
-	.section ".tbss", "awT", @nobits
-	.globl bar
-bar:	.skip	4
-	.text
-	.globl main
-main:	sethi	%tgd_hi22(foo), %l1
-	add	%l1, %tgd_lo10(foo), %l1
-	add	%l7, %l1, %o0, %tgd_add(foo)
-	call	__tls_get_addr, %tgd_call(foo)
-	sethi	%tldm_hi22(bar), %l1
-	add	%l1, %tldm_lo10(bar), %l1
-	add	%l7, %l1, %o0, %tldm_add(bar)
-	call	__tls_get_addr, %tldm_call(bar)
-	sethi	%tldo_hix22(bar), %l1
-	xor	%l1, %tldo_lox10(bar), %l1
-	add	%o0, %l1, %l1, %tldo_add(bar)
-	sethi	%tie_hi22(foo), %l1
-	add	%l1, %tie_lo10(foo), %l1
-	ldx	[%l7 + %l1], %l1, %tie_ldx(foo)
-	add	%g7, %l1, %l1, %tie_add(foo)
-	sethi	%tle_hix22(foo), %l1
-	xor	%l1, %tle_lox10(foo), %l1
-EOF
-changequote([,])dnl
-dnl
-if AC_TRY_COMMAND(${CC-cc} -o conftest.bin $CFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
-  libc_cv_sparc64_tls=yes
-else
-  libc_cv_sparc64_tls=no
-fi
-rm -f conftest*])
-if test $libc_cv_sparc64_tls = yes; then
-  AC_DEFINE(HAVE_TLS_SUPPORT)
-fi
-fi
+AC_DEFINE(HAVE_TLS_SUPPORT) 
+libc_cv_sparc64_tls=yes
 
+dnl if test "$usetls" != no; then
+dnl # Check for support of thread-local storage handling in assembler and linker.
+dnl AC_CACHE_CHECK(for sparc64 TLS support, libc_cv_sparc64_tls, [dnl
+dnl changequote(,)dnl
+dnl cat > conftest.s <<\EOF
+dnl 	.section ".tdata", "awT", @progbits
+dnl 	.globl foo
+dnl foo:	.word	1
+dnl 	.section ".tbss", "awT", @nobits
+dnl 	.globl bar
+dnl bar:	.skip	4
+dnl 	.text
+dnl 	.globl main
+dnl main:	sethi	%tgd_hi22(foo), %l1
+dnl 	add	%l1, %tgd_lo10(foo), %l1
+dnl 	add	%l7, %l1, %o0, %tgd_add(foo)
+dnl 	call	__tls_get_addr, %tgd_call(foo)
+dnl 	sethi	%tldm_hi22(bar), %l1
+dnl 	add	%l1, %tldm_lo10(bar), %l1
+dnl 	add	%l7, %l1, %o0, %tldm_add(bar)
+dnl 	call	__tls_get_addr, %tldm_call(bar)
+dnl 	sethi	%tldo_hix22(bar), %l1
+dnl 	xor	%l1, %tldo_lox10(bar), %l1
+dnl 	add	%o0, %l1, %l1, %tldo_add(bar)
+dnl 	sethi	%tie_hi22(foo), %l1
+dnl 	add	%l1, %tie_lo10(foo), %l1
+dnl 	ldx	[%l7 + %l1], %l1, %tie_ldx(foo)
+dnl 	add	%g7, %l1, %l1, %tie_add(foo)
+dnl 	sethi	%tle_hix22(foo), %l1
+dnl 	xor	%l1, %tle_lox10(foo), %l1
+dnl EOF
+dnl changequote([,])dnl
+dnl dnl
+dnl if AC_TRY_COMMAND(${CC-cc} -o conftest.bin $CFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
+dnl   libc_cv_sparc64_tls=yes
+dnl else
+dnl   libc_cv_sparc64_tls=no
+dnl fi
+dnl rm -f conftest*])
+dnl if test $libc_cv_sparc64_tls = yes; then
+dnl   AC_DEFINE(HAVE_TLS_SUPPORT)
+dnl fi
+dnl fi
+
 # Check for broken WDISP22 in the linker.
 AC_CACHE_CHECK(for sparc64 ld WDISP22 handling, libc_cv_sparc64_wdisp22, [dnl
 echo 'bne foo; nop' > conftest1.s
Index: libc/sysdeps/sparc/bits/mathdef.h
===================================================================
--- libc/sysdeps/sparc/bits/mathdef.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/sparc/bits/mathdef.h	(.../trunk)	(revision 8411)
@@ -29,28 +29,10 @@
 #if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
 # define _MATH_H_MATHDEF	1
 
-# ifdef __GNUC__
-#  if __STDC__ == 1
-
-/* In GNU or ANSI mode, gcc leaves `float' expressions as-is.  */
+/* SPARC has both `float' and `double' arithmetic.  */
 typedef float float_t;
 typedef double double_t;
 
-#  else
-
-/* For `gcc -traditional', `float' expressions are evaluated as `double'. */
-typedef double float_t;
-typedef double double_t;
-
-#  endif
-# else
-
-/* Wild guess at types for float_t and double_t. */
-typedef double float_t;
-typedef double double_t;
-
-# endif
-
 /* The values returned by `ilogb' for 0 and NaN respectively.  */
 # define FP_ILOGB0       (-2147483647)
 # define FP_ILOGBNAN     (2147483647)
Index: libc/sysdeps/sh/sh4/bits/mathdef.h
===================================================================
--- libc/sysdeps/sh/sh4/bits/mathdef.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sysdeps/sh/sh4/bits/mathdef.h	(.../trunk)	(revision 8411)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1997,1998,1999,2000,2004,2006 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
@@ -30,32 +30,10 @@
 #if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
 # define _MATH_H_MATHDEF	1
 
-# ifdef __GNUC__
-#  if __STDC__ == 1
-
-/* In GNU or ANSI mode, gcc leaves `float' expressions as-is.  */
-typedef float float_t;		/* `float' expressions are evaluated as
-				   `float'.  */
-typedef double double_t;	/* `double' expressions are evaluated as
-				   `double'.  */
-
-#  else
-
-/* For `gcc -traditional', `float' expressions are evaluated as `double'. */
-typedef double float_t;		/* `float' expressions are evaluated as
-				   `double'.  */
-typedef double double_t;	/* `double' expressions are evaluated as
-				   `double'.  */
-
-#  endif
-# else
-
-/* Wild guess at types for float_t and double_t. */
-typedef double float_t;
+/* SH has both `float' and `double' arithmetic.  */
+typedef float float_t;
 typedef double double_t;
 
-# endif
-
 /* The values returned by `ilogb' for 0 and NaN respectively.  */
 # define FP_ILOGB0	0x80000001
 # define FP_ILOGBNAN	0x7fffffff
Index: libc/pwd/Makefile
===================================================================
--- libc/pwd/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/pwd/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for pwd portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= pwd
 headers := pwd.h
 
@@ -32,8 +34,10 @@
 
 ifeq ($(have-thread-library),yes)
 
-CFLAGS-getpwuid_r.c = -DUSE_NSCD=1
-CFLAGS-getpwnam_r.c = -DUSE_NSCD=1
+OPTION_EGLIBC_INET-CFLAGS-$(OPTION_EGLIBC_INET) = -DUSE_NSCD=1
+
+CFLAGS-getpwuid_r.c = $(OPTION_EGLIBC_INET-CFLAGS-y)
+CFLAGS-getpwnam_r.c = $(OPTION_EGLIBC_INET-CFLAGS-y)
 CFLAGS-getpwent_r.c = -fexceptions
 CFLAGS-getpwent.c = -fexceptions
 CFLAGS-getpw.c = -fexceptions
Index: libc/catgets/gencat.c
===================================================================
--- libc/catgets/gencat.c	(.../fsf/trunk)	(revision 8411)
+++ libc/catgets/gencat.c	(.../trunk)	(revision 8411)
@@ -225,13 +225,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -242,7 +245,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "gencat (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "gencat %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/catgets/Makefile
===================================================================
--- libc/catgets/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/catgets/Makefile	(.../trunk)	(revision 8411)
@@ -21,16 +21,18 @@
 #
 subdir	:= catgets
 
+include ../option-groups.mak
+
 headers		= nl_types.h
 distribute	= catgetsinfo.h config.h xopen-msg.sed test1.msg test2.msg \
 		  test-gencat.sh sample.SJIS
-routines	= catgets open_catalog
-others		= gencat
-install-bin	= gencat
-extra-objs	= $(gencat-modules:=.o)
+routines-$(OPTION_EGLIBC_CATGETS)    := catgets open_catalog
+others-$(OPTION_EGLIBC_CATGETS)      := gencat
+install-bin-$(OPTION_EGLIBC_CATGETS) := gencat
+extra-objs-$(OPTION_EGLIBC_CATGETS)  := $(gencat-modules:=.o)
 
-tests = tst-catgets
-test-srcs = test-gencat
+tests-$(OPTION_EGLIBC_CATGETS)       := tst-catgets
+test-srcs-$(OPTION_EGLIBC_CATGETS)   := test-gencat
 
 gencat-modules	= xmalloc
 
@@ -53,9 +55,11 @@
 
 tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
 
-ifneq ($(cross-compiling),yes)
+# eglibc: ifneq ($(cross-compiling),yes)
+ifeq (y,$(OPTION_EGLIBC_CATGETS))
 tests: $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
        $(objpfx)test-gencat.out
+endif
 # This test just checks whether the program produces any error or not.
 # The result is not tested.
 $(objpfx)test1.cat: test1.msg $(objpfx)gencat
@@ -83,4 +87,4 @@
 $(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
 	GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \
 	$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@
-endif
+# eglibc: endif
Index: libc/misc/tst-efgcvt.c
===================================================================
--- libc/misc/tst-efgcvt.c	(.../fsf/trunk)	(revision 8411)
+++ libc/misc/tst-efgcvt.c	(.../trunk)	(revision 8411)
@@ -60,7 +60,7 @@
   { 123.01, -4, 3, "" },
   { 126.71, -4, 3, "" },
   { 0.0, 4, 1, "0000" },
-#if DBL_MANT_DIG == 53
+#if DBL_MANT_DIG == 53 && !(defined __powerpc__ && defined __NO_FPRS__ && !defined _SOFT_FLOAT && !defined _SOFT_DOUBLE)
   { 0x1p-1074, 3, -323, "494" },
   { -0x1p-1074, 3, -323, "494" },
 #endif
Index: libc/misc/err.c
===================================================================
--- libc/misc/err.c	(.../fsf/trunk)	(revision 8411)
+++ libc/misc/err.c	(.../trunk)	(revision 8411)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
+#include <gnu/option-groups.h>
 
 #ifdef USE_IN_LIBIO
 # include <wchar.h>
@@ -41,6 +42,7 @@
 }
 
 #ifdef USE_IN_LIBIO
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 static void
 convert_and_print (const char *format, __gnuc_va_list ap)
 {
@@ -86,6 +88,7 @@
   __vfwprintf (stderr, wformat, ap);
 }
 #endif
+#endif
 
 void
 vwarnx (const char *format, __gnuc_va_list ap)
@@ -94,9 +97,13 @@
 #ifdef USE_IN_LIBIO
   if (_IO_fwide (stderr, 0) > 0)
     {
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
       __fwprintf (stderr, L"%s: ", __progname);
       convert_and_print (format, ap);
       putwc_unlocked (L'\n', stderr);
+#else
+      abort ();
+#endif
     }
   else
 #endif
@@ -119,6 +126,7 @@
 #ifdef USE_IN_LIBIO
   if (_IO_fwide (stderr, 0) > 0)
     {
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
       __fwprintf (stderr, L"%s: ", __progname);
       if (format)
 	{
@@ -127,6 +135,9 @@
 	}
       __set_errno (error);
       __fwprintf (stderr, L"%m\n");
+#else
+      abort ();
+#endif
     }
   else
 #endif
Index: libc/misc/error.c
===================================================================
--- libc/misc/error.c	(.../fsf/trunk)	(revision 8411)
+++ libc/misc/error.c	(.../trunk)	(revision 8411)
@@ -29,6 +29,7 @@
 #include <string.h>
 
 #ifdef _LIBC
+# include <gnu/option-groups.h>
 # include <libintl.h>
 # include <stdbool.h>
 # include <stdint.h>
@@ -131,6 +132,7 @@
 #if _LIBC
   if (_IO_fwide (stderr, 0) > 0)
     {
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
 # define ALLOCA_LIMIT 2000
       size_t len = strlen (message) + 1;
       wchar_t *wmessage = NULL;
@@ -192,6 +194,9 @@
 
       if (use_malloc)
 	free (wmessage);
+#else
+      abort ();
+#endif
     }
   else
 #endif
Index: libc/misc/Makefile
===================================================================
--- libc/misc/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/misc/Makefile	(.../trunk)	(revision 8411)
@@ -20,6 +20,10 @@
 #	Sub-makefile for misc portion of the library.
 #
 
+# Some system-dependent implementations of these functions use option
+# groups (see sysdeps/unix/sysv/linux/Makefile, for example).
+include ../option-groups.mak
+
 subdir	:= misc
 
 headers	:= sys/uio.h bits/uio.h sys/ioctl.h bits/ioctls.h bits/ioctl-types.h \
@@ -43,29 +47,32 @@
 	    select pselect \
 	    acct chroot fsync sync fdatasync reboot \
 	    gethostid sethostid \
-	    revoke vhangup \
+	    vhangup \
 	    swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \
 	    mkostemp mkostemp64 \
 	    ualarm usleep \
 	    gtty stty \
 	    ptrace \
-	    fstab mntent mntent_r \
+	    mntent mntent_r \
 	    utimes lutimes futimes futimesat \
 	    truncate ftruncate truncate64 ftruncate64 \
-	    chflags fchflags \
 	    insremque getttyent getusershell getpass ttyslot \
 	    syslog syscall daemon \
 	    mmap mmap64 munmap mprotect msync madvise mincore remap_file_pages\
 	    mlock munlock mlockall munlockall \
-	    efgcvt efgcvt_r qefgcvt qefgcvt_r \
 	    hsearch hsearch_r tsearch lsearch \
 	    err error ustat \
-	    getsysstats dirname regexp \
+	    getsysstats dirname \
 	    getloadavg getclktck \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr
 
+routines-$(OPTION_POSIX_REGEXP) += regexp
+routines-$(OPTION_EGLIBC_FSTAB) += fstab
+routines-$(OPTION_EGLIBC_BSD) += chflags fchflags revoke 
+routines-$(OPTION_EGLIBC_FCVT) += efgcvt efgcvt_r qefgcvt qefgcvt_r
+
 distribute := device-nrs.h
 
 generated := tst-error1.mtrace tst-error1-mem
@@ -78,11 +85,15 @@
 endif
 gpl2lgpl := error.c error.h
 
-tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
-	 tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
-ifeq (no,$(cross-compiling))
+tests := tst-dirname tst-tsearch tst-fdset tst-mntent tst-hsearch \
+	 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) += tst-error1
+tests-$(OPTION_EGLIBC_FCVT) += tst-efgcvt
+# eglibc: ifeq (no,$(cross-compiling))
+ifeq (y,$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO))
 tests: $(objpfx)tst-error1-mem
 endif
+# eglibc: endif
 
 CFLAGS-tsearch.c = $(uses-callbacks)
 CFLAGS-lsearch.c = $(uses-callbacks)
Index: libc/inet/Makefile
===================================================================
--- libc/inet/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/inet/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for inet portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= inet
 
 headers	:= netinet/ether.h netinet/in.h netinet/in_systm.h \
@@ -28,7 +30,8 @@
 
 distribute := netgroup.h
 
-routines := htonl htons		\
+routines-$(OPTION_EGLIBC_INET) \
+	 += htonl htons \
 	    inet_lnaof inet_mkadr	\
 	    inet_netof inet_ntoa inet_net herrno herrno-loc \
 	    gethstbyad gethstbyad_r gethstbynm gethstbynm2 gethstbynm2_r \
@@ -42,18 +45,23 @@
 	    getrpcent_r getrpcbyname_r getrpcbynumber_r \
 	    ether_aton ether_aton_r ether_hton ether_line \
 	    ether_ntoa ether_ntoa_r ether_ntoh \
-	    rcmd rexec ruserpass \
 	    getnetgrent_r getnetgrent \
-	    getaliasent_r getaliasent getaliasname getaliasname_r \
-	    in6_addr getnameinfo if_index ifaddrs inet6_option \
+	    in6_addr getnameinfo if_index ifaddrs \
 	    getipv4sourcefilter setipv4sourcefilter \
-	    getsourcefilter setsourcefilter inet6_opt inet6_rth
+	    getsourcefilter setsourcefilter
+routines-$(OPTION_EGLIBC_RCMD) \
+	 += rcmd rexec ruserpass
+routines-$(OPTION_EGLIBC_DB_ALIASES) \
+	 += getaliasent_r getaliasent getaliasname getaliasname_r
+routines-$(OPTION_EGLIBC_ADVANCED_INET6) \
+	 += inet6_option inet6_opt inet6_rth
 
-aux := check_pf check_native ifreq
+aux-$(OPTION_EGLIBC_INET) += check_pf check_native ifreq
 
 tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
-	 tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
+	 tst-gethnm test-ifaddrs bug-if1 tst-ether_line \
 	 tst-getni1 tst-getni2 tst-inet6_rth
+tests-$(OPTION_EGLIBC_ADVANCED_INET6) += test-inet6_opt
 
 include ../Rules
 
Index: libc/bits/predefs.h
===================================================================
--- libc/bits/predefs.h	(.../fsf/trunk)	(revision 0)
+++ libc/bits/predefs.h	(.../trunk)	(revision 8411)
@@ -0,0 +1,30 @@
+/* Copyright (C) 2005 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _FEATURES_H
+# error "Never use <bits/predefs.h> directly; include <features.h> instead."
+#endif
+
+#ifndef _PREDEFS_H
+#define _PREDEFS_H
+
+/* We do support the IEC 559 math functionality, real and complex.  */
+#define __STDC_IEC_559__		1
+#define __STDC_IEC_559_COMPLEX__	1
+
+#endif /* predefs.h */
Index: libc/bits/wchar.h
===================================================================
--- libc/bits/wchar.h	(.../fsf/trunk)	(revision 8411)
+++ libc/bits/wchar.h	(.../trunk)	(revision 8411)
@@ -20,7 +20,24 @@
 #ifndef _BITS_WCHAR_H
 #define _BITS_WCHAR_H	1
 
-#define __WCHAR_MIN	(-2147483647 - 1)
+/* Use GCC's __WCHAR_MAX__ when available.  */
+#ifdef __WCHAR_MAX__
+#define __WCHAR_MAX	__WCHAR_MAX__
+#else
 #define __WCHAR_MAX	(2147483647)
+#endif
 
+/* GCC may also define __WCHAR_UNSIGNED__.
+   Use L'\0' to give the expression the correct (unsigned) type.  */
+#ifdef __WCHAR_UNSIGNED__
+#define __WCHAR_MIN       L'\0'
+
+/* Failing that, rely on the preprocessor's knowledge of the
+   signedness of wchar_t.  */
+#elif L'\0' - 1 > 0
+#define __WCHAR_MIN       L'\0'
+#else
+#define __WCHAR_MIN       (-__WCHAR_MAX - 1)
+#endif
+
 #endif	/* bits/wchar.h */
Index: libc/nss/fixed-nsswitch.conf
===================================================================
--- libc/nss/fixed-nsswitch.conf	(.../fsf/trunk)	(revision 0)
+++ libc/nss/fixed-nsswitch.conf	(.../trunk)	(revision 8411)
@@ -0,0 +1,22 @@
+# /etc/nsswitch.conf
+#
+# Example configuration for fixed name service.
+# See the description of OPTION_EGLIBC_NSSWITCH in option-groups.def
+# for details.
+#
+
+aliases:        files
+
+passwd:         files
+group:          files
+shadow:         files
+
+hosts:          files dns
+networks:       files dns
+
+protocols:      files
+services:       files
+ethers:         files
+rpc:            files
+
+netgroup:       files
Index: libc/nss/getnssent_r.c
===================================================================
--- libc/nss/getnssent_r.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/getnssent_r.c	(.../trunk)	(revision 8411)
@@ -17,6 +17,7 @@
    02111-1307 USA.  */
 
 #include <errno.h>
+#include <gnu/option-groups.h>
 #include <netdb.h>
 #include "nsswitch.h"
 
@@ -60,11 +61,13 @@
   } fct;
   int no_more;
 
+#if __OPTION_EGLIBC_INET
   if (res && __res_maybe_init (&_res, 0) == -1)
     {
       __set_h_errno (NETDB_INTERNAL);
       return;
     }
+#endif /* __OPTION_EGLIBC_INET */
 
   /* Cycle through the services and run their `setXXent' functions until
      we find an available service.  */
@@ -102,11 +105,13 @@
   } fct;
   int no_more;
 
+#if __OPTION_EGLIBC_INET
   if (res && __res_maybe_init (&_res, 0) == -1)
     {
       __set_h_errno (NETDB_INTERNAL);
       return;
     }
+#endif /* __OPTION_EGLIBC_INET */
 
   /* Cycle through all the services and run their endXXent functions.  */
   no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1);
@@ -142,12 +147,14 @@
   int no_more;
   enum nss_status status;
 
+#if __OPTION_EGLIBC_INET
   if (res && __res_maybe_init (&_res, 0) == -1)
     {
       *h_errnop = NETDB_INTERNAL;
       *result = NULL;
       return errno;
     }
+#endif /* __OPTION_EGLIBC_INET */
 
   /* Initialize status to return if no more functions are found.  */
   status = NSS_STATUS_NOTFOUND;
@@ -162,7 +169,7 @@
       int is_last_nip = *nip == *last_nip;
 
       status = DL_CALL_FCT (fct.f,
-			    (resbuf, buffer, buflen, &errno, &h_errno));
+			    (resbuf, buffer, buflen, &errno, h_errnop));
 
       /* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
 	 provided buffer is too small.  In this case we should give
Index: libc/nss/Makefile
===================================================================
--- libc/nss/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/Makefile	(.../trunk)	(revision 8411)
@@ -19,28 +19,35 @@
 #
 #	Makefile for name service switch.
 #
+include ../option-groups.mak
+
 subdir	:= nss
 
 headers			:= nss.h
 distribute		:= nsswitch.h XXX-lookup.c getXXbyYY.c getXXbyYY_r.c \
 			   getXXent.c getXXent_r.c databases.def \
-			   nsswitch.conf digits_dots.c function.def
+			   nsswitch.conf digits_dots.c function.def \
+			   gen-fixed-nsswitch.c
 
-# This is the trivial part which goes into libc itself.
-routines		= nsswitch getnssent getnssent_r digits_dots \
-			  $(addsuffix -lookup,$(databases))
-
 # These are the databases that go through nss dispatch.
 # Caution: if you add a database here, you must add its real name
 # in databases.def, too.
-databases		= proto service hosts network grp pwd rpc ethers \
-			  spwd netgrp key alias sgrp
+databases-y		= grp pwd spwd sgrp
+databases-$(OPTION_EGLIBC_INET) \
+			+= proto service hosts network rpc ethers \
+			   netgrp key
+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
 
+# This is the trivial part which goes into libc itself.
+routines-y		+= nsswitch getnssent getnssent_r \
+			  $(addsuffix -lookup,$(databases-y))
+routines-$(OPTION_EGLIBC_INET) += digits_dots
+
 others                  := getent
 install-bin             := getent
 
-tests			= test-netdb
-xtests			= bug-erange
+tests-$(OPTION_EGLIBC_INET) += test-netdb
+xtests-$(OPTION_EGLIBC_INET) += bug-erange
 
 include ../Makeconfig
 
@@ -62,7 +69,7 @@
 vpath %.c $(subdir-dirs)
 
 
-libnss_files-routines	:= $(addprefix files-,$(databases)) \
+libnss_files-routines	:= $(addprefix files-,$(databases-y)) \
 			   files-have_o_cloexec
 distribute		+= files-XXX.c files-parse.c
 
@@ -72,6 +79,45 @@
 libnss_files-inhibit-o	= $(filter-out .os,$(object-suffixes))
 endif
 
+ifneq ($(OPTION_EGLIBC_NSSWITCH),y)
+
+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG
+$(error OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG variable left unset)
+endif
+
+ifndef OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS
+$(error OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS variable left unset)
+endif
+
+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)))
+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed config file)
+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG))
+endif
+
+ifeq (,$(wildcard $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)))
+$(warning OPTION_EGLIBC_NSSWITCH is disabled, but fixed functions file)
+$(error does not exist: $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS))
+endif
+
+before-compile := $(objpfx)fixed-nsswitch.h
+generated := fixed-nsswitch.h
+$(objpfx)fixed-nsswitch.h $(objfpx)fixed-nsswitch-libs:	\
+    $(objpfx)gen-fixed-nsswitch				\
+    $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
+	$< $(objpfx)fixed-nsswitch.h			\
+	   $(objpfx)fixed-nsswitch-libs			\
+	   $(OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG)
+
+$(objpfx)gen-fixed-nsswitch: gen-fixed-nsswitch.c	\
+    $(common-objpfx)option-groups.config		\
+    $(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)
+	$(native-compile)
+gen-fixed-nsswitch-CFLAGS =						\
+	-g3 -O -Wall							\
+	-I $(objpfx)							\
+	-DFIXED_FUNCTIONS='"$(OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS)"'
+endif
+
 include ../Rules
 
 
Index: libc/nss/nsswitch.c
===================================================================
--- libc/nss/nsswitch.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/nsswitch.c	(.../trunk)	(revision 8411)
@@ -27,6 +27,7 @@
 #include <stdio_ext.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 #include <aliases.h>
 #include <grp.h>
@@ -41,6 +42,15 @@
 #include "nsswitch.h"
 #include "../nscd/nscd_proto.h"
 
+/* When OPTION_EGLIBC_NSSWITCH is disabled, we use fixed tables of
+   databases and services, generated at library build time.  Thus:
+   - We can't reconfigure individual databases, so we don't need a
+     name-to-database map.
+   - We never add databases or service libraries, or look up functions
+     at runtime, so there's no need for a lock to protect our tables.
+   See ../option-groups.def for the details.  */
+#if __OPTION_EGLIBC_NSSWITCH
+
 /* Prototypes for the local functions.  */
 static name_database *nss_parse_file (const char *fname) internal_function;
 static name_database_entry *nss_getline (char *line) internal_function;
@@ -74,6 +84,9 @@
 
 __libc_lock_define_initialized (static, lock)
 
+#define lock_nsswitch __libc_lock_lock (lock)
+#define unlock_nsswitch __libc_lock_unlock (lock)
+
 #if !defined DO_STATIC_NSS || defined SHARED
 /* String with revision number of the shared object files.  */
 static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
@@ -82,7 +95,21 @@
 /* The root of the whole data base.  */
 static name_database *service_table;
 
+#else /* __OPTION_EGLIBC_NSSWITCH */
 
+/* Bring in the statically initialized service table we generated at
+   build time.  */
+#include "fixed-nsswitch.h"
+
+const static name_database *service_table = &fixed_name_database;
+
+/* Nothing ever changes, so there's no need to lock anything.  */
+#define lock_nsswitch (0)
+#define unlock_nsswitch (0)
+
+#endif /* __OPTION_EGLIBC_NSSWITCH */
+
+
 /* -1 == database not found
     0 == database entry pointer stored */
 int
@@ -90,20 +117,22 @@
 		       const char *defconfig, service_user **ni)
 {
   /* Prevent multiple threads to change the service table.  */
-  __libc_lock_lock (lock);
+  lock_nsswitch;
 
   /* Reconsider database variable in case some other thread called
      `__nss_configure_lookup' while we waited for the lock.  */
   if (*ni != NULL)
     {
-      __libc_lock_unlock (lock);
+      unlock_nsswitch;
       return 0;
     }
 
+#if __OPTION_EGLIBC_NSSWITCH
   /* Are we initialized yet?  */
   if (service_table == NULL)
     /* Read config file.  */
     service_table = nss_parse_file (_PATH_NSSWITCH_CONF);
+#endif
 
   /* Test whether configuration data is available.  */
   if (service_table != NULL)
@@ -125,6 +154,7 @@
 	    *ni = entry->service;
     }
 
+#if __OPTION_EGLIBC_NSSWITCH
   /* No configuration data is available, either because nsswitch.conf
      doesn't exist or because it doesn't has a line for this database.
 
@@ -133,8 +163,18 @@
   if (*ni == NULL)
     *ni = nss_parse_service_list (defconfig
 				  ?: "nis [NOTFOUND=return] files");
+#else
+  /* Without the dynamic behavior, we can't process defconfig.  The
+     databases the user specified at library build time are all you
+     get.  */
+  if (*ni == NULL)
+    {
+      unlock_nsswitch;
+      return -1;
+    }
+#endif
 
-  __libc_lock_unlock (lock);
+  unlock_nsswitch;
 
   return 0;
 }
@@ -213,6 +253,7 @@
 libc_hidden_def (__nss_next2)
 
 
+#if __OPTION_EGLIBC_NSSWITCH
 int
 attribute_compat_text_section
 __nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
@@ -261,12 +302,12 @@
     }
 
   /* Prevent multiple threads to change the service table.  */
-  __libc_lock_lock (lock);
+  lock_nsswitch;
 
   /* Install new rules.  */
   *databases[cnt].dbp = new_db;
 
-  __libc_lock_unlock (lock);
+  unlock_nsswitch;
 
   return 0;
 }
@@ -287,7 +328,7 @@
   void **found, *result;
 
   /* We now modify global data.  Protect it.  */
-  __libc_lock_lock (lock);
+  lock_nsswitch;
 
   /* Search the tree of functions previously requested.  Data in the
      tree are `known_function' structures, whose first member is a
@@ -298,7 +339,7 @@
      enough to a pointer to our structure to use as a lookup key that
      will be passed to `known_compare' (above).  */
 
-  found = __tsearch (&fct_name, &ni->known, &known_compare);
+  found = __tsearch (&fct_name, &ni->known.tree, &known_compare);
   if (*found != &fct_name)
     {
       /* The search found an existing structure in the tree.  */
@@ -318,7 +359,7 @@
 	remove_from_tree:
 	  /* Oops.  We can't instantiate this node properly.
 	     Remove it from the tree.  */
-	  __tdelete (&fct_name, &ni->known, &known_compare);
+	  __tdelete (&fct_name, &ni->known.tree, &known_compare);
 	  result = NULL;
 	}
       else
@@ -432,13 +473,43 @@
     }
 
   /* Remove the lock.  */
-  __libc_lock_unlock (lock);
+  unlock_nsswitch;
 
   return result;
 }
 libc_hidden_def (__nss_lookup_function)
 
 
+#else /* below if ! __OPTION_EGLIBC_NSSWITCH */
+
+
+int
+__nss_configure_lookup (const char *dbname, const char *service_line)
+{
+  /* We can't dynamically configure lookup without
+     OPTION_EGLIBC_NSSWITCH.  */
+  __set_errno (EINVAL);
+  return -1;
+}
+
+
+void *
+__nss_lookup_function (service_user *ni, const char *fct_name)
+{
+  int i;
+  const known_function **known = ni->known.array;
+
+  for (i = 0; known[i]; i++)
+    if (strcmp (fct_name, known[i]->fct_name) == 0)
+      return known[i]->fct_ptr;
+
+  return NULL;
+}
+libc_hidden_def (__nss_lookup_function)
+#endif
+
+
+#if __OPTION_EGLIBC_NSSWITCH
 static name_database *
 internal_function
 nss_parse_file (const char *fname)
@@ -541,8 +612,10 @@
 					     + (line - name + 1));
       if (new_service == NULL)
 	return result;
+      new_service->name = (char *) (new_service + 1);
 
-      *((char *) __mempcpy (new_service->name, name, line - name)) = '\0';
+      *((char *) __mempcpy ((char *) new_service->name, name, line - name))
+        = '\0';
 
       /* Set default actions.  */
       new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
@@ -551,7 +624,7 @@
       new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
       new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
       new_service->library = NULL;
-      new_service->known = NULL;
+      new_service->known.tree = NULL;
       new_service->next = NULL;
 
       while (isspace (line[0]))
@@ -682,9 +755,10 @@
   result = (name_database_entry *) malloc (sizeof (name_database_entry) + len);
   if (result == NULL)
     return NULL;
+  result->name = (char *) (result + 1);
 
   /* Save the database name.  */
-  memcpy (result->name, name, len);
+  memcpy ((char *) result->name, name, len);
 
   /* Parse the list of services.  */
   result->service = nss_parse_service_list (line);
@@ -718,8 +792,10 @@
 
   return *currentp;
 }
+#endif /* __OPTION_EGLIBC_NSSWITCH */
 
 
+#if __OPTION_EGLIBC_INET
 /* Called by nscd and nscd alone.  */
 void
 __nss_disable_nscd (void)
@@ -730,8 +806,10 @@
   __nss_not_use_nscd_hosts = -1;
   __nss_not_use_nscd_services = -1;
 }
+#endif /* __OPTION_EGLIBC_INET */
 
 
+#if __OPTION_EGLIBC_NSSWITCH
 /* Free all resources if necessary.  */
 libc_freeres_fn (free_mem)
 {
@@ -756,8 +834,8 @@
 	{
 	  service_user *olds = service;
 
-	  if (service->known != NULL)
-	    __tdestroy (service->known, free);
+	  if (service->known.tree != NULL)
+	    __tdestroy (service->known.tree, free);
 
 	  service = service->next;
 	  free (olds);
@@ -781,3 +859,4 @@
 
   free (top);
 }
+#endif /* __OPTION_EGLIBC_NSSWITCH */
Index: libc/nss/gen-fixed-nsswitch.c
===================================================================
--- libc/nss/gen-fixed-nsswitch.c	(.../fsf/trunk)	(revision 0)
+++ libc/nss/gen-fixed-nsswitch.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,803 @@
+/* gen-fixed-nsswitch.c --- generate fixed name service data structures
+   Copyright (C) 1996-1999, 2001-2006, 2007 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "gnu/lib-names.h"
+#include "nss.h"
+
+/* Provide a fallback definition to allow this file to be compiled outside
+   libc.  */
+#ifndef internal_function
+# define internal_function
+#endif
+
+
+/* Simple utilities.  */
+
+void __attribute__ ((noreturn))
+error (const char *message)
+{
+  fprintf (stderr, "%s\n", message);
+  exit (1);
+}
+
+
+void *
+check_alloc (void *p)
+{
+  if (p)
+    return p;
+  else
+    error ("out of memory");
+}
+
+void *
+xmalloc (size_t size)
+{
+  return check_alloc (malloc (size));
+}
+
+
+/* Format ARGS according to FORMAT, and return the result as a
+   malloc'ed string.  */
+char *
+saprintf (const char *format, ...)
+{
+  va_list args;
+  size_t len;
+  char *buf;
+  
+  va_start (args, format);
+  len = vsnprintf (NULL, 0, format, args);
+  va_end (args);
+
+  buf = xmalloc (len + 1);
+  va_start (args, format);
+  assert (len == vsnprintf (buf, len + 1, format, args));
+  va_end (args);
+
+  return buf;
+}
+
+
+
+/* Data structures representing the configuration file in memory.  */
+
+/* These are copied from nsswitch.h.
+
+   We could simply #include that file, but this program runs on the
+   build machine and links against the build machine's libraries,
+   whereas that header is meant for use by target code; it uses
+   'libc_hidden_proto', 'internal_function', and related hair.  Since
+   we've copied the parsing code, we might as well copy the data
+   structure definitions as well.  */
+
+/* Actions performed after lookup finished.  */
+typedef enum
+{
+  NSS_ACTION_CONTINUE,
+  NSS_ACTION_RETURN
+} lookup_actions;
+
+
+typedef struct service_library
+{
+  /* Name of service (`files', `dns', `nis', ...).  */
+  const char *name;
+  /* Pointer to the loaded shared library.  */
+  void *lib_handle;
+  /* And the link to the next entry.  */
+  struct service_library *next;
+} service_library;
+
+
+/* For mapping a function name to a function pointer.  It is known in
+   nsswitch.c:nss_lookup_function that a string pointer for the lookup key
+   is the first member.  */
+typedef struct
+{
+  const char *fct_name;
+  void *fct_ptr;
+} known_function;
+
+
+typedef struct service_user
+{
+  /* And the link to the next entry.  */
+  struct service_user *next;
+  /* Action according to result.  */
+  lookup_actions actions[5];
+  /* Link to the underlying library object.  */
+  service_library *library;
+  /* Collection of known functions.
+
+     With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
+     'tsearch'-style tree.
+
+     With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
+     pointers to known_function structures, NULL-terminated.  */
+  union
+  {
+    void *tree;
+    const known_function **array;
+  } known;
+  /* Name of the service (`files', `dns', `nis', ...).  */
+  const char *name;
+} service_user;
+
+/* To access the action based on the status value use this macro.  */
+#define nss_next_action(ni, status) ((ni)->actions[2 + status])
+
+
+typedef struct name_database_entry
+{
+  /* And the link to the next entry.  */
+  struct name_database_entry *next;
+  /* List of service to be used.  */
+  service_user *service;
+  /* Name of the database.  */
+  const char *name;
+} name_database_entry;
+
+
+typedef struct name_database
+{
+  /* List of all known databases.  */
+  name_database_entry *entry;
+  /* List of libraries with service implementation.  */
+  service_library *library;
+} name_database;
+
+
+
+/* Gathering the contents of the FIXED_FUNCTIONS file.  */
+
+/* It should be possible to generate this list automatically by
+   looking at the services and databases used in the nsswitch.conf
+   file, and having a hard-coded set of queries supported on each
+   database.  */
+
+/* We #include the FIXED_FUNCTIONS file several times to build an
+   array of function structures holding its data.  */
+enum function_kind {
+  fk_end = 0,                   /* Last entry.  */
+  fk_setent,                    /* Like setpwent.  */
+  fk_getent,                    /* Like getpwent.  */
+  fk_endent,                    /* Like endpwent.  */
+  fk_getby,                     /* Like gethostbyname.  */
+  fk_get                        /* Like getpwnam.  */
+};
+
+
+struct function {
+  /* What kind of function this is.  */
+  enum function_kind kind;
+
+  /* The database and service of the function being hardwired in.  */
+  char *database, *service;
+
+  /* The kind of entry being queried, for 'fk_setent', 'fk_getent',
+     'fk_endent', and 'fk_getby' functions.  */
+  char *entry;
+
+  /* The key, for 'fk_getby' entries.  */
+  char *key;
+
+  /* The value and key, for 'fk_get' entries.  */
+  char *value_and_key;
+};
+
+
+const struct function functions[] =
+  {
+
+#define DEFINE_ENT(database, service, entry)    \
+    { fk_setent, #database, #service, #entry }, \
+    { fk_getent, #database, #service, #entry }, \
+    { fk_endent, #database, #service, #entry },
+#define DEFINE_GETBY(database, service, entry, key)   \
+    { fk_getby, #database, #service, #entry, #key },
+#define DEFINE_GET(database, service, value_and_key)     \
+    { fk_get, #database, #service, NULL, NULL, #value_and_key },
+
+#include FIXED_FUNCTIONS
+
+#undef DEFINE_ENT
+#undef DEFINE_GETBY
+#undef DEFINE_GET
+
+    { fk_end }
+  };
+
+
+/* Parsing the config file.  Functions copied from nsswitch.c.  */
+
+#define __strchrnul strchrnul
+#define __getline getline
+#define __strncasecmp strncasecmp
+
+/* Prototypes for the local functions.  */
+static name_database *nss_parse_file (const char *fname) internal_function;
+static name_database_entry *nss_getline (char *line) internal_function;
+static service_user *nss_parse_service_list (const char *line)
+     internal_function;
+
+static name_database *
+internal_function
+nss_parse_file (const char *fname)
+{
+  FILE *fp;
+  name_database *result;
+  name_database_entry *last;
+  char *line;
+  size_t len;
+
+  /* Open the configuration file.  */
+  fp = fopen (fname, "rc");
+  if (fp == NULL)
+    return NULL;
+
+  // /* No threads use this stream.  */
+  // __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+  result = (name_database *) xmalloc (sizeof (name_database));
+
+  result->entry = NULL;
+  result->library = NULL;
+  last = NULL;
+  line = NULL;
+  len = 0;
+  do
+    {
+      name_database_entry *this;
+      ssize_t n;
+
+      n = __getline (&line, &len, fp);
+      if (n < 0)
+	break;
+      if (line[n - 1] == '\n')
+	line[n - 1] = '\0';
+
+      /* Because the file format does not know any form of quoting we
+	 can search forward for the next '#' character and if found
+	 make it terminating the line.  */
+      *__strchrnul (line, '#') = '\0';
+
+      /* If the line is blank it is ignored.  */
+      if (line[0] == '\0')
+	continue;
+
+      /* Each line completely specifies the actions for a database.  */
+      this = nss_getline (line);
+      if (this != NULL)
+	{
+	  if (last != NULL)
+	    last->next = this;
+	  else
+	    result->entry = this;
+
+	  last = this;
+	}
+    }
+  while (!feof_unlocked (fp));
+
+  /* Free the buffer.  */
+  free (line);
+  /* Close configuration file.  */
+  fclose (fp);
+
+  return result;
+}
+
+
+/* Read the source names:
+	`( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
+   */
+static service_user *
+internal_function
+nss_parse_service_list (const char *line)
+{
+  service_user *result = NULL, **nextp = &result;
+
+  while (1)
+    {
+      service_user *new_service;
+      const char *name;
+
+      while (isspace (line[0]))
+	++line;
+      if (line[0] == '\0')
+	/* No source specified.  */
+	return result;
+
+      /* Read <source> identifier.  */
+      name = line;
+      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
+	++line;
+      if (name == line)
+	return result;
+
+
+      new_service = (service_user *) xmalloc (sizeof (*new_service));
+      new_service->name = (char *) xmalloc (line - name + 1);
+
+      *((char *) __mempcpy ((char *) new_service->name, name, line - name))
+        = '\0';
+
+      /* Set default actions.  */
+      new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
+      new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE;
+      new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE;
+      new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
+      new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
+      new_service->library = NULL;
+      new_service->known.tree = NULL;
+      new_service->next = NULL;
+
+      while (isspace (line[0]))
+	++line;
+
+      if (line[0] == '[')
+	{
+	  /* Read criterions.  */
+	  do
+	    ++line;
+	  while (line[0] != '\0' && isspace (line[0]));
+
+	  do
+	    {
+	      int not;
+	      enum nss_status status;
+	      lookup_actions action;
+
+	      /* Grok ! before name to mean all statii but that one.  */
+	      not = line[0] == '!';
+	      if (not)
+		++line;
+
+	      /* Read status name.  */
+	      name = line;
+	      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
+		     && line[0] != ']')
+		++line;
+
+	      /* Compare with known statii.  */
+	      if (line - name == 7)
+		{
+		  if (__strncasecmp (name, "SUCCESS", 7) == 0)
+		    status = NSS_STATUS_SUCCESS;
+		  else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
+		    status = NSS_STATUS_UNAVAIL;
+		  else
+		    return result;
+		}
+	      else if (line - name == 8)
+		{
+		  if (__strncasecmp (name, "NOTFOUND", 8) == 0)
+		    status = NSS_STATUS_NOTFOUND;
+		  else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
+		    status = NSS_STATUS_TRYAGAIN;
+		  else
+		    return result;
+		}
+	      else
+		return result;
+
+	      while (isspace (line[0]))
+		++line;
+	      if (line[0] != '=')
+		return result;
+	      do
+		++line;
+	      while (isspace (line[0]));
+
+	      name = line;
+	      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
+		     && line[0] != ']')
+		++line;
+
+	      if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
+		action = NSS_ACTION_RETURN;
+	      else if (line - name == 8
+		       && __strncasecmp (name, "CONTINUE", 8) == 0)
+		action = NSS_ACTION_CONTINUE;
+	      else
+		return result;
+
+	      if (not)
+		{
+		  /* Save the current action setting for this status,
+		     set them all to the given action, and reset this one.  */
+		  const lookup_actions save = new_service->actions[2 + status];
+		  new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action;
+		  new_service->actions[2 + NSS_STATUS_UNAVAIL] = action;
+		  new_service->actions[2 + NSS_STATUS_NOTFOUND] = action;
+		  new_service->actions[2 + NSS_STATUS_SUCCESS] = action;
+		  new_service->actions[2 + status] = save;
+		}
+	      else
+		new_service->actions[2 + status] = action;
+
+	      /* Skip white spaces.  */
+	      while (isspace (line[0]))
+		++line;
+	    }
+	  while (line[0] != ']');
+
+	  /* Skip the ']'.  */
+	  ++line;
+	}
+
+      *nextp = new_service;
+      nextp = &new_service->next;
+    }
+}
+
+static name_database_entry *
+internal_function
+nss_getline (char *line)
+{
+  const char *name;
+  name_database_entry *result;
+  size_t len;
+
+  /* Ignore leading white spaces.  ATTENTION: this is different from
+     what is implemented in Solaris.  The Solaris man page says a line
+     beginning with a white space character is ignored.  We regard
+     this as just another misfeature in Solaris.  */
+  while (isspace (line[0]))
+    ++line;
+
+  /* Recognize `<database> ":"'.  */
+  name = line;
+  while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':')
+    ++line;
+  if (line[0] == '\0' || name == line)
+    /* Syntax error.  */
+    return NULL;
+  *line++ = '\0';
+
+  len = strlen (name) + 1;
+
+  result = (name_database_entry *) xmalloc (sizeof (*result));
+  result->name = (char *) xmalloc (len);
+
+  /* Save the database name.  */
+  memcpy ((char *) result->name, name, len);
+
+  /* Parse the list of services.  */
+  result->service = nss_parse_service_list (line);
+
+  result->next = NULL;
+  return result;
+}
+
+
+
+/* Generating code for statically initialized nsswitch structures.  */
+
+
+/* Return the service-neutral suffix of the name of the service
+   library function referred to by the function F.  The result is
+   allocated with malloc.  */
+char *
+known_function_suffix (const struct function *f)
+{
+  switch (f->kind)
+    {
+    case fk_setent:
+      return saprintf ("set%sent", f->entry);
+
+    case fk_getent:
+      return saprintf ("get%sent_r", f->entry);
+
+    case fk_endent:
+      return saprintf ("end%sent", f->entry);
+
+    case fk_getby:
+      return saprintf ("get%sby%s_r", f->entry, f->key);
+
+    case fk_get:
+      return saprintf ("get%s_r", f->value_and_key);
+
+    default:
+      abort ();
+    }
+}
+
+
+/* Return the name of the service library function referred to by the
+   function F.  The result is allocated with malloc.  */
+char *
+known_function_name (const struct function *f)
+{
+  return saprintf ("_nss_%s_%s", f->service, known_function_suffix (f));
+}
+
+
+/* Write initialized known_function structures to OUT for
+   all the functions we'll use.  */
+void
+generate_known_functions (FILE *out)
+{
+  int i;
+
+  /* First, generate weak references to the functions.  The service
+     libraries depend on libc, and if these references weren't weak,
+     we'd be making libc depend circularly on the service
+     libraries.  */
+  for (i = 0; functions[i].kind; i++)
+    {
+      char *name = known_function_name (&functions[i]);
+      fprintf (out, "typeof (%s) %s __attribute__ ((weak));\n",
+               name, name);
+    }
+  fputs ("\n", out);
+
+  /* Then, a table mapping names to functions.  */
+  fputs ("static const known_function fixed_known_functions[] = {\n",
+         out);
+  for (i = 0; functions[i].kind; i++)
+    {
+      const struct function *f = &functions[i];
+      char *suffix = known_function_suffix (f);
+
+      fprintf (out, "  /* %2d */ { \"%s\", _nss_%s_%s },\n",
+               i, suffix, f->service, suffix);
+    }
+  fputs ("};\n", out);
+  fputs ("\n", out);
+}
+
+
+/* Print code to OUT for an initialized array of pointers to the
+   'known_function' structures needed for USER, which is for
+   DATABASE.  Return its name, allocated with malloc.  */
+char *
+generate_known_function_list (FILE *out,
+                              const name_database_entry *database,
+                              const service_user *user)
+{
+  char *list_name = saprintf ("fixed_%s_%s_known_funcs",
+                              database->name, user->name);
+  fprintf (out, "static const known_function *%s[] = {\n",
+           list_name);
+  int i;
+  for (i = 0; functions[i].kind; i++)
+    if (strcmp (functions[i].database, database->name) == 0
+        && strcmp (functions[i].service, user->name) == 0)
+      fprintf (out, "  &fixed_known_functions[%d], /* %s */\n",
+               i, known_function_name (&functions[i]));
+  fputs ("  NULL\n", out);
+  fputs ("};\n", out);
+  fputs ("\n", out);
+
+  return list_name;
+}
+
+
+/* Return the name of the status value STATUS, as a statically
+   allocated string.  */
+const char *
+lookup_status_name (enum nss_status status)
+{
+  switch (status)
+    {
+    case NSS_STATUS_TRYAGAIN: return "NSS_STATUS_TRYAGAIN";
+    case NSS_STATUS_UNAVAIL: return "NSS_STATUS_UNAVAIL";
+    case NSS_STATUS_NOTFOUND: return "NSS_STATUS_NOTFOUND";
+    case NSS_STATUS_SUCCESS: return "NSS_STATUS_SUCCESS";
+    case NSS_STATUS_RETURN: return "NSS_STATUS_RETURN";
+    default: abort ();
+    };
+}
+
+
+/* Return the name of ACTION as a statically allocated string.  */
+const char *
+lookup_action_name (lookup_actions action)
+{
+  switch (action)
+    {
+    case NSS_ACTION_CONTINUE: return "NSS_ACTION_CONTINUE";
+    case NSS_ACTION_RETURN: return "NSS_ACTION_RETURN";
+    default: abort ();
+    }
+}
+
+
+/* Print code to OUT for the list of service_user structures starting
+   with USER, which are all for DATABASE.  Return the name of the 
+   first structure in that list, or zero if USER is NULL.  */
+char *
+generate_service_user_list (FILE *out,
+                            name_database_entry *database,
+                            service_user *user)
+{
+  if (user)
+    {
+      /* Generate the tail of the list.  */
+      char *next_name = generate_service_user_list (out, database, user->next);
+      /* Generate our known function list.  */
+      char *known_function_list_name =
+        generate_known_function_list (out, database, user);
+
+      char *name = saprintf ("fixed_%s_%s_user", database->name, user->name);
+
+      fprintf (out, "static const service_user %s = {\n", name);
+      if (next_name)
+        fprintf (out, "  (service_user *) &%s,\n", next_name);
+      else
+        fprintf (out, "  NULL, /* no next entry */\n");
+      fputs ("  {\n", out);
+      int i;
+      for (i = 0; i < sizeof (user->actions) / sizeof (user->actions[0]); i++)
+        fprintf (out, "    %s, /* %s */\n",
+                 lookup_action_name (user->actions[i]),
+                 lookup_status_name (i - 2));
+      fputs ("  },\n", out);
+      fprintf (out, "  NULL,  /* we never need the service library */\n");
+      fprintf (out, "  { .array = %s },\n", known_function_list_name);
+      fprintf (out, "  \"%s\"\n", user->name);
+      fputs ("};\n", out);
+      fputs ("\n", out);
+      
+      return name;
+    }
+  else
+    return NULL;
+}
+
+
+/* Print code to OUT for the list of name_database_entry structures
+   starting with DATABASE.  Return the name of the first structure 
+   in that list, or zero if DATABASE is NULL.  */
+char *
+generate_name_database_entries (FILE *out, name_database_entry *database)
+{
+  if (database)
+    {
+      char *next_name = generate_name_database_entries (out, database->next);
+      char *service_user_name
+        = generate_service_user_list (out, database, database->service);
+      char *name = saprintf ("fixed_%s_name_database", database->name);
+
+      fprintf (out, "static const name_database_entry %s = {\n", name);
+
+      if (next_name)
+        fprintf (out, "  (name_database_entry *) &%s,\n", next_name);
+      else
+        fprintf (out, "  NULL,\n");
+      
+      if (service_user_name)
+        fprintf (out, "  (service_user *) &%s,\n", service_user_name);
+      else
+        fprintf (out, "  NULL,\n");
+
+      fprintf (out, "  \"%s\"\n", database->name);
+      fprintf (out, "};\n");
+      fputs ("\n", out);
+
+      return name;
+    }
+  else
+    return NULL;
+}
+
+
+void
+generate_name_database (FILE *out, name_database *service_table)
+{
+  /* Produce a linked list of the known name_database_entry
+     structures.  */
+  char *entries = generate_name_database_entries (out, service_table->entry);
+
+  /* Now produce the main structure that points to them all.  */
+  fprintf (out, "static const name_database fixed_name_database = {\n");
+  if (entries)
+    fprintf (out, "  (name_database_entry *) &%s,\n", entries);
+  else
+    fprintf (out, "  NULL,\n");
+  fputs ("  NULL /* we don't need the libraries */\n"
+         "};\n",
+         out);
+}
+
+
+
+/* Generating the list of service libraries we generate references to.  */
+
+/* String with revision number of the shared object files.  */
+static const char *const nss_shlib_revision = LIBNSS_FILES_SO + 15;
+
+void
+generate_service_lib_list (FILE *out, name_database *service_table)
+{
+  int i, j;
+  int printed_any = 0;
+
+  for (i = 0; functions[i].kind; i++)
+    {
+      /* Mention each service library only once.  */
+      for (j = 0; j < i; j++)
+        if (strcmp (functions[i].service, functions[j].service) == 0)
+          break;
+
+      if (j >= i)
+        {
+          if (printed_any)
+            putc (' ', out);
+          fprintf (out, "-lnss_%s",
+                   functions[i].service,
+                   nss_shlib_revision);
+          printed_any = 1;
+        }
+    }
+}
+
+
+/* Main.  */
+
+int
+main (int argc, char **argv)
+{
+  if (argc != 4)
+    {
+      fprintf (stderr, "usage: gen-fixed-nsswitch HEADER SERVLIBS CONFIG\n");
+      exit (1);
+    }
+  
+  name_database *service_table = nss_parse_file (argv[3]);
+  
+  FILE *header = fopen (argv[1], "w");
+  if (! header)
+    {
+      fprintf (stderr,
+               "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
+               argv[1], strerror (errno));
+      exit (1);
+    }
+  fputs ("/* Generated by nss/gen-fixed-nsswitch.c.  */\n", header);
+  fputs ("\n", header);
+  generate_known_functions (header);
+  generate_name_database (header, service_table);
+  fclose (header);
+
+  FILE *service_lib_list = fopen (argv[2], "w");
+  if (! service_lib_list)
+    {
+      fprintf (stderr,
+               "gen-fixed-nsswitch: couldn't open output file %s: %s\n",
+               argv[2], strerror (errno));
+      exit (1);
+    }
+  generate_service_lib_list (service_lib_list, service_table);
+  fclose (service_lib_list);
+
+  return 0;
+}
Index: libc/nss/nsswitch.h
===================================================================
--- libc/nss/nsswitch.h	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/nsswitch.h	(.../trunk)	(revision 8411)
@@ -66,10 +66,20 @@
   lookup_actions actions[5];
   /* Link to the underlying library object.  */
   service_library *library;
-  /* Collection of known functions.  */
-  void *known;
+  /* Collection of known functions.
+
+     With OPTION_EGLIBC_NSSWITCH enabled, this is the root of a
+     'tsearch'-style tree.
+
+     With OPTION_EGLIBC_NSSWITCH disabled, this is an array of
+     pointers to known_function structures, NULL-terminated.  */
+  union
+  {
+    void *tree;
+    const known_function **array;
+  } known;
   /* Name of the service (`files', `dns', `nis', ...).  */
-  char name[0];
+  const char *name;
 } service_user;
 
 /* To access the action based on the status value use this macro.  */
@@ -83,7 +93,7 @@
   /* List of service to be used.  */
   service_user *service;
   /* Name of the database.  */
-  char name[0];
+  const char *name;
 } name_database_entry;
 
 
Index: libc/nss/makedb.c
===================================================================
--- libc/nss/makedb.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/makedb.c	(.../trunk)	(revision 8411)
@@ -224,13 +224,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -241,7 +244,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "makedb (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "makedb %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/nss/fixed-nsswitch.functions
===================================================================
--- libc/nss/fixed-nsswitch.functions	(.../fsf/trunk)	(revision 0)
+++ libc/nss/fixed-nsswitch.functions	(.../trunk)	(revision 8411)
@@ -0,0 +1,121 @@
+/* List of functions defined for fixed NSS in GNU C Library.
+   Copyright (C) 1996, 1997, 1998, 2005 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* When OPTION_EGLIBC_NSSWITCH is disabled (see option-groups.def),
+   EGLIBC does not use the 'dlopen' and 'dlsym' functions to look for
+   database query functions in the individual name service libraries.
+   Instead, it uses a set of functions chosen at compile time, as
+   directed by the OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS file.  This
+   file is a sample of what you might use there.
+
+   This file is C source code; it should only contain invocations of
+   the following macros:
+
+   - DEFINE_ENT (DATABASE, SERVICE, X)
+
+     Declare the 'setXent', 'getXent_r', and 'endXent' functions that
+     query DATABASE using the service library 'libnss_SERVICE.so.2'.
+     DATABASE should be the full name of the database as it appears in
+     'nsswitch.conf', like 'passwd' or 'aliases'.
+
+     (The non-reentrant 'getXent' functions are implemented in terms
+     of the reentrant 'getXent_r' functions, so there is no need to
+     refer to them explicitly here.)
+
+   - DEFINE_GETBY (DATABASE, SERVICE, X, KEY)
+
+     Declare the 'getXbyKEY_r' functions that query DATABASE using
+     SERVICE.  DATABASE and SERVICE are as described above.
+
+     (The non-reentrant 'getXbyKEY' functions are implemented in terms
+     of the reentrant 'getXbyKEY_r' functions, so there is no need to
+     refer to them explicitly here.)
+
+     Use the special key 'name3' for the service library function that
+     implements the 'getaddrinfo' function.
+
+   - DEFINE_GET (DATABASE, SERVICE, QUERY)
+
+     Declare the 'getQUERY_r' functions that query DATABASE using
+     SERVICE.  This is used for functions like 'getpwnam'.
+
+     (The non-reentrant 'getQUERY' functions are implemented in terms
+     of the reentrant 'getQUERY_r' functions, so there is no need to
+     refer to them explicitly here.)
+
+   This sample file only includes functions that consult the files in
+   '/etc', and the Domain Name System (DNS).  */
+
+/* aliases */
+DEFINE_ENT (aliases, files, alias)
+DEFINE_GETBY (aliases, files, alias, name)
+
+/* ethers */
+DEFINE_ENT (ethers, files, ether)
+
+/* group */
+DEFINE_ENT (group, files, gr)
+DEFINE_GET (group, files, grgid)
+DEFINE_GET (group, files, grnam)
+
+/* hosts */
+DEFINE_ENT (hosts, files, host)
+DEFINE_GETBY (hosts, files, host, addr)
+DEFINE_GETBY (hosts, files, host, name)
+DEFINE_GETBY (hosts, files, host, name2)
+DEFINE_GET (hosts, files, hostton)
+DEFINE_GET (hosts, files, ntohost)
+DEFINE_GETBY (hosts, dns, host, addr)
+DEFINE_GETBY (hosts, dns, host, name)
+DEFINE_GETBY (hosts, dns, host, name2)
+DEFINE_GETBY (hosts, dns, host, name3)
+
+/* netgroup */
+DEFINE_ENT (netgroup, files, netgr)
+
+/* networks */
+DEFINE_ENT (networks, files, net)
+DEFINE_GETBY (networks, files, net, name)
+DEFINE_GETBY (networks, files, net, addr)
+DEFINE_GETBY (networks, dns, net, name)
+DEFINE_GETBY (networks, dns, net, addr)
+
+/* protocols */
+DEFINE_ENT (protocols, files, proto)
+DEFINE_GETBY (protocols, files, proto, name)
+DEFINE_GETBY (protocols, files, proto, number)
+
+/* passwd */
+DEFINE_ENT (passwd, files, pw)
+DEFINE_GET (passwd, files, pwnam)
+DEFINE_GET (passwd, files, pwuid)
+
+/* rpc */
+DEFINE_ENT (rpc, files, rpc)
+DEFINE_GETBY (rpc, files, rpc, name)
+DEFINE_GETBY (rpc, files, rpc, number)
+
+/* services */
+DEFINE_ENT (services, files, serv)
+DEFINE_GETBY (services, files, serv, name)
+DEFINE_GETBY (services, files, serv, port)
+
+/* shadow */
+DEFINE_ENT (shadow, files, sp)
+DEFINE_GET (shadow, files, spnam)
Index: libc/nss/getent.c
===================================================================
--- libc/nss/getent.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nss/getent.c	(.../trunk)	(revision 8411)
@@ -38,6 +38,7 @@
 #include <netinet/ether.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
+#include <gnu/option-groups.h>
 
 /* Get libc version number.  */
 #include <version.h>
@@ -77,7 +78,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "getent (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "getent %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
@@ -86,6 +87,7 @@
   fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
 }
 
+#if __OPTION_EGLIBC_DB_ALIASES
 /* This is for aliases */
 static inline void
 print_aliases (struct aliasent *alias)
@@ -130,7 +132,9 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_DB_ALIASES */
 
+#if __OPTION_EGLIBC_INET
 /* This is for ethers */
 static int
 ethers_keys (int number, char *key[])
@@ -174,6 +178,7 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_INET */
 
 /* This is for group */
 static inline void
@@ -232,6 +237,7 @@
   return result;
 }
 
+#if __OPTION_EGLIBC_INET
 /* This is for hosts */
 static void
 print_hosts (struct hostent *host)
@@ -481,6 +487,7 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_INET */
 
 /* Now is all for passwd */
 static inline void
@@ -533,6 +540,7 @@
   return result;
 }
 
+#if __OPTION_EGLIBC_INET
 /* This is for protocols */
 static inline void
 print_protocols (struct protoent *proto)
@@ -684,6 +692,7 @@
 
   return result;
 }
+#endif /* __OPTION_EGLIBC_INET */
 
 /* This is for shadow */
 static void
@@ -750,19 +759,32 @@
   } databases[] =
   {
 #define D(name) { #name, name ## _keys },
-D(ahosts)
-D(ahostsv4)
-D(ahostsv6)
-D(aliases)
-D(ethers)
+
+#if __OPTION_EGLIBC_INET
+#define DN(name) D(name)
+#else
+#define DN(name)
+#endif
+
+#if __OPTION_EGLIBC_DB_ALIASES
+#define DA(name) D(name)
+#else
+#define DA(name)
+#endif
+
+DN(ahosts)
+DN(ahostsv4)
+DN(ahostsv6)
+DA(aliases)
+DN(ethers)
 D(group)
-D(hosts)
-D(netgroup)
-D(networks)
+DN(hosts)
+DN(netgroup)
+DN(networks)
 D(passwd)
-D(protocols)
-D(rpc)
-D(services)
+DN(protocols)
+DN(rpc)
+DN(services)
 D(shadow)
 #undef D
     { NULL, NULL }
@@ -841,7 +863,7 @@
 
 	  fprintf (fp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO);
 
 	  if (fclose (fp) == 0)
 	    return doc;
Index: libc/Makeconfig
===================================================================
--- libc/Makeconfig	(.../fsf/trunk)	(revision 8411)
+++ libc/Makeconfig	(.../trunk)	(revision 8411)
@@ -552,18 +552,26 @@
 $(subst $(empty) ,:,$(strip $(patsubst -Wl$(comma)-rpath-link=%, %,\
 				       $(filter -Wl$(comma)-rpath-link=%,\
 						$(sysdep-LDFLAGS)))))
-run-program-prefix = $(if $(filter $(notdir $(built-program-file)),\
-				   $(tests-static) $(xtests-static)),, \
-			  $(elf-objpfx)$(rtld-installed-name) \
-			  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)))
+# Never use $(run-via-rtld-prefix) for the statically-linked %-bp test
+# programs, or for tests listed in tests-static or xtests-static.
+run-via-rtld-prefix =							      \
+  $(if $(strip $(filter $(notdir $(built-program-file)),		      \
+			$(tests-static) $(xtests-static))		      \
+	       $(filter %-bp,$(built-program-file))),,			      \
+       $(elf-objpfx)$(rtld-installed-name)				      \
+	 --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)))
 else
-run-program-prefix =
+run-via-rtld-prefix =
 endif
-# Never use $(run-program-prefix) for the statically-linked %-bp test programs
-built-program-cmd = $(patsubst %,$(run-program-prefix),\
-			$(filter-out %-bp,$(built-program-file))) \
-		    $(built-program-file)
+run-program-prefix = $(cross-test-wrapper) $($*-WRAPPER) \
+	             $(run-via-rtld-prefix)
+built-program-cmd = $(cross-test-wrapper) $($*-WRAPPER) \
+		    $(run-via-rtld-prefix) $(built-program-file)
 
+# Same as built-program-cmd, but without the cross-test-wrapper.  Used 
+# to run programs from the test machine, as in nptl/tst-cancel7.
+local-built-program-cmd = $(run-via-rtld-prefix) $(built-program-file)
+
 ifndef LD
 LD := ld -X
 endif
@@ -912,6 +920,24 @@
 endif
 endif
 
+# Generate a header file that #defines preprocessor symbols indicating
+# which option groups are enabled.  Note that the option-groups.config file
+# may not exist at all.
+before-compile += $(common-objpfx)gnu/option-groups.h
+common-generated += gnu/option-groups.h gnu/option-groups.stmp
+headers += gnu/option-groups.h
+$(common-objpfx)gnu/option-groups.h: $(common-objpfx)gnu/option-groups.stmp; @:
+$(common-objpfx)gnu/option-groups.stmp:					\
+		$(..)scripts/option-groups.awk				\
+		$(..)option-groups.defaults				\
+		$(wildcard $(common-objpfx)option-groups.config)
+	$(make-target-directory)
+	@rm -f ${@:stmp=T} $@
+	LC_ALL=C $(AWK) -f $^ > ${@:stmp=T}
+	$(move-if-change) ${@:stmp=T} ${@:stmp=h}
+	touch $@
+
+
 # These are the subdirectories containing the library source.  The order
 # is more or less arbitrary.  The sorting step will take care of the
 # dependencies.
Index: libc/string/tst-strxfrm2.c
===================================================================
--- libc/string/tst-strxfrm2.c	(.../fsf/trunk)	(revision 8411)
+++ libc/string/tst-strxfrm2.c	(.../trunk)	(revision 8411)
@@ -1,6 +1,7 @@
 #include <locale.h>
 #include <stdio.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 static int
 do_test (void)
@@ -38,6 +39,7 @@
       res = 1;
     }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
     {
       puts ("setlocale failed");
@@ -75,6 +77,7 @@
 	  res = 1;
 	}
     }
+#endif
 
   return res;
 }
Index: libc/string/strerror_l.c
===================================================================
--- libc/string/strerror_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/string/strerror_l.c	(.../trunk)	(revision 8411)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
+#include <gnu/option-groups.h>
 
 
 static __thread char *last_value;
@@ -30,10 +31,14 @@
 static const char *
 translate (const char *str, locale_t loc)
 {
+#if __OPTION_EGLIBC_LOCALE_CODE
   locale_t oldloc = __uselocale (loc);
   const char *res = _(str);
   __uselocale (oldloc);
   return res;
+#else
+  return str;
+#endif
 }
 
 
Index: libc/string/strxfrm_l.c
===================================================================
--- libc/string/strxfrm_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/string/strxfrm_l.c	(.../trunk)	(revision 8411)
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
+#include <gnu/option-groups.h>
 
 #ifndef STRING_TYPE
 # define STRING_TYPE char
@@ -87,7 +88,11 @@
 STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
 {
   struct locale_data *current = l->__locales[LC_COLLATE];
+#if __OPTION_EGLIBC_LOCALE_CODE
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+#else
+  const uint_fast32_t nrules = 0;
+#endif
   /* We don't assign the following values right away since it might be
      unnecessary in case there are no rules.  */
   const unsigned char *rulesets;
Index: libc/string/strcoll_l.c
===================================================================
--- libc/string/strcoll_l.c	(.../fsf/trunk)	(revision 8411)
+++ libc/string/strcoll_l.c	(.../trunk)	(revision 8411)
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 #ifndef STRING_TYPE
 # define STRING_TYPE char
@@ -49,7 +50,11 @@
      __locale_t l;
 {
   struct locale_data *current = l->__locales[LC_COLLATE];
+#if __OPTION_EGLIBC_LOCALE_CODE
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+#else
+  const uint_fast32_t nrules = 0;
+#endif
   /* We don't assign the following values right away since it might be
      unnecessary in case there are no rules.  */
   const unsigned char *rulesets;
Index: libc/string/Makefile
===================================================================
--- libc/string/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/string/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for string portion of library.
 #
+include ../option-groups.mak
+
 subdir	:= string
 
 headers	:= string.h strings.h memory.h endian.h bits/endian.h \
@@ -38,10 +40,12 @@
 		   $(addprefix argz-,append count create ctsep next	\
 			             delete extract insert stringify	\
 				     addsep replace)			\
-		   envz basename					\
+		   basename						\
 		   strcoll_l strxfrm_l string-inlines memrchr		\
 		   xpg-strerror strerror_l
 
+routines-$(OPTION_EGLIBC_ENVZ) += envz 
+
 # Gcc internally generates calls to unbounded memcpy and memset
 # for -fbounded-pointer compiles.  Glibc uses memchr for explicit checks.
 o-objects.ob	:= memcpy.o memset.o memchr.o
@@ -52,15 +56,19 @@
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
-		   tst-strtok tst-strxfrm bug-strcoll1 tst-strfry	\
+		   tst-strtok tst-strfry	\
 		   bug-strtok1 $(addprefix test-,$(strop-tests))	\
-		   bug-envz1 tst-strxfrm2 tst-endian tst-svc2
+		   tst-strxfrm2 tst-endian tst-svc2
+tests-$(OPTION_EGLIBC_ENVZ) += bug-envz1 
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+		+= tst-strxfrm bug-strcoll1
 distribute	:= memcopy.h pagecopy.h tst-svc.expect test-string.h	\
 		   str-two-way.h
 
 
 include ../Rules
 
+
 tester-ENV = LANGUAGE=C
 inl-tester-ENV = LANGUAGE=C
 noinl-tester-ENV = LANGUAGE=C
@@ -74,10 +82,10 @@
 CFLAGS-test-ffs.c = -fno-builtin
 CFLAGS-tst-inlcall.c = -fno-builtin
 
-ifeq ($(cross-compiling),no)
+# eglibc: ifeq ($(cross-compiling),no)
 tests: $(objpfx)tst-svc.out
 $(objpfx)tst-svc.out: tst-svc.input $(objpfx)tst-svc
 	GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \
 	  $(built-program-cmd) < $(word 1,$^) > $@
 	@cmp tst-svc.expect $(objpfx)tst-svc.out
-endif
+# eglibc: endif
Index: libc/string/tst-strxfrm.c
===================================================================
--- libc/string/tst-strxfrm.c	(.../fsf/trunk)	(revision 8411)
+++ libc/string/tst-strxfrm.c	(.../trunk)	(revision 8411)
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <gnu/option-groups.h>
 
 
 char const string[] = "";
@@ -64,8 +65,10 @@
   int result = 0;
 
   result |= test ("C");
+#if __OPTION_EGLIBC_LOCALE_CODE
   result |= test ("en_US.ISO-8859-1");
   result |= test ("de_DE.UTF-8");
+#endif
 
   return result;
 }
Index: libc/hesiod/Makefile
===================================================================
--- libc/hesiod/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/hesiod/Makefile	(.../trunk)	(revision 8411)
@@ -19,12 +19,14 @@
 #
 #	Sub-makefile for hesiod portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= hesiod
 
 distribute := hesiod.h hesiod_p.h README.hesiod nss_hesiod/nss_hesiod.h
 
-extra-libs := libnss_hesiod
-extra-libs-others = $(extra-libs)
+extra-libs-$(OPTION_EGLIBC_INET) += libnss_hesiod
+extra-libs-others-y += $(extra-libs-y)
 
 subdir-dirs = nss_hesiod
 vpath %.c nss_hesiod
Index: libc/wctype/Makefile
===================================================================
--- libc/wctype/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/wctype/Makefile	(.../trunk)	(revision 8411)
@@ -19,13 +19,19 @@
 #
 #	Sub-makefile for wctype portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= wctype
 
 headers		:= wctype.h
 distribute	:= wchar-lookup.h
-routines	:= wcfuncs wctype iswctype wctrans towctrans \
-		   wcfuncs_l wctype_l iswctype_l wctrans_l towctrans_l
+routines 	:= wctrans towctrans towctrans_l
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+		:= wcfuncs wctype iswctype \
+		   wcfuncs_l wctype_l iswctype_l wctrans_l
 
-tests	:= test_wctype test_wcfuncs bug-wctypeh
+tests	:= 
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+     += test_wctype test_wcfuncs bug-wctypeh
 
 include ../Rules
Index: libc/iconv/iconvconfig.c
===================================================================
--- libc/iconv/iconvconfig.c	(.../fsf/trunk)	(revision 8411)
+++ libc/iconv/iconvconfig.c	(.../trunk)	(revision 8411)
@@ -373,13 +373,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -391,7 +394,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "iconvconfig (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "iconvconfig %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/iconv/gconv_db.c
===================================================================
--- libc/iconv/gconv_db.c	(.../fsf/trunk)	(revision 8411)
+++ libc/iconv/gconv_db.c	(.../trunk)	(revision 8411)
@@ -27,6 +27,7 @@
 #include <sys/param.h>
 #include <bits/libc-lock.h>
 #include <locale/localeinfo.h>
+#include <gnu/option-groups.h>
 
 #include <dlfcn.h>
 #include <gconv_int.h>
@@ -827,9 +828,11 @@
 /* Free all resources if necessary.  */
 libc_freeres_fn (free_mem)
 {
+#if __OPTION_EGLIBC_LOCALE_CODE
   /* First free locale memory.  This needs to be done before freeing derivations,
      as ctype cleanup functions dereference steps arrays which we free below.  */
   _nl_locale_subfreeres ();
+#endif
 
   /* finddomain.c has similar problem.  */
   extern void _nl_finddomain_subfreeres (void) attribute_hidden;
Index: libc/iconv/Makefile
===================================================================
--- libc/iconv/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/iconv/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for iconv.
 #
+include ../option-groups.mak
+
 subdir	:= iconv
 
 include ../Makeconfig
@@ -70,6 +72,9 @@
 CPPFLAGS-strtab = -DNOT_IN_libc
 CPPFLAGS-charmap = -DNOT_IN_libc
 CPPFLAGS-charmap-dir = -DNOT_IN_libc
+ifneq (y,$(OPTION_EGLIBC_SPAWN))
+CPPFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
+endif
 
 include ../Rules
 
@@ -79,9 +84,9 @@
 $(objpfx)iconv_prog: $(iconv_prog-modules:%=$(objpfx)%.o)
 $(objpfx)iconvconfig: $(iconvconfig-modules:%=$(objpfx)%.o)
 
-ifneq ($(cross-compiling),yes)
+# eglibc: ifneq ($(cross-compiling),yes)
 xtests: test-iconvconfig
-endif
+# eglibc: endif
 
 .PHONY: test-iconvconfig
 test-iconvconfig: /dev/null $(objpfx)iconvconfig
Index: libc/iconv/iconv_prog.c
===================================================================
--- libc/iconv/iconv_prog.c	(.../fsf/trunk)	(revision 8411)
+++ libc/iconv/iconv_prog.c	(.../trunk)	(revision 8411)
@@ -36,6 +36,7 @@
 #ifdef _POSIX_MAPPED_FILES
 # include <sys/mman.h>
 #endif
+#include <gnu/option-groups.h>
 #include <charmap.h>
 #include <gconv_int.h>
 #include "iconv_prog.h"
@@ -222,10 +223,17 @@
 	      bool to_wrong =
 		(iconv_open (to_code, "UTF-8") == (iconv_t) -1
 		 && errno == EINVAL);
+#if __OPTION_EGLIBC_LOCALE_CODE
 	      const char *from_pretty =
 		(from_code[0] ? from_code : nl_langinfo (CODESET));
 	      const char *to_pretty =
 		(orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET));
+#else
+	      const char *from_pretty =
+		(from_code[0] ? from_code : "ANSI_X3.4-1968");
+	      const char *to_pretty =
+                 (orig_to_code[0] ? orig_to_code : "ANSI_X3.4-1968");
+#endif
 
 	      if (from_wrong)
 		{
@@ -401,13 +409,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -419,7 +430,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "iconv (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "iconv %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/iconv/gconv_trans.c
===================================================================
--- libc/iconv/gconv_trans.c	(.../fsf/trunk)	(revision 8411)
+++ libc/iconv/gconv_trans.c	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
+#include <gnu/option-groups.h>
 
 #include <bits/libc-lock.h>
 #include "gconv_int.h"
@@ -60,6 +61,7 @@
     PTR_DEMANGLE (fct);
 #endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   /* If there is no transliteration information in the locale don't do
      anything and return the error.  */
   size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_TAB_SIZE);
@@ -195,6 +197,7 @@
              sorted.  */
 	  break;
     }
+#endif
 
   /* One last chance: use the default replacement.  */
   if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN) != 0)
Index: libc/grp/tst_fgetgrent.sh
===================================================================
--- libc/grp/tst_fgetgrent.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/grp/tst_fgetgrent.sh	(.../trunk)	(revision 8411)
@@ -22,21 +22,26 @@
 common_objpfx=$1; shift
 elf_objpfx=$1; shift
 rtld_installed_name=$1; shift
+cross_test_wrapper="$1"; shift
 
 testout=${common_objpfx}/grp/tst_fgetgrent.out
 library_path=${common_objpfx}
 
 result=0
 
+${cross_test_wrapper} \
 ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 ${common_objpfx}grp/tst_fgetgrent 0 > ${testout} || result=1
 
+${cross_test_wrapper} \
 ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 ${common_objpfx}grp/tst_fgetgrent 1 >> ${testout} || result=1
 
+${cross_test_wrapper} \
 ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 ${common_objpfx}grp/tst_fgetgrent 2 >> ${testout} || result=1
 
+${cross_test_wrapper} \
 ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 ${common_objpfx}grp/tst_fgetgrent 3 >> ${testout} || result=1
 
Index: libc/grp/Makefile
===================================================================
--- libc/grp/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/grp/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for grp portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= grp
 headers := grp.h
 
@@ -31,6 +33,9 @@
 include ../Makeconfig
 
 tests := testgrp
+ifneq (y,$(OPTION_EGLIBC_NSSWITCH))
+LDLIBS-testgrp += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
+endif
 
 ifeq (yes,$(build-shared))
 test-srcs :=  tst_fgetgrent
@@ -47,25 +52,27 @@
 
 ifeq ($(have-thread-library),yes)
 
-CFLAGS-getgrgid_r.c = -DUSE_NSCD=1 -fexceptions
-CFLAGS-getgrnam_r.c = -DUSE_NSCD=1 -fexceptions
+OPTION_EGLIBC_INET-CFLAGS-$(OPTION_EGLIBC_INET) = -DUSE_NSCD=1
+
+CFLAGS-getgrgid_r.c = $(OPTION_EGLIBC_INET-CFLAGS-y) -fexceptions
+CFLAGS-getgrnam_r.c = $(OPTION_EGLIBC_INET-CFLAGS-y) -fexceptions
 CFLAGS-getgrent_r.c = -fexceptions
 CFLAGS-getgrent.c = -fexceptions
 CFLAGS-fgetgrent.c = -fexceptions
 CFLAGS-fgetgrent_r.c = -fexceptions -D_IO_MTSAFE_IO
 CFLAGS-putgrent.c = -fexceptions -D_IO_MTSAFE_IO
-CFLAGS-initgroups.c = -DUSE_NSCD=1 -fexceptions
+CFLAGS-initgroups.c = $(OPTION_EGLIBC_INET-CFLAGS-y) -fexceptions
 CFLAGS-getgrgid.c = -fexceptions
 
 endif
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 # tst_fgetgrent currently only works with shared libraries
 ifeq (yes,$(build-shared))
 tests: $(objpfx)tst_fgetgrent.out
 $(objpfx)tst_fgetgrent.out: tst_fgetgrent.sh $(objpfx)tst_fgetgrent
 	$(SHELL) -e tst_fgetgrent.sh $(common-objpfx) $(elf-objpfx) \
-		 $(rtld-installed-name)
+		 $(rtld-installed-name) "$(cross-test-wrapper)"
 
 endif
-endif
+# eglibc: endif
Index: libc/math/Makefile
===================================================================
--- libc/math/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/math/Makefile	(.../trunk)	(revision 8411)
@@ -21,6 +21,8 @@
 
 subdir		:= math
 
+include ../option-groups.mak
+
 # Installed header files.
 headers		:= math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \
 		   bits/huge_valf.h bits/huge_vall.h bits/inf.h bits/nan.h \
@@ -35,8 +37,8 @@
 
 # Build the -lm library.
 
-extra-libs	:= libm
-extra-libs-others = $(extra-libs)
+extra-libs-$(OPTION_EGLIBC_LIBM) := libm
+extra-libs-others-$(OPTION_EGLIBC_LIBM) = $(extra-libs-$(OPTION_EGLIBC_LIBM))
 
 libm-support = k_standard s_lib_version s_matherr s_signgam		\
 	       fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg		\
Index: libc/option-groups.mak
===================================================================
--- libc/option-groups.mak	(.../fsf/trunk)	(revision 0)
+++ libc/option-groups.mak	(.../trunk)	(revision 8411)
@@ -0,0 +1,40 @@
+# Setup file for subdirectory Makefiles that define EGLIBC option groups.
+
+# EGLIBC shouldn't need to override this.  However, the
+# cross-build-friendly localedef includes this makefile to get option
+# group variable definitions; it uses a single build tree for all the
+# multilibs, and needs to be able to specify a different option group
+# configuration file for each multilib.
+option_group_config_file ?= $(objdir)/option-groups.config
+
+# Read the default settings for all options.
+# We're included before ../Rules, so we can't assume $(..) is set.
+include $(firstword $(..) ../)option-groups.defaults
+
+# Read the developer's option group selections, overriding the
+# defaults from option-groups.defaults.
+-include $(option_group_config_file)
+
+# $(call option-disabled, VAR) is 'y' if VAR is not 'y', or 'n' otherwise.
+# VAR should be a variable name, not a variable reference; this is
+# less general, but more terse for the intended use.
+# You can use it to add a file to a list if an option group is
+# disabled, like this:
+#   routines-$(call option-disabled, OPTION_POSIX_C_LANG_WIDE_CHAR) += ...
+define option-disabled
+$(firstword $(subst y,n,$(filter y,$($(strip $(1))))) y)
+endef
+
+# Establish 'routines-y', etc. as simply-expanded variables.
+aux-y	       	    :=
+extra-libs-others-y :=
+extra-libs-y   	    :=
+extra-objs-y   	    :=
+install-bin-y  	    :=
+install-others-y    :=
+install-sbin-y 	    :=
+others-y       	    :=
+routines-y     	    :=
+test-srcs-y    	    :=   
+tests-y        	    :=
+xtests-y       	    :=
Index: libc/locale/xlocale.c
===================================================================
--- libc/locale/xlocale.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/xlocale.c	(.../trunk)	(revision 8411)
@@ -19,6 +19,7 @@
    02111-1307 USA.  */
 
 #include <locale.h>
+#include <gnu/option-groups.h>
 #include "localeinfo.h"
 
 #define DEFINE_CATEGORY(category, category_name, items, a) \
@@ -26,6 +27,19 @@
 #include "categories.def"
 #undef	DEFINE_CATEGORY
 
+/* If the locale support code isn't enabled, don't generate strong
+   reference to the C locale_data structures here; let the Makefile
+   decide which ones to include.  (In the static linking case, the
+   strong reference to the 'class', 'toupper', and 'tolower' tables
+   will cause C-ctype.o to be brought in, as it should be, even when
+   the reference to _nl_C_LC_CTYPE will be weak.)  */
+#if ! __OPTION_EGLIBC_LOCALE_CODE
+# define DEFINE_CATEGORY(category, category_name, items, a) \
+  weak_extern (_nl_C_##category)
+# include "categories.def"
+# undef	DEFINE_CATEGORY
+#endif
+ 
 /* Defined in locale/C-ctype.c.  */
 extern const char _nl_C_LC_CTYPE_class[] attribute_hidden;
 extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
@@ -53,3 +67,26 @@
     .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128,
     .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128
   };
+
+
+#if ! __OPTION_EGLIBC_LOCALE_CODE
+/* When locale code is enabled, these are each defined in the
+   appropriate lc-CATEGORY.c file, so that static links (when __thread
+   is supported) bring in only those lc-CATEGORY.o files for
+   categories the program actually uses; look for NL_CURRENT_INDIRECT
+   in localeinfo.h.
+
+   When locale code is disabled, the _nl_C_CATEGORY objects are the
+   only possible referents.  At the moment, there isn't a way to get
+   __OPTION_EGLIBC_LOCALE_CODE defined in every compilation unit that
+   #includes localeinfo.h, so we can't just turn off
+   NL_CURRENT_INDIRECT.  So we'll define the _nl_current_CATEGORY
+   pointers here.  */
+#if defined (NL_CURRENT_INDIRECT)
+#define DEFINE_CATEGORY(category, category_name, items, a)      \
+  __thread struct locale_data * const *_nl_current_##category   \
+  attribute_hidden = &_nl_C_locobj.__locales[category];
+#include "categories.def"
+#undef DEFINE_CATEGORY
+#endif
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
Index: libc/locale/Makefile
===================================================================
--- libc/locale/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for locales.
 #
+include ../option-groups.mak
+
 subdir	:= locale
 
 headers		= locale.h bits/locale.h langinfo.h xlocale.h
@@ -26,7 +28,7 @@
 		  iso-4217.def weight.h weightwc.h strlen-hash.h elem-hash.h \
 		  indigits.h indigitswc.h outdigits.h outdigitswc.h \
 		  coll-lookup.h C-translit.h.in C-translit.h gen-translit.pl \
-		  locarchive.h hashval.h \
+		  locarchive.h hashval.h dummy-setlocale.c \
 		  $(addprefix programs/, \
 			      locale.c localedef.c \
 			      $(localedef-modules:=.c) $(locale-modules:=.c) \
@@ -35,22 +37,36 @@
 			      locfile-kw.gperf locfile-kw.h linereader.h \
 			      locfile.h charmap.h repertoire.h localedef.h \
 			      3level.h charmap-dir.h locarchive.c)
-routines	= setlocale findlocale loadlocale loadarchive \
-		  localeconv nl_langinfo nl_langinfo_l mb_cur_max \
-		  newlocale duplocale freelocale uselocale
-tests		= tst-C-locale
+# catnames is needed by OPTION_EGLIBC_LOCALE_CODE and by the 'intl' code.
+# If we put the latter in an option group, too, we can omit catnames
+# when both option groups are disabled.  libstdc++-v3 needs mb_cur_max.
+routines-y      := catnames mb_cur_max
+routines-$(OPTION_EGLIBC_LOCALE_CODE) \
+		+= setlocale findlocale loadlocale loadarchive \
+		   localeconv nl_langinfo nl_langinfo_l \
+		   newlocale duplocale freelocale uselocale
+ifneq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+routines-y	+= dummy-setlocale
+endif
+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-C-locale
 categories	= ctype messages monetary numeric time paper name \
 		  address telephone measurement identification collate
-aux		= $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \
-		  xlocale localename global-locale coll-lookup
-others		= localedef locale
+# C-messages belongs in an intl option group.
+aux-y		:= C-ctype C-time \
+		   SYS_libc C_name xlocale global-locale coll-lookup
+aux-$(OPTION_EGLIBC_LOCALE_CODE) \
+		+= $(filter-out $(aux-y), \
+	                        $(categories:%=lc-%) $(categories:%=C-%)) \
+	           localename
+others-$(OPTION_EGLIBC_LOCALE_CODE) = localedef locale
 #others-static	= localedef locale
-install-bin	= localedef locale
-extra-objs	= $(localedef-modules:=.o) $(localedef-aux:=.o) \
+install-bin	= $(others-y)
+extra-objs-$(OPTION_EGLIBC_LOCALE_CODE) \
+		= $(localedef-modules:=.o) $(localedef-aux:=.o) \
 		  $(locale-modules:=.o) $(lib-modules:=.o)
 
-extra-libs	= libBrokenLocale
-extra-libs-others = $(extra-libs)
+extra-libs-$(OPTION_EGLIBC_LOCALE_CODE) = libBrokenLocale
+extra-libs-others = $(extra-libs-y)
 
 libBrokenLocale-routines = broken_cur_max
 
@@ -101,6 +117,9 @@
 CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts
 CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts
 CFLAGS-charmap-dir.c = -Wno-write-strings
+ifneq (y,$(OPTION_EGLIBC_SPAWN))
+CFLAGS-charmap-dir.c += -DNO_UNCOMPRESS
+endif
 
 # This makes sure -DNOT_IN_libc is passed for all these modules.
 cpp-srcs-left := $(addsuffix .c,$(localedef-modules) $(localedef-aux) \
Index: libc/locale/catnames.c
===================================================================
--- libc/locale/catnames.c	(.../fsf/trunk)	(revision 0)
+++ libc/locale/catnames.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,48 @@
+/* Copyright (C) 2006  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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include "localeinfo.h"
+
+/* Define an array of category names (also the environment variable names).  */
+const union catnamestr_t _nl_category_names attribute_hidden =
+  {
+    {
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+      category_name,
+#include "categories.def"
+#undef DEFINE_CATEGORY
+    }
+  };
+
+const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
+  {
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+    [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
+#include "categories.def"
+#undef DEFINE_CATEGORY
+  };
+
+/* An array of their lengths, for convenience.  */
+const uint8_t _nl_category_name_sizes[] attribute_hidden =
+  {
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+    [category] = sizeof (category_name) - 1,
+#include "categories.def"
+#undef	DEFINE_CATEGORY
+    [LC_ALL] = sizeof ("LC_ALL") - 1
+  };
Index: libc/locale/C-ctype.c
===================================================================
--- libc/locale/C-ctype.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/C-ctype.c	(.../trunk)	(revision 8411)
@@ -19,8 +19,11 @@
 
 #include "localeinfo.h"
 #include <endian.h>
+#include <gnu/option-groups.h>
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 #include "C-translit.h"
+#endif
 
 /* This table's entries are taken from POSIX.2 Table 2-6
    ``LC_CTYPE Category Definition in the POSIX Locale''.
@@ -647,6 +650,7 @@
     { .word = L'7' },
     { .word = L'8' },
     { .word = L'9' },
+#if __OPTION_EGLIBC_LOCALE_CODE
     /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
     { .word = NTRANSLIT },
     /* _NL_CTYPE_TRANSLIT_FROM_IDX */
@@ -657,6 +661,22 @@
     { .wstr = translit_to_idx },
     /* _NL_CTYPE_TRANSLIT_TO_TBL */
     { .wstr = (uint32_t *) translit_to_tbl },
+#else
+    /* If the locale code isn't enabled, we don't have the
+       transliteration code in iconv/gconv_trans.c anyway, so there's
+       no need for the transliteration tables here.  We'll fall back
+       on the default missing replacement, '?'.  */
+    /* _NL_CTYPE_TRANSLIT_TAB_SIZE */
+    { .word = 0 },
+    /* _NL_CTYPE_TRANSLIT_FROM_IDX */
+    { .wstr = NULL },
+    /* _NL_CTYPE_TRANSLIT_FROM_TBL */
+    { .wstr = NULL },
+    /* _NL_CTYPE_TRANSLIT_TO_IDX */
+    { .wstr = NULL },
+    /* _NL_CTYPE_TRANSLIT_TO_TBL */
+    { .wstr = NULL },
+#endif
     /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN */
     { .word = 1 },
     /* _NL_CTYPE_TRANSLIT_DEFAULT_MISSING */
Index: libc/locale/dummy-setlocale.c
===================================================================
--- libc/locale/dummy-setlocale.c	(.../fsf/trunk)	(revision 0)
+++ libc/locale/dummy-setlocale.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,33 @@
+/* Copyright (C) 2006  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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <locale.h>
+
+char *
+setlocale (int category, const char *locale)
+{
+  if (! locale
+      || locale[0] == '\0'
+      || strcmp (locale, "C") == 0
+      || strcmp (locale, "POSIX") == 0)
+    return (char *) "C";
+  else
+    return NULL;
+}
+libc_hidden_def (setlocale)
Index: libc/locale/setlocale.c
===================================================================
--- libc/locale/setlocale.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/setlocale.c	(.../trunk)	(revision 8411)
@@ -66,36 +66,6 @@
 #endif
 
 
-/* Define an array of category names (also the environment variable names).  */
-const union catnamestr_t _nl_category_names attribute_hidden =
-  {
-    {
-#define DEFINE_CATEGORY(category, category_name, items, a) \
-      category_name,
-#include "categories.def"
-#undef DEFINE_CATEGORY
-    }
-  };
-
-const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
-  {
-#define DEFINE_CATEGORY(category, category_name, items, a) \
-    [category] = offsetof (union catnamestr_t, CATNAMEMF (__LINE__)),
-#include "categories.def"
-#undef DEFINE_CATEGORY
-  };
-
-/* An array of their lengths, for convenience.  */
-const uint8_t _nl_category_name_sizes[] attribute_hidden =
-  {
-#define DEFINE_CATEGORY(category, category_name, items, a) \
-    [category] = sizeof (category_name) - 1,
-#include "categories.def"
-#undef	DEFINE_CATEGORY
-    [LC_ALL] = sizeof ("LC_ALL") - 1
-  };
-
-
 #ifdef NL_CURRENT_INDIRECT
 # define WEAK_POSTLOAD(postload) weak_extern (postload)
 #else
Index: libc/locale/programs/ld-numeric.c
===================================================================
--- libc/locale/programs/ld-numeric.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-numeric.c	(.../trunk)	(revision 8411)
@@ -133,61 +133,16 @@
 		const char *output_path)
 {
   struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
-  struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_NUMERIC);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) (numeric->decimal_point ?: "");
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) (numeric->thousands_sep ?: "");
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = numeric->grouping;
-  iov[cnt].iov_len = numeric->grouping_len;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-
-  /* Align following data */
-  iov[cnt].iov_base = (void *) "\0\0";
-  iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
-  idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) &numeric->decimal_point_wc;
-  iov[cnt].iov_len = sizeof (uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &numeric->thousands_sep_wc;
-  iov[cnt].iov_len = sizeof (uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-
-  assert (cnt + 1 == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC));
-
-  write_locale_data (output_path, LC_NUMERIC, "LC_NUMERIC",
-		     3 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC));
+  add_locale_string (&file, numeric->decimal_point ?: "");
+  add_locale_string (&file, numeric->thousands_sep ?: "");
+  add_locale_raw_data (&file, numeric->grouping, numeric->grouping_len);
+  add_locale_uint32 (&file, numeric->decimal_point_wc);
+  add_locale_uint32 (&file, numeric->thousands_sep_wc);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_NUMERIC, "LC_NUMERIC", &file);
 }
 
 
Index: libc/locale/programs/3level.h
===================================================================
--- libc/locale/programs/3level.h	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/3level.h	(.../trunk)	(revision 8411)
@@ -56,9 +56,7 @@
   size_t level3_alloc;
   size_t level3_size;
   ELEMENT *level3;
-  /* Compressed representation.  */
   size_t result_size;
-  char *result;
 };
 
 /* Initialize.  Assumes t->p and t->q have already been set.  */
@@ -208,7 +206,7 @@
 #ifndef NO_FINALIZE
 /* Finalize and shrink.  */
 static void
-CONCAT(TABLE,_finalize) (struct TABLE *t)
+CONCAT(add_locale_,TABLE) (struct locale_file *file, struct TABLE *t)
 {
   size_t i, j, k;
   uint32_t reorder3[t->level3_size];
@@ -263,14 +261,12 @@
     if (t->level1[i] != EMPTY)
       t->level1[i] = reorder2[t->level1[i]];
 
-  /* Create and fill the resulting compressed representation.  */
   last_offset =
     5 * sizeof (uint32_t)
     + t->level1_size * sizeof (uint32_t)
     + (t->level2_size << t->q) * sizeof (uint32_t)
     + (t->level3_size << t->p) * sizeof (ELEMENT);
   t->result_size = (last_offset + 3) & ~3ul;
-  t->result = (char *) xmalloc (t->result_size);
 
   level1_offset =
     5 * sizeof (uint32_t);
@@ -282,30 +278,35 @@
     + t->level1_size * sizeof (uint32_t)
     + (t->level2_size << t->q) * sizeof (uint32_t);
 
-  ((uint32_t *) t->result)[0] = t->q + t->p;
-  ((uint32_t *) t->result)[1] = t->level1_size;
-  ((uint32_t *) t->result)[2] = t->p;
-  ((uint32_t *) t->result)[3] = (1 << t->q) - 1;
-  ((uint32_t *) t->result)[4] = (1 << t->p) - 1;
+  start_locale_structure (file);
+  add_locale_uint32 (file, t->q + t->p);
+  add_locale_uint32 (file, t->level1_size);
+  add_locale_uint32 (file, t->p);
+  add_locale_uint32 (file, (1 << t->q) - 1);
+  add_locale_uint32 (file, (1 << t->p) - 1);
 
   for (i = 0; i < t->level1_size; i++)
-    ((uint32_t *) (t->result + level1_offset))[i] =
-      (t->level1[i] == EMPTY
+    add_locale_uint32
+      (file,
+       t->level1[i] == EMPTY
        ? 0
        : (t->level1[i] << t->q) * sizeof (uint32_t) + level2_offset);
 
   for (i = 0; i < (t->level2_size << t->q); i++)
-    ((uint32_t *) (t->result + level2_offset))[i] =
-      (t->level2[i] == EMPTY
+    add_locale_uint32
+      (file,
+       t->level2[i] == EMPTY
        ? 0
        : (t->level2[i] << t->p) * sizeof (ELEMENT) + level3_offset);
 
-  for (i = 0; i < (t->level3_size << t->p); i++)
-    ((ELEMENT *) (t->result + level3_offset))[i] = t->level3[i];
+  if (sizeof (ELEMENT) == 1)
+    add_locale_raw_data (file, t->level3, t->level3_size << t->p);
+  else if (sizeof (ELEMENT) == sizeof (uint32_t))
+    add_locale_uint32_array (file, (uint32_t *) t->level3,
+			     t->level3_size << t->p);
+  align_locale_data (file, 4);
+  end_locale_structure (file);
 
-  if (last_offset < t->result_size)
-    memset (t->result + last_offset, 0, t->result_size - last_offset);
-
   if (t->level1_alloc > 0)
     free (t->level1);
   if (t->level2_alloc > 0)
Index: libc/locale/programs/ld-paper.c
===================================================================
--- libc/locale/programs/ld-paper.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-paper.c	(.../trunk)	(revision 8411)
@@ -121,40 +121,13 @@
 	      const char *output_path)
 {
   struct locale_paper_t *paper = locale->categories[LC_PAPER].paper;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_PAPER)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_PAPER);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_PAPER);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[cnt - 2].iov_len + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = &paper->height;
-  iov[cnt].iov_len = 4;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = &paper->width;
-  iov[cnt].iov_len = 4;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER));
-
-  write_locale_data (output_path, LC_PAPER, "LC_PAPER",
-		     2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_PAPER));
+  add_locale_uint32 (&file, paper->height);
+  add_locale_uint32 (&file, paper->width);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_PAPER, "LC_PAPER", &file);
 }
 
 
Index: libc/locale/programs/locfile.c
===================================================================
--- libc/locale/programs/locfile.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/locfile.c	(.../trunk)	(revision 8411)
@@ -28,14 +28,19 @@
 #include <unistd.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <assert.h>
+#include <wchar.h>
 
 #include "../../crypt/md5.h"
 #include "localedef.h"
+#include "localeinfo.h"
 #include "locfile.h"
 #include "simple-hash.h"
 
 #include "locfile-kw.h"
 
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
 
 /* Temporary storage of the locale data before writing it to the archive.  */
 static locale_data_t to_archive;
@@ -534,17 +539,188 @@
   return ret;
 }
 
+/* True if the locale files use the opposite endianness to the
+   machine running localedef.  */
+int swap_endianness_p;
 
-/* Write a locale file, with contents given by N_ELEM and VEC.  */
+/* The target's value of __align__(uint32_t) - 1.  */
+unsigned int uint32_align_mask = 3;
+
+/* When called outside a start_locale_structure()/end_locale_structure()
+   or start_locale_prelude()/end_locale_prelude() block, record that the
+   next byte in FILE's obstack will be the first byte of a new element.
+   Do likewise for the first call inside a start_locale_structure()/
+   end_locale_structure() block.  */
+static inline void
+record_offset (struct locale_file *file)
+{
+  if (file->structure_stage < 2)
+    {
+      assert (file->next_element < file->n_elements);
+      file->offsets[file->next_element++]
+	= (obstack_object_size (&file->data)
+	   + (file->n_elements + 2) * sizeof (uint32_t));
+      if (file->structure_stage == 1)
+	file->structure_stage = 2;
+    }
+}
+
+/* Initialize FILE for a new output file.  N_ELEMENTS is the number
+   of elements in the file.  */
 void
+init_locale_data (struct locale_file *file, size_t n_elements)
+{
+  file->n_elements = n_elements;
+  file->next_element = 0;
+  file->offsets = xmalloc (sizeof (uint32_t) * n_elements);
+  obstack_init (&file->data);
+  file->structure_stage = 0;
+}
+
+/* Align the size of FILE's obstack object to BOUNDARY bytes.  */
+void
+align_locale_data (struct locale_file *file, size_t boundary)
+{
+  size_t size = -obstack_object_size (&file->data) & (boundary - 1);
+  obstack_blank (&file->data, size);
+  memset (obstack_next_free (&file->data) - size, 0, size);
+}
+
+/* Record that FILE's next element contains no data.  */
+void
+add_locale_empty (struct locale_file *file)
+{
+  record_offset (file);
+}
+
+/* Record that FILE's next element consists of SIZE bytes starting at DATA.  */
+void
+add_locale_raw_data (struct locale_file *file, const void *data, size_t size)
+{
+  record_offset (file);
+  obstack_grow (&file->data, data, size);
+}
+
+/* Finish the current object on OBSTACK and use it as the data for FILE's
+   next element.  */
+void
+add_locale_raw_obstack (struct locale_file *file, struct obstack *obstack)
+{
+  size_t size = obstack_object_size (obstack);
+  record_offset (file);
+  obstack_grow (&file->data, obstack_finish (obstack), size);
+}
+
+/* Use STRING as FILE's next element.  */
+void
+add_locale_string (struct locale_file *file, const char *string)
+{
+  record_offset (file);
+  obstack_grow (&file->data, string, strlen (string) + 1);
+}
+
+/* Likewise for wide strings.  */
+void
+add_locale_wstring (struct locale_file *file, const uint32_t *string)
+{
+  add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1);
+}
+
+/* Record that FILE's next element is the 32-bit integer VALUE.  */
+void
+add_locale_uint32 (struct locale_file *file, uint32_t value)
+{
+  align_locale_data (file, sizeof (uint32_t));
+  record_offset (file);
+  value = maybe_swap_uint32 (value);
+  obstack_grow (&file->data, &value, sizeof (value));
+}
+
+/* Record that FILE's next element is an array of N_ELEMS integers
+   starting at DATA.  */
+void
+add_locale_uint32_array (struct locale_file *file,
+			 const uint32_t *data, size_t n_elems)
+{
+  align_locale_data (file, sizeof (uint32_t));
+  record_offset (file);
+  obstack_grow (&file->data, data, n_elems * sizeof (uint32_t));
+  maybe_swap_uint32_obstack (&file->data, n_elems);
+}
+
+/* Record that FILE's next element is the single byte given by VALUE.  */
+void
+add_locale_char (struct locale_file *file, char value)
+{
+  record_offset (file);
+  obstack_1grow (&file->data, value);
+}
+
+/* Start building an element that contains several different pieces of data.
+   Subsequent calls to add_locale_*() will add data to the same element up
+   till the next call to end_locale_structure().  The element's alignment
+   is dictated by the first piece of data added to it.  */
+void
+start_locale_structure (struct locale_file *file)
+{
+  assert (file->structure_stage == 0);
+  file->structure_stage = 1;
+}
+
+/* Finish a structure element that was started by start_locale_structure().
+   Empty structures are OK and behave like add_locale_empty().  */
+void
+end_locale_structure (struct locale_file *file)
+{
+  record_offset (file);
+  assert (file->structure_stage == 2);
+  file->structure_stage = 0;
+}
+
+/* Start building data that goes before the next element's recorded offset.
+   Subsequent calls to add_locale_*() will add data to the file without
+   treating any of it as the start of a new element.  Calling
+   end_locale_prelude() switches back to the usual behavior.  */
+void
+start_locale_prelude (struct locale_file *file)
+{
+  assert (file->structure_stage == 0);
+  file->structure_stage = 3;
+}
+
+/* End a block started by start_locale_prelude().  */
+void
+end_locale_prelude (struct locale_file *file)
+{
+  assert (file->structure_stage == 3);
+  file->structure_stage = 0;
+}
+
+/* Write a locale file, with contents given by FILE.  */
+void
 write_locale_data (const char *output_path, int catidx, const char *category,
-		   size_t n_elem, struct iovec *vec)
+		   struct locale_file *file)
 {
   size_t cnt, step, maxiov;
   int fd;
   char *fname;
   const char **other_paths;
+  uint32_t header[2];
+  size_t n_elem;
+  struct iovec vec[3];
 
+  assert (file->n_elements == file->next_element);
+  header[0] = LIMAGIC (catidx);
+  header[1] = file->n_elements;
+  vec[0].iov_len = sizeof (header);
+  vec[0].iov_base = header;
+  vec[1].iov_len = sizeof (uint32_t) * file->n_elements;
+  vec[1].iov_base = file->offsets;
+  vec[2].iov_len = obstack_object_size (&file->data);
+  vec[2].iov_base = obstack_finish (&file->data);
+  maybe_swap_uint32_array (vec[0].iov_base, 2);
+  maybe_swap_uint32_array (vec[1].iov_base, file->n_elements);
+  n_elem = 3;
   if (! no_archive)
     {
       /* The data will be added to the archive.  For now we simply
Index: libc/locale/programs/ld-name.c
===================================================================
--- libc/locale/programs/ld-name.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-name.c	(.../trunk)	(revision 8411)
@@ -157,60 +157,17 @@
 	     const char *output_path)
 {
   struct locale_name_t *name = locale->categories[LC_NAME].name;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NAME)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_NAME);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_NAME);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_fmt;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_gen;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_mr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_mrs;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_miss;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) name->name_ms;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME));
-
-  write_locale_data (output_path, LC_NAME, "LC_NAME",
-		     2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_NAME));
+  add_locale_string (&file, name->name_fmt);
+  add_locale_string (&file, name->name_gen);
+  add_locale_string (&file, name->name_mr);
+  add_locale_string (&file, name->name_mrs);
+  add_locale_string (&file, name->name_miss);
+  add_locale_string (&file, name->name_ms);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_NAME, "LC_NAME", &file);
 }
 
 
Index: libc/locale/programs/locarchive.c
===================================================================
--- libc/locale/programs/locarchive.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/locarchive.c	(.../trunk)	(revision 8411)
@@ -302,6 +302,7 @@
   struct namehashent *oldnamehashtab;
   struct locrecent *oldlocrectab;
   struct locarhandle new_ah;
+  struct oldlocrecent *oldlocrecarray;
   size_t prefix_len = output_prefix ? strlen (output_prefix) : 0;
   char archivefname[prefix_len + sizeof (ARCHIVE_NAME)];
   char fname[prefix_len + sizeof (ARCHIVE_NAME) + sizeof (".XXXXXX") - 1];
@@ -435,7 +436,7 @@
 				       + head->locrectab_offset);
 
   /* Sort the old locrec table in order of data position.  */
-  struct oldlocrecent oldlocrecarray[head->namehash_size];
+  oldlocrecarray = alloca (sizeof (*oldlocrecarray) * head->namehash_size);
   for (cnt = 0, loccnt = 0; cnt < head->namehash_size; ++cnt)
     if (oldnamehashtab[cnt].locrec_offset != 0)
       {
@@ -1109,9 +1110,9 @@
 	unsigned int nstrings;
 	unsigned int strindex[0];
       } *filedata = data[LC_CTYPE].addr;
+      char *normalized_codeset_name = NULL;
       codeset = (char *) filedata
 	+ filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)];
-      char *normalized_codeset_name = NULL;
 
       normalized_codeset = _nl_normalize_codeset (codeset, strlen (codeset));
       mask |= XPG_NORM_CODESET;
Index: libc/locale/programs/ld-ctype.c
===================================================================
--- libc/locale/programs/ld-ctype.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-ctype.c	(.../trunk)	(revision 8411)
@@ -122,7 +122,49 @@
 #define NO_FINALIZE
 #include "3level.h"
 
+#define TABLE wcwidth_table
+#define ELEMENT uint8_t
+#define DEFAULT 0xff
+#include "3level.h"
 
+#define TABLE wctrans_table
+#define ELEMENT int32_t
+#define DEFAULT 0
+#define wctrans_table_add wctrans_table_add_internal
+#include "3level.h"
+#undef wctrans_table_add
+/* The wctrans_table must actually store the difference between the
+   desired result and the argument.  */
+static inline void
+wctrans_table_add (struct wctrans_table *t, uint32_t wc, uint32_t mapped_wc)
+{
+  wctrans_table_add_internal (t, wc, mapped_wc - wc);
+}
+
+/* Construction of sparse 3-level tables.
+   See wchar-lookup.h for their structure and the meaning of p and q.  */
+
+struct wctype_table
+{
+  /* Parameters.  */
+  unsigned int p;
+  unsigned int q;
+  /* Working representation.  */
+  size_t level1_alloc;
+  size_t level1_size;
+  uint32_t *level1;
+  size_t level2_alloc;
+  size_t level2_size;
+  uint32_t *level2;
+  size_t level3_alloc;
+  size_t level3_size;
+  uint32_t *level3;
+  size_t result_size;
+};
+
+static void add_locale_wctype_table (struct locale_file *file,
+				     struct wctype_table *t);
+
 /* The real definition of the struct for the LC_CTYPE locale.  */
 struct locale_ctype_t
 {
@@ -188,11 +230,11 @@
   uint32_t **map_b;
   uint32_t **map32_b;
   uint32_t **class_b;
-  struct iovec *class_3level;
-  struct iovec *map_3level;
+  struct wctype_table *class_3level;
+  struct wctrans_table *map_3level;
   uint32_t *class_name_ptr;
   uint32_t *map_name_ptr;
-  struct iovec width;
+  struct wcwidth_table width;
   uint32_t mb_cur_max;
   const char *codeset_name;
   uint32_t *translit_from_idx;
@@ -227,7 +269,7 @@
 			   struct locale_ctype_t *ctype,
 			   const char *name, const struct charmap_t *charmap);
 static uint32_t *find_idx (struct locale_ctype_t *ctype, uint32_t **table,
-			   size_t *max, size_t *act, unsigned int idx);
+			   size_t *max, size_t *act, uint32_t idx);
 static void set_class_defaults (struct locale_ctype_t *ctype,
 				const struct charmap_t *charmap,
 				struct repertoire_t *repertoire);
@@ -268,9 +310,8 @@
 
 	  /* We have seen no names yet.  */
 	  ctype->charnames_max = charmap->mb_cur_max == 1 ? 256 : 512;
-	  ctype->charnames =
-	    (unsigned int *) xmalloc (ctype->charnames_max
-				      * sizeof (unsigned int));
+	  ctype->charnames = (uint32_t *) xmalloc (ctype->charnames_max
+						   * sizeof (uint32_t));
 	  for (cnt = 0; cnt < 256; ++cnt)
 	    ctype->charnames[cnt] = cnt;
 	  ctype->charnames_act = 256;
@@ -883,33 +924,21 @@
 ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
 	      const char *output_path)
 {
-  static const char nulbytes[4] = { 0, 0, 0, 0 };
   struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
   const size_t nelems = (_NL_ITEM_INDEX (_NL_CTYPE_EXTRA_MAP_1)
 			 + ctype->nr_charclass + ctype->map_collection_nr);
-  struct iovec *iov = alloca (sizeof *iov
-			      * (2 + nelems + 2 * ctype->nr_charclass
-				 + ctype->map_collection_nr + 4));
-  struct locale_file data;
-  uint32_t *idx = alloca (sizeof *idx * (nelems + 1));
+  struct locale_file file;
   uint32_t default_missing_len;
-  size_t elem, cnt, offset, total;
-  char *cp;
+  size_t elem, cnt;
 
   /* Now prepare the output: Find the sizes of the table we can use.  */
   allocate_arrays (ctype, charmap, ctype->repertoire);
 
-  data.magic = LIMAGIC (LC_CTYPE);
-  data.n = nelems;
-  iov[0].iov_base = (void *) &data;
-  iov[0].iov_len = sizeof (data);
+  default_missing_len = (ctype->default_missing
+			 ? wcslen_uint32 (ctype->default_missing)
+			 : 0);
 
-  iov[1].iov_base = (void *) idx;
-  iov[1].iov_len = nelems * sizeof (uint32_t);
-
-  idx[0] = iov[0].iov_len + iov[1].iov_len;
-  offset = 0;
-
+  init_locale_data (&file, nelems);
   for (elem = 0; elem < nelems; ++elem)
     {
       if (elem < _NL_ITEM_INDEX (_NL_CTYPE_EXTRA_MAP_1))
@@ -917,9 +946,7 @@
 	  {
 #define CTYPE_EMPTY(name) \
 	  case name:							      \
-	    iov[2 + elem + offset].iov_base = NULL;			      \
-	    iov[2 + elem + offset].iov_len = 0;				      \
-	    idx[elem + 1] = idx[elem];					      \
+	    add_locale_empty (&file);					      \
 	    break
 
 	  CTYPE_EMPTY(_NL_CTYPE_GAP1);
@@ -929,270 +956,154 @@
 	  CTYPE_EMPTY(_NL_CTYPE_GAP5);
 	  CTYPE_EMPTY(_NL_CTYPE_GAP6);
 
-#define CTYPE_DATA(name, base, len)					      \
+#define CTYPE_RAW_DATA(name, base, size)				      \
 	  case _NL_ITEM_INDEX (name):					      \
-	    iov[2 + elem + offset].iov_base = (base);			      \
-	    iov[2 + elem + offset].iov_len = (len);			      \
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;	      \
+	    add_locale_raw_data (&file, base, size);			      \
 	    break
 
-	  CTYPE_DATA (_NL_CTYPE_CLASS,
-		      ctype->ctype_b,
-		      (256 + 128) * sizeof (char_class_t));
+	  CTYPE_RAW_DATA (_NL_CTYPE_CLASS,
+			  ctype->ctype_b,
+			  (256 + 128) * sizeof (char_class_t));
 
-	  CTYPE_DATA (_NL_CTYPE_TOUPPER,
-		      ctype->map_b[0],
-		      (256 + 128) * sizeof (uint32_t));
-	  CTYPE_DATA (_NL_CTYPE_TOLOWER,
-		      ctype->map_b[1],
-		      (256 + 128) * sizeof (uint32_t));
+#define CTYPE_UINT32_ARRAY(name, base, n_elems)				      \
+	  case _NL_ITEM_INDEX (name):					      \
+	    add_locale_uint32_array (&file, base, n_elems);		      \
+	    break
 
-	  CTYPE_DATA (_NL_CTYPE_TOUPPER32,
-		      ctype->map32_b[0],
-		      256 * sizeof (uint32_t));
-	  CTYPE_DATA (_NL_CTYPE_TOLOWER32,
-		      ctype->map32_b[1],
-		      256 * sizeof (uint32_t));
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TOUPPER, ctype->map_b[0], 256 + 128);
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TOLOWER, ctype->map_b[1], 256 + 128);
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TOUPPER32, ctype->map32_b[0], 256);
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TOLOWER32, ctype->map32_b[1], 256);
+	  CTYPE_RAW_DATA (_NL_CTYPE_CLASS32,
+			  ctype->ctype32_b,
+			  256 * sizeof (char_class32_t));
 
-	  CTYPE_DATA (_NL_CTYPE_CLASS32,
-		      ctype->ctype32_b,
-		      256 * sizeof (char_class32_t));
+#define CTYPE_UINT32(name, value)					      \
+	  case _NL_ITEM_INDEX (name):					      \
+	    add_locale_uint32 (&file, value);				      \
+	    break
 
-	  CTYPE_DATA (_NL_CTYPE_CLASS_OFFSET,
-		      &ctype->class_offset, sizeof (uint32_t));
+	  CTYPE_UINT32 (_NL_CTYPE_CLASS_OFFSET, ctype->class_offset);
+	  CTYPE_UINT32 (_NL_CTYPE_MAP_OFFSET, ctype->map_offset);
+	  CTYPE_UINT32 (_NL_CTYPE_TRANSLIT_TAB_SIZE, ctype->translit_idx_size);
 
-	  CTYPE_DATA (_NL_CTYPE_MAP_OFFSET,
-		      &ctype->map_offset, sizeof (uint32_t));
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TRANSLIT_FROM_IDX,
+			      ctype->translit_from_idx,
+			      ctype->translit_idx_size);
 
-	  CTYPE_DATA (_NL_CTYPE_TRANSLIT_TAB_SIZE,
-		      &ctype->translit_idx_size, sizeof (uint32_t));
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TRANSLIT_FROM_TBL,
+			      ctype->translit_from_tbl,
+			      ctype->translit_from_tbl_size
+			      / sizeof (uint32_t));
 
-	  CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_IDX,
-		      ctype->translit_from_idx,
-		      ctype->translit_idx_size * sizeof (uint32_t));
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TRANSLIT_TO_IDX,
+			      ctype->translit_to_idx,
+			      ctype->translit_idx_size);
 
-	  CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_TBL,
-		      ctype->translit_from_tbl,
-		      ctype->translit_from_tbl_size);
+	  CTYPE_UINT32_ARRAY (_NL_CTYPE_TRANSLIT_TO_TBL,
+			      ctype->translit_to_tbl,
+			      ctype->translit_to_tbl_size / sizeof (uint32_t));
 
-	  CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_IDX,
-		      ctype->translit_to_idx,
-		      ctype->translit_idx_size * sizeof (uint32_t));
-
-	  CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_TBL,
-		      ctype->translit_to_tbl, ctype->translit_to_tbl_size);
-
 	  case _NL_ITEM_INDEX (_NL_CTYPE_CLASS_NAMES):
 	    /* The class name array.  */
-	    total = 0;
-	    for (cnt = 0; cnt < ctype->nr_charclass; ++cnt, ++offset)
-	      {
-		iov[2 + elem + offset].iov_base
-		  = (void *) ctype->classnames[cnt];
-		iov[2 + elem + offset].iov_len
-		  = strlen (ctype->classnames[cnt]) + 1;
-		total += iov[2 + elem + offset].iov_len;
-	      }
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = 4 - (total % 4);
-	    total += 4 - (total % 4);
-
-	    idx[elem + 1] = idx[elem] + total;
+	    start_locale_structure (&file);
+	    for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
+	      add_locale_string (&file, ctype->classnames[cnt]);
+	    add_locale_char (&file, 0);
+	    align_locale_data (&file, 4);
+	    end_locale_structure (&file);
 	    break;
 
 	  case _NL_ITEM_INDEX (_NL_CTYPE_MAP_NAMES):
 	    /* The class name array.  */
-	    total = 0;
-	    for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt, ++offset)
-	      {
-		iov[2 + elem + offset].iov_base
-		  = (void *) ctype->mapnames[cnt];
-		iov[2 + elem + offset].iov_len
-		  = strlen (ctype->mapnames[cnt]) + 1;
-		total += iov[2 + elem + offset].iov_len;
-	      }
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = 4 - (total % 4);
-	    total += 4 - (total % 4);
+	    start_locale_structure (&file);
+	    for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
+	      add_locale_string (&file, ctype->mapnames[cnt]);
+	    add_locale_char (&file, 0);
+	    align_locale_data (&file, 4);
+	    end_locale_structure (&file);
+	    break;
 
-	    idx[elem + 1] = idx[elem] + total;
+	  case _NL_ITEM_INDEX (_NL_CTYPE_WIDTH):
+	    add_locale_wcwidth_table (&file, &ctype->width);
 	    break;
 
-	  CTYPE_DATA (_NL_CTYPE_WIDTH,
-		      ctype->width.iov_base,
-		      ctype->width.iov_len);
+	  CTYPE_UINT32 (_NL_CTYPE_MB_CUR_MAX, ctype->mb_cur_max);
 
-	  CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX,
-		      &ctype->mb_cur_max, sizeof (uint32_t));
-
 	  case _NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME):
-	    total = strlen (ctype->codeset_name) + 1;
-	    if (total % 4 == 0)
-	      iov[2 + elem + offset].iov_base = (char *) ctype->codeset_name;
-	    else
-	      {
-		iov[2 + elem + offset].iov_base = alloca ((total + 3) & ~3);
-		memset (mempcpy (iov[2 + elem + offset].iov_base,
-				 ctype->codeset_name, total),
-			'\0', 4 - (total & 3));
-		total = (total + 3) & ~3;
-	      }
-	    iov[2 + elem + offset].iov_len = total;
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_string (&file, ctype->codeset_name);
 	    break;
 
+	  CTYPE_UINT32 (_NL_CTYPE_MAP_TO_NONASCII, ctype->to_nonascii);
 
-	  CTYPE_DATA (_NL_CTYPE_MAP_TO_NONASCII,
-		      &ctype->to_nonascii, sizeof (uint32_t));
-
 	  case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN):
-	    iov[2 + elem + offset].iov_base = alloca (sizeof (uint32_t));
-	    iov[2 + elem + offset].iov_len = sizeof (uint32_t);
-	    *(uint32_t *) iov[2 + elem + offset].iov_base =
-	      ctype->mbdigits_act / 10;
-	    idx[elem + 1] = idx[elem] + sizeof (uint32_t);
+	    add_locale_uint32 (&file, ctype->mbdigits_act / 10);
 	    break;
 
 	  case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_WC_LEN):
-	    /* Align entries.  */
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = (4 - idx[elem] % 4) % 4;
-	    idx[elem] += iov[2 + elem + offset].iov_len;
-	    ++offset;
-
-	    iov[2 + elem + offset].iov_base = alloca (sizeof (uint32_t));
-	    iov[2 + elem + offset].iov_len = sizeof (uint32_t);
-	    *(uint32_t *) iov[2 + elem + offset].iov_base =
-	      ctype->wcdigits_act / 10;
-	    idx[elem + 1] = idx[elem] + sizeof (uint32_t);
+	    add_locale_uint32 (&file, ctype->wcdigits_act / 10);
 	    break;
 
 	  case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_MB) ... _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS9_MB):
-	    /* Compute the length of all possible characters.  For INDIGITS
-	       there might be more than one.  We simply concatenate all of
-	       them with a NUL byte following.  The NUL byte wouldn't be
-	       necessary but it makes it easier for the user.  */
-	    total = 0;
-
+	    start_locale_structure (&file);
 	    for (cnt = elem - _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_MB);
 		 cnt < ctype->mbdigits_act; cnt += 10)
-	      total += ctype->mbdigits[cnt]->nbytes + 1;
-	    iov[2 + elem + offset].iov_base = (char *) alloca (total);
-	    iov[2 + elem + offset].iov_len = total;
-
-	    cp = iov[2 + elem + offset].iov_base;
-	    for (cnt = elem - _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_MB);
-		 cnt < ctype->mbdigits_act; cnt += 10)
 	      {
-		cp = mempcpy (cp, ctype->mbdigits[cnt]->bytes,
-			      ctype->mbdigits[cnt]->nbytes);
-		*cp++ = '\0';
+		add_locale_raw_data (&file, ctype->mbdigits[cnt]->bytes,
+				     ctype->mbdigits[cnt]->nbytes);
+		add_locale_char (&file, 0);
 	      }
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    end_locale_structure (&file);
 	    break;
 
 	  case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_MB) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_MB):
-	    /* Compute the length of all possible characters.  For INDIGITS
-	       there might be more than one.  We simply concatenate all of
-	       them with a NUL byte following.  The NUL byte wouldn't be
-	       necessary but it makes it easier for the user.  */
+	    start_locale_structure (&file);
 	    cnt = elem - _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_MB);
-	    total = ctype->mboutdigits[cnt]->nbytes + 1;
-	    iov[2 + elem + offset].iov_base = (char *) alloca (total);
-	    iov[2 + elem + offset].iov_len = total;
-
-	    *(char *) mempcpy (iov[2 + elem + offset].iov_base,
-			       ctype->mboutdigits[cnt]->bytes,
-			       ctype->mboutdigits[cnt]->nbytes) = '\0';
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_raw_data (&file, ctype->mboutdigits[cnt]->bytes,
+				 ctype->mboutdigits[cnt]->nbytes);
+	    add_locale_char (&file, 0);
+	    end_locale_structure (&file);
 	    break;
 
 	  case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_WC) ... _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS9_WC):
-	    total = ctype->wcdigits_act / 10;
-
-	    iov[2 + elem + offset].iov_base =
-	      (uint32_t *) alloca (total * sizeof (uint32_t));
-	    iov[2 + elem + offset].iov_len = total * sizeof (uint32_t);
-
+	    start_locale_structure (&file);
 	    for (cnt = elem - _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_WC);
 		 cnt < ctype->wcdigits_act; cnt += 10)
-	      ((uint32_t *) iov[2 + elem + offset].iov_base)[cnt / 10]
-		= ctype->wcdigits[cnt];
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	      add_locale_uint32 (&file, ctype->wcdigits[cnt]);
+	    end_locale_structure (&file);
 	    break;
 
-	  case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC):
-	    /* Align entries.  */
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = (4 - idx[elem] % 4) % 4;
-	    idx[elem] += iov[2 + elem + offset].iov_len;
-	    ++offset;
-	    /* FALLTRHOUGH */
-
-	  case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT1_WC) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC):
+	  case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC):
 	    cnt = elem - _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC);
-	    iov[2 + elem + offset].iov_base = &ctype->wcoutdigits[cnt];
-	    iov[2 + elem + offset].iov_len = sizeof (uint32_t);
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_uint32 (&file, ctype->wcoutdigits[cnt]);
 	    break;
 
 	  case _NL_ITEM_INDEX(_NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN):
-	    /* Align entries.  */
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = (4 - idx[elem] % 4) % 4;
-	    idx[elem] += iov[2 + elem + offset].iov_len;
-	    ++offset;
-
-	    default_missing_len = (ctype->default_missing
-				   ? wcslen ((wchar_t *)ctype->default_missing)
-				   : 0);
-	    iov[2 + elem + offset].iov_base = &default_missing_len;
-	    iov[2 + elem + offset].iov_len = sizeof (uint32_t);
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_uint32 (&file, default_missing_len);
 	    break;
 
 	  case _NL_ITEM_INDEX(_NL_CTYPE_TRANSLIT_DEFAULT_MISSING):
-	    iov[2 + elem + offset].iov_base =
-	      ctype->default_missing ?: (uint32_t *) L"";
-	    iov[2 + elem + offset].iov_len =
-	      wcslen (iov[2 + elem + offset].iov_base) * sizeof (uint32_t);
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_uint32_array (&file, ctype->default_missing,
+				     default_missing_len);
 	    break;
 
 	  case _NL_ITEM_INDEX(_NL_CTYPE_TRANSLIT_IGNORE_LEN):
-	    /* Align entries.  */
-	    iov[2 + elem + offset].iov_base = (void *) nulbytes;
-	    iov[2 + elem + offset].iov_len = (4 - idx[elem] % 4) % 4;
-	    idx[elem] += iov[2 + elem + offset].iov_len;
-	    ++offset;
-
-	    iov[2 + elem + offset].iov_base = &ctype->ntranslit_ignore;
-	    iov[2 + elem + offset].iov_len = sizeof (uint32_t);
-	    idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    add_locale_uint32 (&file, ctype->ntranslit_ignore);
 	    break;
 
 	  case _NL_ITEM_INDEX(_NL_CTYPE_TRANSLIT_IGNORE):
+	    start_locale_structure (&file);
 	    {
-	      uint32_t *ranges = (uint32_t *) alloca (ctype->ntranslit_ignore
-						      * 3 * sizeof (uint32_t));
 	      struct translit_ignore_t *runp;
-
-	      iov[2 + elem + offset].iov_base = ranges;
-	      iov[2 + elem + offset].iov_len = (ctype->ntranslit_ignore
-						* 3 * sizeof (uint32_t));
-
 	      for (runp = ctype->translit_ignore; runp != NULL;
 		   runp = runp->next)
 		{
-		  *ranges++ = runp->from;
-		  *ranges++ = runp->to;
-		  *ranges++ = runp->step;
+		  add_locale_uint32 (&file, runp->from);
+		  add_locale_uint32 (&file, runp->to);
+		  add_locale_uint32 (&file, runp->step);
 		}
 	    }
-	    /* Remove the following line in case a new entry is added
-	       after _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN.  */
-	    if (elem < nelems)
-	      idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+	    end_locale_structure (&file);
 	    break;
 
 	  default:
@@ -1204,28 +1115,21 @@
 	  size_t nr = elem - _NL_ITEM_INDEX (_NL_CTYPE_EXTRA_MAP_1);
 	  if (nr < ctype->nr_charclass)
 	    {
-	      iov[2 + elem + offset].iov_base = ctype->class_b[nr];
-	      iov[2 + elem + offset].iov_len = 256 / 32 * sizeof (uint32_t);
-	      idx[elem] += iov[2 + elem + offset].iov_len;
-	      ++offset;
-
-	      iov[2 + elem + offset] = ctype->class_3level[nr];
+	      start_locale_prelude (&file);
+	      add_locale_uint32_array (&file, ctype->class_b[nr], 256 / 32);
+	      end_locale_prelude (&file);
+	      add_locale_wctype_table (&file, &ctype->class_3level[nr]);
 	    }
 	  else
 	    {
 	      nr -= ctype->nr_charclass;
 	      assert (nr < ctype->map_collection_nr);
-	      iov[2 + elem + offset] = ctype->map_3level[nr];
+	      add_locale_wctrans_table (&file, &ctype->map_3level[nr]);
 	    }
-	  idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
 	}
     }
 
-  assert (2 + elem + offset == (nelems + 2 * ctype->nr_charclass
-				+ ctype->map_collection_nr + 4 + 2));
-
-  write_locale_data (output_path, LC_CTYPE, "LC_CTYPE", 2 + elem + offset,
-		     iov);
+  write_locale_data (output_path, LC_CTYPE, "LC_CTYPE", &file);
 }
 
 
@@ -2040,7 +1944,7 @@
 	    ignore = 1;
 	  else
 	    /* This value is usable.  */
-	    obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4);
+	    obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4);
 
 	  first = 0;
 	}
@@ -2590,8 +2494,8 @@
 	    }
 
 	handle_tok_digit:
-	  class_bit = _ISwdigit;
-	  class256_bit = _ISdigit;
+	  class_bit = BITw (tok_digit);
+	  class256_bit = BIT (tok_digit);
 	  handle_digits = 1;
 	  goto read_charclass;
 
@@ -3506,29 +3410,6 @@
 }
 
 
-/* Construction of sparse 3-level tables.
-   See wchar-lookup.h for their structure and the meaning of p and q.  */
-
-struct wctype_table
-{
-  /* Parameters.  */
-  unsigned int p;
-  unsigned int q;
-  /* Working representation.  */
-  size_t level1_alloc;
-  size_t level1_size;
-  uint32_t *level1;
-  size_t level2_alloc;
-  size_t level2_size;
-  uint32_t *level2;
-  size_t level3_alloc;
-  size_t level3_size;
-  uint32_t *level3;
-  /* Compressed representation.  */
-  size_t result_size;
-  char *result;
-};
-
 /* Initialize.  Assumes t->p and t->q have already been set.  */
 static inline void
 wctype_table_init (struct wctype_table *t)
@@ -3634,7 +3515,7 @@
 
 /* Finalize and shrink.  */
 static void
-wctype_table_finalize (struct wctype_table *t)
+add_locale_wctype_table (struct locale_file *file, struct wctype_table *t)
 {
   size_t i, j, k;
   uint32_t reorder3[t->level3_size];
@@ -3689,13 +3570,11 @@
     if (t->level1[i] != EMPTY)
       t->level1[i] = reorder2[t->level1[i]];
 
-  /* Create and fill the resulting compressed representation.  */
   t->result_size =
     5 * sizeof (uint32_t)
     + t->level1_size * sizeof (uint32_t)
     + (t->level2_size << t->q) * sizeof (uint32_t)
     + (t->level3_size << t->p) * sizeof (uint32_t);
-  t->result = (char *) xmalloc (t->result_size);
 
   level1_offset =
     5 * sizeof (uint32_t);
@@ -3707,26 +3586,29 @@
     + t->level1_size * sizeof (uint32_t)
     + (t->level2_size << t->q) * sizeof (uint32_t);
 
-  ((uint32_t *) t->result)[0] = t->q + t->p + 5;
-  ((uint32_t *) t->result)[1] = t->level1_size;
-  ((uint32_t *) t->result)[2] = t->p + 5;
-  ((uint32_t *) t->result)[3] = (1 << t->q) - 1;
-  ((uint32_t *) t->result)[4] = (1 << t->p) - 1;
+  start_locale_structure (file);
+  add_locale_uint32 (file, t->q + t->p + 5);
+  add_locale_uint32 (file, t->level1_size);
+  add_locale_uint32 (file, t->p + 5);
+  add_locale_uint32 (file, (1 << t->q) - 1);
+  add_locale_uint32 (file, (1 << t->p) - 1);
 
   for (i = 0; i < t->level1_size; i++)
-    ((uint32_t *) (t->result + level1_offset))[i] =
-      (t->level1[i] == EMPTY
+    add_locale_uint32
+      (file,
+       t->level1[i] == EMPTY
        ? 0
        : (t->level1[i] << t->q) * sizeof (uint32_t) + level2_offset);
 
   for (i = 0; i < (t->level2_size << t->q); i++)
-    ((uint32_t *) (t->result + level2_offset))[i] =
-      (t->level2[i] == EMPTY
+    add_locale_uint32
+      (file,
+       t->level2[i] == EMPTY
        ? 0
        : (t->level2[i] << t->p) * sizeof (uint32_t) + level3_offset);
 
-  for (i = 0; i < (t->level3_size << t->p); i++)
-    ((uint32_t *) (t->result + level3_offset))[i] = t->level3[i];
+  add_locale_uint32_array (file, t->level3, t->level3_size << t->p);
+  end_locale_structure (file);
 
   if (t->level1_alloc > 0)
     free (t->level1);
@@ -3736,26 +3618,6 @@
     free (t->level3);
 }
 
-#define TABLE wcwidth_table
-#define ELEMENT uint8_t
-#define DEFAULT 0xff
-#include "3level.h"
-
-#define TABLE wctrans_table
-#define ELEMENT int32_t
-#define DEFAULT 0
-#define wctrans_table_add wctrans_table_add_internal
-#include "3level.h"
-#undef wctrans_table_add
-/* The wctrans_table must actually store the difference between the
-   desired result and the argument.  */
-static inline void
-wctrans_table_add (struct wctrans_table *t, uint32_t wc, uint32_t mapped_wc)
-{
-  wctrans_table_add_internal (t, wc, mapped_wc - wc);
-}
-
-
 /* Flattens the included transliterations into a translit list.
    Inserts them in the list at `cursor', and returns the new cursor.  */
 static struct translit_t **
@@ -3832,8 +3694,8 @@
   ctype->ctype32_b = (char_class32_t *) xcalloc (256, sizeof (char_class32_t));
   ctype->class_b = (uint32_t **)
     xmalloc (ctype->nr_charclass * sizeof (uint32_t *));
-  ctype->class_3level = (struct iovec *)
-    xmalloc (ctype->nr_charclass * sizeof (struct iovec));
+  ctype->class_3level = (struct wctype_table *)
+    xmalloc (ctype->nr_charclass * sizeof (struct wctype_table));
 
   /* This is the array accessed using the multibyte string elements.  */
   for (idx = 0; idx < 256; ++idx)
@@ -3865,34 +3727,30 @@
 
   for (nr = 0; nr < ctype->nr_charclass; nr++)
     {
-      struct wctype_table t;
+      struct wctype_table *t;
 
-      t.p = 4; /* or: 5 */
-      t.q = 7; /* or: 6 */
-      wctype_table_init (&t);
+      t = &ctype->class_3level[nr];
+      t->p = 4; /* or: 5 */
+      t->q = 7; /* or: 6 */
+      wctype_table_init (t);
 
       for (idx = 0; idx < ctype->class_collection_act; ++idx)
 	if (ctype->class_collection[idx] & _ISwbit (nr))
-	  wctype_table_add (&t, ctype->charnames[idx]);
+	  wctype_table_add (t, ctype->charnames[idx]);
 
-      wctype_table_finalize (&t);
-
       if (verbose)
 	WITH_CUR_LOCALE (fprintf (stderr, _("\
 %s: table for class \"%s\": %lu bytes\n"),
 				 "LC_CTYPE", ctype->classnames[nr],
-				 (unsigned long int) t.result_size));
-
-      ctype->class_3level[nr].iov_base = t.result;
-      ctype->class_3level[nr].iov_len = t.result_size;
+				 (unsigned long int) t->result_size));
     }
 
   /* Room for table of mappings.  */
   ctype->map_b = (uint32_t **) xmalloc (2 * sizeof (uint32_t *));
   ctype->map32_b = (uint32_t **) xmalloc (ctype->map_collection_nr
 					  * sizeof (uint32_t *));
-  ctype->map_3level = (struct iovec *)
-    xmalloc (ctype->map_collection_nr * sizeof (struct iovec));
+  ctype->map_3level = (struct wctrans_table *)
+    xmalloc (ctype->map_collection_nr * sizeof (struct wctrans_table));
 
   /* Fill in all mappings.  */
   for (idx = 0; idx < 2; ++idx)
@@ -3933,27 +3791,23 @@
 
   for (nr = 0; nr < ctype->map_collection_nr; nr++)
     {
-      struct wctrans_table t;
+      struct wctrans_table *t;
 
-      t.p = 7;
-      t.q = 9;
-      wctrans_table_init (&t);
+      t = &ctype->map_3level[nr];
+      t->p = 7;
+      t->q = 9;
+      wctrans_table_init (t);
 
       for (idx = 0; idx < ctype->map_collection_act[nr]; ++idx)
 	if (ctype->map_collection[nr][idx] != 0)
-	  wctrans_table_add (&t, ctype->charnames[idx],
+	  wctrans_table_add (t, ctype->charnames[idx],
 			     ctype->map_collection[nr][idx]);
 
-      wctrans_table_finalize (&t);
-
       if (verbose)
 	WITH_CUR_LOCALE (fprintf (stderr, _("\
 %s: table for map \"%s\": %lu bytes\n"),
 				 "LC_CTYPE", ctype->mapnames[nr],
-				 (unsigned long int) t.result_size));
-
-      ctype->map_3level[nr].iov_base = t.result;
-      ctype->map_3level[nr].iov_len = t.result_size;
+				 (unsigned long int) t->result_size));
     }
 
   /* Extra array for class and map names.  */
@@ -3973,11 +3827,12 @@
      saves a run-time check.
      But we put L'\0' in the table.  This again saves a run-time check.  */
   {
-    struct wcwidth_table t;
+    struct wcwidth_table *t;
 
-    t.p = 7;
-    t.q = 9;
-    wcwidth_table_init (&t);
+    t = &ctype->width;
+    t->p = 7;
+    t->q = 9;
+    wcwidth_table_init (t);
 
     /* First set all the printable characters of the character set to
        the default width.  */
@@ -3997,7 +3852,7 @@
 			&ctype->class_collection_act, data->ucs4);
 
 	    if (class_bits != NULL && (*class_bits & BITw (tok_print)))
-	      wcwidth_table_add (&t, data->ucs4, charmap->width_default);
+	      wcwidth_table_add (t, data->ucs4, charmap->width_default);
 	  }
       }
 
@@ -4045,7 +3900,7 @@
 				&ctype->class_collection_act, wch);
 
 		    if (class_bits != NULL && (*class_bits & BITw (tok_print)))
-		      wcwidth_table_add (&t, wch,
+		      wcwidth_table_add (t, wch,
 					 charmap->width_rules[cnt].width);
 		  }
 
@@ -4075,16 +3930,11 @@
       }
 
     /* Set the width of L'\0' to 0.  */
-    wcwidth_table_add (&t, 0, 0);
+    wcwidth_table_add (t, 0, 0);
 
-    wcwidth_table_finalize (&t);
-
     if (verbose)
       WITH_CUR_LOCALE (fprintf (stderr, _("%s: table for width: %lu bytes\n"),
-			       "LC_CTYPE", (unsigned long int) t.result_size));
-
-    ctype->width.iov_base = t.result;
-    ctype->width.iov_len = t.result_size;
+			       "LC_CTYPE", (unsigned long int) t->result_size));
   }
 
   /* Set MB_CUR_MAX.  */
@@ -4131,8 +3981,7 @@
 
 	  while (idx < number)
 	    {
-	      int res = wcscmp ((const wchar_t *) sorted[idx]->from,
-				(const wchar_t *) runp->from);
+	      int res = wcscmp_uint32 (sorted[idx]->from, runp->from);
 	      if (res == 0)
 		{
 		  replace = 1;
@@ -4169,11 +4018,11 @@
       for (cnt = 0; cnt < number; ++cnt)
 	{
 	  struct translit_to_t *srunp;
-	  from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
+	  from_len += wcslen_uint32 (sorted[cnt]->from) + 1;
 	  srunp = sorted[cnt]->to;
 	  while (srunp != NULL)
 	    {
-	      to_len += wcslen ((const wchar_t *) srunp->str) + 1;
+	      to_len += wcslen_uint32 (srunp->str) + 1;
 	      srunp = srunp->next;
 	    }
 	  /* Plus one for the extra NUL character marking the end of
@@ -4197,18 +4046,18 @@
 	  ctype->translit_from_idx[cnt] = from_len;
 	  ctype->translit_to_idx[cnt] = to_len;
 
-	  len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
-	  wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len],
-		   (const wchar_t *) sorted[cnt]->from, len);
+	  len = wcslen_uint32 (sorted[cnt]->from) + 1;
+	  wmemcpy_uint32 (&ctype->translit_from_tbl[from_len],
+			  sorted[cnt]->from, len);
 	  from_len += len;
 
 	  ctype->translit_to_idx[cnt] = to_len;
 	  srunp = sorted[cnt]->to;
 	  while (srunp != NULL)
 	    {
-	      len = wcslen ((const wchar_t *) srunp->str) + 1;
-	      wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len],
-		       (const wchar_t *) srunp->str, len);
+	      len = wcslen_uint32 (srunp->str) + 1;
+	      wmemcpy_uint32 (&ctype->translit_to_tbl[to_len],
+			      srunp->str, len);
 	      to_len += len;
 	      srunp = srunp->next;
 	    }
Index: libc/locale/programs/locfile.h
===================================================================
--- libc/locale/programs/locfile.h	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/locfile.h	(.../trunk)	(revision 8411)
@@ -21,15 +21,16 @@
 
 #include <sys/uio.h>
 
+#include "obstack.h"
 #include "linereader.h"
 #include "localedef.h"
 
-
-/* Header of the locale data files.  */
-struct locale_file
-{
-  int magic;
-  int n;
+/* Structure for storing the contents of a category file.  */
+struct locale_file {
+  size_t n_elements, next_element;
+  uint32_t *offsets;
+  struct obstack data;
+  int structure_stage;
 };
 
 
@@ -65,12 +66,75 @@
 				  const char *locname,
 				  const char *output_path);
 
+extern int swap_endianness_p;
+
+extern unsigned int uint32_align_mask;
+
+/* Change the output to be big-endian if BIG_ENDIAN is true and
+   little-endian otherwise.  */
+static inline void
+set_big_endian (int big_endian)
+{
+  swap_endianness_p = ((big_endian != 0) != (__BYTE_ORDER == __BIG_ENDIAN));
+}
+
+/* Swap the order of the bytes in VALUE.  */
+static inline uint32_t
+swap_uint32 (uint32_t value)
+{
+  return (((value & 0x000000ff) << 24)
+	  | ((value & 0x0000ff00) << 8)
+	  | ((value & 0x00ff0000) >> 8)
+	  | ((value & 0xff000000) >> 24));
+}
+
+/* Munge VALUE so that, when stored, it has the correct byte order
+   for the output files.  */
+static inline uint32_t
+maybe_swap_uint32 (uint32_t value)
+{
+  return swap_endianness_p ? swap_uint32 (value) : value;
+}
+
+/* Likewise, but munge an array of N uint32_ts starting at ARRAY.  */
+static inline void
+maybe_swap_uint32_array (uint32_t *array, size_t n)
+{
+  if (swap_endianness_p)
+    while (n-- > 0)
+      array[n] = swap_uint32 (array[n]);
+}
+
+/* Like maybe_swap_uint32_array, but the array of N elements is at
+   the end of OBSTACK's current object.  */
+static inline void
+maybe_swap_uint32_obstack (struct obstack *obstack, size_t n)
+{
+  maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n);
+}
+
 /* Write out the data.  */
+extern void init_locale_data (struct locale_file *file, size_t n_elements);
+extern void align_locale_data (struct locale_file *file, size_t boundary);
+extern void add_locale_empty (struct locale_file *file);
+extern void add_locale_raw_data (struct locale_file *file, const void *data,
+				 size_t size);
+extern void add_locale_raw_obstack (struct locale_file *file,
+				    struct obstack *obstack);
+extern void add_locale_string (struct locale_file *file, const char *string);
+extern void add_locale_wstring (struct locale_file *file,
+				const uint32_t *string);
+extern void add_locale_uint32 (struct locale_file *file, uint32_t value);
+extern void add_locale_uint32_array (struct locale_file *file,
+				     const uint32_t *data, size_t n_elems);
+extern void add_locale_char (struct locale_file *file, char value);
+extern void start_locale_structure (struct locale_file *file);
+extern void end_locale_structure (struct locale_file *file);
+extern void start_locale_prelude (struct locale_file *file);
+extern void end_locale_prelude (struct locale_file *file);
 extern void write_locale_data (const char *output_path, int catidx,
-			       const char *category, size_t n_elem,
-			       struct iovec *vec);
+			       const char *category, struct locale_file *file);
 
-
 /* Entrypoints for the parsers of the individual categories.  */
 
 /* Handle LC_CTYPE category.  */
@@ -219,4 +283,49 @@
 				   const struct charmap_t *charmap,
 				   const char *output_path);
 
+static inline size_t
+wcslen_uint32 (const uint32_t *str)
+{
+  size_t len = 0;
+  while (str[len] != 0)
+    len++;
+  return len;
+}
+
+static inline int
+wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n)
+{
+  while (n-- != 0)
+    {
+      int diff = *s1++ - *s2++;
+      if (diff != 0)
+	return diff;
+    }
+  return 0;
+}
+
+static inline int
+wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2)
+{
+  while (*s1 != 0 && *s1 == *s2)
+    s1++, s2++;
+  return *s1 - *s2;
+}
+
+static inline uint32_t *
+wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n)
+{
+  return memcpy (s1, s2, n * sizeof (uint32_t));
+}
+
+static inline uint32_t *
+wcschr_uint32 (const uint32_t *s, uint32_t ch)
+{
+  do
+    if (*s == ch)
+      return (uint32_t *) s;
+  while (*s++ != 0);
+  return 0;
+}
+
 #endif /* locfile.h */
Index: libc/locale/programs/ld-identification.c
===================================================================
--- libc/locale/programs/ld-identification.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-identification.c	(.../trunk)	(revision 8411)
@@ -182,116 +182,32 @@
 {
   struct locale_identification_t *identification
     = locale->categories[LC_IDENTIFICATION].identification;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
-		  + (__LC_LAST - 2)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)];
-  size_t cnt = 0;
+  struct locale_file file;
   size_t num;
-  size_t last_idx;
 
-  data.magic = LIMAGIC (LC_IDENTIFICATION);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) identification->title;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->source;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->address;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->contact;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->email;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->tel;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->fax;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->language;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->territory;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->audience;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->application;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->abbreviation;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->revision;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) identification->date;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  last_idx = cnt - 1;
-  idx[last_idx] = idx[cnt - 2];
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION));
+  add_locale_string (&file, identification->title);
+  add_locale_string (&file, identification->source);
+  add_locale_string (&file, identification->address);
+  add_locale_string (&file, identification->contact);
+  add_locale_string (&file, identification->email);
+  add_locale_string (&file, identification->tel);
+  add_locale_string (&file, identification->fax);
+  add_locale_string (&file, identification->language);
+  add_locale_string (&file, identification->territory);
+  add_locale_string (&file, identification->audience);
+  add_locale_string (&file, identification->application);
+  add_locale_string (&file, identification->abbreviation);
+  add_locale_string (&file, identification->revision);
+  add_locale_string (&file, identification->date);
+  start_locale_structure (&file);
   for (num = 0; num < __LC_LAST; ++num)
     if (num != LC_ALL)
-      {
-	iov[cnt].iov_base = (void *) identification->category[num];
-	iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-	idx[last_idx] += iov[cnt].iov_len;
-	++cnt;
-      }
-
-  assert (last_idx == _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION) - 1);
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == (2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
-		  + (__LC_LAST - 2)));
-
-  write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION", cnt,
-		     iov);
+      add_locale_string (&file, identification->category[num]);
+  end_locale_structure (&file);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_IDENTIFICATION, "LC_IDENTIFICATION",
+		     &file);
 }
 
 
Index: libc/locale/programs/ld-time.c
===================================================================
--- libc/locale/programs/ld-time.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-time.c	(.../trunk)	(revision 8411)
@@ -215,8 +215,10 @@
 	}
       else
 	{
+	  static const uint32_t wt_fmt_ampm[]
+	    = { '%','I',':','%','M',':','%','S',' ','%','p',0 };
 	  time->t_fmt_ampm = "%I:%M:%S %p";
-	  time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p";
+	  time->wt_fmt_ampm = wt_fmt_ampm;
 	}
     }
 
@@ -226,7 +228,7 @@
       const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,
 				       31, 31, 30, 31 ,30, 31 };
       size_t idx;
-      wchar_t *wstr;
+      uint32_t *wstr;
 
       time->era_entries =
 	(struct era_data *) xmalloc (time->num_era
@@ -464,18 +466,18 @@
 	    }
 
 	  /* Now generate the wide character name and format.  */
-	  wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */
-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end offset */
-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end start */
-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end end */
+	  wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */
+	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */
+	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */
+	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */
 	  if (wstr != NULL)
 	    {
-	      time->era_entries[idx].wname = (uint32_t *) wstr + 1;
-	      wstr = wcschr (wstr + 1, L':');	/* end name */
+	      time->era_entries[idx].wname = wstr + 1;
+	      wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */
 	      if (wstr != NULL)
 		{
 		  *wstr = L'\0';
-		  time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
+		  time->era_entries[idx].wformat = wstr + 1;
 		}
 	      else
 		time->era_entries[idx].wname =
@@ -530,7 +532,16 @@
   if (time->date_fmt == NULL)
     time->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
   if (time->wdate_fmt == NULL)
-    time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y";
+    {
+      static const uint32_t wdate_fmt[] =
+	{ '%','a',' ',
+	  '%','b',' ',
+	  '%','e',' ',
+	  '%','H',':','%','M',':','%','S',' ',
+	  '%','Z',' ',
+	  '%','Y',0 };
+      time->wdate_fmt = wdate_fmt;
+    }
 }
 
 
@@ -539,394 +550,116 @@
 	     const char *output_path)
 {
   struct locale_time_t *time = locale->categories[LC_TIME].time;
-  struct iovec *iov = alloca (sizeof *iov
-			      * (2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
-				 + time->num_era - 1
-				 + 2 * 99
-				 + 2 + time->num_era * 10));
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
-  size_t cnt, last_idx, num, n;
+  struct locale_file file;
+  size_t num, n;
 
-  data.magic = LIMAGIC (LC_TIME);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TIME);
-  iov[0].iov_base = (void *) &data;
-  iov[0].iov_len = sizeof (data);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
 
-  iov[1].iov_base = (void *) idx;
-  iov[1].iov_len = sizeof (idx);
-
-  idx[0] = iov[0].iov_len + iov[1].iov_len;
-
   /* The ab'days.  */
-  for (cnt = 0; cnt <= _NL_ITEM_INDEX (ABDAY_7); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->abday[cnt - _NL_ITEM_INDEX (ABDAY_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_string (&file, time->abday[n] ?: "");
 
   /* The days.  */
-  for (; cnt <= _NL_ITEM_INDEX (DAY_7); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->day[cnt - _NL_ITEM_INDEX (DAY_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_string (&file, time->day[n] ?: "");
 
   /* The ab'mons.  */
-  for (; cnt <= _NL_ITEM_INDEX (ABMON_12); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->abmon[cnt - _NL_ITEM_INDEX (ABMON_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->abmon[n] ?: "");
 
   /* The mons.  */
-  for (; cnt <= _NL_ITEM_INDEX (MON_12); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->mon[cnt - _NL_ITEM_INDEX (MON_1)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_string (&file, time->mon[n] ?: "");
 
   /* AM/PM.  */
-  for (; cnt <= _NL_ITEM_INDEX (PM_STR); ++cnt)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->am_pm[cnt - _NL_ITEM_INDEX (AM_STR)] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 2; ++n)
+    add_locale_string (&file, time->am_pm[n]);
 
-  iov[2 + cnt].iov_base = (void *) (time->d_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  add_locale_string (&file, time->d_t_fmt ?: "");
+  add_locale_string (&file, time->d_fmt ?: "");
+  add_locale_string (&file, time->t_fmt ?: "");
+  add_locale_string (&file, time->t_fmt_ampm ?: "");
 
-  iov[2 + cnt].iov_base = (void *) (time->d_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  start_locale_structure (&file);
+  for (num = 0; num < time->num_era; ++num)
+    add_locale_string (&file, time->era[num]);
+  end_locale_structure (&file);
 
-  iov[2 + cnt].iov_base = (void *) (time->t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  add_locale_string (&file, time->era_year ?: "");
+  add_locale_string (&file, time->era_d_fmt ?: "");
 
-  iov[2 + cnt].iov_base = (void *) (time->t_fmt_ampm ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  last_idx = ++cnt;
+  start_locale_structure (&file);
+  for (num = 0; num < 100; ++num)
+    add_locale_string (&file, time->alt_digits[num] ?: "");
+  end_locale_structure (&file);
 
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < time->num_era; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) time->era[num];
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
+  add_locale_string (&file, time->era_d_t_fmt ?: "");
+  add_locale_string (&file, time->era_t_fmt ?: "");
+  add_locale_uint32 (&file, time->num_era);
 
-  iov[2 + cnt].iov_base = (void *) (time->era_year ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < 100; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) (time->alt_digits[num] ?: "");
-      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_d_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->era_t_fmt ?: "");
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-
-  /* We must align the following data.  */
-  iov[2 + cnt].iov_base = (void *) "\0\0";
-  iov[2 + cnt].iov_len = ((idx[last_idx] + 3) & ~3) - idx[last_idx];
-  idx[last_idx] = (idx[last_idx] + 3) & ~3;
-  ++cnt;
-
-  /* The `era' data in usable form.  */
-  iov[2 + cnt].iov_base = (void *) &time->num_era;
-  iov[2 + cnt].iov_len = sizeof (uint32_t);
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
+  start_locale_structure (&file);
   for (num = 0; num < time->num_era; ++num)
     {
-      size_t l, l2;
-
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].direction;
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].offset;
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[0];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[1];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].start_date[2];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[0];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[1];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-      iov[2 + cnt].iov_base = (void *) &time->era_entries[num].stop_date[2];
-      iov[2 + cnt].iov_len = sizeof (int32_t);
-      ++cnt;
-
-      l = ((char *) rawmemchr (time->era_entries[num].format, '\0')
-	   - time->era_entries[num].name) + 1;
-      l2 = (l + 3) & ~3;
-      iov[2 + cnt].iov_base = alloca (l2);
-      memset (mempcpy (iov[2 + cnt].iov_base, time->era_entries[num].name, l),
-	      '\0', l2 - l);
-      iov[2 + cnt].iov_len = l2;
-      ++cnt;
-
-      idx[1 + last_idx] += 8 * sizeof (int32_t) + l2;
-
-      assert (idx[1 + last_idx] % 4 == 0);
-
-      iov[2 + cnt].iov_base = (void *) time->era_entries[num].wname;
-      iov[2 + cnt].iov_len = ((wcschr ((wchar_t *) time->era_entries[num].wformat, L'\0')
-			       - (wchar_t *) time->era_entries[num].wname + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-      ++cnt;
+      add_locale_uint32 (&file, time->era_entries[num].direction);
+      add_locale_uint32 (&file, time->era_entries[num].offset);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[0]);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[1]);
+      add_locale_uint32 (&file, time->era_entries[num].start_date[2]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[0]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[1]);
+      add_locale_uint32 (&file, time->era_entries[num].stop_date[2]);
+      add_locale_string (&file, time->era_entries[num].name);
+      add_locale_string (&file, time->era_entries[num].format);
+      add_locale_wstring (&file, time->era_entries[num].wname);
+      add_locale_wstring (&file, time->era_entries[num].wformat);
     }
-  ++last_idx;
+  end_locale_structure (&file);
 
   /* The wide character ab'days.  */
-  for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->wabday[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_wstring (&file, time->wabday[n] ?: empty_wstr);
 
   /* The wide character days.  */
-  for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->wday[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 7; ++n)
+    add_locale_wstring (&file, time->wday[n] ?: empty_wstr);
 
   /* The wide character ab'mons.  */
-  for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->wabmon[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->wabmon[n] ?: empty_wstr);
 
   /* The wide character mons.  */
-  for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->wmon[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 12; ++n)
+    add_locale_wstring (&file, time->wmon[n] ?: empty_wstr);
 
   /* Wide character AM/PM.  */
-  for (n = 0; n < 2; ++n, ++cnt, ++last_idx)
-    {
-      iov[2 + cnt].iov_base =
-	(void *) (time->wam_pm[n] ?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-    }
+  for (n = 0; n < 2; ++n)
+    add_locale_wstring (&file, time->wam_pm[n] ?: empty_wstr);
 
-  iov[2 + cnt].iov_base = (void *) (time->wd_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
+  add_locale_wstring (&file, time->wd_t_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wd_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wt_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wt_fmt_ampm ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_year ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_d_fmt ?: empty_wstr);
 
-  iov[2 + cnt].iov_base = (void *) (time->wd_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
+  start_locale_structure (&file);
+  for (num = 0; num < 100; ++num)
+    add_locale_wstring (&file, time->walt_digits[num] ?: empty_wstr);
+  end_locale_structure (&file);
 
-  iov[2 + cnt].iov_base = (void *) (time->wt_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wt_fmt_ampm ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_year ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_d_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  idx[1 + last_idx] = idx[last_idx];
-  for (num = 0; num < 100; ++num, ++cnt)
-    {
-      iov[2 + cnt].iov_base = (void *) (time->walt_digits[num]
-					?: empty_wstr);
-      iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			      * sizeof (uint32_t));
-      idx[1 + last_idx] += iov[2 + cnt].iov_len;
-    }
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_d_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) (time->wera_t_fmt ?: empty_wstr);
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-			  * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_ndays;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  /* We must align the following data.  */
-  iov[2 + cnt].iov_base = (void *) "\0\0";
-  iov[2 + cnt].iov_len = ((idx[last_idx] + 3) & ~3) - idx[last_idx];
-  idx[last_idx] = (idx[last_idx] + 3) & ~3;
-  ++cnt;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_1stday;
-  iov[2 + cnt].iov_len = sizeof(uint32_t);
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->week_1stweek;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->first_weekday;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->first_workday;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) &time->cal_direction;
-  iov[2 + cnt].iov_len = 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) time->timezone;
-  iov[2 + cnt].iov_len = strlen (time->timezone) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) time->date_fmt;
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  /* We must align the following data.  */
-  iov[2 + cnt].iov_base = (void *) "\0\0";
-  iov[2 + cnt].iov_len = -idx[last_idx] & 3;
-  idx[last_idx] += -idx[last_idx] & 3;
-  ++cnt;
-
-  iov[2 + cnt].iov_base = (void *) time->wdate_fmt;
-  iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
-                          * sizeof (uint32_t));
-  idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
-  ++cnt;
-  ++last_idx;
-
-  iov[2 + cnt].iov_base = (void *) charmap->code_set_name;
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  ++cnt;
-  ++last_idx;
-
-  assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME)
-		  + time->num_era - 1
-		  + 2 * 99
-		  + 2 + time->num_era * 10));
-  assert (last_idx  == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
-
-  write_locale_data (output_path, LC_TIME, "LC_TIME", 2 + cnt, iov);
+  add_locale_wstring (&file, time->wera_d_t_fmt ?: empty_wstr);
+  add_locale_wstring (&file, time->wera_t_fmt ?: empty_wstr);
+  add_locale_char (&file, time->week_ndays);
+  add_locale_uint32 (&file, time->week_1stday);
+  add_locale_char (&file, time->week_1stweek);
+  add_locale_char (&file, time->first_weekday);
+  add_locale_char (&file, time->first_workday);
+  add_locale_char (&file, time->cal_direction);
+  add_locale_string (&file, time->timezone);
+  add_locale_string (&file, time->date_fmt);
+  add_locale_wstring (&file, time->wdate_fmt);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_TIME, "LC_TIME", &file);
 }
 
 
Index: libc/locale/programs/ld-monetary.c
===================================================================
--- libc/locale/programs/ld-monetary.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-monetary.c	(.../trunk)	(revision 8411)
@@ -365,262 +365,57 @@
 {
   struct locale_monetary_t *monetary
     = locale->categories[LC_MONETARY].monetary;
-  struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_MONETARY);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->int_curr_symbol;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->currency_symbol;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->mon_decimal_point;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->mon_thousands_sep;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = monetary->mon_grouping;
-  iov[cnt].iov_len = monetary->mon_grouping_len;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->positive_sign;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->negative_sign;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_frac_digits;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->frac_digits;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->p_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->p_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->n_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->n_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->p_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->n_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->crncystr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_p_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_p_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_n_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_n_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_p_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->int_n_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->duo_int_curr_symbol;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->duo_currency_symbol;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_frac_digits;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_frac_digits;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_p_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_p_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_n_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_n_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_p_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_p_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_n_cs_precedes;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_n_sep_by_space;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_p_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_n_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_p_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_int_n_sign_posn;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-
-  /* Align following data */
-  iov[cnt].iov_base = (void *) "\0\0";
-  iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
-  idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) &monetary->uno_valid_from;
-  iov[cnt].iov_len = sizeof(uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->uno_valid_to;
-  iov[cnt].iov_len = sizeof(uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_valid_from;
-  iov[cnt].iov_len = sizeof(uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->duo_valid_to;
-  iov[cnt].iov_len = sizeof(uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) monetary->conversion_rate;
-  iov[cnt].iov_len = 2 * sizeof(uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->mon_decimal_point_wc;
-  iov[cnt].iov_len = sizeof (uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) &monetary->mon_thousands_sep_wc;
-  iov[cnt].iov_len = sizeof (uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
-
-  write_locale_data (output_path, LC_MONETARY, "LC_MONETARY",
-		     3 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
+  add_locale_string (&file, monetary->int_curr_symbol);
+  add_locale_string (&file, monetary->currency_symbol);
+  add_locale_string (&file, monetary->mon_decimal_point);
+  add_locale_string (&file, monetary->mon_thousands_sep);
+  add_locale_raw_data (&file, monetary->mon_grouping,
+		       monetary->mon_grouping_len);
+  add_locale_string (&file, monetary->positive_sign);
+  add_locale_string (&file, monetary->negative_sign);
+  add_locale_char (&file, monetary->int_frac_digits);
+  add_locale_char (&file, monetary->frac_digits);
+  add_locale_char (&file, monetary->p_cs_precedes);
+  add_locale_char (&file, monetary->p_sep_by_space);
+  add_locale_char (&file, monetary->n_cs_precedes);
+  add_locale_char (&file, monetary->n_sep_by_space);
+  add_locale_char (&file, monetary->p_sign_posn);
+  add_locale_char (&file, monetary->n_sign_posn);
+  add_locale_string (&file, monetary->crncystr);
+  add_locale_char (&file, monetary->int_p_cs_precedes);
+  add_locale_char (&file, monetary->int_p_sep_by_space);
+  add_locale_char (&file, monetary->int_n_cs_precedes);
+  add_locale_char (&file, monetary->int_n_sep_by_space);
+  add_locale_char (&file, monetary->int_p_sign_posn);
+  add_locale_char (&file, monetary->int_n_sign_posn);
+  add_locale_string (&file, monetary->duo_int_curr_symbol);
+  add_locale_string (&file, monetary->duo_currency_symbol);
+  add_locale_char (&file, monetary->duo_int_frac_digits);
+  add_locale_char (&file, monetary->duo_frac_digits);
+  add_locale_char (&file, monetary->duo_p_cs_precedes);
+  add_locale_char (&file, monetary->duo_p_sep_by_space);
+  add_locale_char (&file, monetary->duo_n_cs_precedes);
+  add_locale_char (&file, monetary->duo_n_sep_by_space);
+  add_locale_char (&file, monetary->duo_int_p_cs_precedes);
+  add_locale_char (&file, monetary->duo_int_p_sep_by_space);
+  add_locale_char (&file, monetary->duo_int_n_cs_precedes);
+  add_locale_char (&file, monetary->duo_int_n_sep_by_space);
+  add_locale_char (&file, monetary->duo_p_sign_posn);
+  add_locale_char (&file, monetary->duo_n_sign_posn);
+  add_locale_char (&file, monetary->duo_int_p_sign_posn);
+  add_locale_char (&file, monetary->duo_int_n_sign_posn);
+  add_locale_uint32 (&file, monetary->uno_valid_from);
+  add_locale_uint32 (&file, monetary->uno_valid_to);
+  add_locale_uint32 (&file, monetary->duo_valid_from);
+  add_locale_uint32 (&file, monetary->duo_valid_to);
+  add_locale_uint32_array (&file, monetary->conversion_rate, 2);
+  add_locale_uint32 (&file, monetary->mon_decimal_point_wc);
+  add_locale_uint32 (&file, monetary->mon_thousands_sep_wc);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_MONETARY, "LC_MONETARY", &file);
 }
 
 
Index: libc/locale/programs/locale.c
===================================================================
--- libc/locale/programs/locale.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/locale.c	(.../trunk)	(revision 8411)
@@ -271,13 +271,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -289,7 +292,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "locale (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "locale %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/locale/programs/ld-messages.c
===================================================================
--- libc/locale/programs/ld-messages.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-messages.c	(.../trunk)	(revision 8411)
@@ -25,6 +25,7 @@
 #include <regex.h>
 #include <string.h>
 #include <sys/uio.h>
+#include <gnu/option-groups.h>
 
 #include <assert.h>
 
@@ -124,6 +125,7 @@
     }
   else
     {
+#if __OPTION_POSIX_REGEXP
       int result;
       regex_t re;
 
@@ -140,6 +142,7 @@
 	}
       else if (result != 0)
 	regfree (&re);
+#endif
     }
 
   if (messages->noexpr == NULL)
@@ -158,6 +161,7 @@
     }
   else
     {
+#if __OPTION_POSIX_REGEXP
       int result;
       regex_t re;
 
@@ -174,6 +178,7 @@
 	}
       else if (result != 0)
 	regfree (&re);
+#endif
     }
 }
 
@@ -184,49 +189,15 @@
 {
   struct locale_messages_t *messages
     = locale->categories[LC_MESSAGES].messages;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_MESSAGES);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (char *) messages->yesexpr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (char *) messages->noexpr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (char *) messages->yesstr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (char *) messages->nostr;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (char *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-
-  assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
-
-  write_locale_data (output_path, LC_MESSAGES, "LC_MESSAGES",
-		     2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
+  add_locale_string (&file, messages->yesexpr);
+  add_locale_string (&file, messages->noexpr);
+  add_locale_string (&file, messages->yesstr);
+  add_locale_string (&file, messages->nostr);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_MESSAGES, "LC_MESSAGES", &file);
 }
 
 
Index: libc/locale/programs/linereader.c
===================================================================
--- libc/locale/programs/linereader.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/linereader.c	(.../trunk)	(revision 8411)
@@ -595,7 +595,7 @@
 {
   int return_widestr = lr->return_widestr;
   char *buf;
-  wchar_t *buf2 = NULL;
+  uint32_t *buf2 = NULL;
   size_t bufact;
   size_t bufmax = 56;
 
Index: libc/locale/programs/localedef.c
===================================================================
--- libc/locale/programs/localedef.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/localedef.c	(.../trunk)	(revision 8411)
@@ -113,6 +113,9 @@
 #define OPT_REPLACE 307
 #define OPT_DELETE_FROM_ARCHIVE 308
 #define OPT_LIST_ARCHIVE 309
+#define OPT_LITTLE_ENDIAN 400
+#define OPT_BIG_ENDIAN 401
+#define OPT_UINT32_ALIGN 402
 
 /* Definitions of arguments for argp functions.  */
 static const struct argp_option options[] =
@@ -144,6 +147,11 @@
   { "list-archive", OPT_LIST_ARCHIVE, NULL, 0, N_("List content of archive") },
   { "alias-file", 'A', "FILE", 0,
     N_("locale.alias file to consult when making archive")},
+  { "little-endian", OPT_LITTLE_ENDIAN, NULL, 0,
+    N_("Generate little-endian output") },
+  { "big-endian", OPT_BIG_ENDIAN, NULL, 0, N_("Generate big-endian output") },
+  { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0,
+    N_("Set the target's uint32_t alignment in bytes (default 4)") },
   { NULL, 0, NULL, 0, NULL }
 };
 
@@ -236,12 +244,14 @@
      ctype locale.  (P1003.2 4.35.5.2)  */
   setlocale (LC_CTYPE, "POSIX");
 
+#ifndef NO_SYSCONF
   /* Look whether the system really allows locale definitions.  POSIX
      defines error code 3 for this situation so I think it must be
      a fatal error (see P1003.2 4.35.8).  */
   if (sysconf (_SC_2_LOCALEDEF) < 0)
     WITH_CUR_LOCALE (error (3, 0, _("\
 FATAL: system does not define `_POSIX2_LOCALEDEF'")));
+#endif
 
   /* Process charmap file.  */
   charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);
@@ -329,6 +339,15 @@
     case OPT_LIST_ARCHIVE:
       list_archive = true;
       break;
+    case OPT_LITTLE_ENDIAN:
+      set_big_endian (0);
+      break;
+    case OPT_BIG_ENDIAN:
+      set_big_endian (1);
+      break;
+    case OPT_UINT32_ALIGN:
+      uint32_align_mask = strtol (arg, NULL, 0) - 1;
+      break;
     case 'c':
       force_output = 1;
       break;
@@ -370,7 +389,7 @@
 %s"),
 		    CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n")) < 0)
+"REPORT_BUGS_TO".\n")) < 0)
 	return NULL;
       return cp;
     default:
@@ -383,7 +402,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "localedef (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "localedef %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/locale/programs/ld-telephone.c
===================================================================
--- libc/locale/programs/ld-telephone.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-telephone.c	(.../trunk)	(revision 8411)
@@ -175,50 +175,15 @@
 {
   struct locale_telephone_t *telephone =
     locale->categories[LC_TELEPHONE].telephone;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_TELEPHONE);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) telephone->tel_int_fmt;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) telephone->tel_dom_fmt;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) telephone->int_select;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) telephone->int_prefix;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE));
-
-  write_locale_data (output_path, LC_TELEPHONE, "LC_TELEPHONE",
-		     2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE));
+  add_locale_string (&file, telephone->tel_int_fmt);
+  add_locale_string (&file, telephone->tel_dom_fmt);
+  add_locale_string (&file, telephone->int_select);
+  add_locale_string (&file, telephone->int_prefix);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_TELEPHONE, "LC_TELEPHONE", &file);
 }
 
 
Index: libc/locale/programs/ld-collate.c
===================================================================
--- libc/locale/programs/ld-collate.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-collate.c	(.../trunk)	(revision 8411)
@@ -44,7 +44,9 @@
 __attribute ((always_inline))
 obstack_int32_grow (struct obstack *obstack, int32_t data)
 {
-  if (sizeof (int32_t) == sizeof (int))
+  data = maybe_swap_uint32 (data);
+  if (sizeof (int32_t) == sizeof (int)
+      && (obstack_object_size (obstack) & (__alignof__ (int) - 1)) == 0)
     obstack_int_grow (obstack, data);
   else
     obstack_grow (obstack, &data, sizeof (int32_t));
@@ -54,7 +56,9 @@
 __attribute ((always_inline))
 obstack_int32_grow_fast (struct obstack *obstack, int32_t data)
 {
-  if (sizeof (int32_t) == sizeof (int))
+  data = maybe_swap_uint32 (data);
+  if (sizeof (int32_t) == sizeof (int)
+      && (obstack_object_size (obstack) & (__alignof__ (int) - 1)) == 0)
     obstack_int_grow_fast (obstack, data);
   else
     obstack_grow (obstack, &data, sizeof (int32_t));
@@ -344,8 +348,11 @@
     }
   if (wcs != NULL)
     {
-      size_t nwcs = wcslen ((wchar_t *) wcs);
+      size_t nwcs = wcslen_uint32 (wcs);
       uint32_t zero = 0;
+      /* Handle <U0000> as a single character.  */
+      if (nwcs == 0)
+	nwcs = 1;
       obstack_grow (&collate->mempool, wcs, nwcs * sizeof (uint32_t));
       obstack_grow (&collate->mempool, &zero, sizeof (uint32_t));
       newp->wcs = (uint32_t *) obstack_finish (&collate->mempool);
@@ -1185,6 +1192,7 @@
 		{
 		  struct element_t *elem;
 		  size_t namelen;
+		  void *ptr;
 
 		  /* I don't think this can ever happen.  */
 		  assert (seq->name != NULL);
@@ -1197,7 +1205,6 @@
 		  /* Now we are ready to insert the new value in the
 		     sequence.  Find out whether the element is
 		     already known.  */
-		  void *ptr;
 		  if (find_entry (&collate->seq_table, seq->name, namelen,
 				  &ptr) != 0)
 		    {
@@ -1351,13 +1358,13 @@
 	      struct charseq *seq;
 	      uint32_t wc;
 	      int cnt;
+	      void *ptr;
 
 	      /* Generate the name.  */
 	      sprintf (buf + preflen, base == 10 ? "%0*ld" : "%0*lX",
 		       (int) (lenfrom - preflen), from);
 
 	      /* Look whether this name is already defined.  */
-	      void *ptr;
 	      if (find_entry (&collate->seq_table, buf, symlen, &ptr) == 0)
 		{
 		  /* Copy back the result.  */
@@ -1767,8 +1774,7 @@
 
 	      if ((*eptr)->nwcs == runp->nwcs)
 		{
-		  int c = wmemcmp ((wchar_t *) (*eptr)->wcs,
-				   (wchar_t *) runp->wcs, runp->nwcs);
+		  int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs);
 
 		  if (c == 0)
 		    {
@@ -1811,8 +1817,6 @@
       runp = runp->next;
     }
 
-  collseq_table_finalize (&collate->wcseqorder);
-
   /* Now determine whether the UNDEFINED entry is needed and if yes,
      whether it was defined.  */
   collate->undefined.used_in_level = need_undefined ? ~0ul : 0;
@@ -1955,6 +1959,7 @@
       obstack_int32_grow (pool, j);
 
       obstack_grow (pool, buf, j * sizeof (int32_t));
+      maybe_swap_uint32_obstack (pool, j);
     }
 
   return retval | ((elem->section->ruleidx & 0x7f) << 24);
@@ -2003,9 +2008,9 @@
 	     one consecutive entry.  */
 	  if (runp->wcnext != NULL
 	      && runp->nwcs == runp->wcnext->nwcs
-	      && wmemcmp ((wchar_t *) runp->wcs,
-			  (wchar_t *)runp->wcnext->wcs,
-			  runp->nwcs - 1) == 0
+	      && wmemcmp_uint32 (runp->wcs,
+				 runp->wcnext->wcs,
+				 runp->nwcs - 1) == 0
 	      && (runp->wcs[runp->nwcs - 1]
 		  == runp->wcnext->wcs[runp->nwcs - 1] + 1))
 	    {
@@ -2029,9 +2034,9 @@
 		runp = runp->wcnext;
 	      while (runp->wcnext != NULL
 		     && runp->nwcs == runp->wcnext->nwcs
-		     && wmemcmp ((wchar_t *) runp->wcs,
-				 (wchar_t *)runp->wcnext->wcs,
-				 runp->nwcs - 1) == 0
+		     && wmemcmp_uint32 (runp->wcs,
+					runp->wcnext->wcs,
+					runp->nwcs - 1) == 0
 		     && (runp->wcs[runp->nwcs - 1]
 			 == runp->wcnext->wcs[runp->nwcs - 1] + 1));
 
@@ -2098,10 +2103,7 @@
 {
   struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
   const size_t nelems = _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE);
-  struct iovec iov[2 + nelems];
-  struct locale_file data;
-  uint32_t idx[nelems];
-  size_t cnt;
+  struct locale_file file;
   size_t ch;
   int32_t tablemb[256];
   struct obstack weightpool;
@@ -2114,51 +2116,22 @@
   int i;
   struct element_t *runp;
 
-  data.magic = LIMAGIC (LC_COLLATE);
-  data.n = nelems;
-  iov[0].iov_base = (void *) &data;
-  iov[0].iov_len = sizeof (data);
+  init_locale_data (&file, nelems);
+  add_locale_uint32 (&file, nrules);
 
-  iov[1].iov_base = (void *) idx;
-  iov[1].iov_len = sizeof (idx);
-
-  idx[0] = iov[0].iov_len + iov[1].iov_len;
-  cnt = 0;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_NRULES));
-  iov[2 + cnt].iov_base = &nrules;
-  iov[2 + cnt].iov_len = sizeof (uint32_t);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
-
   /* If we have no LC_COLLATE data emit only the number of rules as zero.  */
   if (collate == NULL)
     {
-      int32_t dummy = 0;
-
-      while (cnt < _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE))
+      size_t idx;
+      for (idx = 1; idx < nelems; idx++)
 	{
 	  /* The words have to be handled specially.  */
-	  if (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
-	    {
-	      iov[2 + cnt].iov_base = &dummy;
-	      iov[2 + cnt].iov_len = sizeof (int32_t);
-	    }
+	  if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
+	    add_locale_uint32 (&file, 0);
 	  else
-	    {
-	      iov[2 + cnt].iov_base = NULL;
-	      iov[2 + cnt].iov_len = 0;
-	    }
-
-	  if (cnt + 1 < _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE))
-	    idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-	  ++cnt;
+	    add_locale_empty (&file);
 	}
-
-      assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
-
-      write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", 2 + cnt, iov);
-
+      write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file);
       return;
     }
 
@@ -2184,18 +2157,8 @@
 	  obstack_1grow_fast (&weightpool, sect->rules[j]);
 	++i;
       }
-  /* And align the output.  */
-  i = (nrules * i) % __alignof__ (int32_t);
-  if (i > 0)
-    do
-      obstack_1grow (&weightpool, '\0');
-    while (++i < __alignof__ (int32_t));
 
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_RULESETS));
-  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);
-  iov[2 + cnt].iov_base = obstack_finish (&weightpool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
+  add_locale_raw_obstack (&file, &weightpool);
 
   /* Generate the 8-bit table.  Walk through the lists of sequences
      starting with the same byte and add them one after the other to
@@ -2239,8 +2202,7 @@
 	struct element_t *runp = collate->mbheads[ch];
 	struct element_t *lastp;
 
-	assert ((obstack_object_size (&extrapool)
-		 & (__alignof__ (int32_t) - 1)) == 0);
+	assert ((obstack_object_size (&extrapool) & uint32_align_mask) == 0);
 
 	tablemb[ch] = -obstack_object_size (&extrapool);
 
@@ -2266,10 +2228,10 @@
 
 		/* Compute how much space we will need.  */
 		added = ((sizeof (int32_t) + 1 + 2 * (runp->nmbs - 1)
-			  + __alignof__ (int32_t) - 1)
-			 & ~(__alignof__ (int32_t) - 1));
+			  + uint32_align_mask)
+			 & ~uint32_align_mask);
 		assert ((obstack_object_size (&extrapool)
-			 & (__alignof__ (int32_t) - 1)) == 0);
+			 & uint32_align_mask) == 0);
 		obstack_make_room (&extrapool, added);
 
 		/* More than one consecutive entry.  We mark this by having
@@ -2327,10 +2289,10 @@
 		weightidx = output_weight (&weightpool, collate, runp);
 
 		added = ((sizeof (int32_t) + 1 + runp->nmbs - 1
-			  + __alignof__ (int32_t) - 1)
-			 & ~(__alignof__ (int32_t) - 1));
+			  + uint32_align_mask)
+			 & ~uint32_align_mask);
 		assert ((obstack_object_size (&extrapool)
-			 & (__alignof__ (int32_t) - 1)) == 0);
+			 & uint32_align_mask) == 0);
 		obstack_make_room (&extrapool, added);
 
 		obstack_int32_grow_fast (&extrapool, weightidx);
@@ -2342,8 +2304,7 @@
 	      }
 
 	    /* Add alignment bytes if necessary.  */
-	    while ((obstack_object_size (&extrapool)
-		    & (__alignof__ (int32_t) - 1)) != 0)
+	    while ((obstack_object_size (&extrapool) & uint32_align_mask) != 0)
 	      obstack_1grow_fast (&extrapool, '\0');
 
 	    /* Next entry.  */
@@ -2352,15 +2313,14 @@
 	  }
 	while (runp != NULL);
 
-	assert ((obstack_object_size (&extrapool)
-		 & (__alignof__ (int32_t) - 1)) == 0);
+	assert ((obstack_object_size (&extrapool) & uint32_align_mask) == 0);
 
 	/* If the final entry in the list is not a single character we
            add an UNDEFINED entry here.  */
 	if (lastp->nmbs != 1)
 	  {
-	    int added = ((sizeof (int32_t) + 1 + 1 + __alignof__ (int32_t) - 1)
-			 & ~(__alignof__ (int32_t) - 1));
+	    int added = ((sizeof (int32_t) + 1 + 1 + uint32_align_mask)
+			 & ~uint32_align_mask);
 	    obstack_make_room (&extrapool, added);
 
 	    obstack_int32_grow_fast (&extrapool, 0);
@@ -2370,68 +2330,27 @@
 	    obstack_1grow_fast (&extrapool, 0);
 
 	    /* Add alignment bytes if necessary.  */
-	    while ((obstack_object_size (&extrapool)
-		    & (__alignof__ (int32_t) - 1)) != 0)
+	    while ((obstack_object_size (&extrapool) & uint32_align_mask) != 0)
 	      obstack_1grow_fast (&extrapool, '\0');
 	  }
       }
 
   /* Add padding to the tables if necessary.  */
-  while ((obstack_object_size (&weightpool) & (__alignof__ (int32_t) - 1))
-	 != 0)
+  while ((obstack_object_size (&weightpool) & uint32_align_mask) != 0)
     obstack_1grow (&weightpool, 0);
 
   /* Now add the four tables.  */
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_TABLEMB));
-  iov[2 + cnt].iov_base = tablemb;
-  iov[2 + cnt].iov_len = sizeof (tablemb);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert ((iov[2 + cnt].iov_len & (__alignof__ (int32_t) - 1)) == 0);
-  ++cnt;
+  add_locale_uint32_array (&file, tablemb, 256);
+  add_locale_raw_obstack (&file, &weightpool);
+  add_locale_raw_obstack (&file, &extrapool);
+  add_locale_raw_obstack (&file, &indirectpool);
 
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_WEIGHTMB));
-  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);
-  iov[2 + cnt].iov_base = obstack_finish (&weightpool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_EXTRAMB));
-  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);
-  iov[2 + cnt].iov_base = obstack_finish (&extrapool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_INDIRECTMB));
-  iov[2 + cnt].iov_len = obstack_object_size (&indirectpool);
-  iov[2 + cnt].iov_base = obstack_finish (&indirectpool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert ((iov[2 + cnt].iov_len & (__alignof__ (int32_t) - 1)) == 0);
-  ++cnt;
-
-
   /* Now the same for the wide character table.  We need to store some
      more information here.  */
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_GAP1));
-  iov[2 + cnt].iov_base = NULL;
-  iov[2 + cnt].iov_len = 0;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
+  add_locale_empty (&file);
+  add_locale_empty (&file);
+  add_locale_empty (&file);
 
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_GAP2));
-  iov[2 + cnt].iov_base = NULL;
-  iov[2 + cnt].iov_len = 0;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_GAP3));
-  iov[2 + cnt].iov_base = NULL;
-  iov[2 + cnt].iov_len = 0;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
   /* Since we are using the sign of an integer to mark indirection the
      offsets in the arrays we are indirectly referring to must not be
      zero since -0 == 0.  Therefore we add a bit of dummy content.  */
@@ -2462,42 +2381,12 @@
 
   memset (&atwc, 0, sizeof (atwc));
 
-  collidx_table_finalize (&tablewc);
-
   /* Now add the four tables.  */
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_TABLEWC));
-  iov[2 + cnt].iov_base = tablewc.result;
-  iov[2 + cnt].iov_len = tablewc.result_size;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
+  add_locale_collidx_table (&file, &tablewc);
+  add_locale_raw_obstack (&file, &weightpool);
+  add_locale_raw_obstack (&file, &extrapool);
+  add_locale_raw_obstack (&file, &indirectpool);
 
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_WEIGHTWC));
-  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);
-  iov[2 + cnt].iov_base = obstack_finish (&weightpool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_EXTRAWC));
-  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);
-  iov[2 + cnt].iov_base = obstack_finish (&extrapool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_INDIRECTWC));
-  iov[2 + cnt].iov_len = obstack_object_size (&indirectpool);
-  iov[2 + cnt].iov_base = obstack_finish (&indirectpool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-
   /* Finally write the table with collation element names out.  It is
      a hash table with a simple function which gets the name of the
      character as the input.  One character might have many names.  The
@@ -2586,6 +2475,7 @@
 	  obstack_int32_grow (&extrapool, runp->nwcs);
 	  obstack_grow (&extrapool, runp->wcs,
 			runp->nwcs * sizeof (uint32_t));
+	  maybe_swap_uint32_obstack (&extrapool, runp->nwcs);
 
 	  obstack_int32_grow (&extrapool, runp->wcseqorder);
 	}
@@ -2594,48 +2484,14 @@
     }
 
   /* Prepare to write out this data.  */
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB));
-  iov[2 + cnt].iov_base = &elem_size;
-  iov[2 + cnt].iov_len = sizeof (int32_t);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
+  add_locale_uint32 (&file, elem_size);
+  add_locale_uint32_array (&file, elem_table, 2 * elem_size);
+  add_locale_raw_obstack (&file, &extrapool);
+  add_locale_raw_data (&file, collate->mbseqorder, 256);
+  add_locale_collseq_table (&file, &collate->wcseqorder);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file);
 
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_TABLEMB));
-  iov[2 + cnt].iov_base = elem_table;
-  iov[2 + cnt].iov_len = elem_size * 2 * sizeof (int32_t);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_EXTRAMB));
-  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);
-  iov[2 + cnt].iov_base = obstack_finish (&extrapool);
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQMB));
-  iov[2 + cnt].iov_base = collate->mbseqorder;
-  iov[2 + cnt].iov_len = 256;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQWC));
-  iov[2 + cnt].iov_base = collate->wcseqorder.result;
-  iov[2 + cnt].iov_len = collate->wcseqorder.result_size;
-  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
-  assert (idx[cnt] % __alignof__ (int32_t) == 0);
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_CODESET));
-  iov[2 + cnt].iov_base = (void *) charmap->code_set_name;
-  iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
-
-  write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", 2 + cnt, iov);
-
   obstack_free (&weightpool, NULL);
   obstack_free (&extrapool, NULL);
   obstack_free (&indirectpool, NULL);
Index: libc/locale/programs/ld-address.c
===================================================================
--- libc/locale/programs/ld-address.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-address.c	(.../trunk)	(revision 8411)
@@ -349,97 +349,23 @@
 		const char *output_path)
 {
   struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
-  struct iovec iov[3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_ADDRESS);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = (void *) address->postal_fmt;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_post;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_ab2;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_ab3;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_car;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-
-  /* Align following data */
-  iov[cnt].iov_base = (void *) "\0\0";
-  iov[cnt].iov_len = ((idx[cnt - 2] + 3) & ~3) - idx[cnt - 2];
-  idx[cnt - 2] = (idx[cnt - 2] + 3) & ~3;
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) &address->country_num;
-  iov[cnt].iov_len = sizeof (uint32_t);
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->country_isbn;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->lang_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->lang_ab;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->lang_term;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) address->lang_lib;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  idx[cnt - 3] = idx[cnt - 4] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
-
-  write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS",
-		     3 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
+  add_locale_string (&file, address->postal_fmt);
+  add_locale_string (&file, address->country_name);
+  add_locale_string (&file, address->country_post);
+  add_locale_string (&file, address->country_ab2);
+  add_locale_string (&file, address->country_ab3);
+  add_locale_string (&file, address->country_car);
+  add_locale_uint32 (&file, address->country_num);
+  add_locale_string (&file, address->country_isbn);
+  add_locale_string (&file, address->lang_name);
+  add_locale_string (&file, address->lang_ab);
+  add_locale_string (&file, address->lang_term);
+  add_locale_string (&file, address->lang_lib);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_ADDRESS, "LC_ADDRESS", &file);
 }
 
 
Index: libc/locale/programs/ld-measurement.c
===================================================================
--- libc/locale/programs/ld-measurement.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/ld-measurement.c	(.../trunk)	(revision 8411)
@@ -122,35 +122,12 @@
 {
   struct locale_measurement_t *measurement =
     locale->categories[LC_MEASUREMENT].measurement;
-  struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT)];
-  struct locale_file data;
-  uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT)];
-  size_t cnt = 0;
+  struct locale_file file;
 
-  data.magic = LIMAGIC (LC_MEASUREMENT);
-  data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT);
-  iov[cnt].iov_base = (void *) &data;
-  iov[cnt].iov_len = sizeof (data);
-  ++cnt;
-
-  iov[cnt].iov_base = (void *) idx;
-  iov[cnt].iov_len = sizeof (idx);
-  ++cnt;
-
-  idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
-  iov[cnt].iov_base = &measurement->measurement;
-  iov[cnt].iov_len = 1;
-  ++cnt;
-
-  idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
-  iov[cnt].iov_base = (void *) charmap->code_set_name;
-  iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
-  ++cnt;
-
-  assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT));
-
-  write_locale_data (output_path, LC_MEASUREMENT, "LC_MEASUREMENT",
-		     2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT), iov);
+  init_locale_data (&file, _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT));
+  add_locale_char (&file, measurement->measurement);
+  add_locale_string (&file, charmap->code_set_name);
+  write_locale_data (output_path, LC_MEASUREMENT, "LC_MEASUREMENT", &file);
 }
 
 
Index: libc/locale/programs/charmap-dir.c
===================================================================
--- libc/locale/programs/charmap-dir.c	(.../fsf/trunk)	(revision 8411)
+++ libc/locale/programs/charmap-dir.c	(.../trunk)	(revision 8411)
@@ -21,7 +21,9 @@
 #include <error.h>
 #include <fcntl.h>
 #include <libintl.h>
+#ifndef NO_UNCOMPRESS
 #include <spawn.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -158,6 +160,7 @@
   return closedir (dir);
 }
 
+#ifndef NO_UNCOMPRESS
 /* Creates a subprocess decompressing the given pathname, and returns
    a stream reading its output (the decompressed data).  */
 static
@@ -206,6 +209,7 @@
     }
   return NULL;
 }
+#endif
 
 /* Opens a charmap for reading, given its name (not an alias name).  */
 FILE *
@@ -228,6 +232,7 @@
   if (stream != NULL)
     return stream;
 
+#ifndef NO_UNCOMPRESS
   memcpy (p, ".gz", 4);
   stream = fopen_uncompressed (pathname, "gzip");
   if (stream != NULL)
@@ -237,6 +242,7 @@
   stream = fopen_uncompressed (pathname, "bzip2");
   if (stream != NULL)
     return stream;
+#endif
 
   return NULL;
 }
@@ -265,8 +271,8 @@
       char *alias = NULL;
       char junk[BUFSIZ];
 
-      if (fscanf (stream, " <code_set_name> %ms", &alias) == 1
-          || fscanf (stream, "%% alias %ms", &alias) == 1)
+      if (fscanf (stream, " <code_set_name> %as", &alias) == 1
+          || fscanf (stream, "%% alias %as", &alias) == 1)
         {
           aliases = (char **) xrealloc (aliases,
                                         (naliases + 2) * sizeof (char *));
Index: libc/INSTALL
===================================================================
--- libc/INSTALL	(.../fsf/trunk)	(revision 8411)
+++ libc/INSTALL	(.../trunk)	(revision 8411)
@@ -1,3 +1,15 @@
+Installing EGLIBC
+*****************
+
+This is EGLIBC, a variant of the GNU C Library (GLIBC) that is
+designed to work well on embedded systems.  This file contains the
+original GLIBC installation instructions, which mostly deal with
+native develelopment.  'EGLIBC.cross-building' provides general
+instructions for building EGLIBC and an accompanying compiler for
+cross-development.
+
+Here are the original GLIBC installation instructions:
+
 Installing the GNU C Library
 ****************************
 
Index: libc/dlfcn/Makefile
===================================================================
--- libc/dlfcn/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/dlfcn/Makefile	(.../trunk)	(revision 8411)
@@ -16,6 +16,8 @@
 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 # 02111-1307 USA.
 
+include ../option-groups.mak
+
 subdir		:= dlfcn
 headers		:= bits/dlfcn.h dlfcn.h
 extra-libs	:= libdl
@@ -42,7 +44,9 @@
 ifeq (yes,$(build-shared))
 tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
 	bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
-	bug-atexit3 tstatexit
+	tstatexit
+
+tests-$(OPTION_EGLIBC_CXX_TESTS) += bug-atexit3 
 endif
 modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
 		defaultmod2 errmsg1mod modatexit modcxaatexit \
@@ -57,8 +61,10 @@
 tests += tststatic tststatic2
 tests-static += tststatic tststatic2
 modules-names += modstatic modstatic2
-tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
-tststatic2-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic-ENV = EGLIBC_TEST_LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic-WRAPPER = $(..)scripts/run-with-env.sh
+tststatic2-ENV = EGLIBC_TEST_LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+tststatic2-WRAPPER = $(..)scripts/run-with-env.sh
 endif
 
 extra-test-objs += $(modules-names:=.os)
Index: libc/Makerules
===================================================================
--- libc/Makerules	(.../fsf/trunk)	(revision 8411)
+++ libc/Makerules	(.../trunk)	(revision 8411)
@@ -391,6 +391,24 @@
 endef
 endif
 
+# Include targets in the selected option groups.
+aux                  += $(aux-y)
+extra-libs           += $(extra-libs-y)
+extra-libs-others    += $(extra-libs-others-y)
+extra-objs           += $(extra-objs-y)
+install-bin          += $(install-bin-y)
+install-others       += $(install-others-y)
+install-sbin         += $(install-sbin-y)
+modules              += $(modules-y)
+others               += $(others-y)
+routines             += $(routines-y)
+static-only-routines += $(static-only-routines-y)
+sysdep_routines      += $(sysdep_routines-y)
+test-srcs            += $(test-srcs-y)
+tests                += $(tests-y)
+xtests               += $(xtests-y)
+
+
 # Modify the list of routines we build for different targets
 
 ifeq (yesyes,$(build-shared)$(elf))
@@ -608,6 +626,9 @@
 $(common-objpfx)libc.so: $(common-objpfx)libc.map
 endif
 common-generated += libc.so libc_pic.os
+ifndef subdir
+install-extras := soinit.o sofini.o
+endif
 ifdef libc.so-version
 $(common-objpfx)libc.so$(libc.so-version): $(common-objpfx)libc.so
 	$(make-link)
@@ -853,6 +874,7 @@
 installed-libcs := $(foreach o,$(filter-out .os,$(object-suffixes-for-libc)),\
 			     $(inst_libdir)/$(patsubst %,$(libtype$o),\
 						     $(libprefix)$(libc-name)))
+installed-libcs := $(installed-libcs) $(inst_libdir)/libc_pic.a
 install: $(installed-libcs)
 $(installed-libcs): $(inst_libdir)/lib$(libprefix)%: lib $(+force)
 	$(make-target-directory)
@@ -884,6 +906,22 @@
 install-lib.so-versioned := $(filter $(versioned), $(install-lib.so))
 install-lib.so-unversioned := $(filter-out $(versioned), $(install-lib.so))
 
+# Install the _pic.a files for versioned libraries, and corresponding
+# .map files.
+# libpthread_pic.a breaks mklibs, so don't install it and its map.
+install-lib := $(install-lib) $(install-lib.so-versioned:%.so=%_pic.a)
+install-lib := $(filter-out libpthread_pic.a,$(install-lib))
+# Despite having a soname libhurduser and libmachuser do not use symbol
+# versioning, so don't install the corresponding .map files.
+ifeq ($(versioning),yes)
+install-map := $(patsubst %.so,%.map,\
+			$(foreach L,$(install-lib.so-versioned),$(notdir $L)))
+install-map := $(filter-out libhurduser.map libmachuser.map libpthread.map,$(install-map))
+ifndef subdir
+install-map := $(install-map) libc.map
+endif
+endif
+
 # For versioned libraries, we install three files:
 #	$(inst_libdir)/libfoo.so	-- for linking, symlink or ld script
 #	$(inst_slibdir)/libfoo.so.NN	-- for loading by SONAME, symlink
@@ -1119,9 +1157,22 @@
 endif	# headers-nonh
 endif	# headers
 
+ifdef install-map
+$(addprefix $(inst_libdir)/,$(patsubst lib%.map,lib%_pic.map,$(install-map))): \
+  $(inst_libdir)/lib%_pic.map: $(common-objpfx)lib%.map $(+force)
+	$(do-install)
+endif
+
+ifdef install-extras
+$(addprefix $(inst_libdir)/libc_pic/,$(install-extras)): \
+  $(inst_libdir)/libc_pic/%.o: $(elfobjdir)/%.os $(+force)
+	$(do-install)
+endif
+
 .PHONY: install-bin-nosubdir install-bin-script-nosubdir \
 	install-rootsbin-nosubdir install-sbin-nosubdir install-lib-nosubdir \
-	install-data-nosubdir install-headers-nosubdir
+	install-data-nosubdir install-headers-nosubdir install-map-nosubdir \
+	install-extras-nosubdir
 install-bin-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin))
 install-bin-script-nosubdir: $(addprefix $(inst_bindir)/,$(install-bin-script))
 install-rootsbin-nosubdir: \
@@ -1134,6 +1185,10 @@
 install-headers-nosubdir: $(addprefix $(inst_includedir)/,$(headers))
 install-others-nosubdir: $(install-others)
 install-others-programs-nosubdir: $(install-others-programs)
+install-map-nosubdir: $(addprefix $(inst_libdir)/,\
+		       $(patsubst lib%.map,lib%_pic.map,$(install-map)))
+install-extras-nosubdir: $(addprefix $(inst_libdir)/libc_pic/,\
+		       $(install-extras))
 
 # We need all the `-nosubdir' targets so that `install' in the parent
 # doesn't depend on several things which each iterate over the subdirs.
@@ -1143,7 +1198,8 @@
 
 .PHONY: install install-no-libc.a-nosubdir
 install-no-libc.a-nosubdir: install-headers-nosubdir install-data-nosubdir \
-			    install-lib-nosubdir install-others-nosubdir
+			    install-lib-nosubdir install-others-nosubdir \
+			    install-map-nosubdir install-extras-nosubdir
 ifeq ($(build-programs),yes)
 install-no-libc.a-nosubdir: install-bin-nosubdir install-bin-script-nosubdir \
 			    install-rootsbin-nosubdir install-sbin-nosubdir \
Index: libc/argp/argp-help.c
===================================================================
--- libc/argp/argp-help.c	(.../fsf/trunk)	(revision 8411)
+++ libc/argp/argp-help.c	(.../trunk)	(revision 8411)
@@ -52,6 +52,7 @@
 #ifdef _LIBC
 # include <../libio/libioP.h>
 # include <wchar.h>
+# include <gnu/option-groups.h>
 #endif
 
 #ifndef _
@@ -1703,7 +1704,7 @@
 }
 
 char *
-__argp_short_program_name (void)
+(__argp_short_program_name) (void)
 {
 # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
   return program_invocation_short_name;
@@ -1876,7 +1877,13 @@
 
 #ifdef USE_IN_LIBIO
 	  if (_IO_fwide (stream, 0) > 0)
-	    putwc_unlocked (L'\n', stream);
+            {
+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+              putwc_unlocked (L'\n', stream);
+#else
+              abort ();
+#endif
+            }
 	  else
 #endif
 	    putc_unlocked ('\n', stream);
Index: libc/argp/argp-namefrob.h
===================================================================
--- libc/argp/argp-namefrob.h	(.../fsf/trunk)	(revision 8411)
+++ libc/argp/argp-namefrob.h	(.../trunk)	(revision 8411)
@@ -77,10 +77,12 @@
 #undef __argp_fmtstream_wmargin
 #define __argp_fmtstream_wmargin argp_fmtstream_wmargin
 
+#if 0
 #include "mempcpy.h"
 #include "strcase.h"
 #include "strchrnul.h"
 #include "strndup.h"
+#endif
 
 /* normal libc functions we call */
 #undef __flockfile
Index: libc/argp/argp-fmtstream.c
===================================================================
--- libc/argp/argp-fmtstream.c	(.../fsf/trunk)	(revision 8411)
+++ libc/argp/argp-fmtstream.c	(.../trunk)	(revision 8411)
@@ -43,6 +43,7 @@
 #if defined _LIBC && defined USE_IN_LIBIO
 # include <wchar.h>
 # include <libio/libioP.h>
+# include <gnu/option-groups.h>
 # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
 #endif
 
@@ -152,7 +153,13 @@
 		{
 #ifdef USE_IN_LIBIO
 		  if (_IO_fwide (fs->stream, 0) > 0)
-		    putwc_unlocked (L' ', fs->stream);
+                    {
+#if ! _LIBC || __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+                      putwc_unlocked (L' ', fs->stream);
+#else
+                      abort ();
+#endif
+                    }
 		  else
 #endif
 		    putc_unlocked (' ', fs->stream);
@@ -317,7 +324,13 @@
 	    for (i = 0; i < fs->wmargin; ++i)
 #ifdef USE_IN_LIBIO
 	      if (_IO_fwide (fs->stream, 0) > 0)
-		putwc_unlocked (L' ', fs->stream);
+                {
+#ifdef OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+                  putwc_unlocked (L' ', fs->stream);
+#else
+                  abort ();
+#endif
+                }
 	      else
 #endif
 		putc_unlocked (' ', fs->stream);
Index: libc/argp/Makefile
===================================================================
--- libc/argp/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/argp/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for argp.
 #
+include ../option-groups.mak
+
 subdir	:= argp
 
 headers		= argp.h
Index: libc/csu/version.c
===================================================================
--- libc/csu/version.c	(.../fsf/trunk)	(revision 8411)
+++ libc/csu/version.c	(.../trunk)	(revision 8411)
@@ -24,7 +24,7 @@
 static const char __libc_version[] = VERSION;
 
 static const char banner[] =
-"GNU C Library "RELEASE" release version "VERSION", by Roland McGrath et al.\n\
+"GNU C Library "PKGVERSION RELEASE" release version "VERSION", by Roland McGrath et al.\n\
 Copyright (C) 2009 Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.\n\
 There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
@@ -35,7 +35,7 @@
 "The oldest ABI supported: " GLIBC_OLDEST_ABI ".\n"
 #endif
 "For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n";
+"REPORT_BUGS_TO".\n";
 
 #include <unistd.h>
 
Index: libc/csu/Makefile
===================================================================
--- libc/csu/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/csu/Makefile	(.../trunk)	(revision 8411)
@@ -104,12 +104,12 @@
 # We only have one kind of startup code files.	Static binaries and
 # shared libraries are build using the PIC version.
 $(objpfx)crti.S: $(objpfx)initfini.s
-	sed -n -e '1,/@HEADER_ENDS/p' \
+	sed -n -e '/^[ 	]*\.file[ 	]/d' -e '1,/@HEADER_ENDS/p' \
 	       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
 	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
 
 $(objpfx)crtn.S: $(objpfx)initfini.s
-	sed -n -e '1,/@HEADER_ENDS/p' \
+	sed -n -e '/^[ 	]*\.file[ 	]/d' -e '1,/@HEADER_ENDS/p' \
 	       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
 	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
 
Index: libc/option-groups.defaults
===================================================================
--- libc/option-groups.defaults	(.../fsf/trunk)	(revision 0)
+++ libc/option-groups.defaults	(.../trunk)	(revision 8411)
@@ -0,0 +1,40 @@
+# This file sets default values for all option group variables
+# mentioned in option-groups.def; see that file for a description of
+# each option group.
+#
+# Subdirectory makefiles include this file before including the user's
+# settings from option-groups.config at the top of the build tree;
+# that file need only refer to those options whose default settings
+# are to be changed.
+#
+# By default, all option groups are enabled.
+OPTION_EGLIBC_ADVANCED_INET6 = y
+OPTION_EGLIBC_BACKTRACE = y
+OPTION_EGLIBC_BSD = y
+OPTION_EGLIBC_CXX_TESTS = y
+OPTION_EGLIBC_CATGETS = y
+OPTION_EGLIBC_CHARSETS = y
+OPTION_EGLIBC_DB_ALIASES = y
+OPTION_EGLIBC_ENVZ = y
+OPTION_EGLIBC_FCVT = y
+OPTION_EGLIBC_FMTMSG = y
+OPTION_EGLIBC_FSTAB = y
+OPTION_EGLIBC_FTRAVERSE = y
+OPTION_EGLIBC_GETLOGIN = y
+OPTION_EGLIBC_INET = y
+OPTION_EGLIBC_LIBM = y
+OPTION_EGLIBC_LOCALES = y
+OPTION_EGLIBC_LOCALE_CODE = y
+OPTION_EGLIBC_NIS = y
+OPTION_EGLIBC_NSSWITCH = y
+OPTION_EGLIBC_RCMD = y
+OPTION_EGLIBC_SPAWN = y
+OPTION_EGLIBC_STREAMS = y
+OPTION_EGLIBC_SUNRPC = y
+OPTION_EGLIBC_UTMP = y
+OPTION_EGLIBC_UTMPX = y
+OPTION_EGLIBC_WORDEXP = y
+OPTION_POSIX_C_LANG_WIDE_CHAR = y
+OPTION_POSIX_REGEXP = y
+OPTION_POSIX_REGEXP_GLIBC = y
+OPTION_POSIX_WIDE_CHAR_DEVICE_IO = y
Index: libc/extra-lib.mk
===================================================================
--- libc/extra-lib.mk	(.../fsf/trunk)	(revision 8411)
+++ libc/extra-lib.mk	(.../trunk)	(revision 8411)
@@ -25,7 +25,9 @@
 extra-objs := $(extra-objs)
 
 # The modules that go in $(lib).
-all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines)
+all-$(lib)-routines := $($(lib)-routines)		\
+	               $($(lib)-routines-y)		\
+		       $($(lib)-sysdep_routines)
 
 # Add each flavor of library to the lists of things to build and install.
 install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
@@ -96,7 +98,7 @@
 endif
 
 # This will define `libof-ROUTINE := LIB' for each of the routines.
-cpp-srcs-left := $($(lib)-routines) $($(lib)-sysdep_routines)
+cpp-srcs-left := $(all-$(lib)-routines)
 ifneq (,$(cpp-srcs-left))
 include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
 endif
Index: libc/README
===================================================================
--- libc/README	(.../fsf/trunk)	(revision 8411)
+++ libc/README	(.../trunk)	(revision 8411)
@@ -1,3 +1,31 @@
+This directory contains the Embedded GNU C Library (EGLIBC).
+
+EGLIBC is a variant of the GNU C Library (GLIBC) that is designed to
+work well on embedded systems. EGLIBC strives to be source and binary
+compatible with GLIBC. EGLIBC's goals include reduced footprint,
+configurable components, better support for cross-compilation and
+cross-testing.  More information is available at
+http://www.eglibc.org.
+
+Files in this directory describe EGLIBC's features for embedded
+developers:
+
+- EGLIBC.cross-building provides general instructions for building
+  EGLIBC and an accompanying compiler for cross-development.  (And
+  explains why this isn't as simple as 'configure; make'.)
+
+- EGLIBC.option-groups explains EGLIBC's facilities for paring down
+  the library functionality to the features you really need, to reduce
+  disk and memory consumption.  (A one-line file disabling the
+  OPTION_EGLIBC_LOCALES option reduces the on-disk footprint of EGLIBC
+  by 92%.)
+
+- EGLIBC.cross-testing explains how to test a cross-compiled EGLIBC.
+
+Here is the original GLIBC README:
+
+---
+
 This directory contains the sources of the GNU C Library.
 See the file "version.h" for what release version you have.
 
Index: libc/malloc/memusagestat.c
===================================================================
--- libc/malloc/memusagestat.c	(.../fsf/trunk)	(revision 8411)
+++ libc/malloc/memusagestat.c	(.../trunk)	(revision 8411)
@@ -523,20 +523,17 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
-  char *orig;
-  char *cp;
+  char *tp;
 
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      orig = gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n");
-      cp = strdup (orig);
-      if (cp == NULL)
-	cp = orig;
-      return cp;
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -547,7 +544,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "memusagestat (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "memusagestat %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/malloc/mtrace.pl
===================================================================
--- libc/malloc/mtrace.pl	(.../fsf/trunk)	(revision 8411)
+++ libc/malloc/mtrace.pl	(.../trunk)	(revision 8411)
@@ -22,7 +22,8 @@
 # 02111-1307 USA.
 
 $VERSION = "@VERSION@";
-$PACKAGE = "libc";
+$PKGVERSION = "@PKGVERSION@";
+$REPORT_BUGS_TO = '@REPORT_BUGS_TO@';
 $progname = $0;
 
 sub usage {
@@ -31,7 +32,7 @@
     print "  --version    print version number, then exit\n";
     print "\n";
     print "For bug reporting instructions, please see:\n";
-    print "<http://www.gnu.org/software/libc/bugs.html>.\n";
+    print "$REPORT_BUGS_TO.\n";
     exit 0;
 }
 
@@ -44,7 +45,7 @@
     if ($ARGV[0] eq "--v" || $ARGV[0] eq "--ve" || $ARGV[0] eq "--ver" ||
 	$ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" ||
 	$ARGV[0] eq "--versio" || $ARGV[0] eq "--version") {
-	print "mtrace (GNU $PACKAGE) $VERSION\n";
+	print "mtrace $PKGVERSION$VERSION\n";
 	print "Copyright (C) 2009 Free Software Foundation, Inc.\n";
 	print "This is free software; see the source for copying conditions.  There is NO\n";
 	print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
Index: libc/malloc/tst-mtrace.sh
===================================================================
--- libc/malloc/tst-mtrace.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/malloc/tst-mtrace.sh	(.../trunk)	(revision 8411)
@@ -20,12 +20,14 @@
 # 02111-1307 USA.
 
 common_objpfx=$1; shift
+cross_test_wrapper="$1"; shift
 
 status=0
 trap "rm -f ${common_objpfx}malloc/tst-mtrace.leak; exit 1" 1 2 15
 
 MALLOC_TRACE=${common_objpfx}malloc/tst-mtrace.leak \
 LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}iconvdata \
+${cross_test_wrapper} \
 ${common_objpfx}elf/ld.so --library-path $common_objpfx \
   ${common_objpfx}malloc/tst-mtrace || status=1
 
Index: libc/malloc/memusage.sh
===================================================================
--- libc/malloc/memusage.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/malloc/memusage.sh	(.../trunk)	(revision 8411)
@@ -36,7 +36,7 @@
 
 # Print help message
 do_help() {
-  echo $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
+  printf $"Usage: memusage [OPTION]... PROGRAM [PROGRAMOPTION]...
 Profile memory usage of PROGRAM.
 
    -n,--progname=NAME     Name of the program file to profile
@@ -62,14 +62,14 @@
 short options.
 
 "
-  print $"For bug reporting instructions, please see:
-<http://www.gnu.org/software/libc/bugs.html>.
-"
+  printf $"For bug reporting instructions, please see:
+%s.
+" "@REPORT_BUGS_TO@"
   exit 0
 }
 
 do_version() {
-  echo 'memusage (GNU libc) @VERSION@'
+  echo 'memusage @PKGVERSION@@VERSION@'
   printf $"Copyright (C) %s Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Index: libc/malloc/Makefile
===================================================================
--- libc/malloc/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/malloc/Makefile	(.../trunk)	(revision 8411)
@@ -112,15 +112,15 @@
 
 lib: $(objpfx)libmcheck.a
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 ifeq (yes,$(build-shared))
 ifneq ($(PERL),no)
 tests: $(objpfx)tst-mtrace.out
 $(objpfx)tst-mtrace.out: tst-mtrace.sh $(objpfx)tst-mtrace
-	$(SHELL) -e $< $(common-objpfx)
+	$(SHELL) -e $< $(common-objpfx) '$(cross-test-wrapper)'
 endif
 endif
-endif
+# eglibc: endif
 
 tst-mcheck-ENV = MALLOC_CHECK_=3
 
@@ -135,13 +135,17 @@
 $(objpfx)mtrace: mtrace.pl
 	rm -f $@.new
 	sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \
-	    -e 's|@VERSION@|$(version)|' $^ > $@.new \
+	    -e 's|@VERSION@|$(version)|' \
+	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
+	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
 	&& rm -f $@ && mv $@.new $@ && chmod +x $@
 
 $(objpfx)memusage: memusage.sh
 	rm -f $@.new
 	sed -e 's|@BASH@|$(BASH)|' -e 's|@VERSION@|$(version)|' \
-	    -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \
+	    -e 's|@SLIBDIR@|$(sLIBdir)|' -e 's|@BINDIR@|$(bindir)|' \
+	    -e 's|@PKGVERSION@|$(PKGVERSION)|' \
+	    -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
 	&& rm -f $@ && mv $@.new $@ && chmod +x $@
 
 
Index: libc/nptl/tst-cancel-wrappers.sh
===================================================================
--- libc/nptl/tst-cancel-wrappers.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/tst-cancel-wrappers.sh	(.../trunk)	(revision 8411)
@@ -19,8 +19,9 @@
 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 # 02111-1307 USA.
 
+nm="$1"; shift
 while [ $# -gt 0 ]; do
-  ( nm -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
+  ( $nm -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
 C["accept"]=1
 C["close"]=1
 C["connect"]=1
Index: libc/nptl/Makefile
===================================================================
--- libc/nptl/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/Makefile	(.../trunk)	(revision 8411)
@@ -20,6 +20,8 @@
 #
 #	Sub-makefile for NPTL portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= nptl
 
 headers := pthread.h semaphore.h bits/semaphore.h
@@ -113,7 +115,7 @@
 		      pt-raise pt-system \
 		      flockfile ftrylockfile funlockfile \
 		      sigaction \
-		      herrno res pt-allocrtsig \
+		      pt-allocrtsig \
 		      pthread_kill_other_threads \
 		      pthread_getaffinity pthread_setaffinity \
 		      pthread_attr_getaffinity pthread_attr_setaffinity \
@@ -130,6 +132,8 @@
 #		      pthread_setgid pthread_setegid pthread_setregid \
 #		      pthread_setresgid
 
+libpthread-routines-$(OPTION_EGLIBC_INET) := herrno res 
+
 libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind
 libpthread-static-only-routines = pthread_atfork
 
@@ -234,31 +238,41 @@
 	tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
 	tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
 	tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
-	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
+	tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel25 \
 	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
 	tst-flock1 tst-flock2 \
 	tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
 	tst-signal6 tst-signal7 \
-	tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
+	tst-exec2 tst-exec3 tst-exec4 \
 	tst-exit1 tst-exit2 tst-exit3 \
 	tst-stdio1 tst-stdio2 \
 	tst-stack1 tst-stack2 tst-stack3 \
 	tst-unload \
 	tst-dlsym1 \
 	tst-sysconf \
-	tst-locale1 tst-locale2 \
+	tst-locale2 \
 	tst-umask1 \
 	tst-popen1 \
 	tst-clock1 \
 	tst-context1 \
 	tst-sched1 \
-	tst-backtrace1 \
 	tst-oddstacklimit \
 	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
 	tst-getpid1 tst-getpid2 tst-getpid3 \
 	tst-initializers1 $(patsubst %,tst-initializers1-%,c89 gnu89 c99 gnu99)
 xtests = tst-setuid1 tst-setuid1-static tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
 
+# This test uses the posix_spawn functions.
+tests-$(OPTION_EGLIBC_SPAWN) += tst-exec1
+
+# This test uses the 'backtrace' functions.
+tests-$(OPTION_EGLIBC_BACKTRACE) += tst-backtrace1
+
+# This test is written in C++.
+tests-$(OPTION_EGLIBC_CXX_TESTS) += tst-cancel24
+
+tests-$(OPTION_EGLIBC_LOCALE_CODE) += tst-locale1 
+
 # Files which must not be linked with libpthread.
 tests-nolibpthread = tst-unload
 
@@ -433,7 +447,7 @@
 CFLAGS-tst-initializers1-gnu89.c = $(CFLAGS-tst-initializers1-<)
 CFLAGS-tst-initializers1-gnu99.c = $(CFLAGS-tst-initializers1-<)
 
-tst-cancel7-ARGS = --command "$(built-program-cmd)"
+tst-cancel7-ARGS = --command "exec $(local-built-program-cmd)"
 tst-cancelx7-ARGS = $(tst-cancel7-ARGS)
 tst-umask1-ARGS = $(objpfx)tst-umask1.temp
 
@@ -469,7 +483,8 @@
 		       $(objpfx)tst-tls5modc.so $(objpfx)tst-tls5modd.so \
 		       $(objpfx)tst-tls5mode.so $(objpfx)tst-tls5modf.so
 	$(SHELL) -e tst-tls6.sh $(common-objpfx) $(elf-objpfx) \
-		    $(rtld-installed-name)
+		    $(rtld-installed-name) '$(cross-test-wrapper)' \
+		    $(..)scripts/run-with-env.sh
 endif
 
 $(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
@@ -544,16 +559,16 @@
 		$(patsubst -f%,-fno-%,$(exceptions)) -o $@
 
 $(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
-	$(make-test-out) 2>&1 | cmp - tst-cleanup0.expect >& $@
+	$(make-test-out) 2>&1 | cmp - tst-cleanup0.expect > $@ 2>&1
 
 # We only have one kind of startup code files.  Static binaries and
 # shared libraries are build using the PIC version.
 $(objpfx)crti.S: $(objpfx)pt-initfini.s
-	sed -n -e '1,/@HEADER_ENDS/p' \
+	sed -n -e '/^[ 	]*\.file[ 	]/d' -e '1,/@HEADER_ENDS/p' \
 	       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
 	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
 $(objpfx)crtn.S: $(objpfx)pt-initfini.s
-	sed -n -e '1,/@HEADER_ENDS/p' \
+	sed -n -e '/^[ 	]*\.file[ 	]/d' -e '1,/@HEADER_ENDS/p' \
 	       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
 	       -e '/@TRAILER_BEGINS/,$$p' $< > $@
 
@@ -591,18 +606,19 @@
 LDFLAGS-pthread.so += -e __nptl_main
 endif
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 ifeq (yes,$(build-shared))
 tests: $(objpfx)tst-cancel-wrappers.out
 $(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
-	$(SHELL) $< $(common-objpfx)libc_pic.a \
+	$(SHELL) $< '$(NM)' \
+		    $(common-objpfx)libc_pic.a \
 		    $(common-objpfx)libc.a \
 		    $(objpfx)libpthread_pic.a \
 		    $(objpfx)libpthread.a > $@
 endif
-endif
+# eglibc: endif
 
-tst-exec4-ARGS = $(built-program-cmd)
+tst-exec4-ARGS = $(local-built-program-cmd)
 
 $(objpfx)tst-execstack: $(libdl)
 $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
@@ -610,7 +626,7 @@
 
 $(objpfx)tst-fini1mod.so: $(shared-thread-library)
 
-tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
+tst-stackguard1-ARGS = --command "$(local-built-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
 
 # The tests here better do not run in parallel
Index: libc/nptl/init.c
===================================================================
--- libc/nptl/init.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/init.c	(.../trunk)	(revision 8411)
@@ -245,12 +245,21 @@
 
   /* Reset the SETXID flag.  */
   struct pthread *self = THREAD_SELF;
-  int flags = THREAD_GETMEM (self, cancelhandling);
-  THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
+  int flags, newval;
+  do
+    {
+      flags = THREAD_GETMEM (self, cancelhandling);
+      newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+					  flags & ~SETXID_BITMASK, flags);
+    }
+  while (flags != newval);
 
   /* And release the futex.  */
   self->setxid_futex = 1;
   lll_futex_wake (&self->setxid_futex, 1, LLL_PRIVATE);
+
+  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
+    lll_futex_wake (&__xidcmd->cntr, 1, LLL_PRIVATE);
 }
 
 
Index: libc/nptl/sysdeps/unix/sysv/linux/timer_create.c
===================================================================
--- libc/nptl/sysdeps/unix/sysv/linux/timer_create.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/sysdeps/unix/sysv/linux/timer_create.c	(.../trunk)	(revision 8411)
@@ -167,6 +167,7 @@
 	      /* Copy the thread parameters the user provided.  */
 	      newp->sival = evp->sigev_value;
 	      newp->thrfunc = evp->sigev_notify_function;
+	      newp->sigev_notify = SIGEV_THREAD;
 
 	      /* We cannot simply copy the thread attributes since the
 		 implementation might keep internal information for
Index: libc/nptl/sysdeps/pthread/configure.in
===================================================================
--- libc/nptl/sysdeps/pthread/configure.in	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/sysdeps/pthread/configure.in	(.../trunk)	(revision 8411)
@@ -19,31 +19,41 @@
   esac
 fi
 
-dnl Iff <unwind.h> is available, make sure it is the right one and it
-dnl contains struct _Unwind_Exception.
-AC_CACHE_CHECK(dnl
-for forced unwind support, libc_cv_forced_unwind, [dnl
-AC_TRY_LINK([#include <unwind.h>], [
-struct _Unwind_Exception exc;
-struct _Unwind_Context *context;
-_Unwind_GetCFA (context)],
-libc_cv_forced_unwind=yes, libc_cv_forced_unwind=no)])
-if test $libc_cv_forced_unwind = yes; then
-  AC_DEFINE(HAVE_FORCED_UNWIND)
-dnl Check for C cleanup handling.
-  old_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror -fexceptions"
-  AC_CACHE_CHECK([for C cleanup handling], libc_cv_c_cleanup, [dnl
-  AC_TRY_LINK([
-#include <stdio.h>
-void cl (void *a) { }], [
-  int a __attribute__ ((cleanup (cl)));
-  puts ("test")],
-libc_cv_c_cleanup=yes, libc_cv_c_cleanup=no)])
-  CFLAGS="$old_CFLAGS"
-  if test $libc_cv_c_cleanup = no; then
-    AC_MSG_ERROR([the compiler must support C cleanup handling])
-  fi
-else
-  AC_MSG_ERROR(forced unwind support is required)
-fi
+dnl These link tests made bootstrapping EGLIBC difficult (how do you
+dnl link if you haven't built a libc yet?), and this test is only used
+dnl to produce an error message anyway.  We've already checked the
+dnl GCC, as, and ld versions in the top-level configure script, and we
+dnl only use the results of these tests to produce an error message,
+dnl so we just disable these tests entirely.
+dnl 
+dnl dnl Iff <unwind.h> is available, make sure it is the right one and it
+dnl dnl contains struct _Unwind_Exception.
+dnl AC_CACHE_CHECK(dnl
+dnl for forced unwind support, libc_cv_forced_unwind, [dnl
+dnl AC_TRY_LINK([#include <unwind.h>], [
+dnl struct _Unwind_Exception exc;
+dnl struct _Unwind_Context *context;
+dnl _Unwind_GetCFA (context)],
+dnl libc_cv_forced_unwind=yes, libc_cv_forced_unwind=no)])
+dnl if test $libc_cv_forced_unwind = yes; then
+dnl   AC_DEFINE(HAVE_FORCED_UNWIND)
+dnl dnl Check for C cleanup handling.
+dnl   old_CFLAGS="$CFLAGS"
+dnl   CFLAGS="$CFLAGS -Werror -fexceptions"
+dnl   AC_CACHE_CHECK([for C cleanup handling], libc_cv_c_cleanup, [dnl
+dnl   AC_TRY_LINK([
+dnl #include <stdio.h>
+dnl void cl (void *a) { }], [
+dnl   int a __attribute__ ((cleanup (cl)));
+dnl   puts ("test")],
+dnl libc_cv_c_cleanup=yes, libc_cv_c_cleanup=no)])
+dnl   CFLAGS="$old_CFLAGS"
+dnl   if test $libc_cv_c_cleanup = no; then
+dnl     AC_MSG_ERROR([the compiler must support C cleanup handling])
+dnl   fi
+dnl else
+dnl   AC_MSG_ERROR(forced unwind support is required)
+dnl fi
+libc_cv_forced_unwind=yes
+AC_DEFINE(HAVE_FORCED_UNWIND)
+libc_cv_c_cleanup=yes
Index: libc/nptl/sysdeps/pthread/pt-initfini.c
===================================================================
--- libc/nptl/sysdeps/pthread/pt-initfini.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/sysdeps/pthread/pt-initfini.c	(.../trunk)	(revision 8411)
@@ -45,6 +45,11 @@
 /* Embed an #include to pull in the alignment and .end directives. */
 asm ("\n#include \"defs.h\"");
 
+asm ("\n#if defined __i686 && defined __ASSEMBLER__");
+asm ("\n#undef __i686");
+asm ("\n#define __i686 __i686");
+asm ("\n#endif");
+
 /* The initial common code ends here. */
 asm ("\n/*@HEADER_ENDS*/");
 
Index: libc/nptl/pthread_create.c
===================================================================
--- libc/nptl/pthread_create.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/pthread_create.c	(.../trunk)	(revision 8411)
@@ -28,6 +28,7 @@
 #include <libc-internal.h>
 #include <resolv.h>
 #include <kernel-features.h>
+#include <gnu/option-groups.h>
 
 #include <shlib-compat.h>
 
@@ -236,8 +237,10 @@
   THREAD_SETMEM (pd, cpuclock_offset, now);
 #endif
 
+#if __OPTION_EGLIBC_INET
   /* Initialize resolver state pointer.  */
   __resp = &pd->res;
+#endif
 
 #ifdef __NR_set_robust_list
 # ifndef __ASSUME_SET_ROBUST_LIST
@@ -303,8 +306,10 @@
   /* Run the destructor for the thread-local data.  */
   __nptl_deallocate_tsd ();
 
+#if __OPTION_EGLIBC_INET
   /* Clean up any state libc stored in thread-local variables.  */
   __libc_thread_freeres ();
+#endif
 
   /* If this is the last thread we terminate the process now.  We
      do not notify the debugger, it might just irritate it if there
Index: libc/nptl/allocatestack.c
===================================================================
--- libc/nptl/allocatestack.c	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/allocatestack.c	(.../trunk)	(revision 8411)
@@ -965,23 +965,54 @@
 
 static void
 internal_function
-setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
+setxid_mark_thread (struct xid_command *cmdp, struct pthread *t)
 {
-  if (! IS_DETACHED (t))
+  int ch;
+
+  /* Don't let the thread exit before the setxid handler runs.  */
+  t->setxid_futex = 0;
+
+  do
     {
-      int ch;
-      do
-	{
-	  ch = t->cancelhandling;
+      ch = t->cancelhandling;
 
-	  /* If the thread is exiting right now, ignore it.  */
-	  if ((ch & EXITING_BITMASK) != 0)
-	    return;
-	}
-      while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
-						   ch | SETXID_BITMASK, ch));
+      /* If the thread is exiting right now, ignore it.  */
+      if ((ch & EXITING_BITMASK) != 0)
+	return;
     }
+  while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
+					       ch | SETXID_BITMASK, ch));
+}
 
+
+static void
+internal_function
+setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t)
+{
+  int ch;
+
+  do
+    {
+      ch = t->cancelhandling;
+      if ((ch & SETXID_BITMASK) == 0)
+	return;
+    }
+  while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling,
+					       ch & ~SETXID_BITMASK, ch));
+
+  /* Release the futex just in case.  */
+  t->setxid_futex = 1;
+  lll_futex_wake (&t->setxid_futex, 1, LLL_PRIVATE);
+}
+
+
+static int
+internal_function
+setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
+{
+  if ((t->cancelhandling & SETXID_BITMASK) == 0)
+    return 0;
+
   int val;
   INTERNAL_SYSCALL_DECL (err);
 #if __ASSUME_TGKILL
@@ -997,8 +1028,14 @@
     val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
 #endif
 
+  /* If this failed, it must have had not started yet or else exited.  */
   if (!INTERNAL_SYSCALL_ERROR_P (val, err))
-    atomic_increment (&cmdp->cntr);
+    {
+      atomic_increment (&cmdp->cntr);
+      return 1;
+    }
+  else
+    return 0;
 }
 
 
@@ -1006,6 +1043,7 @@
 attribute_hidden
 __nptl_setxid (struct xid_command *cmdp)
 {
+  int signalled;
   int result;
   lll_lock (stack_cache_lock, LLL_PRIVATE);
 
@@ -1022,7 +1060,7 @@
       if (t == self)
 	continue;
 
-      setxid_signal_thread (cmdp, t);
+      setxid_mark_thread (cmdp, t);
     }
 
   /* Now the list with threads using user-allocated stacks.  */
@@ -1032,16 +1070,63 @@
       if (t == self)
 	continue;
 
-      setxid_signal_thread (cmdp, t);
+      setxid_mark_thread (cmdp, t);
     }
 
-  int cur = cmdp->cntr;
-  while (cur != 0)
+  /* Iterate until we don't succeed in signalling anyone.  That means
+     we have gotten all running threads, and their children will be
+     automatically correct once started.  */
+  do
     {
-      lll_futex_wait (&cmdp->cntr, cur, LLL_PRIVATE);
-      cur = cmdp->cntr;
+      signalled = 0;
+
+      list_for_each (runp, &stack_used)
+	{
+	  struct pthread *t = list_entry (runp, struct pthread, list);
+	  if (t == self)
+	    continue;
+
+	  signalled += setxid_signal_thread (cmdp, t);
+	}
+
+      list_for_each (runp, &__stack_user)
+	{
+	  struct pthread *t = list_entry (runp, struct pthread, list);
+	  if (t == self)
+	    continue;
+
+	  signalled += setxid_signal_thread (cmdp, t);
+	}
+
+      int cur = cmdp->cntr;
+      while (cur != 0)
+	{
+	  lll_futex_wait (&cmdp->cntr, cur, LLL_PRIVATE);
+	  cur = cmdp->cntr;
+	}
     }
+  while (signalled != 0);
 
+  /* Clean up flags, so that no thread blocks during exit waiting
+     for a signal which will never come.  */
+  list_for_each (runp, &stack_used)
+    {
+      struct pthread *t = list_entry (runp, struct pthread, list);
+      if (t == self)
+	continue;
+
+      setxid_unmark_thread (cmdp, t);
+    }
+
+  list_for_each (runp, &__stack_user)
+    {
+      struct pthread *t = list_entry (runp, struct pthread, list);
+      if (t == self)
+	continue;
+
+      setxid_unmark_thread (cmdp, t);
+    }
+
   /* This must be last, otherwise the current thread might not have
      permissions to send SIGSETXID syscall to the other threads.  */
   INTERNAL_SYSCALL_DECL (err);
Index: libc/nptl/tst-tls6.sh
===================================================================
--- libc/nptl/tst-tls6.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/nptl/tst-tls6.sh	(.../trunk)	(revision 8411)
@@ -3,12 +3,15 @@
 common_objpfx=$1; shift
 elf_objpfx=$1; shift
 rtld_installed_name=$1; shift
+cross_test_wrapper=$1; shift
+run_with_env=$1; shift
 logfile=$common_objpfx/nptl/tst-tls6.out
 
 # We have to find libc and nptl
 library_path=${common_objpfx}:${common_objpfx}nptl
 tst_tls5="${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 	  ${common_objpfx}/nptl/tst-tls5"
+tst_tls5="$cross_test_wrapper $run_with_env $tst_tls5"
 
 LC_ALL=C
 export LC_ALL
@@ -18,36 +21,44 @@
 > $logfile
 fail=0
 
+preloads () {
+    l=''
+    for s in "$@"; do
+        l="$l ${common_objpfx}nptl/tst-tls5mod$s.so"
+    done
+    echo $l | sed 's/:$//;s/: /:/g'
+}
+
 for aligned in a e f; do
   echo "preload tst-tls5mod{$aligned,b,c,d}.so" >> $logfile
   echo "===============" >> $logfile
-  LD_PRELOAD=`echo ${common_objpfx}nptl/tst-tls5mod{$aligned,b,c,d}.so \
-	      | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+  EGLIBC_TEST_LD_PRELOAD=`preloads $aligned b c d` \
+	      ${tst_tls5} >> $logfile || fail=1
   echo >> $logfile
 
   echo "preload tst-tls5mod{b,$aligned,c,d}.so" >> $logfile
   echo "===============" >> $logfile
-  LD_PRELOAD=`echo ${common_objpfx}nptl/tst-tls5mod{b,$aligned,c,d}.so \
-	      | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+  EGLIBC_TEST_LD_PRELOAD=`preloads b $aligned c d` \
+	      ${tst_tls5} >> $logfile || fail=1
   echo >> $logfile
 
   echo "preload tst-tls5mod{b,c,d,$aligned}.so" >> $logfile
   echo "===============" >> $logfile
-  LD_PRELOAD=`echo ${common_objpfx}nptl/tst-tls5mod{b,c,d,$aligned}.so \
-	      | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+  EGLIBC_TEST_LD_PRELOAD=`preloads b c d $aligned` \
+	      ${tst_tls5} >> $logfile || fail=1
   echo >> $logfile
 done
 
 echo "preload tst-tls5mod{d,a,b,c,e}" >> $logfile
 echo "===============" >> $logfile
-LD_PRELOAD=`echo ${common_objpfx}nptl/tst-tls5mod{d,a,b,c,e}.so \
-	    | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+EGLIBC_TEST_LD_PRELOAD=`preloads d a b c e` \
+	    ${tst_tls5} >> $logfile || fail=1
 echo >> $logfile
 
 echo "preload tst-tls5mod{d,a,b,e,f}" >> $logfile
 echo "===============" >> $logfile
-LD_PRELOAD=`echo ${common_objpfx}nptl/tst-tls5mod{d,a,b,e,f}.so \
-	    | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+EGLIBC_TEST_LD_PRELOAD=`preloads d a b e f` \
+	    ${tst_tls5} >> $logfile || fail=1
 echo >> $logfile
 
 exit $fail
Index: libc/aclocal.m4
===================================================================
--- libc/aclocal.m4	(.../fsf/trunk)	(revision 8411)
+++ libc/aclocal.m4	(.../trunk)	(revision 8411)
@@ -97,6 +97,8 @@
 LD=`$CC -print-prog-name=ld`
 AR=`$CC -print-prog-name=ar`
 AC_SUBST(AR)
+NM=`$CC -print-prog-name=nm`
+AC_SUBST(NM)
 OBJDUMP=`$CC -print-prog-name=objdump`
 AC_SUBST(OBJDUMP)
 
@@ -121,3 +123,49 @@
 [LIBC_PROG_FOO_GNU($LD, libc_cv_prog_ld_gnu=yes, libc_cv_prog_ld_gnu=no)])
 gnu_ld=$libc_cv_prog_ld_gnu
 ])
+
+# These two macros are taken from GCC's config/acx.m4.
+dnl Support the --with-pkgversion configure option.
+dnl ACX_PKGVERSION(default-pkgversion)
+AC_DEFUN([ACX_PKGVERSION],[
+  AC_ARG_WITH(pkgversion,
+    AS_HELP_STRING([--with-pkgversion=PKG],
+                   [Use PKG in the version string in place of "$1"]),
+    [case "$withval" in
+      yes) AC_MSG_ERROR([package version not specified]) ;;
+      no)  PKGVERSION= ;;
+      *)   PKGVERSION="($withval) " ;;
+     esac],
+    PKGVERSION="($1) "
+  )
+  AC_SUBST(PKGVERSION)
+])
+
+dnl Support the --with-bugurl configure option.
+dnl ACX_BUGURL(default-bugurl)
+AC_DEFUN([ACX_BUGURL],[
+  AC_ARG_WITH(bugurl,
+    AS_HELP_STRING([--with-bugurl=URL],
+                   [Direct users to URL to report a bug]),
+    [case "$withval" in
+      yes) AC_MSG_ERROR([bug URL not specified]) ;;
+      no)  BUGURL=
+	   ;;
+      *)   BUGURL="$withval"
+	   ;;
+     esac],
+     BUGURL="$1"
+  )
+  case ${BUGURL} in
+  "")
+    REPORT_BUGS_TO=
+    REPORT_BUGS_TEXI=
+    ;;
+  *)
+    REPORT_BUGS_TO="<$BUGURL>"
+    REPORT_BUGS_TEXI=@uref{`echo "$BUGURL" | sed 's/@/@@/g'`}
+    ;;
+  esac;
+  AC_SUBST(REPORT_BUGS_TO)
+  AC_SUBST(REPORT_BUGS_TEXI)
+])
Index: libc/streams/Makefile
===================================================================
--- libc/streams/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/streams/Makefile	(.../trunk)	(revision 8411)
@@ -19,9 +19,12 @@
 #
 #	Makefile for streams.
 #
+include ../option-groups.mak
+
 subdir	:= streams
 
 headers		= stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
-routines	= isastream getmsg getpmsg putmsg putpmsg fattach fdetach
+routines-$(OPTION_EGLIBC_STREAMS) \
+	       += isastream getmsg getpmsg putmsg putpmsg fattach fdetach
 
 include ../Rules
Index: libc/option-groups.def
===================================================================
--- libc/option-groups.def	(.../fsf/trunk)	(revision 0)
+++ libc/option-groups.def	(.../trunk)	(revision 8411)
@@ -0,0 +1,796 @@
+# This file documents the option groups EGLIBC currently supports, in
+# a format akin to the Linux Kconfig system's.  The syntax may change
+# over time.
+#
+# An entry of the form:
+#
+#   config OPTION_GROUP_NAME
+#       bool "one-line explanation of what this option group controls"
+#       help
+#           Multi-line help explaining the option group's meaning in
+#           some detail, terminated by indentation level.
+#
+# defines an option group whose variable is OPTION_GROUP_NAME, with
+# meaningful values 'y' (enabled) and 'n' (disabled).  The
+# documentation is formatted to be consumed by some sort of
+# interactive configuration interface, but EGLIBC doesn't have such an
+# interface yet.
+#
+# An option may have a 'depends' line, indicating which other options
+# must also be enabled if this option is.  At present, EGLIBC doesn't
+# check that these dependencies are satisfied.
+# 
+# Option group variables get their default values from the file
+# 'option-groups.defaults', in the top directory of the EGLIBC source
+# tree.  By default, all EGLIBC option groups are enabled --- their
+# variables are set to 'y'.
+#
+# After including 'option-groups.defaults', the EGLIBC make machinery
+# includes the file 'option-groups.config' from the top of the build
+# tree, if it is present.  Developers can place assignments to option
+# group variables in that file to override the defaults.  For example,
+# to disable an option group, place a line of the form:
+#
+#    OPTION_GROUP_NAME = n
+#
+# in 'option-groups.config' at the top of your build tree.  To
+# explicitly enable an option group, you may also write:
+#
+#    OPTION_GROUP_NAME = y
+# 
+# although this simply reestablishes the value already set by
+# 'option-groups.defaults'.
+
+config OPTION_EGLIBC_ADVANCED_INET6
+   bool "IPv6 Advanced Sockets API support (RFC3542)"
+   depends OPTION_EGLIBC_INET
+   help
+       This option group includes the functions specified by RFC 3542,
+       "Advanced Sockets Application Program Interface (API) for
+       IPv6".
+
+       This option group includes the following functions:
+
+         inet6_opt_append
+         inet6_opt_find
+         inet6_opt_finish
+         inet6_opt_get_val
+         inet6_opt_init
+         inet6_option_alloc
+         inet6_option_append
+         inet6_option_find
+         inet6_option_init
+         inet6_option_next
+         inet6_option_space
+         inet6_opt_next
+         inet6_opt_set_val
+         inet6_rth_add
+         inet6_rth_getaddr
+         inet6_rth_init
+         inet6_rth_reverse
+         inet6_rth_segments
+         inet6_rth_space
+
+config OPTION_EGLIBC_BACKTRACE
+   bool "Functions for producing backtraces"
+   help
+       This option group includes functions for producing a list of
+       the function calls that are currently active in a thread, from
+       within the thread itself.  These functions are often used
+       within signal handlers, to produce diagnostic output.
+
+       This option group includes the following functions:
+
+         backtrace
+         backtrace_symbols
+         backtrace_symbols_fd
+
+config OPTION_EGLIBC_BSD
+   bool "BSD-specific functions, and their compatibility stubs"
+   help
+       This option group includes functions specific to BSD kernels.
+       A number of these functions have stub versions that are also
+       included in libraries built for non-BSD systems for
+       compatibility.
+
+       This option group includes the following functions:
+
+         chflags
+         fchflags
+         lchmod
+         revoke
+         setlogin
+
+config OPTION_EGLIBC_CXX_TESTS
+   bool "Tests that link against the standard C++ library."
+   depends OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+   depends OPTION_EGLIBC_LIBM
+   help
+       This option group does not include any C library functions;
+       instead, it controls which EGLIBC tests an ordinary 'make
+       tests' runs.  With this group disabled, tests that would
+       normally link against the standard C++ library are not
+       run.
+
+       The standard C++ library depends on the math library 'libm' and
+       the wide character I/O functions included in EGLIBC.  If those
+       option groups are disabled, this test must also be disabled.
+
+config OPTION_EGLIBC_CATGETS
+   bool "Functions for accessing message catalogs"
+   depends OPTION_EGLIBC_LOCALE_CODE
+   help
+       This option group includes functions for accessing message
+       catalogs: catopen, catclose, and catgets.
+
+       This option group depends on the OPTION_EGLIBC_LOCALE_CODE
+       option group; if you disable that, you must also disable this.
+
+config OPTION_EGLIBC_CHARSETS
+   bool "iconv/gconv character set conversion libraries"
+   help
+
+       This option group includes support for character sets other
+       than ASCII (ANSI_X3.4-1968) and Unicode and ISO-10646 in their
+       various encodings.  This affects both the character sets
+       supported by the wide and multibyte character functions, and
+       those supported by the 'iconv' functions.
+
+       With this option group disabled, EGLIBC supports only the
+       following character sets:
+
+          ANSI_X3.4         - ASCII
+          ANSI_X3.4-1968
+          ANSI_X3.4-1986
+          ASCII
+          CP367
+          CSASCII
+          IBM367
+          ISO-IR-6
+          ISO646-US
+          ISO_646.IRV:1991
+          OSF00010020
+          US
+          US-ASCII
+
+          10646-1:1993      - ISO 10646, in big-endian UCS4 form
+          10646-1:1993/UCS4
+          CSUCS4
+          ISO-10646
+          ISO-10646/UCS4
+          OSF00010104
+          OSF00010105
+          OSF00010106
+          UCS-4
+          UCS-4BE
+          UCS4
+
+          UCS-4LE           - ISO 10646, in little-endian UCS4 form
+
+          ISO-10646/UTF-8   - ISO 10646, in UTF-8 form
+          ISO-10646/UTF8
+          ISO-IR-193
+          OSF05010001
+          UTF-8
+          UTF8
+
+          ISO-10646/UCS2    - ISO 10646, in target-endian UCS2 form
+          OSF00010100
+          OSF00010101
+          OSF00010102
+          UCS-2
+          UCS2
+
+          UCS-2BE           - ISO 10646, in big-endian UCS2 form
+          UNICODEBIG
+
+          UCS-2LE           - ISO 10646, in little-endian UCS2 form
+          UNICODELITTLE
+
+          WCHAR_T           - EGLIBC's internal form (target-endian,
+                              32-bit ISO 10646)
+
+config OPTION_EGLIBC_DB_ALIASES
+   bool "Functions for accessing the mail aliases database"
+   help
+       This option group includues functions for looking up mail
+       aliases in '/etc/aliases' or using nsswitch.  It includes the
+       following functions:
+
+         endaliasent
+         getaliasbyname
+         getaliasbyname_r
+         getaliasent
+         getaliasent_r
+         setaliasent
+
+       When this option group is disabled, the NSS service libraries
+       also lack support for querying their mail alias tables.
+
+config OPTION_EGLIBC_ENVZ
+   bool "Functions for handling envz-style environment vectors."
+   help
+       This option group contains functions for creating and operating
+       on envz vectors.  An "envz vector" is a vector of strings in a
+       contiguous block of memory, where each element is a name-value
+       pair, and elements are separated from their neighbors by null
+       characters.
+
+       This option group includes the following functions:
+
+        envz_add        envz_merge 
+        envz_entry      envz_remove
+        envz_get        envz_strip 
+
+config OPTION_EGLIBC_FCVT
+   bool "Functions for converting floating-point numbers to strings"
+   help
+       This option group includes functions for converting
+       floating-point numbers to strings.
+
+       This option group includes the following functions:
+
+         ecvt           qecvt
+	 ecvt_r		qecvt_r
+         fcvt		qfcvt
+	 fcvt_r		qfcvt_r
+         gcvt		qgcvt
+
+config OPTION_EGLIBC_FMTMSG
+   bool "Functions for formatting messages"
+   help
+       This option group includes the following functions:
+
+         addseverity    fmtmsg
+
+config OPTION_EGLIBC_FSTAB
+   bool "Access functions for 'fstab'"
+   help
+       This option group includes functions for reading the mount
+       point specification table, '/etc/fstab'.  These functions are
+       not included in the POSIX standard, which provides the
+       'getmntent' family of functions instead.
+
+       This option group includes the following functions:
+
+         endfsent       getfsspec
+         getfsent       setfsent
+         getfsfile
+
+config OPTION_EGLIBC_FTRAVERSE
+   bool "Functions for traversing file hierarchies"
+   help
+       This option group includes functions for traversing file
+       UNIX file hierachies.
+
+       This option group includes the following functions:
+
+         fts_open       ftw
+	 fts_read	nftw
+         fts_children	ftw64
+	 fts_set	nftw64
+         fts_close
+
+config OPTION_EGLIBC_GETLOGIN
+   bool "The getlogin function"
+   depends OPTION_EGLIBC_UTMP
+   help
+       This function group includes the 'getlogin' and 'getlogin_r'
+       functions, which return the user name associated by the login
+       activity with the current process's controlling terminal.
+
+       With this option group disabled, the 'glob' function will not
+       fall back on 'getlogin' to find the user's login name for tilde
+       expansion when the 'HOME' environment variable is not set.
+
+config OPTION_EGLIBC_INET
+   bool "Networking support"
+   help
+       This option group includes networking-specific functions and
+       data.  With OPTION_EGLIBC_INET disabled, the EGLIBC
+       installation and API changes as follows:
+
+       - The following libraries are not installed:
+
+         libanl
+         libnsl
+         libnss_compat
+         libnss_dns
+         libnss_hesiod
+         libnss_nis
+         libnss_nisplus
+         libresolv
+         
+       - The following functions and variables are omitted from libc:
+
+         authdes_create           hstrerror              svc_fdset
+         authdes_getucred         htonl                  svc_getreq
+         authdes_pk_create        htons                  svc_getreq_common
+         authnone_create          if_freenameindex       svc_getreq_poll
+         authunix_create          if_indextoname         svc_getreqset
+         authunix_create_default  if_nameindex           svc_max_pollfd
+         bindresvport             if_nametoindex         svc_pollfd
+         callrpc                  in6addr_any            svcraw_create
+         cbc_crypt                in6addr_loopback       svc_register
+         clnt_broadcast           inet6_opt_append       svc_run
+         clnt_create              inet6_opt_find         svc_sendreply
+         clnt_pcreateerror        inet6_opt_finish       svctcp_create
+         clnt_perrno              inet6_opt_get_val      svcudp_bufcreate
+         clnt_perror              inet6_opt_init         svcudp_create
+         clntraw_create           inet6_option_alloc     svcudp_enablecache
+         clnt_spcreateerror       inet6_option_append    svcunix_create
+         clnt_sperrno             inet6_option_find      svcunixfd_create
+         clnt_sperror             inet6_option_init      svc_unregister
+         clnttcp_create           inet6_option_next      user2netname
+         clntudp_bufcreate        inet6_option_space     xdecrypt
+         clntudp_create           inet6_opt_next         xdr_accepted_reply
+         clntunix_create          inet6_opt_set_val      xdr_array
+         des_setparity            inet6_rth_add          xdr_authdes_cred
+         ecb_crypt                inet6_rth_getaddr      xdr_authdes_verf
+         endaliasent              inet6_rth_init         xdr_authunix_parms
+         endhostent               inet6_rth_reverse      xdr_bool
+         endnetent                inet6_rth_segments     xdr_bytes
+         endnetgrent              inet6_rth_space        xdr_callhdr
+         endprotoent              inet_addr              xdr_callmsg
+         endrpcent                inet_aton              xdr_char
+         endservent               inet_lnaof             xdr_cryptkeyarg
+         ether_aton               inet_makeaddr          xdr_cryptkeyarg2
+         ether_aton_r             inet_netof             xdr_cryptkeyres
+         ether_hostton            inet_network           xdr_des_block
+         ether_line               inet_nsap_addr         xdr_double
+         ether_ntoa               inet_nsap_ntoa         xdr_enum
+         ether_ntoa_r             inet_ntoa              xdr_float
+         ether_ntohost            inet_ntop              xdr_free
+         freeaddrinfo             inet_pton              xdr_getcredres
+         freeifaddrs              innetgr                xdr_hyper
+         gai_strerror             iruserok               xdr_int
+         getaddrinfo              iruserok_af            xdr_int16_t
+         getaliasbyname           key_decryptsession     xdr_int32_t
+         getaliasbyname_r         key_decryptsession_pk  xdr_int64_t
+         getaliasent              key_encryptsession     xdr_int8_t
+         getaliasent_r            key_encryptsession_pk  xdr_keybuf
+         gethostbyaddr            key_gendes             xdr_key_netstarg
+         gethostbyaddr_r          key_get_conv           xdr_key_netstres
+         gethostbyname            key_secretkey_is_set   xdr_keystatus
+         gethostbyname2           key_setnet             xdr_long
+         gethostbyname2_r         key_setsecret          xdr_longlong_t
+         gethostbyname_r          netname2host           xdrmem_create
+         gethostent               netname2user           xdr_netnamestr
+         gethostent_r             ntohl                  xdr_netobj
+         getifaddrs               ntohs                  xdr_opaque
+         getipv4sourcefilter      passwd2des             xdr_opaque_auth
+         get_myaddress            pmap_getmaps           xdr_pmap
+         getnameinfo              pmap_getport           xdr_pmaplist
+         getnetbyaddr             pmap_rmtcall           xdr_pointer
+         getnetbyaddr_r           pmap_set               xdr_quad_t
+         getnetbyname             pmap_unset             xdrrec_create
+         getnetbyname_r           rcmd                   xdrrec_endofrecord
+         getnetent                rcmd_af                xdrrec_eof
+         getnetent_r              registerrpc            xdrrec_skiprecord
+         getnetgrent              res_init               xdr_reference
+         getnetgrent_r            rexec                  xdr_rejected_reply
+         getnetname               rexec_af               xdr_replymsg
+         getprotobyname           rexecoptions           xdr_rmtcall_args
+         getprotobyname_r         rpc_createerr          xdr_rmtcallres
+         getprotobynumber         rresvport              xdr_short
+         getprotobynumber_r       rresvport_af           xdr_sizeof
+         getprotoent              rtime                  xdrstdio_create
+         getprotoent_r            ruserok                xdr_string
+         getpublickey             ruserok_af             xdr_u_char
+         getrpcbyname             ruserpass              xdr_u_hyper
+         getrpcbyname_r           setaliasent            xdr_u_int
+         getrpcbynumber           sethostent             xdr_uint16_t
+         getrpcbynumber_r         setipv4sourcefilter    xdr_uint32_t
+         getrpcent                setnetent              xdr_uint64_t
+         getrpcent_r              setnetgrent            xdr_uint8_t
+         getrpcport               setprotoent            xdr_u_long
+         getsecretkey             setrpcent              xdr_u_longlong_t
+         getservbyname            setservent             xdr_union
+         getservbyname_r          setsourcefilter        xdr_unixcred
+         getservbyport            svcauthdes_stats       xdr_u_quad_t
+         getservbyport_r          svcerr_auth            xdr_u_short
+         getservent               svcerr_decode          xdr_vector
+         getservent_r             svcerr_noproc          xdr_void
+         getsourcefilter          svcerr_noprog          xdr_wrapstring
+         h_errlist                svcerr_progvers        xencrypt
+         h_errno                  svcerr_systemerr       xprt_register
+         herror                   svcerr_weakauth        xprt_unregister
+         h_nerr                   svc_exit
+         host2netname             svcfd_create
+
+       - The rpcgen, nscd, and rpcinfo commands are not installed.
+
+       - The 'rpc' file (a text file listing RPC services) is not installed.
+
+       Socket-related system calls do not fall in this option group,
+       because many are also used for other inter-process
+       communication mechanisms.  For example, the 'syslog' routines
+       use Unix-domain sockets to communicate with the syslog daemon;
+       syslog is valuable in non-networked contexts.
+
+config OPTION_EGLIBC_LIBM
+   bool "libm (math library)"
+   help
+       This option group includes the 'libm' library, containing
+       mathematical functions.  If this option group is omitted, then
+       an EGLIBC installation does not include shared or unshared versions
+       of the math library.
+
+       Note that this does not remove all floating-point related
+       functionality from EGLIBC; for example, 'printf' and 'scanf'
+       can still print and read floating-point values with this option
+       group disabled.
+
+       Note that the ISO Standard C++ library 'libstdc++' depends on
+       EGLIBC's math library 'libm'.  If you disable this option
+       group, you will not be able to build 'libstdc++' against the
+       resulting EGLIBC installation.
+
+config OPTION_EGLIBC_LOCALES
+   bool "Locale definitions"
+   help
+       This option group includes all locale definitions other than
+       that for the "C" locale.  If this option group is omitted, then
+       only the "C" locale is supported.
+
+
+config OPTION_EGLIBC_LOCALE_CODE
+   bool "Locale functions"
+   depends OPTION_POSIX_C_LANG_WIDE_CHAR
+   help
+       This option group includes locale support functions, programs,
+       and libraries.  With OPTION_EGLIBC_LOCALE_FUNCTIONS disabled,
+       EGLIBC supports only the 'C' locale (also known as 'POSIX'),
+       and ignores the settings of the 'LANG' and 'LC_*' environment
+       variables.
+
+       With OPTION_EGLIBC_LOCALE_CODE disabled, the following
+       functions are omitted from libc:
+
+         duplocale   localeconv  nl_langinfo    rpmatch  strfmon_l
+         freelocale  newlocale   nl_langinfo_l  strfmon  uselocale
+
+       Furthermore, only the LC_CTYPE and LC_TIME categories of the
+       standard "C" locale are available.
+
+       The OPTION_EGLIBC_CATGETS option group depends on this option
+       group; if you disable OPTION_EGLIBC_LOCALE_CODE, you must also
+       disable OPTION_EGLIBC_CATGETS.
+
+config OPTION_EGLIBC_NIS
+   bool "Support for NIS, NIS+, and the special 'compat' services."
+   depends OPTION_EGLIBC_INET
+   depends OPTION_EGLIBC_SUNRPC
+   help
+       This option group includes the NIS, NIS+, and 'compat' Name
+       Service Switch service libraries.  When it is disabled, those
+       services libraries are not installed; you should remove any
+       references to them from your 'nsswitch.conf' file.
+
+       This option group depends on the OPTION_EGLIBC_INET option
+       group; you must enable that to enable this option group.
+
+config OPTION_EGLIBC_NSSWITCH
+   bool "Name service switch (nsswitch) support"
+   help
+
+       This option group includes support for the 'nsswitch' facility.
+       With this option group enabled, all EGLIBC functions for
+       accessing various system databases (passwords and groups;
+       networking; aliases; public keys; and so on) consult the
+       '/etc/nsswitch.conf' configuration file to decide how to handle
+       queries.
+
+       With this option group disabled, EGLIBC uses a fixed list of
+       services to satisfy queries on each database, as requested by
+       configuration files specified when EGLIBC is built.  Your
+       'option-groups.config' file must set the following two
+       variables:
+
+       OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG
+
+          Set this to the name of a file whose contents observe the
+          same syntax as an ordinary '/etc/nsswitch.conf' file.  The
+          EGLIBC build process parses this file just as EGLIBC would
+          at run time if OPTION_EGLIBC_NSSWITCH were enabled, and
+          produces a C library that uses the nsswitch service
+          libraries to search for database entries as this file
+          specifies, instead of consulting '/etc/nsswitch.conf' at run
+          time.
+
+          This should be an absolute filename.  The EGLIBC build
+          process may use it from several different working
+          directories.  It may include references to Makefile
+          variables like 'common-objpfx' (the top of the build tree,
+          with a trailing slash), or '..' (the top of the source tree,
+          with a trailing slash).
+
+          The EGLIBC source tree includes a sample configuration file
+          named 'nss/fixed-nsswitch.conf'; for simple configurations,
+          you will probably want to delete references to databases not
+          needed on your system.
+
+       OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS
+
+          The EGLIBC build process uses this file to decide which
+          functions to make available from which service libraries.
+          The file 'nss/fixed-nsswitch.functions' serves as a sample
+          configuration file for this setting, and explains its syntax
+          and meaning in more detail.
+
+          This should be an absolute file name.  The EGLIBC build
+          process may use it from several different working
+          directories.  It may include references to Makefile
+          variables like 'common-objpfx' (the top of the build tree,
+          with a trailing slash), or '..' (the top of the source tree,
+          with a trailing slash).
+
+          Be sure to mention each function in each service you wish to
+          use.  If you do not mention a service's function here, the
+          EGLIBC database access functions will not find it, even if
+          it is listed in the OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG
+          file.
+
+       In this arrangement, EGLIBC will not use the 'dlopen' and
+       'dlsym' functions to find database access functions.  Instead,
+       libc hard-codes references to the service libraries' database
+       access functions.  You must explicitly link your program
+       against the name service libraries (those whose names start
+       with 'libnss_', in the sysroot's '/lib' directory) whose
+       functions you intend to use.  This arrangement helps
+       system-wide static analysis tools decide which functions a
+       system actually uses.
+
+       Note that some nsswitch service libraries require other option
+       groups to be enabled; for example, the OPTION_EGLIBC_INET
+       option group must be enabled to use the 'libnss_dns.so.2'
+       service library, which uses the Domain Name System network
+       protocol to answer queries.
+
+config OPTION_EGLIBC_RCMD
+   bool "Support for 'rcmd' and related library functions"
+   depends OPTION_EGLIBC_INET
+   help
+      This option group includes functions for running commands on
+      remote machines via the 'rsh' protocol, and doing authentication
+      related to those functions.  This also includes functions that
+      use the 'rexec' protocol.
+
+      This option group includes the following functions:
+
+        rcmd            ruserok
+        rcmd_af         ruserok_af
+        rexec           iruserok
+        rexec_af        iruserok_af
+        rresvport       ruserpass
+        rresvport_af
+        
+config OPTION_EGLIBC_SPAWN
+   bool "Support for POSIX posix_spawn functions"
+   help
+      This option group includes the POSIX functions for executing
+      programs in child processes without using 'fork' or 'vfork'.
+
+      This option group includes the following functions:
+
+        posix_spawn
+        posix_spawnattr_destroy
+        posix_spawnattr_getflags
+        posix_spawnattr_getpgroup
+        posix_spawnattr_getschedparam
+        posix_spawnattr_getschedpolicy
+        posix_spawnattr_getsigdefault
+        posix_spawnattr_getsigmask
+        posix_spawnattr_init
+        posix_spawnattr_setflags
+        posix_spawnattr_setpgroup
+        posix_spawnattr_setschedparam
+        posix_spawnattr_setschedpolicy
+        posix_spawnattr_setsigdefault
+        posix_spawnattr_setsigmask
+        posix_spawn_file_actions_addclose
+        posix_spawn_file_actions_adddup2
+        posix_spawn_file_actions_addopen
+        posix_spawn_file_actions_destroy
+        posix_spawn_file_actions_init
+        posix_spawnp
+
+      This option group also provides the ability for the iconv,
+      localedef, and locale programs to operate transparently on
+      compressed charset definitions.  When this option group is
+      disabled, those programs will only operate on uncompressed
+      charmap files.
+
+config OPTION_EGLIBC_STREAMS
+   bool "Support for accessing STREAMS."
+   help
+      This option group includes functions for reading and writing
+      messages to and from STREAMS.  The STREAMS interface provides a
+      uniform mechanism for implementing networking services and other
+      character-based I/O.  (STREAMS are not to be confused with
+      <stdio.h> FILE objects, also called 'streams'.)
+
+      This option group includes the following functions:
+
+        getmsg          putpmsg
+        getpmsg         fattach
+        isastream       fdetach
+        putmsg
+
+config OPTION_EGLIBC_SUNRPC
+   bool "Support for the Sun 'RPC' protocol."
+   depends OPTION_EGLIBC_INET
+   help
+      This option group includes support for the Sun RPC protocols,
+      including the 'rpcgen' and 'rpcinfo' programs.
+
+config OPTION_EGLIBC_UTMP
+    bool "Older access functions for 'utmp' login records"
+    help
+       This option group includes the older 'utent' family of
+       functions for accessing user login records in the 'utmp' file.
+       POSIX omits these functions in favor of the 'utxent' family,
+       and they are obsolete on systems other than Linux.
+
+       This option group includes the following functions:
+
+         endutent
+         getutent
+         getutent_r
+         getutid
+         getutid_r
+         getutline
+         getutline_r
+         logwtmp
+         pututline
+         setutent
+         updwtmp
+         utmpname
+
+       This option group includes the following libraries:
+
+         libutil.so (and libutil.a)
+
+config OPTION_EGLIBC_UTMPX
+    bool "POSIX access functions for 'utmp' login records"
+    depends OPTION_EGLIBC_UTMP    
+    help
+       This option group includes the POSIX functions for reading and
+       writing user login records in the 'utmp' file (usually
+       '/var/run/utmp').  The POSIX functions operate on 'struct
+       utmpx' structures, as opposed to the family of older 'utent'
+       functions, which operate on 'struct utmp' structures.
+
+       This option group includes the following functions:
+
+         endutxent
+         getutmp
+         getutmpx
+         getutxent
+         getutxid
+         getutxline
+         pututxline
+         setutxent
+         updwtmpx
+         utmpxname
+
+config OPTION_EGLIBC_WORDEXP
+    bool "Shell-style word expansion"
+    help
+        This option group includes the 'wordexp' function for
+        performing word expansion in the manner of the shell, and the
+        accompanying 'wordfree' function.
+
+config OPTION_POSIX_C_LANG_WIDE_CHAR
+    bool "ISO C library wide character functions, excluding I/O"
+    help
+        This option group includes the functions defined by the ISO C
+        standard for working with wide and multibyte characters in
+        memory.  Functions for reading and writing wide and multibyte
+        characters from and to files call in the
+        OPTION_POSIX_WIDE_CHAR_DEVICE_IO option group.
+
+        This option group includes the following functions:
+
+          btowc         mbsinit       wcscspn       wcstoll
+          iswalnum      mbsrtowcs     wcsftime      wcstombs
+          iswalpha      mbstowcs      wcslen        wcstoul
+          iswblank      mbtowc        wcsncat       wcstoull
+          iswcntrl      swprintf      wcsncmp       wcstoumax
+          iswctype      swscanf       wcsncpy       wcsxfrm
+          iswdigit      towctrans     wcspbrk       wctob
+          iswgraph      towlower      wcsrchr       wctomb
+          iswlower      towupper      wcsrtombs     wctrans
+          iswprint      vswprintf     wcsspn        wctype
+          iswpunct      vswscanf      wcsstr        wmemchr
+          iswspace      wcrtomb       wcstod        wmemcmp
+          iswupper      wcscat        wcstof        wmemcpy
+          iswxdigit     wcschr        wcstoimax     wmemmove
+          mblen         wcscmp        wcstok        wmemset
+          mbrlen        wcscoll       wcstol
+          mbrtowc       wcscpy        wcstold
+
+config OPTION_POSIX_REGEXP
+    bool "Regular expressions"
+    help
+        This option group includes the POSIX regular expression
+        functions, and the associated non-POSIX extensions and
+        compatibility functions.
+
+        With OPTION_POSIX_REGEXP disabled, the following functions are
+        omitted from libc:
+
+          re_comp                 re_max_failures         regcomp
+          re_compile_fastmap      re_search               regerror
+          re_compile_pattern      re_search_2             regexec
+          re_exec                 re_set_registers        regfree
+          re_match                re_set_syntax           rpmatch
+          re_match_2              re_syntax_options
+
+        Furthermore, the compatibility regexp interface defined in the
+        <regexp.h> header file, 'compile', 'step', and 'advance', is
+        omitted.
+
+config OPTION_POSIX_REGEXP_GLIBC
+    bool "Regular expressions from GLIBC"
+    depends OPTION_POSIX_REGEXP
+    help
+	This option group specifies which regular expression
+        library to use.  The choice is between regex
+        implementation from GLIBC and regex implementation from
+        libiberty.  The GLIBC variant is fully POSIX conformant and
+        optimized for speed; regex from libiberty is more than twice
+        as small while still is enough for most practical purposes.
+
+config OPTION_POSIX_WIDE_CHAR_DEVICE_IO
+    bool "Input and output functions for wide characters"
+    depends OPTION_POSIX_C_LANG_WIDE_CHAR
+    help
+        This option group includes functions for reading and writing
+        wide characters to and from <stdio.h> streams.
+
+        This option group includes the following functions:
+
+          fgetwc        fwprintf      putwchar      vwscanf
+          fgetws        fwscanf       ungetwc       wprintf
+          fputwc        getwc         vfwprintf     wscanf
+          fputws        getwchar      vfwscanf
+          fwide         putwc         vwprintf
+
+        This option group further includes the following unlocked
+        variants of the above functions:
+
+          fgetwc_unlocked           getwc_unlocked
+          fgetws_unlocked           getwchar_unlocked
+          fputwc_unlocked           putwc_unlocked
+          fputws_unlocked           putwchar_unlocked
+                    
+        Note that the GNU standard C++ library, 'libstdc++.so', uses
+        some of these functions; you will not be able to link or run
+        C++ programs if you disable this option group.
+
+        This option group also affects the behavior of the following
+        functions:
+
+          fdopen
+          fopen
+          fopen64
+          freopen
+          freopen64
+
+        These functions all take an OPENTYPE parameter which may
+        contain a string of the form ",ccs=CHARSET", indicating that
+        the underlying file uses the character set named CHARSET.
+        This produces a wide-oriented stream, which is only useful
+        when the functions included in this option group are present.
+        If the user attempts to open a file specifying a character set
+        in the OPENTYPE parameter, and EGLIBC was built with this
+        option group disabled, the function returns NULL, and sets
+        errno to EINVAL.
+
+
+# This helps Emacs users browse this file using the page motion commands
+# and commands like 'pages-directory'.
+# Local Variables:
+# page-delimiter: "^config\\s-"
+# End:
Index: libc/timezone/tzselect.ksh
===================================================================
--- libc/timezone/tzselect.ksh	(.../fsf/trunk)	(revision 8411)
+++ libc/timezone/tzselect.ksh	(.../trunk)	(revision 8411)
@@ -1,6 +1,8 @@
 #! @KSH@
 
-# '@(#)tzselect.ksh	8.1'
+VERSION='@(#)tzselect.ksh	8.1'
+PKGVERSION='@PKGVERSION@'
+REPORT_BUGS_TO='@REPORT_BUGS_TO@'
 
 # Ask the user about the time zone, and output the resulting TZ value to stdout.
 # Interact with the user via stderr and stdin.
@@ -45,6 +47,22 @@
 	exit 1
 }
 
+if [ "$1" = "--help" ]; then
+    cat <<EOF
+Usage: tzselect
+Select a time zone interactively.
+
+For bug reporting instructions, please see:
+$REPORT_BUGS_TO.
+EOF
+    exit 0
+elif [ "$1" = "--version" ]; then
+    cat <<EOF
+tzselect $PKGVERSION$VERSION
+EOF
+    exit 0
+fi
+
 # Make sure the tables are readable.
 TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
 TZ_ZONE_TABLE=$TZDIR/zone.tab
Index: libc/timezone/Makefile
===================================================================
--- libc/timezone/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/timezone/Makefile	(.../trunk)	(revision 8411)
@@ -69,13 +69,10 @@
 					 $(addprefix $(inst_zonedir)/, \
 						     $(posixrules-file)))
 
-ifeq ($(cross-compiling),no)
-# Don't try to install the zoneinfo files since we can't run zic.
 install-others = $(addprefix $(inst_zonedir)/,$(zonenames) \
 					      $(zonenames:%=posix/%) \
 					      $(zonenames:%=right/%)) \
 		 $(installed-localtime-file) $(installed-posixrules-file)
-endif
 
 ifeq ($(have-ksh),yes)
 install-others += $(inst_zonedir)/iso3166.tab $(inst_zonedir)/zone.tab
@@ -106,18 +103,35 @@
 	   echo '$$(addprefix $$(inst_zonedir)/,$$($*-zones)): \'	    ;\
 	   echo '$$(foreach t,$$(tzbases),$$(addprefix $$(inst_zonedir)/,$$($$t-zones)))' ;\
 	 fi								    ;\
-	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/right/,$$($*-zones)): \' ;\
-	 echo '$< $$(objpfx)zic leapseconds yearistype'			    ;\
-	 echo '	$$(tzcompile)'						    ;\
-	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/posix/,$$($*-zones)): \' ;\
-	 echo '$< $$(objpfx)zic /dev/null yearistype'			    ;\
-	 echo '	$$(tzcompile)'						    ;\
-	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/,$$($*-zones)): \' ;\
-	 echo '$< $$(objpfx)zic $$(leapseconds) yearistype'		    ;\
-	 echo '	$$(tzcompile)'						    ;\
+	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/right/,$$($*-zones)): \' ;) > $@.new
+
+ifeq (no,$(cross-compiling))
+	(echo '$< $$(objpfx)zic leapseconds yearistype'			    ;) >> $@.new
+else
+	(echo '$< $$(objpfx)cross-zic leapseconds yearistype'		    ;) >> $@.new
+endif
+
+	(echo '	$$(tzcompile)'						    ;\
+	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/posix/,$$($*-zones)): \' ;) >> $@.new
+
+ifeq (no,$(cross-compiling))
+	(echo '$< $$(objpfx)zic /dev/null yearistype'			    ;) >> $@.new
+else
+	(echo '$< $$(objpfx)cross-zic /dev/null yearistype'		    ;) >> $@.new
+endif
+
+	(echo '	$$(tzcompile)'						    ;\
+	 echo '$$(addprefix $$(dir $$(inst_zonedir))zone%/,$$($*-zones)): \' ;) >> $@.new
+
+ifeq (no,$(cross-compiling))
+	(echo '$< $$(objpfx)zic $$(leapseconds) yearistype'		    ;) >> $@.new
+else
+	(echo '$< $$(objpfx)cross-zic $$(leapseconds) yearistype'	    ;) >> $@.new
+endif
+
+	(echo '	$$(tzcompile)'						    ;\
 	 echo 'endif'							    ;\
-	 echo 'zonenames := $$(zonenames) $$($*-zones)'			    ;\
-	) > $@.new
+	 echo 'zonenames := $$(zonenames) $$($*-zones)'			    ;) >> $@.new
 	mv $@.new $@
 
 .PHONY: echo-zonenames
@@ -128,7 +142,11 @@
 # We have to use `-d $(inst_zonedir)' to explictly tell zic where to
 # place the output files although $(zonedir) is compiled in.  But the
 # user might have set $(install_root) on the command line of `make install'.
+ifeq (no,$(cross-compiling))
 zic-cmd = $(built-program-cmd) -d $(inst_zonedir)
+else
+zic-cmd = $(objpfx)cross-zic -d $(inst_zonedir)
+endif
 tzcompile = $(zic-cmd)$(target-zone-flavor) -L $(word 3,$^) \
 	    -y $(dir $(word 4,$^))$(notdir $(word 4,$^)) $<
 
@@ -158,9 +176,17 @@
 	$(zic-cmd) -p $(posixrules)
 endif
 
+zic-objs = zic.o ialloc.o scheck.o
 
-$(objpfx)zic: $(objpfx)scheck.o $(objpfx)ialloc.o
+$(objpfx)zic: $(addprefix $(objpfx), $(zic-objs))
 
+$(addprefix $(objpfx)cross-,$(zic-objs)): $(objpfx)cross-%.o: %.c
+	gcc $< -c $(OUTPUT_OPTION) $(CFLAGS-$*.c) $(CPPFLAGS-$*) \
+		-DCROSS_ZIC $(compile-mkdep-flags)
+
+$(objpfx)cross-zic: $(addprefix $(objpfx)cross-,$(zic-objs))
+	gcc $(addprefix $(objpfx)cross-,$(zic-objs)) -o $@
+
 tz-cflags = -DTZDIR='"$(zonedir)"' \
 	    -DTZDEFAULT='"$(localtime-file)"' \
 	    -DTZDEFRULES='"$(posixrules-file)"' \
@@ -176,10 +202,17 @@
 # Don't add leapseconds here since test-tz made checks that work only without
 # leapseconds.
 testdata = $(objpfx)testdata
+ifeq (no,$(cross-compiling))
 define build-testdata
 GCONV_PATH=${common-objpfx}iconvdata LANGUAGE=C LC_ALL=C \
   $(built-program-cmd) -d $(testdata) -y ./yearistype $<
 endef
+else
+define build-testdata
+LANGUAGE=C LC_ALL=C \
+  $(objpfx)cross-zic -d $(testdata) -y ./yearistype $<
+endef
+endif
 
 $(objpfx)test-tz.out: $(addprefix $(testdata)/, America/New_York Etc/UTC UTC)
 $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \
@@ -192,7 +225,11 @@
 tst-timezone-ENV = TZDIR=$(testdata)
 
 # Note this must come second in the deps list for $(built-program-cmd) to work.
+ifeq (no,$(cross-compiling))
 zic-deps = $(objpfx)zic $(leapseconds) yearistype
+else
+zic-deps = $(objpfx)cross-zic $(objpfx)zic $(leapseconds) yearistype
+endif
 
 $(testdata)/America/New_York: northamerica $(zic-deps)
 	$(build-testdata)
@@ -214,7 +251,9 @@
 
 $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make
 	sed -e 's%@KSH@%$(KSH)%g' \
-	    -e 's%@TZDIR@%$(zonedir)%g' < $< > $@.new
+	    -e 's%@TZDIR@%$(zonedir)%g' \
+	    -e 's%@PKGVERSION@%$(PKGVERSION)%g' \
+	    -e 's%@REPORT_BUGS_TO@%$(REPORT_BUGS_TO)%g' < $< > $@.new
 	chmod 555 $@.new
 	mv -f $@.new $@
 
Index: libc/timezone/zdump.c
===================================================================
--- libc/timezone/zdump.c	(.../fsf/trunk)	(revision 8411)
+++ libc/timezone/zdump.c	(.../trunk)	(revision 8411)
@@ -6,6 +6,7 @@
 ** You can use this code to help in verifying other implementations.
 */
 
+#include "config.h"
 #include "stdio.h"	/* for stdout, stderr, perror */
 #include "string.h"	/* for strcpy */
 #include "sys/types.h"	/* for time_t */
@@ -230,6 +231,18 @@
 	warned = TRUE;
 }
 
+static void
+usage(const char *progname, FILE *stream, int status)
+{
+	(void) fprintf(stream,
+_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\
+\n\
+For bug reporting instructions, please see:\n\
+%s.\n"),
+		       progname, progname, REPORT_BUGS_TO);
+	exit(status);
+}
+
 int
 main(argc, argv)
 int	argc;
@@ -264,8 +277,10 @@
 	progname = argv[0];
 	for (i = 1; i < argc; ++i)
 		if (strcmp(argv[i], "--version") == 0) {
-			(void) printf("%s\n", elsieid);
+			(void) printf("zdump %s%s\n", PKGVERSION, elsieid);
 			exit(EXIT_SUCCESS);
+		} else if (strcmp(argv[i], "--help") == 0) {
+			usage(progname, stdout, EXIT_SUCCESS);
 		}
 	vflag = 0;
 	cutarg = NULL;
@@ -275,10 +290,7 @@
 		else	cutarg = optarg;
 	if ((c != EOF && c != -1) ||
 		(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
-			(void) fprintf(stderr,
-_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
-				progname, progname);
-			exit(EXIT_FAILURE);
+			usage(progname, stderr, EXIT_FAILURE);
 	}
 	if (vflag) {
 		if (cutarg != NULL) {
Index: libc/timezone/zic.c
===================================================================
--- libc/timezone/zic.c	(.../fsf/trunk)	(revision 8411)
+++ libc/timezone/zic.c	(.../trunk)	(revision 8411)
@@ -5,6 +5,12 @@
 
 static char	elsieid[] = "@(#)zic.c	8.17";
 
+#ifdef CROSS_ZIC
+#define REPORT_BUGS_TO ""
+#define PKGVERSION ""
+#else
+#include "config.h"
+#endif
 #include "private.h"
 #include "locale.h"
 #include "tzfile.h"
@@ -156,7 +162,7 @@
 			const struct zone * zp, int ntzones);
 static void	setboundaries(void);
 static zic_t	tadd(zic_t t1, long t2);
-static void	usage(void);
+static void	usage(FILE *stream, int status);
 static void	writezone(const char * name, const char * string);
 static int	yearistype(int year, const char * type);
 
@@ -454,13 +460,16 @@
 }
 
 static void
-usage(void)
+usage(FILE *stream, int status)
 {
-	(void) fprintf(stderr, _("%s: usage is %s \
-[ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
-\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
-		progname, progname);
-	exit(EXIT_FAILURE);
+	(void) fprintf(stream, _("%s: usage is %s \
+[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
+\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
+\n\
+For bug reporting instructions, please see:\n\
+%s.\n"),
+		       progname, progname, REPORT_BUGS_TO);
+	exit(status);
 }
 
 static const char *	psxrules;
@@ -496,13 +505,15 @@
 	}
 	for (i = 1; i < argc; ++i)
 		if (strcmp(argv[i], "--version") == 0) {
-			(void) printf("%s\n", elsieid);
+			(void) printf("zic %s%s\n", PKGVERSION, elsieid);
 			exit(EXIT_SUCCESS);
+		} else if (strcmp(argv[i], "--help") == 0) {
+			usage(stdout, EXIT_SUCCESS);
 		}
 	while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
 		switch (c) {
 			default:
-				usage();
+			  usage(stderr, EXIT_FAILURE);
 			case 'd':
 				if (directory == NULL)
 					directory = optarg;
@@ -561,7 +572,7 @@
 				break;
 		}
 	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
-		usage();	/* usage message by request */
+		usage(stderr, EXIT_FAILURE);	/* usage message by request */
 	if (directory == NULL)
 		directory = TZDIR;
 	if (yitcommand == NULL)
Index: libc/Rules
===================================================================
--- libc/Rules	(.../fsf/trunk)	(revision 8411)
+++ libc/Rules	(.../trunk)	(revision 8411)
@@ -91,17 +91,17 @@
 else
 others: $(addprefix $(objpfx),$(extra-objs))
 endif
-ifeq ($(cross-compiling),yes)
-tests: $(addprefix $(objpfx),$(tests) $(test-srcs))
-xtests: tests
-else
+# eglibc: ifeq ($(cross-compiling),yes)
+# eglibc: tests: $(addprefix $(objpfx),$(tests) $(test-srcs))
+# eglibc: xtests: tests
+# eglibc: else
 ifeq ($(build-bounded),yes)
 tests-bp.out = $(tests:%=$(objpfx)%-bp.out)
 xtests-bp.out = $(xtests:%=$(objpfx)%-bp.out)
 endif
 tests: $(tests:%=$(objpfx)%.out) $(tests-bp.out)
 xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-bp.out)
-endif
+# eglibc: endif
 
 ifeq ($(build-programs),yes)
 binaries-all = $(others) $(sysdep-others) $(tests) $(xtests) $(test-srcs)
Index: libc/login/Makefile
===================================================================
--- libc/login/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/login/Makefile	(.../trunk)	(revision 8411)
@@ -19,17 +19,21 @@
 #
 #	Sub-makefile for login portion of the library.
 #
+include ../option-groups.mak
 
 subdir	:= login
 
 headers	:= utmp.h bits/utmp.h lastlog.h pty.h
 
-routines := getutent getutent_r getutid getutline getutid_r getutline_r \
-	    utmp_file utmpname updwtmp getpt grantpt unlockpt ptsname
+routines := getpt grantpt unlockpt ptsname
+routines-$(OPTION_EGLIBC_UTMP) \
+	 += getutent getutent_r getutid getutline getutid_r getutline_r \
+	    utmp_file utmpname updwtmp
 
 CFLAGS-grantpt.c = -DLIBEXECDIR='"$(libexecdir)"'
 
-others = utmpdump pt_chown
+others = pt_chown
+others-$(OPTION_EGLIBC_UTMP) += utmpdump
 install-others-programs = $(inst_libexecdir)/pt_chown
 
 distribute := utmp-private.h utmp-equal.h pty-private.h
@@ -40,8 +44,8 @@
 tests := tst-utmp tst-utmpx tst-grantpt
 
 # Build the -lutil library with these extra functions.
-extra-libs      := libutil
-extra-libs-others := $(extra-libs)
+extra-libs-$(OPTION_EGLIBC_UTMP) := libutil
+extra-libs-others := $(extra-libs-y)
 
 libutil-routines:= login login_tty logout logwtmp openpty forkpty
 
Index: libc/login/programs/pt_chown.c
===================================================================
--- libc/login/programs/pt_chown.c	(.../fsf/trunk)	(revision 8411)
+++ libc/login/programs/pt_chown.c	(.../trunk)	(revision 8411)
@@ -55,7 +55,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "pt_chown (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
@@ -87,7 +87,7 @@
 %s"),
 		TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+"REPORT_BUGS_TO".\n"));
       return cp;
     default:
       break;
Index: libc/iconvdata/run-iconv-test.sh
===================================================================
--- libc/iconvdata/run-iconv-test.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/iconvdata/run-iconv-test.sh	(.../trunk)	(revision 8411)
@@ -21,6 +21,7 @@
 # 02111-1307 USA.
 
 codir=$1
+cross_test_wrapper="$2"
 
 # We use always the same temporary file.
 temp1=$codir/iconvdata/iconv-test.xxx
@@ -39,6 +40,7 @@
 # How the start the iconv(1) program.
 ICONV='$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so \
        $codir/iconv/iconv_prog'
+ICONV="$cross_test_wrapper $ICONV"
 
 # Which echo?
 if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
@@ -49,8 +51,13 @@
 
 # We read the file named TESTS.  All non-empty lines not starting with
 # `#' are interpreted as commands.
+# Avoid reading from stdin, since the while loop's body inherits that;
+# if cross_test_wrapper is a program like ssh that reads its input
+# even if the program running on the remote side doesn't, it will
+# steal input from the loop.
 failed=0
-while read from to subset targets; do
+exec 5< TESTS
+while read from to subset targets <&5; do
   # Ignore empty and comment lines.
   if test -z "$subset" || test "$from" = '#'; then continue; fi
 
@@ -141,11 +148,18 @@
       { echo "/FAILED"; failed=1; continue; }
     echo "/OK"
   fi
-done < TESTS
+done
+# Close TESTS.
+exec 5<&-
 
 # We read the file named TESTS2.  All non-empty lines not starting with
 # `#' are interpreted as commands.
-while read utf8 from filename; do
+# Avoid reading from stdin, since the while loop's body inherits that;
+# if cross_test_wrapper is a program like ssh that reads its input
+# even if the program running on the remote side doesn't, it will
+# steal input from the loop.
+exec 5< TESTS2
+while read utf8 from filename <&5; do
   # Ignore empty and comment lines.
   if test -z "$filename" || test "$utf8" = '#'; then continue; fi
 
@@ -184,7 +198,8 @@
     { echo "/FAILED"; failed=1; continue; }
   echo "OK"
 
-done < TESTS2
+done
+exec 5<&-
 
 exit $failed
 # Local Variables:
Index: libc/iconvdata/tst-tables.sh
===================================================================
--- libc/iconvdata/tst-tables.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/iconvdata/tst-tables.sh	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 
 common_objpfx=$1
 objpfx=$2
+cross_test_wrapper="$3"
 
 status=0
 
@@ -257,7 +258,10 @@
   if test "$charset" = GB18030; then echo "This might take a while" 1>&2; fi
   case ${charset} in \#*) continue;; esac
   echo -n "Testing ${charset}" 1>&2
-  if ${SHELL} tst-table.sh ${common_objpfx} ${objpfx} ${charset} ${charmap}; then
+  # Redirect input from /dev/null, so that using ssh (which reads its
+  # input before the remote program needs it) won't consume the rest of the 
+  # charset/charmap table, making the while loop terminate early.
+  if ${SHELL} tst-table.sh ${common_objpfx} ${objpfx} "${cross_test_wrapper}" ${charset} ${charmap} < /dev/null; then
     echo 1>&2
   else
     echo "failed: ./tst-table.sh ${common_objpfx} ${objpfx} ${charset} ${charmap}"
Index: libc/iconvdata/tst-table.sh
===================================================================
--- libc/iconvdata/tst-table.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/iconvdata/tst-table.sh	(.../trunk)	(revision 8411)
@@ -24,8 +24,9 @@
 
 common_objpfx=$1
 objpfx=$2
-charset=$3
-charmap=$4
+cross_test_wrapper="$3"
+charset=$4
+charmap=$5
 
 GCONV_PATH=${common_objpfx}iconvdata
 export GCONV_PATH
@@ -60,12 +61,12 @@
 fi
 
 # iconv in one direction.
-${common_objpfx}elf/ld.so --library-path $common_objpfx \
+${cross_test_wrapper} ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-table-from ${charset} \
   > ${objpfx}tst-${charset}.table
 
 # iconv in the other direction.
-${common_objpfx}elf/ld.so --library-path $common_objpfx \
+${cross_test_wrapper} ${common_objpfx}elf/ld.so --library-path $common_objpfx \
 ${objpfx}tst-table-to ${charset} | sort \
   > ${objpfx}tst-${charset}.inverse.table
 
Index: libc/iconvdata/Makefile
===================================================================
--- libc/iconvdata/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/iconvdata/Makefile	(.../trunk)	(revision 8411)
@@ -19,10 +19,13 @@
 #
 #	Makefile for iconv data and code.
 #
+include ../option-groups.mak
+
 subdir	:= iconvdata
 
 # Names of all the shared objects which implement the transformations.
-modules	:= ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5		 \
+modules-$(OPTION_EGLIBC_CHARSETS)					 \
+	:= ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5		 \
 	   ISO8859-6 ISO8859-7 ISO8859-8 ISO8859-9 ISO8859-10		 \
 	   ISO8859-11 ISO8859-13 ISO8859-14 ISO8859-15 ISO8859-16	 \
 	   T.61 ISO_6937 SJIS KOI-8 HP-ROMAN8 HP-ROMAN9 EBCDIC-AT-DE	 \
@@ -61,13 +64,14 @@
 	   IBM1364 IBM1371 IBM1388 IBM1390 IBM1399 ISO_11548-1 MIK BRF	 \
 	   MAC-CENTRALEUROPE KOI8-RU ISO8859-9E
 
-modules.so := $(addsuffix .so, $(modules))
+modules.so := $(addsuffix .so, $(modules-y))
 
 include ../Makeconfig
 
 ifeq (yes,$(build-shared))
 tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
-	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7
+	tst-iconv6 bug-iconv5
+tests-$(OPTION_EGLIBC_LOCALE_CODE) += bug-iconv6 tst-iconv7
 ifeq ($(have-thread-library),yes)
 tests += bug-iconv3
 endif
@@ -210,13 +214,13 @@
 # Rule to generate the shared objects.
 charmaps = ../localedata/charmaps
 -include $(objpfx)iconv-rules
-extra-modules-left := $(modules)
+extra-modules-left := $(modules-y)
 include extra-module.mk
 
 
 extra-objs	+= $(modules.so)
-install-others	= $(addprefix $(inst_gconvdir)/, $(modules.so))	\
-		  $(inst_gconvdir)/gconv-modules
+install-others-y += $(addprefix $(inst_gconvdir)/, $(modules.so))
+install-others-$(OPTION_EGLIBC_CHARSETS) += $(inst_gconvdir)/gconv-modules
 
 # We can build the conversion tables for numerous charsets automatically.
 
@@ -283,7 +287,7 @@
 ifndef avoid-generated
 $(objpfx)iconv-rules: Makefile
 	$(make-target-directory)
-	{ echo $(filter-out lib%, $(modules)); \
+	{ echo $(filter-out lib%, $(modules-y)); \
 	  echo 8bit $(gen-8bit-modules); \
 	  echo 8bit-gap $(gen-8bit-gap-modules); } | \
 	LC_ALL=C \
@@ -326,7 +330,7 @@
 	$(do-install-program)
 $(inst_gconvdir)/gconv-modules: gconv-modules $(+force)
 	$(do-install)
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary
 # if this libc has more gconv modules than the previously installed one.
 	if test -f "$(inst_gconvdir)/gconv-modules.cache"; then \
@@ -335,22 +339,22 @@
 	   $(common-objpfx)iconv/iconvconfig \
 	     $(addprefix --prefix=,$(install_root)); \
 	fi
-else
-	@echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
-endif
+# eglibc: else
+# eglibc:	@echo '*@*@*@ You should recreate $(inst_gconvdir)/gconv-modules.cache'
+# eglibc: endif
 
 endif # build-shared = yes
 
 include ../Rules
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 ifeq (yes,$(build-shared))
 tests: $(objpfx)iconv-test.out $(objpfx)tst-tables.out
 ifneq (no,$(PERL))
 tests: $(objpfx)mtrace-tst-loading
 endif
 endif
-endif
+# eglibc: endif
 
 tst-loading-ENV = MALLOC_TRACE=$(objpfx)tst-loading.mtrace
 $(objpfx)mtrace-tst-loading: $(objpfx)tst-loading.out
@@ -375,12 +379,13 @@
 $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
 			 $(addprefix $(objpfx),$(modules.so)) \
 			 $(common-objdir)/iconv/iconv_prog TESTS
-	$(SHELL) -e $< $(common-objdir) > $@
+	$(SHELL) -e $< $(common-objdir) '$(cross-test-wrapper)' > $@
 
 $(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
 			 $(addprefix $(objpfx),$(modules.so)) \
 			 $(objpfx)tst-table-from $(objpfx)tst-table-to
-	$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ > $@
+	$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ \
+		    '$(cross-test-wrapper)' > $@
 
 do-tests-clean common-mostlyclean: tst-tables-clean
 
Index: libc/Makefile
===================================================================
--- libc/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/Makefile	(.../trunk)	(revision 8411)
@@ -70,7 +70,7 @@
 		   $(addprefix install-, no-libc.a bin lib data headers others)
 
 headers := limits.h values.h features.h gnu-versions.h bits/libc-lock.h \
-	   bits/xopen_lim.h gnu/libc-version.h
+	   bits/xopen_lim.h gnu/libc-version.h bits/predefs.h
 
 echo-headers: subdir_echo-headers
 
@@ -79,9 +79,18 @@
 vpath %.h $(subdir-dirs)
 
 # What to install.
-install-others = $(inst_includedir)/gnu/stubs.h
 install-bin-script =
 
+# If we're bootstrapping, install a dummy gnu/stubs.h along with the
+# other headers, so 'make install-headers' produces a useable include
+# tree.  Otherwise, install gnu/stubs.h later, after the rest of the
+# build is done.
+ifeq ($(install-bootstrap-headers),yes)
+install-headers: $(inst_includedir)/gnu/stubs.h
+else
+install-others = $(inst_includedir)/gnu/stubs.h
+endif
+
 ifeq (yes,$(build-shared))
 headers += gnu/lib-names.h
 endif
@@ -159,6 +168,16 @@
 
 subdir-stubs := $(foreach dir,$(subdirs),$(common-objpfx)$(dir)/stubs)
 
+# gnu/stubs.h depends (via the subdir 'stubs' targets) on all the .o
+# files in EGLIBC.  For bootstrapping a GCC/EGLIBC pair, an empty
+# gnu/stubs.h is good enough.
+ifeq ($(install-bootstrap-headers),yes)
+$(inst_includedir)/gnu/stubs.h: include/stubs-bootstrap.h $(+force)
+	$(make-target-directory)
+	$(INSTALL_DATA) $< $@
+
+installed-stubs = 
+else 
 ifeq ($(biarch),no)
 installed-stubs = $(inst_includedir)/gnu/stubs.h
 else
@@ -170,6 +189,7 @@
 
 install-others-nosubdir: $(installed-stubs)
 endif
+endif
 
 
 # Since stubs.h is never needed when building the library, we simplify the
@@ -341,9 +361,10 @@
 
 .PHONY: TAGS
 TAGS:
-	scripts/list-sources.sh | sed -n '/Makefile/p;\
-	  $(foreach S,[chsSyl] cxx sh bash pl,\
-		    $(subst .,\.,/.$S\(.in\)*$$/p;))' \
+	scripts/list-sources.sh \
+        | sed -n -e '/Makefile/p;' \
+		 -e '$(foreach S,[chsSyl] cxx sh bash pl,\
+		               $(subst .,\.,/.$S\(.in\)*$$/p;))' \
 	| $(ETAGS) -o $@ -
 
 # Make the distribution tarfile.
Index: libc/config.h.in
===================================================================
--- libc/config.h.in	(.../fsf/trunk)	(revision 8411)
+++ libc/config.h.in	(.../trunk)	(revision 8411)
@@ -189,6 +189,12 @@
 /* Define if __stack_chk_guard canary should be randomized at program startup.  */
 #undef ENABLE_STACKGUARD_RANDOMIZE
 
+/* Additional package description.  */
+#undef PKGVERSION
+
+/* Bug reporting address.  */
+#undef REPORT_BUGS_TO
+
 /* Define if multi-arch DSOs should be generated.  */
 #undef USE_MULTIARCH
 
Index: libc/crypt/sha512c-test.c
===================================================================
--- libc/crypt/sha512c-test.c	(.../fsf/trunk)	(revision 8411)
+++ libc/crypt/sha512c-test.c	(.../trunk)	(revision 8411)
@@ -60,4 +60,5 @@
 
 #define TIMEOUT 6
 #define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
 #include "../test-skeleton.c"
Index: libc/posix/regcomp.c
===================================================================
--- libc/posix/regcomp.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/regcomp.c	(.../trunk)	(revision 8411)
@@ -305,7 +305,7 @@
 {
   re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
   int node_cnt;
-  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
+  int icase = (dfa_mb_cur_max (dfa) == 1 && (bufp->syntax & RE_ICASE));
   for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
     {
       int node = init_state->nodes.elems[node_cnt];
@@ -315,9 +315,9 @@
 	{
 	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
 #ifdef RE_ENABLE_I18N
-	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+	  if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
 	    {
-	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;
+	      unsigned char *buf = alloca (dfa_mb_cur_max (dfa)), *p;
 	      wchar_t wc;
 	      mbstate_t state;
 
@@ -348,7 +348,11 @@
 		  re_set_fastmap (fastmap, icase, ch);
 	    }
 	}
-#ifdef RE_ENABLE_I18N
+
+      /* When OPTION_EGLIBC_LOCALE_CODE is disabled, the current
+         locale is always C, which has no rules and no multi-byte
+         characters.  */
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
       else if (type == COMPLEX_BRACKET)
 	{
 	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;
@@ -376,7 +380,7 @@
 	     i.e. where we would not find an invalid sequence.  This only
 	     applies to multibyte character sets; for single byte character
 	     sets, the SIMPLE_BRACKET again suffices.  */
-	  if (dfa->mb_cur_max > 1
+	  if (dfa_mb_cur_max (dfa) > 1
 	      && (cset->nchar_classes || cset->non_match
 # ifdef _LIBC
 		  || cset->nequiv_classes
@@ -404,7 +408,7 @@
 		  memset (&state, '\0', sizeof (state));
 		  if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
 		    re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
-		  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+		  if ((bufp->syntax & RE_ICASE) && dfa_mb_cur_max (dfa) > 1)
 		    {
 		      if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
 			  != (size_t) -1)
@@ -413,7 +417,7 @@
  		}
  	    }
 	}
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
       else if (type == OP_PERIOD
 #ifdef RE_ENABLE_I18N
 	       || type == OP_UTF8_PERIOD
@@ -856,11 +860,15 @@
 
   dfa->mb_cur_max = MB_CUR_MAX;
 #ifdef _LIBC
-  if (dfa->mb_cur_max == 6
+  if (dfa_mb_cur_max (dfa) == 6
       && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
     dfa->is_utf8 = 1;
+# if __OPTION_EGLIBC_LOCALE_CODE
   dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
 		       != 0);
+# else
+  dfa->map_notascii = 0;
+# endif
 #else
 # ifdef HAVE_LANGINFO_CODESET
   codeset_name = nl_langinfo (CODESET);
@@ -886,7 +894,7 @@
 #endif
 
 #ifdef RE_ENABLE_I18N
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     {
       if (dfa->is_utf8)
 	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
@@ -1743,7 +1751,7 @@
   token->word_char = 0;
 #ifdef RE_ENABLE_I18N
   token->mb_partial = 0;
-  if (input->mb_cur_max > 1 &&
+  if (string_mb_cur_max (input) > 1 &&
       !re_string_first_byte (input, re_string_cur_idx (input)))
     {
       token->type = CHARACTER;
@@ -1764,7 +1772,7 @@
       token->opr.c = c2;
       token->type = CHARACTER;
 #ifdef RE_ENABLE_I18N
-      if (input->mb_cur_max > 1)
+      if (string_mb_cur_max (input) > 1)
 	{
 	  wint_t wc = re_string_wchar_at (input,
 					  re_string_cur_idx (input) + 1);
@@ -1878,7 +1886,7 @@
 
   token->type = CHARACTER;
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1)
+  if (string_mb_cur_max (input) > 1)
     {
       wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
       token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
@@ -1978,7 +1986,7 @@
   token->opr.c = c;
 
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1 &&
+  if (string_mb_cur_max (input) > 1 &&
       !re_string_first_byte (input, re_string_cur_idx (input)))
     {
       token->type = CHARACTER;
@@ -2192,7 +2200,7 @@
 	  return NULL;
 	}
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	{
 	  while (!re_string_eoi (regexp)
 		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
@@ -2330,7 +2338,7 @@
 	  *err = REG_ESPACE;
 	  return NULL;
 	}
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	dfa->has_mb_node = 1;
       break;
     case OP_WORD:
@@ -2623,7 +2631,7 @@
        However, for !_LIBC we have no collation elements: if the
        character set is single byte, the single byte character set
        that we build below suffices.  parse_bracket_exp passes
-       no MBCSET if dfa->mb_cur_max == 1.  */
+       no MBCSET if dfa_mb_cur_max (dfa) == 1.  */
     if (mbcset)
       {
         /* Check the space of the arrays.  */
@@ -2719,7 +2727,13 @@
 		   reg_syntax_t syntax, reg_errcode_t *err)
 {
 #ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
   const unsigned char *collseqmb;
+# define COLLSEQMB_LOOKUP(ix) (collseqmb[(ix)])
+#else
+# define COLLSEQMB_LOOKUP(ix) (ix)
+#endif
+
   const char *collseqwc;
   uint32_t nrules;
   int32_t table_size;
@@ -2779,18 +2793,20 @@
 	  if (MB_CUR_MAX == 1)
 	  */
 	  if (nrules == 0)
-	    return collseqmb[br_elem->opr.ch];
+	    return COLLSEQMB_LOOKUP (br_elem->opr.ch);
 	  else
 	    {
 	      wint_t wc = __btowc (br_elem->opr.ch);
 	      return __collseq_table_lookup (collseqwc, wc);
 	    }
 	}
+#if __OPTION_EGLIBC_LOCALE_CODE
       else if (br_elem->type == MB_CHAR)
 	{
 	  if (nrules != 0)
 	    return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
 	}
+#endif
       else if (br_elem->type == COLL_SYM)
 	{
 	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
@@ -2821,11 +2837,11 @@
 		{
 		  /* No valid character.  Match it as a single byte
 		     character.  */
-		  return collseqmb[br_elem->opr.name[0]];
+		  return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
 		}
 	    }
 	  else if (sym_name_len == 1)
-	    return collseqmb[br_elem->opr.name[0]];
+	    return COLLSEQMB_LOOKUP (br_elem->opr.name[0]);
 	}
       return UINT_MAX;
     }
@@ -2868,7 +2884,7 @@
 	 However, if we have no collation elements, and the character set
 	 is single byte, the single byte character set that we
 	 build below suffices. */
-      if (nrules > 0 || dfa->mb_cur_max > 1)
+      if (nrules > 0 || dfa_mb_cur_max (dfa) > 1)
 	{
           /* Check the space of the arrays.  */
           if (BE (*range_alloc == mbcset->nranges, 0))
@@ -2905,7 +2921,7 @@
 	  if (MB_CUR_MAX == 1)
 	  */
 	  if (nrules == 0)
-	    ch_collseq = collseqmb[ch];
+	    ch_collseq = COLLSEQMB_LOOKUP (ch);
 	  else
 	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
 	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
@@ -2986,7 +3002,10 @@
   re_bitset_ptr_t sbcset;
 #ifdef RE_ENABLE_I18N
   re_charset_t *mbcset;
-  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
+  int coll_sym_alloc = 0, range_alloc = 0;
+#if __OPTION_EGLIBC_LOCALE_CODE
+  int mbchar_alloc = 0;
+#endif
   int equiv_class_alloc = 0, char_class_alloc = 0;
 #endif /* not RE_ENABLE_I18N */
   int non_match = 0;
@@ -2994,9 +3013,15 @@
   int token_len;
   int first_round = 1;
 #ifdef _LIBC
+#if __OPTION_EGLIBC_LOCALE_CODE
   collseqmb = (const unsigned char *)
     _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
   nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+#else
+  /* This is true when OPTION_EGLIBC_LOCALE_CODE is disabled, but the
+     compiler can't figure that out.  */
+  nrules = 0;
+#endif
   if (nrules)
     {
       /*
@@ -3120,7 +3145,7 @@
 #else
 # ifdef RE_ENABLE_I18N
 	  *err = build_range_exp (sbcset,
-				  dfa->mb_cur_max > 1 ? mbcset : NULL,
+				  dfa_mb_cur_max (dfa) > 1 ? mbcset : NULL,
 				  &range_alloc, &start_elem, &end_elem);
 # else
 	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
@@ -3136,7 +3161,7 @@
 	    case SB_CHAR:
 	      bitset_set (sbcset, start_elem.opr.ch);
 	      break;
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
 	    case MB_CHAR:
 	      /* Check whether the array has enough space.  */
 	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
@@ -3154,7 +3179,7 @@
 		}
 	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
 	      break;
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
 	    case EQUIV_CLASS:
 	      *err = build_equiv_class (sbcset,
 #ifdef RE_ENABLE_I18N
@@ -3204,11 +3229,11 @@
 
 #ifdef RE_ENABLE_I18N
   /* Ensure only single byte characters are set.  */
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     bitset_mask (sbcset, dfa->sb_char);
 
   if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
-      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
+      || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes
 						     || mbcset->non_match)))
     {
       bin_tree_t *mbc_tree;
@@ -3277,7 +3302,7 @@
 		       re_token_t *token, int token_len, re_dfa_t *dfa,
 		       reg_syntax_t syntax, int accept_hyphen)
 {
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
   int cur_char_size;
   cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
   if (cur_char_size > 1)
@@ -3287,7 +3312,7 @@
       re_string_skip_bytes (regexp, cur_char_size);
       return REG_NOERROR;
     }
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
   re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
   if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
       || token->type == OP_OPEN_EQUIV_CLASS)
@@ -3367,7 +3392,9 @@
 build_equiv_class (bitset_t sbcset, const unsigned char *name)
 #endif /* not RE_ENABLE_I18N */
 {
-#ifdef _LIBC
+  /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C locale
+     is supported; it has no collation rules.  */
+#if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
   uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
   if (nrules != 0)
     {
@@ -3440,7 +3467,7 @@
       mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
     }
   else
-#endif /* _LIBC */
+#endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
     {
       if (BE (strlen ((const char *) name) != 1, 0))
 	return REG_ECOLLATE;
@@ -3474,7 +3501,7 @@
       && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
     name = "alpha";
 
-#ifdef RE_ENABLE_I18N
+#if defined RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE
   /* Check the space of the arrays.  */
   if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
     {
@@ -3490,7 +3517,7 @@
       *char_class_alloc = new_char_class_alloc;
     }
   mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
-#endif /* RE_ENABLE_I18N */
+#endif /* RE_ENABLE_I18N && __OPTION_EGLIBC_LOCALE_CODE */
 
 #define BUILD_CHARCLASS_LOOP(ctype_func)	\
   do {						\
@@ -3601,7 +3628,7 @@
 
 #ifdef RE_ENABLE_I18N
   /* Ensure only single byte characters are set.  */
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     bitset_mask (sbcset, dfa->sb_char);
 #endif
 
@@ -3613,7 +3640,7 @@
     goto build_word_op_espace;
 
 #ifdef RE_ENABLE_I18N
-  if (dfa->mb_cur_max > 1)
+  if (dfa_mb_cur_max (dfa) > 1)
     {
       bin_tree_t *mbc_tree;
       /* Build a tree for complex bracket.  */
Index: libc/posix/confstr.c
===================================================================
--- libc/posix/confstr.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/confstr.c	(.../trunk)	(revision 8411)
@@ -45,195 +45,10 @@
       }
       break;
 
-    case _CS_V7_WIDTH_RESTRICTED_ENVS:
-      /* We have to return a newline-separated list of named of
-	 programming environements in which the widths of blksize_t,
-	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
-	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
-	 wint_t types are no greater than the width of type long.
+      /* eglibc: We share code in confstr.inc with cross-getconf.c.  */
+#include "confstr.inc"
+      /* eglibc: end.  */
 
-	 Currently this means all environment which the system allows.  */
-      {
-	char restenvs[4 * sizeof "POSIX_V7_LPBIG_OFFBIG"];
-
-	string_len = 0;
-#ifndef _POSIX_V7_ILP32_OFF32
-        if (__sysconf (_SC_V7_ILP32_OFF32) > 0)
-#endif
-#if !defined _POSIX_V7_ILP32_OFF32 || _POSIX_V7_ILP32_OFF32 > 0
-          {
-            memcpy (restenvs + string_len, "POSIX_V7_ILP32_OFF32",
-                    sizeof "POSIX_V7_ILP32_OFF32" - 1);
-            string_len += sizeof "POSIX_V7_ILP32_OFF32" - 1;
-          }
-#endif
-#ifndef _POSIX_V7_ILP32_OFFBIG
-        if (__sysconf (_SC_V7_ILP32_OFFBIG) > 0)
-#endif
-#if !defined _POSIX_V7_ILP32_OFFBIG || _POSIX_V7_ILP32_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V7_ILP32_OFFBIG",
-                    sizeof "POSIX_V7_ILP32_OFFBIG" - 1);
-            string_len += sizeof "POSIX_V7_ILP32_OFFBIG" - 1;
-          }
-#endif
-#ifndef _POSIX_V7_LP64_OFF64
-        if (__sysconf (_SC_V7_LP64_OFF64) > 0)
-#endif
-#if !defined _POSIX_V7_LP64_OFF64 || _POSIX_V7_LP64_OFF64 > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V7_LP64_OFF64",
-                    sizeof "POSIX_V7_LP64_OFF64" - 1);
-            string_len += sizeof "POSIX_V7_LP64_OFF64" - 1;
-          }
-#endif
-#ifndef _POSIX_V7_LPBIG_OFFBIG
-        if (__sysconf (_SC_V7_LPBIG_OFFBIG) > 0)
-#endif
-#if !defined _POSIX_V7_LPBIG_OFFBIG || _POSIX_V7_LPBIG_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V7_LPBIG_OFFBIG",
-                    sizeof "POSIX_V7_LPBIG_OFFBIG" - 1);
-            string_len += sizeof "POSIX_V7_LPBIG_OFFBIG" - 1;
-          }
-#endif
-        restenvs[string_len++] = '\0';
-	string = restenvs;
-      }
-      break;
-
-    case _CS_V6_WIDTH_RESTRICTED_ENVS:
-      /* We have to return a newline-separated list of named of
-	 programming environements in which the widths of blksize_t,
-	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
-	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
-	 wint_t types are no greater than the width of type long.
-
-	 Currently this means all environment which the system allows.  */
-      {
-	char restenvs[4 * sizeof "POSIX_V6_LPBIG_OFFBIG"];
-
-	string_len = 0;
-#ifndef _POSIX_V6_ILP32_OFF32
-        if (__sysconf (_SC_V6_ILP32_OFF32) > 0)
-#endif
-#if !defined _POSIX_V6_ILP32_OFF32 || _POSIX_V6_ILP32_OFF32 > 0
-          {
-            memcpy (restenvs + string_len, "POSIX_V6_ILP32_OFF32",
-                    sizeof "POSIX_V6_ILP32_OFF32" - 1);
-            string_len += sizeof "POSIX_V6_ILP32_OFF32" - 1;
-          }
-#endif
-#ifndef _POSIX_V6_ILP32_OFFBIG
-        if (__sysconf (_SC_V6_ILP32_OFFBIG) > 0)
-#endif
-#if !defined _POSIX_V6_ILP32_OFFBIG || _POSIX_V6_ILP32_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V6_ILP32_OFFBIG",
-                    sizeof "POSIX_V6_ILP32_OFFBIG" - 1);
-            string_len += sizeof "POSIX_V6_ILP32_OFFBIG" - 1;
-          }
-#endif
-#ifndef _POSIX_V6_LP64_OFF64
-        if (__sysconf (_SC_V6_LP64_OFF64) > 0)
-#endif
-#if !defined _POSIX_V6_LP64_OFF64 || _POSIX_V6_LP64_OFF64 > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V6_LP64_OFF64",
-                    sizeof "POSIX_V6_LP64_OFF64" - 1);
-            string_len += sizeof "POSIX_V6_LP64_OFF64" - 1;
-          }
-#endif
-#ifndef _POSIX_V6_LPBIG_OFFBIG
-        if (__sysconf (_SC_V6_LPBIG_OFFBIG) > 0)
-#endif
-#if !defined _POSIX_V6_LPBIG_OFFBIG || _POSIX_V6_LPBIG_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "POSIX_V6_LPBIG_OFFBIG",
-                    sizeof "POSIX_V6_LPBIG_OFFBIG" - 1);
-            string_len += sizeof "POSIX_V6_LPBIG_OFFBIG" - 1;
-          }
-#endif
-        restenvs[string_len++] = '\0';
-	string = restenvs;
-      }
-      break;
-
-    case _CS_V5_WIDTH_RESTRICTED_ENVS:
-      /* We have to return a newline-separated list of named of
-	 programming environements in which the widths of blksize_t,
-	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
-	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
-	 wint_t types are no greater than the width of type long.
-
-	 Currently this means all environment which the system allows.  */
-      {
-	char restenvs[4 * sizeof "XBS5_LPBIG_OFFBIG"];
-
-	string_len = 0;
-#ifndef _XBS5_ILP32_OFF32
-        if (__sysconf (_SC_XBS5_ILP32_OFF32) > 0)
-#endif
-#if !defined _XBS5_ILP32_OFF32 || _XBS5_ILP32_OFF32 > 0
-          {
-            memcpy (restenvs + string_len, "XBS5_ILP32_OFF32",
-                    sizeof "XBS5_ILP32_OFF32" - 1);
-            string_len += sizeof "XBS5_ILP32_OFF32" - 1;
-          }
-#endif
-#ifndef _XBS5_ILP32_OFFBIG
-        if (__sysconf (_SC_XBS5_ILP32_OFFBIG) > 0)
-#endif
-#if !defined _XBS5_ILP32_OFFBIG || _XBS5_ILP32_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "XBS5_ILP32_OFFBIG",
-                    sizeof "XBS5_ILP32_OFFBIG" - 1);
-            string_len += sizeof "XBS5_ILP32_OFFBIG" - 1;
-          }
-#endif
-#ifndef _XBS5_LP64_OFF64
-        if (__sysconf (_SC_XBS5_LP64_OFF64) > 0)
-#endif
-#if !defined _XBS5_LP64_OFF64 || _XBS5_LP64_OFF64 > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "XBS5_LP64_OFF64",
-                    sizeof "XBS5_LP64_OFF64" - 1);
-            string_len += sizeof "XBS5_LP64_OFF64" - 1;
-          }
-#endif
-#ifndef _XBS5_LPBIG_OFFBIG
-        if (__sysconf (_SC_XBS5_LPBIG_OFFBIG) > 0)
-#endif
-#if !defined _XBS5_LPBIG_OFFBIG || _XBS5_LPBIG_OFFBIG > 0
-          {
-            if (string_len)
-              restenvs[string_len++] = '\n';
-            memcpy (restenvs + string_len, "XBS5_LPBIG_OFFBIG",
-                    sizeof "XBS5_LPBIG_OFFBIG" - 1);
-            string_len += sizeof "XBS5_LPBIG_OFFBIG" - 1;
-          }
-#endif
-        restenvs[string_len++] = '\0';
-	string = restenvs;
-      }
-      break;
-
     case _CS_XBS5_ILP32_OFF32_CFLAGS:
     case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
     case _CS_POSIX_V7_ILP32_OFF32_CFLAGS:
Index: libc/posix/regexec-compat.c
===================================================================
--- libc/posix/regexec-compat.c	(.../fsf/trunk)	(revision 0)
+++ libc/posix/regexec-compat.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,39 @@
+/* Extended regular expression matching and search library.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+__typeof__ (__regexec) __compat_regexec;
+
+int
+attribute_compat_text_section
+__compat_regexec (const regex_t *__restrict preg,
+		  const char *__restrict string, size_t nmatch,
+		  regmatch_t pmatch[], int eflags)
+{
+  return regexec (preg, string, nmatch, pmatch,
+		  eflags & (REG_NOTBOL | REG_NOTEOL));
+}
+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
+# endif
+#endif
Index: libc/posix/confstr.inc
===================================================================
--- libc/posix/confstr.inc	(.../fsf/trunk)	(revision 0)
+++ libc/posix/confstr.inc	(.../trunk)	(revision 8411)
@@ -0,0 +1,210 @@
+/* Copyright (C) 2008
+   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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* eglibc: The following piece of code was extracted from
+   confstr.c to share it with cross-getconf.c.  */
+
+    case _CS_V7_WIDTH_RESTRICTED_ENVS:
+      /* We have to return a newline-separated list of named of
+	 programming environements in which the widths of blksize_t,
+	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
+	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
+	 wint_t types are no greater than the width of type long.
+
+	 Currently this means all environment which the system allows.  */
+      {
+	char restenvs[4 * sizeof "POSIX_V7_LPBIG_OFFBIG"];
+
+	string_len = 0;
+#ifndef _POSIX_V7_ILP32_OFF32
+        if (__sysconf (_SC_V7_ILP32_OFF32) > 0)
+#endif
+#if !defined _POSIX_V7_ILP32_OFF32 || _POSIX_V7_ILP32_OFF32 > 0
+          {
+            memcpy (restenvs + string_len, "POSIX_V7_ILP32_OFF32",
+                    sizeof "POSIX_V7_ILP32_OFF32" - 1);
+            string_len += sizeof "POSIX_V7_ILP32_OFF32" - 1;
+          }
+#endif
+#ifndef _POSIX_V7_ILP32_OFFBIG
+        if (__sysconf (_SC_V7_ILP32_OFFBIG) > 0)
+#endif
+#if !defined _POSIX_V7_ILP32_OFFBIG || _POSIX_V7_ILP32_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V7_ILP32_OFFBIG",
+                    sizeof "POSIX_V7_ILP32_OFFBIG" - 1);
+            string_len += sizeof "POSIX_V7_ILP32_OFFBIG" - 1;
+          }
+#endif
+#ifndef _POSIX_V7_LP64_OFF64
+        if (__sysconf (_SC_V7_LP64_OFF64) > 0)
+#endif
+#if !defined _POSIX_V7_LP64_OFF64 || _POSIX_V7_LP64_OFF64 > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V7_LP64_OFF64",
+                    sizeof "POSIX_V7_LP64_OFF64" - 1);
+            string_len += sizeof "POSIX_V7_LP64_OFF64" - 1;
+          }
+#endif
+#ifndef _POSIX_V7_LPBIG_OFFBIG
+        if (__sysconf (_SC_V7_LPBIG_OFFBIG) > 0)
+#endif
+#if !defined _POSIX_V7_LPBIG_OFFBIG || _POSIX_V7_LPBIG_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V7_LPBIG_OFFBIG",
+                    sizeof "POSIX_V7_LPBIG_OFFBIG" - 1);
+            string_len += sizeof "POSIX_V7_LPBIG_OFFBIG" - 1;
+          }
+#endif
+        restenvs[string_len++] = '\0';
+	string = restenvs;
+      }
+      break;
+
+    case _CS_V6_WIDTH_RESTRICTED_ENVS:
+      /* We have to return a newline-separated list of named of
+	 programming environements in which the widths of blksize_t,
+	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
+	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
+	 wint_t types are no greater than the width of type long.
+
+	 Currently this means all environment which the system allows.  */
+      {
+	char restenvs[4 * sizeof "POSIX_V6_LPBIG_OFFBIG"];
+
+	string_len = 0;
+#ifndef _POSIX_V6_ILP32_OFF32
+        if (__sysconf (_SC_V6_ILP32_OFF32) > 0)
+#endif
+#if !defined _POSIX_V6_ILP32_OFF32 || _POSIX_V6_ILP32_OFF32 > 0
+          {
+            memcpy (restenvs + string_len, "POSIX_V6_ILP32_OFF32",
+                    sizeof "POSIX_V6_ILP32_OFF32" - 1);
+            string_len += sizeof "POSIX_V6_ILP32_OFF32" - 1;
+          }
+#endif
+#ifndef _POSIX_V6_ILP32_OFFBIG
+        if (__sysconf (_SC_V6_ILP32_OFFBIG) > 0)
+#endif
+#if !defined _POSIX_V6_ILP32_OFFBIG || _POSIX_V6_ILP32_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V6_ILP32_OFFBIG",
+                    sizeof "POSIX_V6_ILP32_OFFBIG" - 1);
+            string_len += sizeof "POSIX_V6_ILP32_OFFBIG" - 1;
+          }
+#endif
+#ifndef _POSIX_V6_LP64_OFF64
+        if (__sysconf (_SC_V6_LP64_OFF64) > 0)
+#endif
+#if !defined _POSIX_V6_LP64_OFF64 || _POSIX_V6_LP64_OFF64 > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V6_LP64_OFF64",
+                    sizeof "POSIX_V6_LP64_OFF64" - 1);
+            string_len += sizeof "POSIX_V6_LP64_OFF64" - 1;
+          }
+#endif
+#ifndef _POSIX_V6_LPBIG_OFFBIG
+        if (__sysconf (_SC_V6_LPBIG_OFFBIG) > 0)
+#endif
+#if !defined _POSIX_V6_LPBIG_OFFBIG || _POSIX_V6_LPBIG_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "POSIX_V6_LPBIG_OFFBIG",
+                    sizeof "POSIX_V6_LPBIG_OFFBIG" - 1);
+            string_len += sizeof "POSIX_V6_LPBIG_OFFBIG" - 1;
+          }
+#endif
+        restenvs[string_len++] = '\0';
+	string = restenvs;
+      }
+      break;
+
+    case _CS_V5_WIDTH_RESTRICTED_ENVS:
+      /* We have to return a newline-separated list of named of
+	 programming environements in which the widths of blksize_t,
+	 cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t,
+	 ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and
+	 wint_t types are no greater than the width of type long.
+
+	 Currently this means all environment which the system allows.  */
+      {
+	char restenvs[4 * sizeof "XBS5_LPBIG_OFFBIG"];
+
+	string_len = 0;
+#ifndef _XBS5_ILP32_OFF32
+        if (__sysconf (_SC_XBS5_ILP32_OFF32) > 0)
+#endif
+#if !defined _XBS5_ILP32_OFF32 || _XBS5_ILP32_OFF32 > 0
+          {
+            memcpy (restenvs + string_len, "XBS5_ILP32_OFF32",
+                    sizeof "XBS5_ILP32_OFF32" - 1);
+            string_len += sizeof "XBS5_ILP32_OFF32" - 1;
+          }
+#endif
+#ifndef _XBS5_ILP32_OFFBIG
+        if (__sysconf (_SC_XBS5_ILP32_OFFBIG) > 0)
+#endif
+#if !defined _XBS5_ILP32_OFFBIG || _XBS5_ILP32_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "XBS5_ILP32_OFFBIG",
+                    sizeof "XBS5_ILP32_OFFBIG" - 1);
+            string_len += sizeof "XBS5_ILP32_OFFBIG" - 1;
+          }
+#endif
+#ifndef _XBS5_LP64_OFF64
+        if (__sysconf (_SC_XBS5_LP64_OFF64) > 0)
+#endif
+#if !defined _XBS5_LP64_OFF64 || _XBS5_LP64_OFF64 > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "XBS5_LP64_OFF64",
+                    sizeof "XBS5_LP64_OFF64" - 1);
+            string_len += sizeof "XBS5_LP64_OFF64" - 1;
+          }
+#endif
+#ifndef _XBS5_LPBIG_OFFBIG
+        if (__sysconf (_SC_XBS5_LPBIG_OFFBIG) > 0)
+#endif
+#if !defined _XBS5_LPBIG_OFFBIG || _XBS5_LPBIG_OFFBIG > 0
+          {
+            if (string_len)
+              restenvs[string_len++] = '\n';
+            memcpy (restenvs + string_len, "XBS5_LPBIG_OFFBIG",
+                    sizeof "XBS5_LPBIG_OFFBIG" - 1);
+            string_len += sizeof "XBS5_LPBIG_OFFBIG" - 1;
+          }
+#endif
+        restenvs[string_len++] = '\0';
+	string = restenvs;
+      }
+      break;
Index: libc/posix/regex_internal.c
===================================================================
--- libc/posix/regex_internal.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/regex_internal.c	(.../trunk)	(revision 8411)
@@ -44,8 +44,8 @@
   int init_buf_len;
 
   /* Ensure at least one character fits into the buffers.  */
-  if (init_len < dfa->mb_cur_max)
-    init_len = dfa->mb_cur_max;
+  if (init_len < dfa_mb_cur_max (dfa))
+    init_len = dfa_mb_cur_max (dfa);
   init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
   re_string_construct_common (str, len, pstr, trans, icase, dfa);
 
@@ -56,7 +56,7 @@
   pstr->word_char = dfa->word_char;
   pstr->word_ops_used = dfa->word_ops_used;
   pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
-  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
+  pstr->valid_len = (pstr->mbs_allocated || dfa_mb_cur_max (dfa) > 1) ? 0 : len;
   pstr->valid_raw_len = pstr->valid_len;
   return REG_NOERROR;
 }
@@ -83,7 +83,7 @@
   if (icase)
     {
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	{
 	  while (1)
 	    {
@@ -92,7 +92,7 @@
 		return ret;
 	      if (pstr->valid_raw_len >= len)
 		break;
-	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
+	      if (pstr->bufs_len > pstr->valid_len + dfa_mb_cur_max (dfa))
 		break;
 	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
 	      if (BE (ret != REG_NOERROR, 0))
@@ -106,7 +106,7 @@
   else
     {
 #ifdef RE_ENABLE_I18N
-      if (dfa->mb_cur_max > 1)
+      if (dfa_mb_cur_max (dfa) > 1)
 	build_wcs_buffer (pstr);
       else
 #endif /* RE_ENABLE_I18N  */
@@ -131,7 +131,7 @@
 re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
 {
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1)
+  if (string_mb_cur_max (pstr) > 1)
     {
       wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
       if (BE (new_wcs == NULL, 0))
@@ -171,7 +171,7 @@
   pstr->trans = trans;
   pstr->icase = icase ? 1 : 0;
   pstr->mbs_allocated = (trans != NULL || icase);
-  pstr->mb_cur_max = dfa->mb_cur_max;
+  pstr->mb_cur_max = dfa_mb_cur_max (dfa);
   pstr->is_utf8 = dfa->is_utf8;
   pstr->map_notascii = dfa->map_notascii;
   pstr->stop = pstr->len;
@@ -197,7 +197,7 @@
 {
 #ifdef _LIBC
   unsigned char buf[MB_LEN_MAX];
-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
 #else
   unsigned char buf[64];
 #endif
@@ -220,7 +220,7 @@
 	{
 	  int i, ch;
 
-	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	  for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
 	    {
 	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
 	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
@@ -268,7 +268,7 @@
   size_t mbclen;
 #ifdef _LIBC
   char buf[MB_LEN_MAX];
-  assert (MB_LEN_MAX >= pstr->mb_cur_max);
+  assert (MB_LEN_MAX >= string_mb_cur_max (pstr));
 #else
   char buf[64];
 #endif
@@ -360,7 +360,7 @@
 	  {
 	    int i, ch;
 
-	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
+	    for (i = 0; i < string_mb_cur_max (pstr) && i < remain_len; ++i)
 	      {
 		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
 		buf[i] = pstr->trans[ch];
@@ -555,8 +555,9 @@
 }
 
 /* This function re-construct the buffers.
-   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
-   convert to upper case in case of REG_ICASE, apply translation.  */
+   Concretely, convert to wide character in case of
+   string_mb_cur_max (pstr) > 1, convert to upper case in case of
+   REG_ICASE, apply translation.  */
 
 static reg_errcode_t
 internal_function
@@ -567,7 +568,7 @@
     {
       /* Reset buffer.  */
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
 #endif /* RE_ENABLE_I18N */
       pstr->len = pstr->raw_len;
@@ -658,7 +659,7 @@
 	      pstr->tip_context = re_string_context_at (pstr, offset - 1,
 							eflags);
 #ifdef RE_ENABLE_I18N
-	      if (pstr->mb_cur_max > 1)
+	      if (string_mb_cur_max (pstr) > 1)
 		memmove (pstr->wcs, pstr->wcs + offset,
 			 (pstr->valid_len - offset) * sizeof (wint_t));
 #endif /* RE_ENABLE_I18N */
@@ -687,7 +688,7 @@
 #endif
 	  pstr->valid_len = 0;
 #ifdef RE_ENABLE_I18N
-	  if (pstr->mb_cur_max > 1)
+	  if (string_mb_cur_max (pstr) > 1)
 	    {
 	      int wcs_idx;
 	      wint_t wc = WEOF;
@@ -699,7 +700,7 @@
 		  /* Special case UTF-8.  Multi-byte chars start with any
 		     byte other than 0x80 - 0xbf.  */
 		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
-		  end = raw + (offset - pstr->mb_cur_max);
+		  end = raw + (offset - string_mb_cur_max (pstr));
 		  if (end < pstr->raw_mbs)
 		    end = pstr->raw_mbs;
 		  p = raw + offset - 1;
@@ -791,7 +792,7 @@
 
   /* Then build the buffers.  */
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1)
+  if (string_mb_cur_max (pstr) > 1)
     {
       if (pstr->icase)
 	{
@@ -829,7 +830,7 @@
     return re_string_peek_byte (pstr, idx);
 
 #ifdef RE_ENABLE_I18N
-  if (pstr->mb_cur_max > 1
+  if (string_mb_cur_max (pstr) > 1
       && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
     return re_string_peek_byte (pstr, idx);
 #endif
@@ -918,7 +919,7 @@
     return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
 	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
 #ifdef RE_ENABLE_I18N
-  if (input->mb_cur_max > 1)
+  if (string_mb_cur_max (input) > 1)
     {
       wint_t wc;
       int wc_idx = idx;
@@ -1429,7 +1430,7 @@
   dfa->nodes[dfa->nodes_len].constraint = 0;
 #ifdef RE_ENABLE_I18N
   dfa->nodes[dfa->nodes_len].accept_mb =
-    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
+    (type == OP_PERIOD && dfa_mb_cur_max (dfa) > 1) || type == COMPLEX_BRACKET;
 #endif
   dfa->nexts[dfa->nodes_len] = -1;
   re_node_set_init_empty (dfa->edests + dfa->nodes_len);
Index: libc/posix/regex_internal.h
===================================================================
--- libc/posix/regex_internal.h	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/regex_internal.h	(.../trunk)	(revision 8411)
@@ -27,6 +27,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
 # include <langinfo.h>
 #endif
@@ -374,6 +378,13 @@
 };
 typedef struct re_string_t re_string_t;
 
+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
+   help the compiler make use of that fact.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define string_mb_cur_max(str) ((str)->mb_cur_max + 0)
+#else
+# define string_mb_cur_max(str) (1)
+#endif
 
 struct re_dfa_t;
 typedef struct re_dfa_t re_dfa_t;
@@ -659,6 +670,14 @@
   __libc_lock_define (, lock)
 };
 
+/* When OPTION_EGLIBC_LOCALE_CODE is disabled, this is always 1;
+   help the compiler make use of that fact.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define dfa_mb_cur_max(dfa) ((dfa)->mb_cur_max + 0)
+#else
+# define dfa_mb_cur_max(dfa) (1)
+#endif
+
 #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
 #define re_node_set_remove(set,id) \
   (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
@@ -719,7 +738,7 @@
 re_string_char_size_at (const re_string_t *pstr, int idx)
 {
   int byte_idx;
-  if (pstr->mb_cur_max == 1)
+  if (string_mb_cur_max (pstr) == 1)
     return 1;
   for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
     if (pstr->wcs[idx + byte_idx] != WEOF)
@@ -731,7 +750,7 @@
 internal_function __attribute ((pure))
 re_string_wchar_at (const re_string_t *pstr, int idx)
 {
-  if (pstr->mb_cur_max == 1)
+  if (string_mb_cur_max (pstr) == 1)
     return (wint_t) pstr->mbs[idx];
   return (wint_t) pstr->wcs[idx];
 }
Index: libc/posix/tst-getconf.sh
===================================================================
--- libc/posix/tst-getconf.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/tst-getconf.sh	(.../trunk)	(revision 8411)
@@ -2,14 +2,17 @@
 
 common_objpfx=$1; shift
 elf_objpfx=$1; shift
+cross_test_wrapper=$1; shift
 if [ $# -eq 0 ]; then
   # Static case.
   runit() {
+    ${cross_test_wrapper} \
     "$@"
   }
 else
   rtld_installed_name=$1; shift
   runit() {
+    ${cross_test_wrapper} \
     ${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} "$@"
   }
 fi
@@ -26,7 +29,10 @@
 result=0
 while read name; do
   echo -n "getconf $name: " >> $logfile
-  runit ${common_objpfx}posix/getconf "$name" 2>> $logfile >> $logfile
+  # Redirect input from /dev/null in case runit consumes input when it
+  # shouldn't (ssh, say)
+  runit ${common_objpfx}posix/getconf "$name" \
+        < /dev/null 2>> $logfile >> $logfile
   if test $? -ne 0; then
     echo "*** $name FAILED" >> $logfile
     result=1
@@ -204,7 +210,10 @@
 
 while read name; do
   echo -n "getconf $name /: " >> $logfile
-  runit ${common_objpfx}posix/getconf "$name" / 2>> $logfile >> $logfile
+  # Redirect input from /dev/null in case runit consumes input when it
+  # shouldn't (ssh, say)
+  runit ${common_objpfx}posix/getconf "$name" / \
+      < /dev/null 2>> $logfile >> $logfile
   if test $? -ne 0; then
     echo "*** $name FAILED" >> $logfile
     result=1
Index: libc/posix/globtest.sh
===================================================================
--- libc/posix/globtest.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/globtest.sh	(.../trunk)	(revision 8411)
@@ -3,6 +3,7 @@
 common_objpfx=$1; shift
 elf_objpfx=$1; shift
 rtld_installed_name=$1; shift
+cross_test_wrapper=$1; shift
 logfile=$common_objpfx/posix/globtest.out
 
 #CMP=cmp
@@ -20,6 +21,9 @@
 # We have to find the libc and the NSS modules.
 library_path=${common_objpfx}:${common_objpfx}nss:${common_objpfx}nis:${common_objpfx}db2:${common_objpfx}hesiod
 
+run_program_prefix="${cross_test_wrapper} \
+${elf_objpfx}${rtld_installed_name} --library-path ${library_path}"
+
 # Since we use `sort' we must make sure to use the same locale everywhere.
 LC_ALL=C
 export LC_ALL
@@ -59,7 +63,7 @@
 
 # Normal test
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -86,7 +90,7 @@
 
 # Don't let glob sort it
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -s "$testdir" "*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -113,7 +117,7 @@
 
 # Mark directories
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -m "$testdir" "*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -140,7 +144,7 @@
 
 # Find files starting with .
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -p "$testdir" "*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -170,7 +174,7 @@
 
 # Test braces
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" "file{1,2}" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -183,7 +187,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" "{file{1,2},-file3}" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -197,7 +201,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" "{" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -210,7 +214,7 @@
 
 # Test NOCHECK
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -c "$testdir" "abc" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -223,7 +227,7 @@
 
 # Test NOMAGIC without magic characters
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -g "$testdir" "abc" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -236,7 +240,7 @@
 
 # Test NOMAGIC with magic characters
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -g "$testdir" "abc*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -249,7 +253,7 @@
 
 # Test NOMAGIC for subdirs
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -g "$testdir" "*/does-not-exist" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -262,7 +266,7 @@
 
 # Test subdirs correctly
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -278,7 +282,7 @@
 
 # Test subdirs for invalid names
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/1" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -291,7 +295,7 @@
 
 # Test subdirs with wildcard
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/*1_1" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -305,7 +309,7 @@
 
 # Test subdirs with ?
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/*?_?" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -320,7 +324,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/file1_1" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -333,7 +337,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*-/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -345,7 +349,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*-" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -358,7 +362,7 @@
 
 # Test subdirs with ?
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/*?_?" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -374,7 +378,7 @@
 
 # Test subdirs with [ .. ]
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "*/file1_[12]" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -390,7 +394,7 @@
 
 # Test ']' inside bracket expression
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "dir1/file1_[]12]" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -404,7 +408,7 @@
 
 # Test tilde expansion
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -q -t "$testdir" "~" |
 sort >$testout
 echo ~ | $CMP - $testout >> $logfile || failed=1
@@ -419,7 +423,7 @@
 
 # Test tilde expansion with trailing slash
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -q -t "$testdir" "~/" |
 sort > $testout
 # Some shell incorrectly(?) convert ~/ into // if ~ expands to /.
@@ -439,7 +443,7 @@
 
 # Test tilde expansion with username
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -q -t "$testdir" "~"$USER |
 sort > $testout
 eval echo ~$USER | $CMP - $testout >> $logfile || failed=1
@@ -454,7 +458,7 @@
 
 # Tilde expansion shouldn't match a file
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -T "$testdir" "~file4" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -467,7 +471,7 @@
 
 # Matching \** should only find *file6
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "\**" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -481,7 +485,7 @@
 # ... unless NOESCAPE is used, in which case it should entries with a
 # leading \.
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -e "$testdir" "\**" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -496,7 +500,7 @@
 
 # Matching \*file6 should find *file6
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "\*file6" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -509,7 +513,7 @@
 
 # GLOB_BRACE alone
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" '\{file7\,\}' |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -522,7 +526,7 @@
 
 # GLOB_BRACE and GLOB_NOESCAPE
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b -e "$testdir" '\{file9\,file9b\}' |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -535,7 +539,7 @@
 
 # Escaped comma
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" '{filea\,}' |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -548,7 +552,7 @@
 
 # Escaped closing brace
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -b "$testdir" '{fileb\}c}' |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -561,7 +565,7 @@
 
 # Try a recursive failed search
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -e "$testdir" "a*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -574,7 +578,7 @@
 
 # ... with GLOB_ERR
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -E "$testdir" "a*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -587,7 +591,7 @@
 
 # Try a recursive search in unreadable directory
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "noread/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -599,7 +603,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "noread*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -617,14 +621,14 @@
 fi
 if test "$user" != root; then
     # ... with GLOB_ERR
-    ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+    ${run_program_prefix} \
     ${common_objpfx}posix/globtest -E "$testdir" "noread/*" |
     sort > $testout
     cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
 GLOB_ABORTED
 EOF
 
-    ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+    ${run_program_prefix} \
     ${common_objpfx}posix/globtest -E "$testdir" "noread*/*" |
     sort > $testout
     cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -638,7 +642,7 @@
 
 # Try multiple patterns (GLOB_APPEND)
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest "$testdir" "file1" "*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -655,7 +659,7 @@
 
 # Try multiple patterns (GLOB_APPEND) with offset (GLOB_DOOFFS)
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -o "$testdir" "file1" "*/*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -673,7 +677,7 @@
 
 # Test NOCHECK with non-existing file in subdir.
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -c "$testdir" "*/blahblah" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -686,7 +690,7 @@
 
 # Test [[:punct:]] not matching leading period.
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -c "$testdir" "[[:punct:]]*" |
 sort > $testout
 cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
@@ -715,10 +719,10 @@
 echo 6 > $testdir/dir6/'file1[a'
 echo 7 > $testdir/dir6/'file1[ab]'
 failed=0
-v=`${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+v=`${run_program_prefix} \
    ${common_objpfx}posix/globtest "$testdir" 'dir3\*/file2'`
 test "$v" != 'GLOB_NOMATCH' && echo "$v" >> $logfile && failed=1
-${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+${run_program_prefix} \
 ${common_objpfx}posix/globtest -c "$testdir" \
 'dir3\*/file1' 'dir3\*/file2' 'dir1/file\1_1' 'dir1/file\1_9' \
 'dir2\/' 'nondir\/' 'dir4[a/fil*1' 'di*r4[a/file2' 'dir5[ab]/file[12]' \
@@ -739,7 +743,8 @@
 `dir6/fil*[a'
 `nondir\/'
 EOF
-HOME="$testdir" \
+${cross_test_wrapper} \
+env HOME="$testdir" \
 ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
 ${common_objpfx}posix/globtest -ct "$testdir" \
 '~/dir1/file1_1' '~/dir1/file1_9' '~/dir3\*/file1' '~/dir3\*/file2' \
@@ -755,15 +760,15 @@
 if eval test -d ~"$USER"/; then
   user=`echo "$USER" | sed -n -e 's/^\([^\\]\)\([^\\][^\\]*\)$/~\1\\\\\2/p'`
   if test -n "$user"; then
-    ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+    ${run_program_prefix} \
     ${common_objpfx}posix/globtest -ctq "$testdir" "$user/" |
     sort > $testout
     eval echo ~$USER/ | $CMP - $testout >> $logfile || failed=1
-    ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+    ${run_program_prefix} \
     ${common_objpfx}posix/globtest -ctq "$testdir" "$user\\/" |
     sort > $testout
     eval echo ~$USER/ | $CMP - $testout >> $logfile || failed=1
-    ${elf_objpfx}${rtld_installed_name} --library-path ${library_path} \
+    ${run_program_prefix} \
     ${common_objpfx}posix/globtest -ctq "$testdir" "$user" |
     sort > $testout
     eval echo ~$USER | $CMP - $testout >> $logfile || failed=1
Index: libc/posix/regex.h
===================================================================
--- libc/posix/regex.h	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/regex.h	(.../trunk)	(revision 8411)
@@ -23,6 +23,7 @@
 #define _REGEX_H 1
 
 #include <sys/types.h>
+#include <gnu/option-groups.h>
 
 /* Allow the use in C++ code.  */
 #ifdef __cplusplus
@@ -158,6 +159,8 @@
    treated as 'a\{1'.  */
 # define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
 
+/* EGLIBC: Old regex implementation does not support these.  */
+# ifdef __OPTION_POSIX_REGEXP_GLIBC
 /* If this bit is set, then ignore case when matching.
    If not set, then case is significant.  */
 # define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
@@ -174,6 +177,7 @@
 /* If this bit is set, then no_sub will be set to 1 during
    re_compile_pattern.  */
 # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
+# endif /* __OPTION_POSIX_REGEXP_GLIBC */
 #endif
 
 /* This global variable defines the particular regexp syntax to use (for
@@ -230,8 +234,13 @@
   (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
    | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
 
+#ifdef __OPTION_POSIX_REGEXP_GLIBC
 #define RE_SYNTAX_POSIX_BASIC						\
   (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
+#else
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+#endif
 
 /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
    RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
@@ -297,9 +306,11 @@
 /* Like REG_NOTBOL, except for the end-of-line.  */
 #define REG_NOTEOL (1 << 1)
 
+#ifdef __OPTION_POSIX_REGEXP_GLIBC
 /* Use PMATCH[0] to delimit the start and end of the search in the
    buffer.  */
 #define REG_STARTEND (1 << 2)
+#endif
 
 
 /* If any error codes are removed, changed, or added, update the
Index: libc/posix/glob.c
===================================================================
--- libc/posix/glob.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/glob.c	(.../trunk)	(revision 8411)
@@ -27,6 +27,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stddef.h>
+#ifdef _LIBC
+# include <gnu/option-groups.h>
+#endif
 
 /* Outcomment the following line for production quality code.  */
 /* #define NDEBUG 1 */
@@ -566,6 +569,7 @@
 	  if (home_dir == NULL || home_dir[0] == '\0')
             home_dir = "c:/users/default"; /* poor default */
 #  else
+#   if ! _LIBC || __OPTION_EGLIBC_GETLOGIN
 	  if (home_dir == NULL || home_dir[0] == '\0')
 	    {
 	      int success;
@@ -582,18 +586,18 @@
 	      if (success)
 		{
 		  struct passwd *p;
-#   if defined HAVE_GETPWNAM_R || defined _LIBC
+#    if defined HAVE_GETPWNAM_R || defined _LIBC
 		  long int pwbuflen = GETPW_R_SIZE_MAX ();
 		  char *pwtmpbuf;
 		  struct passwd pwbuf;
 		  int save = errno;
 
-#    ifndef _LIBC
+#     ifndef _LIBC
 		  if (pwbuflen == -1)
 		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
 		       Try a moderate value.  */
 		    pwbuflen = 1024;
-#    endif
+#     endif
 		  pwtmpbuf = (char *) __alloca (pwbuflen);
 
 		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
@@ -604,22 +608,23 @@
 			  p = NULL;
 			  break;
 			}
-#    ifdef _LIBC
+#     ifdef _LIBC
 		      pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
 						2 * pwbuflen);
-#    else
+#     else
 		      pwbuflen *= 2;
 		      pwtmpbuf = (char *) __alloca (pwbuflen);
-#    endif
+#     endif
 		      __set_errno (save);
 		    }
-#   else
+#    else
 		  p = getpwnam (name);
-#   endif
+#    endif
 		  if (p != NULL)
 		    home_dir = p->pw_dir;
 		}
 	    }
+#   endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
 	  if (home_dir == NULL || home_dir[0] == '\0')
 	    {
 	      if (flags & GLOB_TILDE_CHECK)
Index: libc/posix/bug-regex1.c
===================================================================
--- libc/posix/bug-regex1.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/bug-regex1.c	(.../trunk)	(revision 8411)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <regex.h>
 #include <wchar.h>
+#include <gnu/option-groups.h>
 
 int
 main (void)
@@ -17,7 +18,9 @@
   memset (&regex, '\0', sizeof (regex));
 
   setlocale (LC_ALL, "de_DE.ISO-8859-1");
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
   fwide (stdout, -1);
+#endif
 
   re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_DEBUG);
 
Index: libc/posix/fnmatch_loop.c
===================================================================
--- libc/posix/fnmatch_loop.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/fnmatch_loop.c	(.../trunk)	(revision 8411)
@@ -52,10 +52,15 @@
   const char *collseq = (const char *)
     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
 # else
+#  if __OPTION_EGLIBC_LOCALE_CODE
   const UCHAR *collseq = (const UCHAR *)
     _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
-# endif
-#endif
+#   define COLLSEQ_BYTE_LOOKUP(ix) (collseq[(ix)])
+#  else
+#   define COLLSEQ_BYTE_LOOKUP(ix) (ix)
+#  endif /* __OPTION_EGLIBC_LOCALE_CODE */
+# endif /* WIDE_CHAR_VERSION */
+#endif /* _LIBC */
 
   while ((c = *p++) != L('\0'))
     {
@@ -277,7 +282,7 @@
 		    /* Leave room for the null.  */
 		    CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
 		    size_t c1 = 0;
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 		    wctype_t wt;
 #endif
 		    const CHAR *startp = p;
@@ -307,7 +312,7 @@
 		      }
 		    str[c1] = L('\0');
 
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+#if defined _LIBC ? __OPTION_POSIX_C_LANG_WIDE_CHAR : (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
 		    wt = IS_CHAR_CLASS (str);
 		    if (wt == 0)
 		      /* Invalid character class name.  */
@@ -676,8 +681,10 @@
 			else
 			  lcollseq = __collseq_table_lookup (collseq, cold);
 # else
-			fcollseq = collseq[fn];
-			lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+			fcollseq = COLLSEQ_BYTE_LOOKUP (fn);
+			lcollseq = (is_seqval
+                                    ? cold
+                                    : COLLSEQ_BYTE_LOOKUP ((UCHAR) cold));
 # endif
 
 			is_seqval = 0;
@@ -853,7 +860,7 @@
 				    goto matched;
 				  }
 # else
-				hcollseq = collseq[cend];
+				hcollseq = COLLSEQ_BYTE_LOOKUP (cend);
 # endif
 			      }
 
Index: libc/posix/cross-getconf.c
===================================================================
--- libc/posix/cross-getconf.c	(.../fsf/trunk)	(revision 0)
+++ libc/posix/cross-getconf.c	(.../trunk)	(revision 8411)
@@ -0,0 +1,140 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Undefine macros that should be defined in cross-getconf.h.  */
+#undef _POSIX_V7_ILP32_OFF32
+#undef _POSIX_V7_ILP32_OFFBIG
+#undef _POSIX_V7_LP64_OFF64
+#undef _POSIX_V7_LPBIG_OFFBIG
+#undef _POSIX_V6_ILP32_OFF32
+#undef _POSIX_V6_ILP32_OFFBIG
+#undef _POSIX_V6_LP64_OFF64
+#undef _POSIX_V6_LPBIG_OFFBIG
+#undef _XBS5_ILP32_OFF32
+#undef _XBS5_ILP32_OFFBIG
+#undef _XBS5_LP64_OFF64
+#undef _XBS5_LPBIG_OFFBIG
+
+#include "cross-getconf.h"
+
+/* Define macros cross-getconf.h doesn't define to (-1).
+   This will prevent using host's __sysconf in confstr.inc.  */
+#ifndef _POSIX_V7_ILP32_OFF32
+# define _POSIX_V7_ILP32_OFF32 (-1)
+#endif
+#ifndef _POSIX_V7_ILP32_OFFBIG
+# define _POSIX_V7_ILP32_OFFBIG (-1)
+#endif
+#ifndef _POSIX_V7_LP64_OFF64
+# define _POSIX_V7_LP64_OFF64 (-1)
+#endif
+#ifndef _POSIX_V7_LPBIG_OFFBIG
+# define _POSIX_V7_LPBIG_OFFBIG (-1)
+#endif
+#ifndef _POSIX_V6_ILP32_OFF32
+# define _POSIX_V6_ILP32_OFF32 (-1)
+#endif
+#ifndef _POSIX_V6_ILP32_OFFBIG
+# define _POSIX_V6_ILP32_OFFBIG (-1)
+#endif
+#ifndef _POSIX_V6_LP64_OFF64
+# define _POSIX_V6_LP64_OFF64 (-1)
+#endif
+#ifndef _POSIX_V6_LPBIG_OFFBIG
+# define _POSIX_V6_LPBIG_OFFBIG (-1)
+#endif
+#ifndef _XBS5_ILP32_OFF32
+# define _XBS5_ILP32_OFF32 (-1)
+#endif
+#ifndef _XBS5_ILP32_OFFBIG
+# define _XBS5_ILP32_OFFBIG (-1)
+#endif
+#ifndef _XBS5_LP64_OFF64
+# define _XBS5_LP64_OFF64 (-1)
+#endif
+#ifndef _XBS5_LPBIG_OFFBIG
+# define _XBS5_LPBIG_OFFBIG (-1)
+#endif
+
+#undef _CS_V5_WIDTH_RESTRICTED_ENVS
+#define _CS_V5_WIDTH_RESTRICTED_ENVS 5
+
+#undef _CS_V6_WIDTH_RESTRICTED_ENVS
+#define _CS_V6_WIDTH_RESTRICTED_ENVS 6
+
+#undef _CS_V7_WIDTH_RESTRICTED_ENVS
+#define _CS_V7_WIDTH_RESTRICTED_ENVS 7
+
+/* Cross-getconf is a very simple program that assumes fixed
+   input and produces fixed output.  It handles only cases
+   that are necessary to cross-compile EGLIBC.  */
+
+void
+cross_getconf (int name)
+{
+  const char *string = "";
+  size_t string_len = 1;
+
+  switch (name)
+    {
+#include "confstr.inc"
+    }
+
+  printf ("%.*s\n", (int) string_len, string);
+}
+
+int
+main (int argc, char *argv[])
+{
+  const char *getconf_dir;
+
+  if (argc != 2)
+    {
+      fprintf (stderr,
+	       "%s: must be called with exactly one argument\n", argv[0]);
+      return 1;
+    }
+
+  getconf_dir = getenv ("GETCONF_DIR");
+  if (getconf_dir == NULL
+      || strcmp (getconf_dir, "/dev/null") != 0)
+    {
+      fprintf (stderr, "%s: GETCONF_DIR should be /dev/null\n", argv[0]);
+      return 1;
+    }
+
+  if (strcmp (argv[1], "_POSIX_V7_WIDTH_RESTRICTED_ENVS") == 0)
+    cross_getconf (_CS_V7_WIDTH_RESTRICTED_ENVS);
+  else if (strcmp (argv[1], "_POSIX_V6_WIDTH_RESTRICTED_ENVS") == 0)
+    cross_getconf (_CS_V6_WIDTH_RESTRICTED_ENVS);
+  else if (strcmp (argv[1], "_XBS5_WIDTH_RESTRICTED_ENVS") == 0)
+    cross_getconf (_CS_V5_WIDTH_RESTRICTED_ENVS);
+  else
+    {
+      fprintf (stderr,
+	       "%s: the only supported arguments value are "
+	       "_POSIX_V7_WIDTH_RESTRICTED_ENVS, "
+	       "_POSIX_V6_WIDTH_RESTRICTED_ENVS, and "
+	       "_XBS5_WIDTH_RESTRICTED_ENVS\n", argv[0]);
+      return 1;
+    }
+  return 0;
+}
Index: libc/posix/regexec.c
===================================================================
--- libc/posix/regexec.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/regexec.c	(.../trunk)	(revision 8411)
@@ -185,11 +185,11 @@
 static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
 				    const re_string_t *input, int idx)
      internal_function;
-# ifdef _LIBC
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
 static unsigned int find_collation_sequence_value (const unsigned char *mbs,
 						   size_t name_len)
      internal_function;
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 #endif /* RE_ENABLE_I18N */
 static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
 				       const re_dfastate_t *state,
@@ -254,26 +254,10 @@
   return err != REG_NOERROR;
 }
 
-#ifdef _LIBC
-# include <shlib-compat.h>
-versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
+/* EGLIBC: The code that used to be here was move to a separate file
+   so that it can be shared with xregex.c.  */
+#include "regexec-compat.c"
 
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-__typeof__ (__regexec) __compat_regexec;
-
-int
-attribute_compat_text_section
-__compat_regexec (const regex_t *__restrict preg,
-		  const char *__restrict string, size_t nmatch,
-		  regmatch_t pmatch[], int eflags)
-{
-  return regexec (preg, string, nmatch, pmatch,
-		  eflags & (REG_NOTBOL | REG_NOTEOL));
-}
-compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
-# endif
-#endif
-
 /* Entry points for GNU code.  */
 
 /* re_match, re_search, re_match_2, re_search_2
@@ -711,7 +695,7 @@
   incr = (range < 0) ? -1 : 1;
   left_lim = (range < 0) ? start + range : start;
   right_lim = (range < 0) ? start : start + range;
-  sb = dfa->mb_cur_max == 1;
+  sb = dfa_mb_cur_max (dfa) == 1;
   match_kind =
     (fastmap
      ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
@@ -3410,7 +3394,7 @@
 	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
 	    goto out_free;
 
-	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
+	  if (dest_states[i] != dest_states_word[i] && dfa_mb_cur_max (dfa) > 1)
 	    need_word_trtable = 1;
 
 	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
@@ -3552,7 +3536,7 @@
       else if (type == OP_PERIOD)
 	{
 #ifdef RE_ENABLE_I18N
-	  if (dfa->mb_cur_max > 1)
+	  if (dfa_mb_cur_max (dfa) > 1)
 	    bitset_merge (accepts, dfa->sb_char);
 	  else
 #endif
@@ -3603,7 +3587,7 @@
 		  continue;
 		}
 #ifdef RE_ENABLE_I18N
-	      if (dfa->mb_cur_max > 1)
+	      if (dfa_mb_cur_max (dfa) > 1)
 		for (j = 0; j < BITSET_WORDS; ++j)
 		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
 	      else
@@ -3622,7 +3606,7 @@
 		  continue;
 		}
 #ifdef RE_ENABLE_I18N
-	      if (dfa->mb_cur_max > 1)
+	      if (dfa_mb_cur_max (dfa) > 1)
 		for (j = 0; j < BITSET_WORDS; ++j)
 		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
 	      else
@@ -3794,12 +3778,6 @@
   if (node->type == COMPLEX_BRACKET)
     {
       const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
-      const unsigned char *pin
-	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
-      int j;
-      uint32_t nrules;
-# endif /* _LIBC */
       int match_len = 0;
       wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
 		    ? re_string_wchar_at (input, str_idx) : 0);
@@ -3811,6 +3789,7 @@
 	    match_len = char_len;
 	    goto check_node_accept_bytes_match;
 	  }
+#if __OPTION_EGLIBC_LOCALE_CODE
       /* match with character_class?  */
       for (i = 0; i < cset->nchar_classes; ++i)
 	{
@@ -3821,8 +3800,16 @@
 	      goto check_node_accept_bytes_match;
 	    }
 	}
+#endif
 
-# ifdef _LIBC
+      /* When __OPTION_EGLIBC_LOCALE_CODE is disabled, only the C
+         locale is supported; it has no collation rules.  */
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
+      const unsigned char *pin
+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
+      int j;
+      uint32_t nrules;
+
       nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
       if (nrules != 0)
 	{
@@ -3915,8 +3902,12 @@
 	    }
 	}
       else
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 	{
+          /* In the _LIBC version, if OPTION_EGLIBC_LOCALE_CODE is
+             disabled, there can be no multibyte range endpoints, and
+             cset->nranges is always zero.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
 	  /* match with range expression?  */
 #if __GNUC__ >= 2
 	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
@@ -3935,6 +3926,7 @@
 		  goto check_node_accept_bytes_match;
 		}
 	    }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 	}
     check_node_accept_bytes_match:
       if (!cset->non_match)
@@ -3950,7 +3942,7 @@
   return 0;
 }
 
-# ifdef _LIBC
+# if defined _LIBC && __OPTION_EGLIBC_LOCALE_CODE
 static unsigned int
 internal_function
 find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
@@ -4008,7 +4000,7 @@
       return UINT_MAX;
     }
 }
-# endif /* _LIBC */
+# endif /* _LIBC && __OPTION_EGLIBC_LOCALE_CODE */
 #endif /* RE_ENABLE_I18N */
 
 /* Check whether the node accepts the byte which is IDX-th
@@ -4093,7 +4085,7 @@
   if (pstr->icase)
     {
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	{
 	  ret = build_wcs_upper_buffer (pstr);
 	  if (BE (ret != REG_NOERROR, 0))
@@ -4106,7 +4098,7 @@
   else
     {
 #ifdef RE_ENABLE_I18N
-      if (pstr->mb_cur_max > 1)
+      if (string_mb_cur_max (pstr) > 1)
 	build_wcs_buffer (pstr);
       else
 #endif /* RE_ENABLE_I18N  */
Index: libc/posix/Makefile
===================================================================
--- libc/posix/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for POSIX portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= posix
 
 headers	:= sys/utsname.h sys/times.h sys/wait.h sys/types.h unistd.h	      \
@@ -48,15 +50,25 @@
 	getuid geteuid getgid getegid getgroups setuid setgid group_member    \
 	getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid	      \
 	getresuid getresgid setresuid setresgid				      \
-	getlogin getlogin_r setlogin					      \
 	pathconf sysconf fpathconf					      \
-	glob glob64 fnmatch regex					      \
+	glob glob64 fnmatch						      \
 	confstr								      \
 	getopt getopt1 getopt_init					      \
 	sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax  \
 	sched_primin sched_rr_gi sched_getaffinity sched_setaffinity	      \
-	getaddrinfo gai_strerror wordexp				      \
 	pread pwrite pread64 pwrite64					      \
+	posix_madvise							      \
+	get_child_max sched_cpucount sched_cpualloc sched_cpufree
+
+routines-$(OPTION_EGLIBC_INET) += getaddrinfo gai_strerror 
+
+ifeq (y,$(OPTION_POSIX_REGEXP_GLIBC))
+routines-$(OPTION_POSIX_REGEXP) += regex
+else
+routines-$(OPTION_POSIX_REGEXP) += xregex
+endif
+
+routines-$(OPTION_EGLIBC_SPAWN) +=					      \
 	spawn_faction_init spawn_faction_destroy spawn_faction_addclose	      \
 	spawn_faction_addopen spawn_faction_adddup2			      \
 	spawnattr_init spawnattr_destroy				      \
@@ -64,38 +76,52 @@
 	spawnattr_getflags spawnattr_setflags				      \
 	spawnattr_getpgroup spawnattr_setpgroup spawn spawnp spawni	      \
 	spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
-	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
-	posix_madvise							      \
-	get_child_max sched_cpucount sched_cpualloc sched_cpufree
+	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam
+routines-$(OPTION_EGLIBC_GETLOGIN) += getlogin getlogin_r
+routines-$(OPTION_EGLIBC_WORDEXP) += wordexp
+routines-$(OPTION_EGLIBC_BSD) += setlogin
 
 include ../Makeconfig
 
 aux		:= init-posix environ
-tests		:= tstgetopt testfnm runtests runptests	     \
+tests		:= tstgetopt testfnm runtests \
 		   tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \
-		   tst-getlogin tst-mmap tst-getaddrinfo tst-truncate \
-		   tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \
-		   tst-chmod bug-regex1 bug-regex2 bug-regex3 bug-regex4 \
-		   tst-gnuglob tst-regex bug-regex5 bug-regex6 bug-regex7 \
-		   bug-regex8 bug-regex9 bug-regex10 bug-regex11 bug-regex12 \
-		   bug-regex13 bug-regex14 bug-regex15 bug-regex16 \
-		   bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
-		   bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
-		   bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
-		   tst-nice tst-nanosleep tst-regex2 \
-		   transbug tst-rxspencer tst-pcre tst-boost \
-		   bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
-		   tst-getaddrinfo2 bug-glob1 bug-glob2 tst-sysconf \
+		   tst-getlogin tst-mmap tst-truncate \
+		   tst-truncate64 tst-fork tst-dir \
+		   tst-chmod bug-regex2 bug-regex3 bug-regex4 \
+		   tst-gnuglob bug-regex6 bug-regex7 \
+		   bug-regex8 bug-regex9 bug-regex10 bug-regex12 \
+		   bug-regex14 bug-regex15 \
+		   bug-regex21 bug-regex24 \
+		   bug-regex27 bug-regex28 \
+		   tst-nice tst-nanosleep \
+		   transbug \
+		   tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
+		   bug-glob1 bug-glob2 tst-sysconf \
 		   tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
 		   tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
 		   tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
-		   tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
-		   tst-rfc3484-3 \
-		   tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset
-xtests		:= bug-ga2
+		   tst-execvp3 tst-execvp4 \
+		   tst-fnmatch2 tst-cpucount tst-cpuset
+tests-$(OPTION_EGLIBC_LOCALE_CODE)					    \
+		+= tst-fnmatch tst-regexloc bug-regex1 bug-regex5 \
+		   bug-regex23 bug-regex25
+tests-$(OPTION_EGLIBC_INET) \
+	        += tst-getaddrinfo bug-ga1 tst-getaddrinfo2 \
+		   tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 tst-getaddrinfo3
+tests-$(OPTION_POSIX_REGEXP_GLIBC) \
+		+= runptests bug-regex11 bug-regex13 bug-regex16 \
+		   tst-regex2 tst-rxspencer tst-pcre tst-boost
+ifeq (yy,$(OPTION_EGLIBC_LOCALE_CODE)$(OPTION_POSIX_REGEXP_GLIBC))
+tests           += tst-regex bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
+		   bug-regex22 bug-regex26
+endif
+xtests-$(OPTION_EGLIBC_INET) += bug-ga2
 ifeq (yes,$(build-shared))
 test-srcs	:= globtest
-tests           += wordexp-test tst-exec tst-spawn
+tests           += tst-exec
+tests-$(OPTION_EGLIBC_SPAWN) += tst-spawn
+tests-$(OPTION_EGLIBC_WORDEXP) += wordexp-test
 endif
 others		:= getconf
 install-bin	:= getconf
@@ -123,21 +149,27 @@
 			$(resolvobjdir)/libresolv.a)
 endif
 
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 # globtest and wordexp-test currently only works with shared libraries
 ifeq (yes,$(build-shared))
-tests: $(objpfx)globtest.out $(objpfx)wordexp-tst.out
+tests: $(objpfx)globtest.out
 $(objpfx)globtest.out: globtest.sh $(objpfx)globtest
 	$(SHELL) -e globtest.sh $(common-objpfx) $(elf-objpfx) \
-		 $(rtld-installed-name)
+		 $(rtld-installed-name) '$(cross-test-wrapper)'
+LDLIBS-globtest += $(shell cat $(common-objpfx)nss/fixed-nsswitch-libs)
+ifeq (y,$(OPTION_EGLIBC_WORDEXP))
+tests: $(objpfx)wordexp-tst.out
 $(objpfx)wordexp-tst.out: wordexp-tst.sh $(objpfx)wordexp-test
 	$(SHELL) -e wordexp-tst.sh $(common-objpfx) $(elf-objpfx) \
-		 $(rtld-installed-name)
+		 $(rtld-installed-name) '$(cross-test-wrapper)'
 endif
 endif
+# eglibc: endif
 
+OPTION_EGLIBC_INET-CFLAGS-$(OPTION_EGLIBC_INET) = -DUSE_NSCD=1
+
 CFLAGS-regex.c = -Wno-strict-prototypes
-CFLAGS-getaddrinfo.c = -DRESOLVER -fexceptions -DUSE_NSCD
+CFLAGS-getaddrinfo.c = -DRESOLVER -fexceptions $(OPTION_EGLIBC_INET-CFLAGS-y)
 CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables
@@ -173,8 +205,8 @@
 tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
 		--none random --col --color --colour
 
-tst-exec-ARGS = -- $(built-program-cmd)
-tst-spawn-ARGS = -- $(built-program-cmd)
+tst-exec-ARGS = -- $(local-built-program-cmd)
+tst-spawn-ARGS = -- $(local-built-program-cmd)
 tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
 tst-chmod-ARGS = `pwd`
 tst-vfork3-ARGS = --test-dir=$(objpfx)
@@ -194,7 +226,10 @@
 bug-regex23-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex25-ENV = LOCPATH=$(common-objpfx)localedata
 bug-regex26-ENV = LOCPATH=$(common-objpfx)localedata
-tst-rxspencer-ARGS = --utf8 rxspencer/tests
+tst-rxspencer-ARGS = rxspencer/tests
+ifeq (y,$(OPTION_EGLIBC_LOCALE_CODE))
+tst-rxspencer-ARGS += --utf8 
+endif
 tst-rxspencer-ENV = LOCPATH=$(common-objpfx)localedata
 tst-pcre-ARGS = PCRE.tests
 tst-boost-ARGS = BOOST.tests
@@ -218,13 +253,17 @@
 # Run a test on the header files we use.
 # XXX Please note that for now we ignore the result of this test.
 tests: $(objpfx)annexc.out
-ifeq (no,$(cross-compiling))
-tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \
-  $(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \
-  $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \
+# eglibc: ifeq (no,$(cross-compiling))
+tests: $(objpfx)bug-regex2-mem \
+  $(objpfx)bug-regex21-mem \
+  $(objpfx)tst-getconf.out \
   $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem
+ifeq (y,($OPTION_POSIX_REGEXP_GLIBC))
+tests: $(objpfx)bug-regex14-mem $(objpfx)tst-rxspencer-mem \
+  $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem 
+endif
 xtests: $(objpfx)bug-ga2-mem
-endif
+# eglibc: endif
 
 $(objpfx)annexc.out: $(objpfx)annexc
 	-$(dir $<)$(notdir $<) '$(CC)' \
@@ -272,7 +311,8 @@
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-boost.mtrace > $@
 
 $(objpfx)tst-getconf.out: tst-getconf.sh $(objpfx)getconf
-	$(SHELL) -e $< $(common-objpfx) $(elf-objpfx) $(rtld-installed-name)
+	$(SHELL) -e $< $(common-objpfx) $(elf-objpfx) \
+		'$(cross-test-wrapper)' $(rtld-installed-name)
 
 ifeq (yes,$(build-shared))
 $(objpfx)tst-regex: $(common-objpfx)rt/librt.so
@@ -301,15 +341,36 @@
 	  mv -f $@/$$spec.new $@/$$spec; \
 	done < $(objpfx)getconf.speclist
 
-$(objpfx)getconf.speclist: $(objpfx)getconf
+# eglibc: If we are cross-compiling, build cross-getconf utility and use it
+# instead of getconf.
+
+# We moved a piece of confstr.c to confstr.inc to share the later with
+# cross-getconf.c.
+confstr.c: confstr.inc
+
 ifeq (no,$(cross-compiling))
+getconf-dep = $(objpfx)getconf
+getconf-cmd = $(run-program-prefix) $(objpfx)getconf
+else
+getconf-dep = $(objpfx)cross-getconf
+getconf-cmd = $(objpfx)cross-getconf
+
+# Get configuration defines for cross-getconf by preprocessing confstr.c.
+$(objpfx)cross-getconf.h: confstr.c
+	$(compile.c) -E -dM -o - | grep "define _POSIX_V7_ILP32_OFF32\|define _POSIX_V7_ILP32_OFFBIG\|define _POSIX_V7_LP64_OFF64\|define _POSIX_V7_LPBIG_OFFBIG\|_POSIX_V6_ILP32_OFF32\|define _POSIX_V6_ILP32_OFFBIG\|define _POSIX_V6_LP64_OFF64\|define _POSIX_V6_LPBIG_OFFBIG\|_XBS5_ILP32_OFF32\|define _XBS5_ILP32_OFFBIG\|define _XBS5_LP64_OFF64\|define _XBS5_LPBIG_OFFBIG" > $(objpfx)cross-getconf.h
+
+cross-getconf-CFLAGS = -O -I$(objpfx)
+
+$(objpfx)cross-getconf: cross-getconf.c $(objpfx)cross-getconf.h
+	$(native-compile)
+endif
+
+$(objpfx)getconf.speclist: $(getconf-dep)
 	LC_ALL=C GETCONF_DIR=/dev/null \
-	$(run-program-prefix) $< _POSIX_V7_WIDTH_RESTRICTED_ENVS > $@.new
+		$(getconf-cmd) _POSIX_V7_WIDTH_RESTRICTED_ENVS > $@.new
 	LC_ALL=C GETCONF_DIR=/dev/null \
-	$(run-program-prefix) $< _POSIX_V6_WIDTH_RESTRICTED_ENVS >> $@.new
+		$(getconf-cmd) _POSIX_V6_WIDTH_RESTRICTED_ENVS >> $@.new
 	LC_ALL=C GETCONF_DIR=/dev/null \
-	$(run-program-prefix) $< _XBS5_WIDTH_RESTRICTED_ENVS >> $@.new
-else
-	> $@.new
-endif
+		$(getconf-cmd) _XBS5_WIDTH_RESTRICTED_ENVS >> $@.new
 	mv -f $@.new $@
+# eglibc: end.
Index: libc/posix/getconf.c
===================================================================
--- libc/posix/getconf.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/getconf.c	(.../trunk)	(revision 8411)
@@ -1099,7 +1099,7 @@
 
   if (argc > 1 && strcmp (argv[1], "--version") == 0)
     {
-      printf ("getconf (GNU %s) %s\n", PACKAGE, VERSION);
+      printf ("getconf %s%s\n", PKGVERSION, VERSION);
       printf (gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
@@ -1119,7 +1119,7 @@
 for path PATH.  If SPEC is given, give values for compilation\n\
 environment SPEC.\n\n"));
       printf (gettext ("For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO);
       return 0;
     }
 
Index: libc/posix/bug-regex6.c
===================================================================
--- libc/posix/bug-regex6.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/bug-regex6.c	(.../trunk)	(revision 8411)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <regex.h>
+#include <gnu/option-groups.h>
 
 
 int
@@ -31,7 +32,12 @@
   regex_t re;
   regmatch_t mat[10];
   int i, j, ret = 0;
-  const char *locales[] = { "C", "de_DE.UTF-8" };
+  const char *locales[] = {
+    "C",
+#if __OPTION_EGLIBC_LOCALE_CODE
+    "de_DE.UTF-8"
+#endif
+  };
   const char *string = "http://www.regex.com/pattern/matching.html#intro";
   regmatch_t expect[10] = {
     { 0, 48 }, { 0, 5 }, { 0, 4 }, { 5, 20 }, { 7, 20 }, { 20, 42 },
Index: libc/posix/fnmatch.c
===================================================================
--- libc/posix/fnmatch.c	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/fnmatch.c	(.../trunk)	(revision 8411)
@@ -31,6 +31,10 @@
 #include <fnmatch.h>
 #include <ctype.h>
 
+#if defined _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 #if HAVE_STRING_H || defined _LIBC
 # include <string.h>
 #else
@@ -132,7 +136,7 @@
 #   define ISWCTYPE(WC, WT)	iswctype (WC, WT)
 #  endif
 
-#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
+#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || (_LIBC && __OPTION_EGLIBC_LOCALE_CODE)
 /* In this case we are implementing the multibyte character handling.  */
 #   define HANDLE_MULTIBYTE	1
 #  endif
Index: libc/posix/wordexp-tst.sh
===================================================================
--- libc/posix/wordexp-tst.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/posix/wordexp-tst.sh	(.../trunk)	(revision 8411)
@@ -7,6 +7,11 @@
 common_objpfx=$1; shift
 elf_objpfx=$1; shift
 rtld_installed_name=$1; shift
+cross_test_wrapper=$1; shift
+
+run_program_prefix="${cross_test_wrapper} \
+${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx}"
+
 logfile=${common_objpfx}posix/wordexp-tst.out
 testout=${common_objpfx}posix/wordexp-test-result
 
@@ -20,7 +25,7 @@
 export IFS
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '$*' > ${testout}1
 cat <<"EOF" | cmp - ${testout}1 >> $logfile || failed=1
 wordexp returned 0
@@ -32,7 +37,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '${*}' unquoted > ${testout}2
 cat <<"EOF" | cmp - ${testout}2 >> $logfile || failed=1
 wordexp returned 0
@@ -45,7 +50,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '$@' unquoted > ${testout}3
 cat <<"EOF" | cmp - ${testout}3 >> $logfile || failed=1
 wordexp returned 0
@@ -58,7 +63,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '"$* quoted"' param > ${testout}4
 cat <<"EOF" | cmp - ${testout}4 >> $logfile || failed=1
 wordexp returned 0
@@ -70,7 +75,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '"$@ quoted"' param > ${testout}5
 cat <<"EOF" | cmp - ${testout}5 >> $logfile || failed=1
 wordexp returned 0
@@ -84,7 +89,7 @@
 # Why?  Because bash does it that way..
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '$#' 2 3 4 5 > ${testout}6
 cat <<"EOF" | cmp - ${testout}6 >> $logfile || failed=1
 wordexp returned 0
@@ -96,7 +101,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '$2 ${3} $4' 2nd 3rd "4 th" > ${testout}7
 cat <<"EOF" | cmp - ${testout}7 >> $logfile || failed=1
 wordexp returned 0
@@ -111,7 +116,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '${11}' 2 3 4 5 6 7 8 9 10 11 > ${testout}8
 cat <<"EOF" | cmp - ${testout}8 >> $logfile || failed=1
 wordexp returned 0
@@ -123,7 +128,7 @@
 fi
 
 failed=0
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '"a $@ b"' c d > ${testout}9
 cat <<"EOF" | cmp - ${testout}9 >> $logfile || failed=1
 wordexp returned 0
@@ -136,7 +141,7 @@
   status=1
 fi
 
-${elf_objpfx}${rtld_installed_name} --library-path ${common_objpfx} \
+${run_program_prefix} \
 ${common_objpfx}posix/wordexp-test '${#@} ${#2} *$**' two 3 4 > ${testout}10
 cat <<"EOF" | cmp - ${testout}10 || failed=1
 wordexp returned 0
Index: libc/stdio-common/printf_fp.c
===================================================================
--- libc/stdio-common/printf_fp.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/printf_fp.c	(.../trunk)	(revision 8411)
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <wchar.h>
+#include <gnu/option-groups.h>
 
 #ifdef COMPILE_WPRINTF
 # define CHAR_T        wchar_t
@@ -149,6 +150,10 @@
 			      wchar_t thousands_sep, int ngroups)
      internal_function;
 
+/* Ideally, when OPTION_EGLIBC_LOCALE_CODE is disabled, this should do
+   all its work in ordinary characters, rather than doing it in wide
+   characters and then converting at the end.  But that is a challenge
+   for another day.  */
 
 int
 ___printf_fp (FILE *fp,
@@ -210,7 +215,14 @@
   mp_limb_t cy;
 
   /* Nonzero if this is output on a wide character stream.  */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   int wide = info->wide;
+#else
+  /* This should never be called on a wide-oriented stream when
+     OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+     be trusted to figure that out.  */
+  const int wide = 0;
+#endif
 
   /* Buffer in which we produce the output.  */
   wchar_t *wbuffer = NULL;
@@ -262,6 +274,7 @@
 
 
   /* Figure out the decimal point character.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (info->extra == 0)
     {
       decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
@@ -281,7 +294,13 @@
   /* The decimal point character must not be zero.  */
   assert (*decimal != '\0');
   assert (decimalwc != L'\0');
+#else
+  /* Hard-code values from 'C' locale.  */
+  decimal = ".";
+  decimalwc = L'.';
+#endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (info->group)
     {
       if (info->extra == 0)
@@ -325,6 +344,9 @@
     }
   else
     grouping = NULL;
+#else
+  grouping = NULL;
+#endif
 
   /* Fetch the argument value.	*/
 #ifndef __NO_LONG_DOUBLE_MATH
Index: libc/stdio-common/printf_fphex.c
===================================================================
--- libc/stdio-common/printf_fphex.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/printf_fphex.c	(.../trunk)	(revision 8411)
@@ -29,6 +29,7 @@
 #include "_itoa.h"
 #include "_itowa.h"
 #include <locale/localeinfo.h>
+#include <gnu/option-groups.h>
 
 /* #define NDEBUG 1*/		/* Undefine this for debugging assertions.  */
 #include <assert.h>
@@ -144,10 +145,18 @@
   int done = 0;
 
   /* Nonzero if this is output on a wide character stream.  */
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   int wide = info->wide;
+#else
+  /* This should never be called on a wide-oriented stream when
+     OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+     be trusted to figure that out.  */
+  const int wide = 0;
+#endif
 
 
   /* Figure out the decimal point character.  */
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (info->extra == 0)
     {
       decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
@@ -161,6 +170,10 @@
     }
   /* The decimal point character must never be zero.  */
   assert (*decimal != '\0' && decimalwc != L'\0');
+#else
+  decimal = ".";
+  decimalwc = L'.';
+#endif
 
 
   /* Fetch the argument value.	*/
Index: libc/stdio-common/scanf14.c
===================================================================
--- libc/stdio-common/scanf14.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/scanf14.c	(.../trunk)	(revision 8411)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
+#include <gnu/option-groups.h>
 
 #define FAIL() \
   do {							\
@@ -36,6 +37,7 @@
     FAIL ();
   else if (d != 2.25 || memcmp (c, " x", 2) != 0)
     FAIL ();
+#if __OPTION_EGLIBC_LOCALE_CODE
   if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
     FAIL ();
   else
@@ -45,6 +47,7 @@
       memset (lsp, 'x', sizeof L"3.25");
       free (lsp);
     }
+#endif
   if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
     FAIL ();
   else
Index: libc/stdio-common/_i18n_number.h
===================================================================
--- libc/stdio-common/_i18n_number.h	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/_i18n_number.h	(.../trunk)	(revision 8411)
@@ -19,10 +19,13 @@
 
 #include <wchar.h>
 #include <wctype.h>
+#include <gnu/option-groups.h>
 
 #include "../locale/outdigits.h"
 #include "../locale/outdigitswc.h"
 
+#if __OPTION_EGLIBC_LOCALE_CODE
+
 static CHAR_T *
 _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
 {
@@ -109,3 +112,13 @@
 
   return w;
 }
+
+#else
+
+static CHAR_T *
+_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
+{
+  return w;
+}
+
+#endif
Index: libc/stdio-common/tst-popen.c
===================================================================
--- libc/stdio-common/tst-popen.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/tst-popen.c	(.../trunk)	(revision 8411)
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <wchar.h>
+#include <gnu/option-groups.h>
 
 static int
 do_test (void)
@@ -35,12 +36,14 @@
       return 1;
     }
 
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
   /* POSIX says that pipe streams are byte-oriented.  */
   if (fwide (f, 0) >= 0)
     {
       puts ("popen did not return byte-oriented stream");
       result = 1;
     }
+#endif
 
   if (getline (&line, &len, f) != 5)
     {
Index: libc/stdio-common/printf_size.c
===================================================================
--- libc/stdio-common/printf_size.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/printf_size.c	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 #include <math.h>
 #include <printf.h>
 #include <libioP.h>
+#include <gnu/option-groups.h>
 
 
 /* This defines make it possible to use the same code for GNU C library and
@@ -117,7 +118,14 @@
 
   struct printf_info fp_info;
   int done = 0;
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   int wide = info->wide;
+#else
+  /* This should never be called on a wide-oriented stream when
+     OPTION_POSIX_C_LANG_WIDE_CHAR is disabled, but the compiler can't
+     be trusted to figure that out.  */
+  const int wide = 0;
+#endif
 
 
   /* Fetch the argument value.	*/
Index: libc/stdio-common/Makefile
===================================================================
--- libc/stdio-common/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Specific makefile for stdio-common.
 #
+include ../option-groups.mak
+
 subdir	:= stdio-common
 
 headers	:= stdio_ext.h printf.h bits/printf-ldbl.h
@@ -29,7 +31,7 @@
 	vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex	      \
 	reg-modifier reg-type						      \
 	printf_size fprintf printf snprintf sprintf asprintf dprintf	      \
-	vfwprintf vfscanf vfwscanf					      \
+	vfscanf								      \
 	fscanf scanf sscanf						      \
 	perror psignal							      \
 	tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname		      \
@@ -39,12 +41,18 @@
 	isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
 	isoc99_vsscanf							      \
 	psiginfo
+# Ideally, _itowa and itowa-digits would be in this option group as
+# well, but it is used unconditionally by printf_fp and printf_fphex,
+# and it didn't seem straightforward to disentangle it.
+routines-$(OPTION_POSIX_C_LANG_WIDE_CHAR) +=				      \
+	vfwprintf vfwscanf
 
-install-others = $(inst_includedir)/bits/stdio_lim.h
-
 include ../Makeconfig
 
-aux	:= errlist siglist printf-parsemb printf-parsewc fxprintf
+install-headers-nosubdir: $(inst_includedir)/bits/stdio_lim.h
+
+aux	:= errlist siglist printf-parsemb fxprintf
+aux-$(OPTION_POSIX_C_LANG_WIDE_CHAR) += printf-parsewc
 distribute := _itoa.h _itowa.h _i18n_number.h \
 	      printf-parse.h stdio_lim.h.in tst-unbputc.sh tst-printf.sh
 
@@ -52,15 +60,21 @@
 	 temptest tst-fileno test-fwrite tst-ungetc tst-ferror \
 	 xbug errnobug \
 	 bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
-	 tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
+	 tfformat tiformat tllformat tstdiomisc tst-printfsz \
 	 scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
-	 scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
-	 tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
-	 tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \
+	 scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf \
+	 tst-fseek tst-fmemopen tst-gets \
+	 tst-sprintf tst-rndseek tst-fdopen tst-fphex \
 	 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
-	 tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
-	 bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
-	 scanf16 scanf17 tst-setvbuf1
+	 tst-fwrite bug16 bug17 tst-sprintf2 bug18 \
+	 bug19 tst-popen2 scanf14 scanf15 bug21 bug22 scanf16 scanf17 \
+	 tst-setvbuf1
+tests-$(OPTION_EGLIBC_LOCALE_CODE) \
+      += tst-sscanf tst-swprintf bug15 test-vfprintf bug14 scanf13
+tests-$(OPTION_POSIX_WIDE_CHAR_DEVICE_IO) \
+      += tst-perror bug19a bug20
+tests-$(OPTION_POSIX_C_LANG_WIDE_CHAR) \
+      += bug18a tst-swscanf tst-wc-printf
 
 test-srcs = tst-unbputc tst-printf
 
@@ -69,7 +83,7 @@
 $(inst_includedir)/bits/stdio_lim.h: $(common-objpfx)bits/stdio_lim.h $(+force)
 	$(do-install)
 
-ifeq ($(cross-compiling),no)
+# eglibc: ifeq ($(cross-compiling),no)
 .PHONY: do-tst-unbputc do-tst-printf
 tests: do-tst-unbputc do-tst-printf
 
@@ -80,7 +94,7 @@
 do-tst-printf: $(objpfx)tst-printf.out
 $(objpfx)tst-printf.out: $(objpfx)tst-printf tst-printf.sh
 	$(SHELL) -e tst-printf.sh $(common-objpfx) '$(run-program-prefix)'
-endif
+# eglibc: endif
 
 CFLAGS-vfprintf.c = -Wno-uninitialized
 CFLAGS-vfwprintf.c = -Wno-uninitialized
Index: libc/stdio-common/vfprintf.c
===================================================================
--- libc/stdio-common/vfprintf.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/vfprintf.c	(.../trunk)	(revision 8411)
@@ -30,6 +30,7 @@
 #include "_itoa.h"
 #include <locale/localeinfo.h>
 #include <stdio.h>
+#include <gnu/option-groups.h>
 
 /* This code is shared between the standard stdio implementation found
    in GNU C library and the libio implementation originally found in
@@ -118,6 +119,18 @@
 # define EOF WEOF
 #endif
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define MULTIBYTE_SUPPORT (1)
+#else
+# define MULTIBYTE_SUPPORT (0)
+#endif
+
+#if __OPTION_EGLIBC_LOCALE_CODE
+# define LOCALE_SUPPORT (1)
+#else
+# define LOCALE_SUPPORT (0)
+#endif
+
 #include "_i18n_number.h"
 
 /* Include the shared code for parsing the format string.  */
@@ -1088,8 +1101,11 @@
 # define process_string_arg(fspec) \
     LABEL (form_character):						      \
       /* Character.  */							      \
-      if (is_long)							      \
-	goto LABEL (form_wcharacter);					      \
+      if (is_long)                                                            \
+        {                                                                     \
+          assert (MULTIBYTE_SUPPORT);                                         \
+          goto LABEL (form_wcharacter);                                       \
+        }                                                                     \
       --width;	/* Account for the character itself.  */		      \
       if (!left)							      \
 	PAD (' ');							      \
@@ -1102,6 +1118,7 @@
       break;								      \
 									      \
     LABEL (form_wcharacter):						      \
+      assert (MULTIBYTE_SUPPORT);                                             \
       {									      \
 	/* Wide character.  */						      \
 	char buf[MB_CUR_MAX];						      \
@@ -1164,7 +1181,8 @@
 		/* Search for the end of the string, but don't search past    \
 		   the length (in bytes) specified by the precision.  Also    \
 		   don't use incomplete characters.  */			      \
-		if (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1)   \
+		if (! LOCALE_SUPPORT                                          \
+                    ||_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) == 1) \
 		  len = __strnlen (string, prec);			      \
 		else							      \
 		  {							      \
@@ -1200,6 +1218,7 @@
 	  }								      \
 	else								      \
 	  {								      \
+            assert (MULTIBYTE_SUPPORT);                                       \
 	    const wchar_t *s2 = (const wchar_t *) string;		      \
 	    mbstate_t mbstate;						      \
 									      \
@@ -1394,7 +1413,9 @@
     LABEL (flag_quote):
       group = 1;
 
-      if (grouping == (const char *) -1)
+      if (! LOCALE_SUPPORT)
+        grouping = NULL;
+      else if (grouping == (const char *) -1)
 	{
 #ifdef COMPILE_WPRINTF
 	  thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
@@ -1643,7 +1664,9 @@
     free (workstart);
     workstart = NULL;
 
-    if (grouping == (const char *) -1)
+    if (! LOCALE_SUPPORT)
+      grouping = NULL;
+    else if (grouping == (const char *) -1)
       {
 #ifdef COMPILE_WPRINTF
 	thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
Index: libc/stdio-common/fxprintf.c
===================================================================
--- libc/stdio-common/fxprintf.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/fxprintf.c	(.../trunk)	(revision 8411)
@@ -24,6 +24,7 @@
 #include <wchar.h>
 #include <string.h>
 #include <libioP.h>
+#include <gnu/option-groups.h>
 
 
 int
@@ -38,6 +39,7 @@
   int res;
   if (_IO_fwide (fp, 0) > 0)
     {
+#if __OPTION_POSIX_WIDE_CHAR_DEVICE_IO
       size_t len = strlen (fmt) + 1;
       wchar_t wfmt[len];
       for (size_t i = 0; i < len; ++i)
@@ -46,6 +48,9 @@
 	  wfmt[i] = fmt[i];
 	}
       res = __vfwprintf (fp, wfmt, ap);
+#else
+      abort();
+#endif
     }
   else
     res = INTUSE(_IO_vfprintf) (fp, fmt, ap);
Index: libc/stdio-common/tst-sprintf.c
===================================================================
--- libc/stdio-common/tst-sprintf.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/tst-sprintf.c	(.../trunk)	(revision 8411)
@@ -9,12 +9,14 @@
   char buf[100];
   int result = 0;
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   if (sprintf (buf, "%.0ls", L"foo") != 0
       || strlen (buf) != 0)
     {
       puts ("sprintf (buf, \"%.0ls\", L\"foo\") produced some output");
       result = 1;
     }
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
 
 #define SIZE (1024*70000)
 #define STR(x) #x
Index: libc/stdio-common/vfscanf.c
===================================================================
--- libc/stdio-common/vfscanf.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/vfscanf.c	(.../trunk)	(revision 8411)
@@ -29,6 +29,7 @@
 #include <wctype.h>
 #include <bits/libc-lock.h>
 #include <locale/localeinfo.h>
+#include <gnu/option-groups.h>
 
 #ifdef	__GNUC__
 # define HAVE_LONGLONG
@@ -133,6 +134,12 @@
 # define WINT_T		int
 #endif
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
+# define MULTIBYTE_SUPPORT (1)
+#else
+# define MULTIBYTE_SUPPORT (0)
+#endif
+
 #define encode_error() do {						      \
 			  errval = 4;					      \
 			  __set_errno (EILSEQ);				      \
@@ -293,24 +300,35 @@
   ARGCHECK (s, format);
 
  {
-#ifndef COMPILE_WSCANF
+#if __OPTION_EGLIBC_LOCALE_CODE && !defined (COMPILE_WSCANF)
    struct locale_data *const curnumeric = loc->__locales[LC_NUMERIC];
 #endif
 
+#if __OPTION_EGLIBC_LOCALE_CODE
    /* Figure out the decimal point character.  */
-#ifdef COMPILE_WSCANF
+# ifdef COMPILE_WSCANF
    decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
-#else
+# else
    decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string;
-#endif
+# endif
    /* Figure out the thousands separator character.  */
-#ifdef COMPILE_WSCANF
+# ifdef COMPILE_WSCANF
    thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
-#else
+# else
    thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string;
    if (*thousands == '\0')
      thousands = NULL;
-#endif
+# endif
+#else /* if ! __OPTION_EGLIBC_LOCALE_CODE */
+   /* Hard-code values from the C locale.  */
+# ifdef COMPILE_WSCANF
+   decimal = L'.';
+   thousands = L'\0';
+# else
+   decimal = ".";
+   thousands = NULL;
+# endif
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
  }
 
   /* Lock the stream.  */
@@ -362,6 +380,8 @@
 #ifndef COMPILE_WSCANF
       if (!isascii ((unsigned char) *f))
 	{
+          assert (MULTIBYTE_SUPPORT);
+
 	  /* Non-ASCII, may be a multibyte.  */
 	  int len = __mbrlen (f, strlen (f), &state);
 	  if (len > 0)
@@ -798,6 +818,8 @@
 	    }
 	  /* FALLTHROUGH */
 	case L_('C'):
+          assert (MULTIBYTE_SUPPORT);
+
 	  if (width == -1)
 	    width = 1;
 
@@ -1124,6 +1146,8 @@
 	  /* FALLTHROUGH */
 
 	case L_('S'):
+          assert (MULTIBYTE_SUPPORT);
+
 	  {
 #ifndef COMPILE_WSCANF
 	    mbstate_t cstate;
@@ -1365,10 +1389,17 @@
 	      const char *mbdigits[10];
 	      const char *mbdigits_extended[10];
 #endif
+#if __OPTION_EGLIBC_LOCALE_CODE
 	      /*  "to_inpunct" is a map from ASCII digits to their
 		  equivalent in locale. This is defined for locales
 		  which use an extra digits set.  */
 	      wctrans_t map = __wctrans ("to_inpunct");
+#else
+              /* This will always be the case when
+                 OPTION_EGLIBC_LOCALE_CODE is disabled, but the
+                 compiler can't figure that out.  */
+              wctrans_t map = NULL;
+#endif
 	      int n;
 
 	      from_level = 0;
@@ -2026,6 +2057,7 @@
 		--width;
 	    }
 
+#if __OPTION_EGLIBC_LOCALE_CODE
 	  wctrans_t map;
 	  if (__builtin_expect ((flags & I18N) != 0, 0)
 	      /* Hexadecimal floats make no sense, fixing localized
@@ -2242,6 +2274,7 @@
 	      ;
 #endif
 	    }
+#endif /* __OPTION_EGLIBC_LOCALE_CODE */
 
 	  /* Have we read any character?  If we try to read a number
 	     in hexadecimal notation and we have read only the `0x'
@@ -2281,7 +2314,10 @@
 
 	case L_('['):	/* Character class.  */
 	  if (flags & LONG)
-	    STRING_ARG (wstr, wchar_t, 100);
+            {
+              assert (MULTIBYTE_SUPPORT);
+              STRING_ARG (wstr, wchar_t, 100);
+            }
 	  else
 	    STRING_ARG (str, char, 100);
 
@@ -2355,6 +2391,7 @@
 	  if (flags & LONG)
 	    {
 	      size_t now = read_in;
+              assert (MULTIBYTE_SUPPORT);
 #ifdef COMPILE_WSCANF
 	      if (__builtin_expect (inchar () == WEOF, 0))
 		input_error ();
Index: libc/stdio-common/tstdiomisc.c
===================================================================
--- libc/stdio-common/tstdiomisc.c	(.../fsf/trunk)	(revision 8411)
+++ libc/stdio-common/tstdiomisc.c	(.../trunk)	(revision 8411)
@@ -66,6 +66,7 @@
   result |= strcmp (buf, "inf INF") != 0;
   printf ("expected \"inf INF\", got \"%s\"\n", buf);
 
+#if __OPTION_POSIX_C_LANG_WIDE_CHAR
   swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%f %F", nanval, nanval);
   result |= wcscmp (wbuf, L"nan NAN") != 0;
   printf ("expected L\"nan NAN\", got L\"%S\"\n", wbuf);
@@ -74,6 +75,7 @@
 	    DBL_MAX * DBL_MAX, DBL_MAX * DBL_MAX);
   result |= wcscmp (wbuf, L"inf INF") != 0;
   printf ("expected L\"inf INF\", got L\"%S\"\n", wbuf);
+#endif /* __OPTION_POSIX_C_LANG_WIDE_CHAR */
 
   return result;
 }
Index: libc/sunrpc/proto.h
===================================================================
--- libc/sunrpc/proto.h	(.../fsf/trunk)	(revision 8411)
+++ libc/sunrpc/proto.h	(.../trunk)	(revision 8411)
@@ -50,3 +50,27 @@
 void tabify(FILE *f, int tab);
 char *make_argname(const char *pname, const char *vname);
 void add_type(int len, const char *type);
+
+/* This header is the last one included in all rpc_*.c files,
+   so we define stuff for cross-rpcgen here to avoid conflicts with
+   $build's C library and $host's GLIBC.  */
+#ifdef _CROSS_RPCGEN_
+
+/* Rather then defining _GNU_SOURCE before including $build's <string.h>
+   we just declare stpcpy here.  */
+extern char *stpcpy (char *, const char *);
+
+/* Use $build's i18n support as we can't use $host's.  */
+#define _(X) (gettext (X))
+
+/* rpcgen sources check for __GNU_LIBRARY__ to tweak for GLIBC code
+   that rpcgen generates.  The proper fix would be to rename all those checks
+   to something like '#if defined(TWEAK_FOR_GLIBC) || 1'.  */
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__
+#endif
+
+#define REPORT_BUGS_TO ""
+#define PKGVERSION ""
+
+#endif
Index: libc/sunrpc/Makefile
===================================================================
--- libc/sunrpc/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/sunrpc/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for sunrpc portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= sunrpc
 
 # The code in this subdirectory is taken from Sun's RPCSRC-4.0
@@ -52,12 +54,12 @@
 			   svc_auth.h types.h xdr.h auth_des.h \
 			   des_crypt.h key_prot.h rpc_des.h) \
 	  $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h
-install-others = $(inst_sysconfdir)/rpc
 generated = $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \
 	    $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen
 generated-dirs := rpcsvc
 
-routines := auth_none auth_unix authuxprot bindrsvprt \
+routines-$(OPTION_EGLIBC_SUNRPC) \
+         += auth_none auth_unix authuxprot bindrsvprt \
 	    clnt_gen clnt_perr clnt_raw clnt_simp clnt_tcp \
 	    clnt_udp rpc_dtable get_myaddr getrpcport \
 	    pmap_clnt pm_getmaps pm_getport pmap_prot \
@@ -65,13 +67,16 @@
 	    svc svc_auth svc_authux svc_raw svc_run svc_simple \
 	    svc_tcp svc_udp xdr xdr_array xdr_float xdr_mem \
 	    xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof \
-	    auth_des authdes_prot des_crypt des_impl des_soft \
-	    key_call key_prot netname openchild rtime svcauth_des xcrypt\
+	    auth_des authdes_prot \
+	    key_call key_prot netname openchild rtime svcauth_des \
 	    clnt_unix svc_unix create_xid xdr_intXX_t
 
-others := rpcinfo
-install-bin := rpcgen
-install-sbin := rpcinfo
+# xdecrypt is also used by nss/nss_files/files-key.c.
+routines-y += xcrypt des_crypt des_impl des_soft
+
+others-$(OPTION_EGLIBC_SUNRPC) += rpcinfo
+install-bin-$(OPTION_EGLIBC_SUNRPC) += rpcgen
+install-sbin-$(OPTION_EGLIBC_SUNRPC) += rpcinfo
 rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
 	      rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \
 	      rpc_tblout.o rpc_sample.o
@@ -79,17 +84,19 @@
 distribute := proto.h rpc_util.h rpc_parse.h rpc_scan.h \
 	      $(rpcgen-objs:.o=.c) etc.rpc \
 	      errqueue.h
-extra-objs = $(rpcgen-objs)
+extra-objs-$(OPTION_EGLIBC_SUNRPC) += $(rpcgen-objs)
 
 all: # Make this the default target; it will be defined in Rules.
 
 include ../Makeconfig
 
-tests = tst-xdrmem tst-xdrmem2
-xtests := tst-getmyaddr
+install-others-$(OPTION_EGLIBC_SUNRPC) += $(inst_sysconfdir)/rpc
 
+tests-$(OPTION_EGLIBC_SUNRPC) = tst-xdrmem tst-xdrmem2
+xtests-$(OPTION_EGLIBC_SUNRPC) := tst-getmyaddr
+
 ifeq ($(have-thread-library),yes)
-xtests += thrsvc
+xtests-$(OPTION_EGLIBC_SUNRPC) += thrsvc
 endif
 distribute += thrsvc.c
 
@@ -98,11 +105,11 @@
 	     $(resolvobjdir)/libresolv.a
 endif
 
-ifeq (no,$(cross-compiling))
-# We can only build this library if we can run the rpcgen we build.
+ifneq (yes,$(install-bootstrap-headers))
 headers += $(rpcsvc:%.x=rpcsvc/%.h)
-extra-libs := librpcsvc
-extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass.
+extra-libs-$(OPTION_EGLIBC_SUNRPC) += librpcsvc
+# Make it in `others' pass, not `lib' pass.
+extra-libs-others-y += $(extra-libs-y)
 librpcsvc-routines = $(rpcsvc:%.x=x%)
 librpcsvc-inhibit-o = .os # Build no shared rpcsvc library.
 omit-deps = $(librpcsvc-routines)
@@ -136,13 +143,30 @@
   $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
 	$(+link)
 
+$(addprefix $(objpfx)cross-,$(rpcgen-objs)): $(objpfx)cross-%.o: %.c
+	gcc $< -c -D_RPC_THREAD_SAFE_ -D_CROSS_RPCGEN_ \
+		$(OUTPUT_OPTION) $(compile-mkdep-flags)
+
+$(objpfx)cross-rpcgen: $(addprefix $(objpfx)cross-,$(rpcgen-objs))
+	gcc $^ -o $@
+
 # This makes sure -DNOT_IN_libc is passed for all these modules.
 cpp-srcs-left := $(rpcgen-objs:.o=.c)
 lib := nonlib
 include $(patsubst %,$(..)cppflags-iterator.mk,$(cpp-srcs-left))
 
+ifeq (no,$(cross-compiling))
 # Tell rpcgen where to find the C preprocessor.
 rpcgen-cmd = CPP='$(CC) -E -x c-header' $(built-program-cmd) -Y ../scripts
+# Depend rpcsvc headers and sources on rpcgen.
+rpcgen-dep = $(objpfx)rpcgen
+else
+# Tell rpcgen where to find the C preprocessor.
+rpcgen-cmd = CPP='$(CC) -E -x c-header' $(objpfx)cross-rpcgen -Y ../scripts
+# Depend rpcsvc headers and sources on cross-rpcgen and rpcgen (to trigger
+# its build).
+rpcgen-dep = $(objpfx)rpcgen $(objpfx)cross-rpcgen
+endif
 
 # Install the rpc data base file.
 $(inst_sysconfdir)/rpc: etc.rpc $(+force)
@@ -153,7 +177,7 @@
 # relinked.
 $(rpcsvc:%.x=$(objpfx)rpcsvc/%.h): $(objpfx)rpcsvc/%.h: $(objpfx)rpcsvc/%.stmp
 	@:
-$(objpfx)rpcsvc/%.stmp: rpcsvc/%.x $(objpfx)rpcgen
+$(objpfx)rpcsvc/%.stmp: rpcsvc/%.x $(rpcgen-dep)
 	$(make-target-directory)
 	-@rm -f ${@:stmp=T} $@
 	$(rpcgen-cmd) -h $< -o ${@:stmp=T}
@@ -163,7 +187,7 @@
 # Generate the rpcsvc XDR functions with rpcgen.
 $(rpcsvc:%.x=$(objpfx)x%.c): $(objpfx)x%.c: $(objpfx)x%.stmp
 	@:
-$(objpfx)x%.stmp: rpcsvc/%.x $(objpfx)rpcgen
+$(objpfx)x%.stmp: rpcsvc/%.x $(rpcgen-dep)
 	-@rm -f ${@:stmp=T} $@
 	$(rpcgen-cmd) -c $< -o ${@:stmp=T}
 	$(move-if-change) $(@:stmp=T) $(@:stmp=c)
Index: libc/sunrpc/rpcinfo.c
===================================================================
--- libc/sunrpc/rpcinfo.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sunrpc/rpcinfo.c	(.../trunk)	(revision 8411)
@@ -695,16 +695,15 @@
   fputs (_("       rpcinfo -p [ host ]\n"), stream);
   fputs (_("       rpcinfo -b prognum versnum\n"), stream);
   fputs (_("       rpcinfo -d prognum versnum\n"), stream);
-  fputc ('\n', stream);
-  fprintf (stream, _("\
+  fprintf (stream, _("\n\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO);
 }
 
 static void
 print_version (void)
 {
-  printf ("rpcinfo (GNU %s) %s\n", PACKAGE, VERSION);
+  printf ("rpcinfo %s%s\n", PKGVERSION, VERSION);
 }
 
 static u_long
Index: libc/sunrpc/rpc_main.c
===================================================================
--- libc/sunrpc/rpc_main.c	(.../fsf/trunk)	(revision 8411)
+++ libc/sunrpc/rpc_main.c	(.../trunk)	(revision 8411)
@@ -1491,15 +1491,15 @@
   f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n"));
   f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n"));
 
-  f_print (stream, "\n%s", _("\
+  f_print (stream, "\n\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n", REPORT_BUGS_TO);
   exit (status);
 }
 
 static void
 print_version (void)
 {
-  printf ("rpcgen (GNU %s) %s\n", PACKAGE, VERSION);
+  printf ("rpcgen %s%s\n", PKGVERSION, VERSION);
   exit (0);
 }
Index: libc/resolv/Makefile
===================================================================
--- libc/resolv/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/resolv/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for resolv portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= resolv
 
 headers	:= resolv.h \
@@ -28,22 +30,23 @@
 distribute := ../conf/portability.h mapv4v6addr.h mapv4v6hostent.h \
 	      Banner res_hconf.h res_debug.h README gai_misc.h ga_test.c
 
-routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
+routines-$(OPTION_EGLIBC_INET) \
+	 += herror inet_addr inet_ntop inet_pton nsap_addr res_init \
 	    res_hconf res_libc res-state
 
-tests = tst-aton tst-leaks tst-inet_ntop
-xtests = tst-leaks2
+tests-$(OPTION_EGLIBC_INET) += tst-aton tst-leaks tst-inet_ntop
+xtests-$(OPTION_EGLIBC_INET) += tst-leaks2
 
 generate := mtrace-tst-leaks tst-leaks.mtrace tst-leaks2.mtrace
 
 include ../Makeconfig
 
-extra-libs := libresolv libnss_dns
+extra-libs-$(OPTION_EGLIBC_INET) += libresolv libnss_dns
 ifeq ($(have-thread-library),yes)
-extra-libs += libanl
-routines += gai_sigqueue
+extra-libs-$(OPTION_EGLIBC_INET) += libanl
+routines-$(OPTION_EGLIBC_INET) += gai_sigqueue
 endif
-extra-libs-others = $(extra-libs)
+extra-libs-others-y += $(extra-libs-y)
 libresolv-routines := gethnamaddr res_comp res_debug	\
 		      res_data res_mkquery res_query res_send		\
 		      inet_net_ntop inet_net_pton inet_neta base64	\
@@ -61,7 +64,7 @@
 libnss_dns-inhibit-o	= $(filter-out .os,$(object-suffixes))
 endif
 
-ifeq (yesyes,$(build-shared)$(have-thread-library))
+ifeq (yesyesy,$(build-shared)$(have-thread-library)$(OPTION_EGLIBC_INET))
 tests: $(objpfx)ga_test
 endif
 
@@ -100,17 +103,17 @@
 tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace
 $(objpfx)mtrace-tst-leaks: $(objpfx)tst-leaks.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 ifneq (no,$(PERL))
 tests: $(objpfx)mtrace-tst-leaks
 endif
-endif
+# eglibc: endif
 
 tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
 $(objpfx)mtrace-tst-leaks2: $(objpfx)tst-leaks2.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@
-ifeq (no,$(cross-compiling))
+# eglibc: ifeq (no,$(cross-compiling))
 ifneq (no,$(PERL))
 xtests: $(objpfx)mtrace-tst-leaks2
 endif
-endif
+# eglibc: endif
Index: libc/manual/libc.texinfo
===================================================================
--- libc/manual/libc.texinfo	(.../fsf/trunk)	(revision 8411)
+++ libc/manual/libc.texinfo	(.../trunk)	(revision 8411)
@@ -11,6 +11,8 @@
 @end direntry
 @include dir-add.texi
 
+@include pkgvers.texi
+
 @c This tells texinfo.tex to use the real section titles in xrefs in
 @c place of the node name, when no section title is explicitly given.
 @set xref-automatic-section-title
@@ -27,7 +29,8 @@
 This file documents the GNU C library.
 
 This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU C Library Reference Manual}, for version @value{VERSION}.
+of @cite{The GNU C Library Reference Manual}, for version
+@value{VERSION} @value{PKGVERSION}.
 
 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002,
 2003, 2007, 2008 Free Software Foundation, Inc.
@@ -63,6 +66,8 @@
 @center last updated @value{UPDATED}
 @sp 1
 @center for version @value{VERSION}
+@sp 1
+@center @value{PKGVERSION}
 @page
 @vskip 0pt plus 1filll
 @insertcopying
@@ -87,6 +92,7 @@
 @top Main Menu
 This is Edition @value{EDITION}, last updated @value{UPDATED}, of
 @cite{The GNU C Library Reference Manual}, for Version @value{VERSION}
+@value{PKGVERSION}
 of the GNU C Library.
 @end ifnottex
 
Index: libc/manual/Makefile
===================================================================
--- libc/manual/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/manual/Makefile	(.../trunk)	(revision 8411)
@@ -76,11 +76,12 @@
 	AWK=$(AWK) $(SHELL) $< '$(chapters)' '$(add-chapters)' '$(appendices)'
 
 libc.dvi libc.pdf libc.info: chapters.texi top-menu.texi dir-add.texi \
-			     libm-err.texi
+			     libm-err.texi pkgvers.texi
 libc.dvi libc.pdf: texinfo.tex
 
 html: libc/index.html
-libc/index.html: chapters.texi top-menu.texi dir-add.texi libm-err.texi
+libc/index.html: chapters.texi top-menu.texi dir-add.texi libm-err.texi \
+		 pkgvers.texi
 	$(MAKEINFO) --html libc.texinfo
 
 # Generate the summary from the Texinfo source files for each chapter.
@@ -109,6 +110,14 @@
 	$(move-if-change) libm-err-tmp libm-err.texi
 	touch $@
 
+# Package version and bug reporting URL.
+pkgvers.texi: stamp-pkgvers
+stamp-pkgvers:
+	echo "@set PKGVERSION $(PKGVERSION)" > pkgvers-tmp
+	echo "@set REPORT_BUGS_TO $(REPORT_BUGS_TO)" >> pkgvers-tmp
+	$(move-if-change) pkgvers-tmp pkgvers.texi
+	touch $@
+
 # Generate Texinfo files from the C source for the example programs.
 %.c.texi: examples/%.c
 	sed -e 's,[{}],@&,g'				\
Index: libc/manual/install.texi
===================================================================
--- libc/manual/install.texi	(.../fsf/trunk)	(revision 8411)
+++ libc/manual/install.texi	(.../trunk)	(revision 8411)
@@ -476,7 +476,8 @@
 
 It is a good idea to verify that the problem has not already been
 reported.  Bugs are documented in two places: The file @file{BUGS}
-describes a number of well known bugs and the bug tracking system has a
+describes a number of well known bugs and the upstream GNU C library
+bug tracking system has a
 WWW interface at
 @url{http://sources.redhat.com/bugzilla/}.  The WWW
 interface gives you access to open and closed reports.  A closed report
@@ -501,7 +502,7 @@
 function call, if possible.  This should not be too difficult.
 
 The final step when you have a simple test case is to report the bug.
-Do this using the WWW interface to the bug database.
+Do this at @value{REPORT_BUGS_TO}.
 
 If you are not sure how a function should behave, and this manual
 doesn't tell you, that's a bug in the manual.  Report that too!  If the

Property changes on: libc/manual
___________________________________________________________________
Added: svn:ignore
   + *.c.texi
*.info
*.info-*
chapters.texi
top-menu.texi
dir-add.texi
summary.texi
libm-err.texi
texis
stamp-libm-err
stamp-summary


Index: libc/EGLIBC.cross-testing
===================================================================
--- libc/EGLIBC.cross-testing	(.../fsf/trunk)	(revision 0)
+++ libc/EGLIBC.cross-testing	(.../trunk)	(revision 8411)
@@ -0,0 +1,205 @@
+                                                        -*- mode: text -*-
+
+                      Cross-Testing With EGLIBC
+                  Jim Blandy <jimb@codesourcery.com>
+
+
+Introduction
+
+Developers writing software for embedded systems often use a desktop
+or other similarly capable computer for development, but need to run
+tests on the embedded system, or perhaps on a simulator.  When
+configured for cross-compilation, the stock GNU C library simply
+disables running tests altogether: the command 'make tests' builds
+test programs, but does not run them.  EGLIBC, however, provides
+facilities for compiling tests and generating data files on the build
+system, but running the test programs themselves on a remote system or
+simulator.
+
+
+Test environment requirements
+
+The test environment must meet certain conditions for EGLIBC's
+cross-testing facilities to work:
+
+- Shared filesystems.  The 'build' system, on which you configure and
+  compile EGLIBC, and the 'host' system, on which you intend to run
+  EGLIBC, must share a filesystem containing the EGLIBC build and
+  source trees.  Files must appear at the same paths on both systems.
+
+- Remote-shell like invocation.  There must be a way to run a program
+  on the host system from the build system, passing it properly quoted
+  command-line arguments, setting environment variables, and
+  inheriting the caller's standard input and output.
+
+
+Usage
+
+To use EGLIBC's cross-testing support, provide values for the
+following Make variables when you invoke 'make':
+
+- cross-test-wrapper
+
+  This should be the name of the cross-testing wrapper command, along
+  with any arguments.
+
+- cross-localedef
+
+  This should be the name of a cross-capable localedef program, like
+  that included in the EGLIBC 'localedef' module, along with any
+  arguments needed.
+
+These are each explained in detail below.
+
+
+The Cross-Testing Wrapper
+
+To run test programs reliably, the stock GNU C library takes care to
+ensure that test programs use the newly compiled dynamic linker and
+shared libraries, and never the host system's installed libraries.  To
+accomplish this, it runs the tests by explicitly invoking the dynamic
+linker from the build tree, passing it a list of build tree
+directories to search for shared libraries, followed by the name of
+the executable to run and its arguments.
+
+For example, where one might normally run a test program like this:
+
+    $ ./tst-foo arg1 arg2
+
+the GNU C library might run that program like this:
+
+    $ $objdir/elf/ld-linux.so.3 --library-path $objdir \
+      ./tst-foo arg1 arg2
+
+(where $objdir is the path to the top of the build tree, and the
+trailing backslash indicates a continuation of the command).  In other
+words, each test program invocation is 'wrapped up' inside an explicit
+invocation of the dynamic linker, which must itself execute the test
+program, having loaded shared libraries from the appropriate
+directories.
+
+To support cross-testing, EGLIBC allows the developer to optionally
+set the 'cross-test-wrapper' Make variable to another wrapper command,
+to which it passes the entire dynamic linker invocation shown above as
+arguments.  For example, if the developer supplies a wrapper of
+'my-wrapper hostname', then EGLIBC would run the test above as
+follows:
+
+    $ my-wrapper hostname \
+      $objdir/elf/ld-linux.so.3 --library-path $objdir \
+      ./tst-foo arg1 arg2
+
+The 'my-wrapper' command is responsible for executing the command
+given on the host system.
+
+Since tests are run in varying directories, the wrapper should either
+be in your command search path, or 'cross-test-wrapper' should give an
+absolute path for the wrapper.
+
+The wrapper must meet several requirements:
+
+- It must preserve the current directory.  As explained above, the
+  build directory tree must be visible on both the build and host
+  systems, at the same path.  The test wrapper must ensure that the
+  current directory it inherits is also inherited by the dynamic
+  linker (and thus the test program itself).
+
+- It must preserve environment variables' values.  Many EGLIBC tests
+  set environment variables for test runs; in native testing, it
+  invokes programs like this:
+
+    $ GCONV_PATH=$objdir/iconvdata \
+      $objdir/elf/ld-linux.so.3 --library-path $objdir \
+      ./tst-foo arg1 arg2
+
+  With the cross-testing wrapper, that invocation becomes:
+
+    $ GCONV_PATH=$objdir/iconvdata \
+      my-wrapper hostname \
+      $objdir/elf/ld-linux.so.3 --library-path $objdir \
+      ./tst-foo arg1 arg2
+
+  Here, 'my-wrapper' must ensure that the value it sees for
+  'GCONV_PATH' will be seen by the dynamic linker, and thus 'tst-foo'
+  itself.  (The wrapper supplied with GLIBC simply preserves the
+  values of *all* enviroment variables, with a fixed set of
+  exceptions.)
+
+  If your wrapper is a shell script, take care to correctly propagate
+  environment variables whose values contain spaces and shell
+  metacharacters.
+
+- It must pass the command's arguments, unmodified.  The arguments
+  seen by the test program should be exactly those seen by the wrapper
+  (after whatever arguments are given to the wrapper itself).  The
+  EGLIBC test framework performs all needed shell word splitting and
+  expansion (wildcard expansion, parameter substitution, and so on)
+  before invoking the wrapper; further expansion may break the tests.
+
+
+The 'cross-test-ssh.sh' script
+
+If you want to use 'ssh' (or something sufficiently similar) to run
+test programs on your host system, EGLIBC includes a shell script,
+'scripts/cross-test-ssh.sh', which you can use as your wrapper
+command.  This script takes care of setting the test command's current
+directory, propagating environment variable values, and carrying
+command-line arguments, all across an 'ssh' connection.  You may even
+supply an alternative to 'ssh' on the command line, if needed.
+
+For more details, pass 'cross-test-ssh.sh' the '--help' option.
+
+
+The Cross-Compiling Locale Definition Command
+
+Some EGLIBC tests rely on locales generated especially for the test
+process.  In a native configuration, these tests simply run the
+'localedef' command built by the normal EGLIBC build process,
+'locale/localedef', to process and install their locales.  However, in
+a cross-compiling configuration, this 'localedef' is built for the
+host system, not the build system, and since it requires quite a bit
+of memory to run (we have seen it fail on systems with 64MiB of
+memory), it may not be practical to run it on the host system.
+
+If set, EGLIBC uses the 'cross-localedef' Make variable as the command
+to run on the build system to process and install locales.  The
+localedef program built from the EGLIBC 'localedef' module is
+suitable.
+
+The value of 'cross-localedef' may also include command-line arguments
+to be passed to the program; if you are using EGLIBC's 'localedef',
+you may include endianness and 'uint32_t' alignment arguments here.
+
+
+Example
+
+In developing EGLIBC's cross-testing facility, we invoked 'make' with
+the following script:
+
+    #!/bin/sh
+
+    srcdir=...
+    test_hostname=...
+    localedefdir=...
+    cross_gxx=...-g++
+
+    wrapper="$srcdir/scripts/cross-test-ssh.sh $test_hostname"
+    localedef="$localedefdir/localedef --little-endian --uint32-align=4"
+
+    make cross-test-wrapper="$wrapper" \
+         cross-localedef="$localedef" \
+         CXX="$cross_gxx" \
+         "$@"
+
+
+Other Cross-Testing Concerns
+
+Here are notes on some other issues which you may encounter in running
+the EGLIBC tests in a cross-compiling environment:
+
+- Some tests require a C++ cross-compiler; you should set the 'CXX'
+  Make variable to the name of an appropriate cross-compiler.
+
+- Some tests require access to libstdc++.so.6 and libgcc_s.so.1; we
+  simply place copies of these libraries in the top EGLIBC build
+  directory.
Index: libc/nis/Makefile
===================================================================
--- libc/nis/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/nis/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Makefile for NIS/NIS+ part.
 #
+include ../option-groups.mak
+
 subdir	:= nis
 
 aux			:= nis_hash
@@ -29,19 +31,26 @@
 
 # These are the databases available for the nis (and perhaps later nisplus)
 # service.  This must be a superset of the services in nss.
-databases		= proto service hosts network grp pwd rpc ethers \
-			  spwd netgrp alias publickey
+databases-y		:= proto service hosts network grp pwd rpc ethers \
+			   spwd netgrp publickey
+databases-$(OPTION_EGLIBC_DB_ALIASES) += alias
 
 # Specify rules for the nss_* modules.
-services		:= nis nisplus compat
+# The 'compat' module includes nis support, and the 'nss' directory
+# includes a bare-bones "files" library, so we'll include 'compat' in
+# OPTION_EGLIBC_NIS.
+services-y		:=
+services-$(OPTION_EGLIBC_NIS) += nis nisplus compat
 
-extra-libs		= libnsl $(services:%=libnss_%)
+extra-libs-$(OPTION_EGLIBC_NIS) += libnsl
+extra-libs-y		+= $(services-y:%=libnss_%)
+
 # These libraries will be built in the `others' pass rather than
 # the `lib' pass, because they depend on libc.so being built already.
-extra-libs-others	= $(extra-libs)
+extra-libs-others-y	+= $(extra-libs-y)
 
 # The sources are found in the appropriate subdir.
-subdir-dirs = $(services:%=nss_%)
+subdir-dirs = $(services-y:%=nss_%)
 vpath %.c $(subdir-dirs)
 
 libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
@@ -59,11 +68,11 @@
 libnss_compat-routines	:= $(addprefix compat-,grp pwd spwd initgroups)
 libnss_compat-inhibit-o	= $(filter-out .os,$(object-suffixes))
 
-libnss_nis-routines	:= $(addprefix nis-,$(databases)) nis-initgroups \
+libnss_nis-routines	:= $(addprefix nis-,$(databases-y)) nis-initgroups \
 			   nss-nis
 libnss_nis-inhibit-o	= $(filter-out .os,$(object-suffixes))
 
-libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases)) nisplus-parser \
+libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases-y)) nisplus-parser \
 			   nss-nisplus nisplus-initgroups
 libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
 
@@ -78,12 +87,12 @@
 # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
 # This ensures they will load libc.so for needed symbols if loaded by
 # a statically-linked program that hasn't already loaded it.
-$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: $(common-objpfx)libc.so\
-					       $(common-objpfx)libc_nonshared.a
+$(services-y:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
+	$(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a
 
 
 ifeq ($(build-shared),yes)
-$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
 else
-$(others:%=$(objpfx)%): $(objpfx)libnsl.a
+$(others-y:%=$(objpfx)%): $(objpfx)libnsl.a
 endif
Index: libc/libidn/toutf8.c
===================================================================
--- libc/libidn/toutf8.c	(.../fsf/trunk)	(revision 8411)
+++ libc/libidn/toutf8.c	(.../trunk)	(revision 8411)
@@ -35,6 +35,11 @@
 /* Get strlen. */
 #include <string.h>
 
+/* Get __OPTION_EGLIBC_LOCALE_CODE.  */
+#ifdef _LIBC
+# include <gnu/option-groups.h>
+#endif
+
 /* Get iconv_string. */
 #include "iconvme.h"
 
@@ -49,7 +54,11 @@
 #endif
 
 #ifdef _LIBC
-# define stringprep_locale_charset() nl_langinfo (CODESET)
+# if __OPTION_EGLIBC_LOCALE_CODE
+#  define stringprep_locale_charset() nl_langinfo (CODESET)
+# else
+#  define stringprep_locale_charset() "ANSI_X3.4-1968"
+# endif
 #else
 /**
  * stringprep_locale_charset - return charset used in current locale
Index: libc/libidn/Makefile
===================================================================
--- libc/libidn/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/libidn/Makefile	(.../trunk)	(revision 8411)
@@ -17,6 +17,7 @@
 # 02111-1307 USA.
 
 # Makefile for libidn subdirectory of GNU C Library.
+include ../option-groups.mak
 
 subdir	:= libidn
 
Index: libc/elf/dl-reloc.c
===================================================================
--- libc/elf/dl-reloc.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/dl-reloc.c	(.../trunk)	(revision 8411)
@@ -274,6 +274,17 @@
 	   relocations.  If the shared object lacks a PLT (for example
 	   if it only contains lead function) the l_info[DT_PLTRELSZ]
 	   will be NULL.  */
+#ifdef ELF_MACHINE_NO_PLT
+	l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), 1);
+	if (l->l_reloc_result == NULL)
+	  {
+	    errstring = N_("\
+%s: out of memory to store relocation results for %s\n");
+	    _dl_fatal_printf (errstring,
+			      rtld_progname ?: "<program name unknown>",
+			      l->l_name);
+	  }
+#else
 	if (l->l_info[DT_PLTRELSZ] == NULL)
 	  {
 	    errstring = N_("%s: no PLTREL found in object %s\n");
@@ -291,6 +302,7 @@
 %s: out of memory to store relocation results for %s\n");
 	    goto fatal;
 	  }
+#endif
       }
 #endif
   }
Index: libc/elf/dl-profile.c
===================================================================
--- libc/elf/dl-profile.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/dl-profile.c	(.../trunk)	(revision 8411)
@@ -131,7 +131,7 @@
   {
     uintptr_t from_pc;
     uintptr_t self_pc;
-    uint32_t count;
+    uint32_t count __attribute__((aligned(__alignof__(uint32_t))));
   } __attribute__ ((packed));
 
 static struct here_cg_arc_record *data;
Index: libc/elf/Makefile
===================================================================
--- libc/elf/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/Makefile	(.../trunk)	(revision 8411)
@@ -150,7 +150,8 @@
 ifeq (yesyesyes,$(build-static)$(build-shared)$(elf))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
-       LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+  EGLIBC_TEST_LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+tst-tls9-static-WRAPPER = $(..)scripts/run-with-env.sh
 endif
 ifeq (yes,$(have-initfini-array))
 tests-static += tst-array1-static tst-array5-static
@@ -359,7 +360,9 @@
 
 
 common-ldd-rewrite = -e 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' \
-		     -e 's%@VERSION@%$(version)%g'
+		     -e 's%@VERSION@%$(version)%g' \
+		     -e 's%@PKGVERSION@%$(PKGVERSION)%g' \
+		     -e 's%@REPORT_BUGS_TO@%$(REPORT_BUGS_TO)%g'
 sh-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%/bin/sh%g;s/\$$"/"/g'
 bash-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%$(BASH)%g' \
 		   -e 's%@TEXTDOMAINDIR@%$(msgcatdir)%g'
@@ -401,10 +404,10 @@
 generated += $(addsuffix .so,$(strip $(modules-names)))
 
 ifeq (yes,$(build-shared))
-ifeq ($(cross-compiling),no)
+# eglibc: ifeq ($(cross-compiling),no)
 tests: $(objpfx)tst-pathopt.out
+# eglibc: endif
 endif
-endif
 
 $(objpfx)testobj1.so: $(libdl)
 $(objpfx)testobj1_1.so: $(objpfx)testobj1.so $(libdl)
@@ -544,7 +547,8 @@
 LDFLAGS-preloadtest = -rdynamic
 $(objpfx)preloadtest.out: $(preloadtest-preloads:%=$(objpfx)%.so)
 preloadtest-ENV = \
-  LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
+  EGLIBC_TEST_LD_PRELOAD=$(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so)))
+preloadtest-WRAPPER = $(..)scripts/run-with-env.sh
 
 $(objpfx)loadfail: $(libdl)
 LDFLAGS-loadfail = -rdynamic
@@ -582,6 +586,7 @@
 $(objpfx)order: $(addprefix $(objpfx),dep4.so dep3.so dep2.so dep1.so)
 
 $(objpfx)order.out: $(objpfx)order
+	$(cross-test-wrapper) \
 	$(elf-objpfx)$(rtld-installed-name) \
 	  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
 	  $(objpfx)order > $@
@@ -589,7 +594,8 @@
 
 $(objpfx)vismain: $(addprefix $(objpfx),vismod1.so vismod2.so)
 $(objpfx)vismain.out: $(addprefix $(objpfx),vismod3.so)
-vismain-ENV = LD_PRELOAD=$(addprefix $(objpfx),vismod3.so)
+vismain-ENV = EGLIBC_TEST_LD_PRELOAD=$(addprefix $(objpfx),vismod3.so)
+vismain-WRAPPER = $(..)scripts/run-with-env.sh
 
 $(objpfx)noload: $(objpfx)testobj1.so
 LDFLAGS-noload = -rdynamic
@@ -643,7 +649,8 @@
 $(objpfx)tst-pathopt: $(libdl)
 $(objpfx)tst-pathopt.out: tst-pathopt.sh $(objpfx)tst-pathopt \
 			  $(objpfx)pathoptobj.so
-	$(SHELL) -e $< $(common-objpfx)
+	$(SHELL) -e $< $(common-objpfx) "$(cross-test-wrapper)" \
+		$(..)scripts/run-with-env.sh
 
 $(objpfx)initfirst: $(libdl)
 $(objpfx)initfirst.out: $(objpfx)firstobj.so
@@ -821,6 +828,7 @@
 CFLAGS-tst-pie1.c += $(pie-ccflag)
 
 $(objpfx)tst-pie1.out: $(objpfx)tst-pie1
+	$(cross-test-wrapper) \
 	$(elf-objpfx)$(rtld-installed-name) \
 	  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
 	  $< > $@
@@ -909,10 +917,12 @@
 $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
 
 $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so
-tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+tst-audit1-ENV = EGLIBC_TEST_LD_AUDIT=$(objpfx)tst-auditmod1.so
+tst-audit1-WRAPPER = $(..)scripts/run-with-env.sh
 
 $(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
-tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+tst-audit2-ENV = EGLIBC_TEST_LD_AUDIT=$(objpfx)tst-auditmod1.so
+tst-audit2-WRAPPER = $(..)scripts/run-with-env.sh
 
 $(objpfx)tst-global1: $(libdl)
 $(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
@@ -920,6 +930,7 @@
 $(objpfx)order2: $(libdl)
 $(objpfx)order2.out: $(objpfx)order2 $(objpfx)order2mod1.so \
 		     $(objpfx)order2mod2.so
+	$(cross-test-wrapper) \
 	$(elf-objpfx)$(rtld-installed-name) \
 	  --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
 	  $(objpfx)order2 > $@
@@ -929,7 +940,7 @@
 $(objpfx)order2mod2.so: $(objpfx)order2mod3.so
 order2mod2.so-no-z-defs = yes
 
-tst-stackguard1-ARGS = --command "$(built-program-cmd) --child"
+tst-stackguard1-ARGS = --command "$(local-built-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
 
 $(objpfx)tst-leaks1: $(libdl)
Index: libc/elf/sprof.c
===================================================================
--- libc/elf/sprof.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/sprof.c	(.../trunk)	(revision 8411)
@@ -364,13 +364,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -382,7 +385,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "sprof (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "sprof %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/elf/dl-close.c
===================================================================
--- libc/elf/dl-close.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/dl-close.c	(.../trunk)	(revision 8411)
@@ -669,7 +669,7 @@
   if (any_tls)
     {
       if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
-	_dl_fatal_printf ("TLS generation counter wrapped!  Please report as described in <http://www.gnu.org/software/libc/bugs.html>.\n");
+	_dl_fatal_printf ("TLS generation counter wrapped!  Please report as described in "REPORT_BUGS_TO".\n");
 
       if (tls_free_end == GL(dl_tls_static_used))
 	GL(dl_tls_static_used) = tls_free_start;
Index: libc/elf/ldd.bash.in
===================================================================
--- libc/elf/ldd.bash.in	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/ldd.bash.in	(.../trunk)	(revision 8411)
@@ -35,7 +35,7 @@
 while test $# -gt 0; do
   case "$1" in
   --vers | --versi | --versio | --version)
-    echo 'ldd (GNU libc) @VERSION@'
+    echo 'ldd @PKGVERSION@@VERSION@'
     printf $"Copyright (C) %s Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -45,7 +45,7 @@
     exit 0
     ;;
   --h | --he | --hel | --help)
-    echo $"Usage: ldd [OPTION]... FILE...
+    printf $"Usage: ldd [OPTION]... FILE...
       --help              print this help and exit
       --version           print version information and exit
   -d, --data-relocs       process data relocations
@@ -53,9 +53,9 @@
   -u, --unused            print unused direct dependencies
   -v, --verbose           print all information
 "
-    echo $"For bug reporting instructions, please see:
-<http://www.gnu.org/software/libc/bugs.html>.
-"
+    printf $"For bug reporting instructions, please see:
+%s.
+" "@REPORT_BUGS_TO@"
     exit 0
     ;;
   -d | --d | --da | --dat | --data | --data- | --data-r | --data-re | \
@@ -112,7 +112,7 @@
 # environments where the executed program might not have permissions
 # to write to the console/tty.  But only bash 3.x supports the pipefail
 # option, and we don't bother to handle the case for older bash versions.
-if set -o pipefail 2> /dev/null; then
+if x=`set -o` && test "$x" != "${x#*pipefail}" && set -o pipefail ; then
   try_trace() {
     eval $add_env '"$@"' | cat
   }
Index: libc/elf/sln.c
===================================================================
--- libc/elf/sln.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/sln.c	(.../trunk)	(revision 8411)
@@ -59,7 +59,7 @@
     {
     case 2:
       if (strcmp (argv[1], "--version") == 0) {
-	printf ("sln (GNU libc) %s\n", VERSION);
+	printf ("sln %s%s\n", PKGVERSION, VERSION);
 	return 0;
       } else if (strcmp (argv[1], "--help") == 0) {
 	usage ();
@@ -84,7 +84,7 @@
 {
   printf (_("Usage: sln src dest|file\n\n"));
   printf (_("For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO);
 }
 
 static int
Index: libc/elf/tst-pathopt.sh
===================================================================
--- libc/elf/tst-pathopt.sh	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/tst-pathopt.sh	(.../trunk)	(revision 8411)
@@ -20,7 +20,8 @@
 # 02111-1307 USA.
 
 common_objpfx=$1
-run_program_prefix=$2
+cross_test_wrapper="$2"
+run_with_env="$3"
 
 test -e ${common_objpfx}elf/will-be-empty &&
   rm -fr ${common_objpfx}elf/will-be-empty
@@ -30,8 +31,9 @@
 cp ${common_objpfx}elf/pathoptobj.so ${common_objpfx}elf/for-renamed/renamed.so
 
 LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}iconvdata \
-LC_ALL=C LD_LIBRARY_PATH=${common_objpfx}elf/will-be-empty:${common_objpfx}elf/for-renamed:${common_objpfx}.:${common_objpfx}dlfcn \
-  ${common_objpfx}elf/ld.so ${common_objpfx}elf/tst-pathopt \
+LC_ALL=C EGLIBC_TEST_LD_LIBRARY_PATH=${common_objpfx}elf/will-be-empty:${common_objpfx}elf/for-renamed:${common_objpfx}.:${common_objpfx}dlfcn \
+  ${cross_test_wrapper} ${run_with_env} ${common_objpfx}elf/ld.so \
+    ${common_objpfx}elf/tst-pathopt \
     > ${common_objpfx}elf/tst-pathopt.out
 
 exit $?
Index: libc/elf/ldconfig.c
===================================================================
--- libc/elf/ldconfig.c	(.../fsf/trunk)	(revision 8411)
+++ libc/elf/ldconfig.c	(.../trunk)	(revision 8411)
@@ -295,13 +295,16 @@
 static char *
 more_help (int key, const char *text, void *input)
 {
+  char *tp = NULL;
   switch (key)
     {
     case ARGP_KEY_HELP_EXTRA:
       /* We print some extra information.  */
-      return strdup (gettext ("\
+      if (asprintf (&tp, gettext ("\
 For bug reporting instructions, please see:\n\
-<http://www.gnu.org/software/libc/bugs.html>.\n"));
+%s.\n"), REPORT_BUGS_TO) < 0)
+	return NULL;
+      return tp;
     default:
       break;
     }
@@ -312,7 +315,7 @@
 static void
 print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, "ldconfig %s%s\n", PKGVERSION, VERSION);
   fprintf (stream, gettext ("\
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
Index: libc/io/sys/stat.h
===================================================================
--- libc/io/sys/stat.h	(.../fsf/trunk)	(revision 8411)
+++ libc/io/sys/stat.h	(.../trunk)	(revision 8411)
@@ -444,7 +444,7 @@
 		       __mode_t __mode, __dev_t *__dev)
      __THROW __nonnull ((3, 5));
 
-#if defined __GNUC__ && __GNUC__ >= 2 && defined __USE_EXTERN_INLINES
+#if defined __GNUC__ && __GNUC__ >= 2 && defined __USE_EXTERN_INLINES_IN_LIBC
 /* Inlined versions of the real stat and mknod functions.  */
 
 __extern_inline int
Index: libc/io/Makefile
===================================================================
--- libc/io/Makefile	(.../fsf/trunk)	(revision 8411)
+++ libc/io/Makefile	(.../trunk)	(revision 8411)
@@ -19,6 +19,8 @@
 #
 #	Sub-makefile for I/O portion of the library.
 #
+include ../option-groups.mak
+
 subdir	:= io
 
 headers := sys/stat.h bits/stat.h sys/statfs.h bits/statfs.h sys/vfs.h \
@@ -35,7 +37,7 @@
 	fxstatat fxstatat64						\
 	statfs fstatfs statfs64 fstatfs64				\
 	statvfs fstatvfs statvfs64 fstatvfs64				\
-	umask chmod fchmod lchmod fchmodat				\
+	umask chmod fchmod fchmodat					\
 	mkdir mkdirat							\
 	open open64 openat openat64 close				\
 	read write lseek lseek64 access euidaccess faccessat		\
@@ -48,11 +50,13 @@
 	ttyname ttyname_r isatty					\
 	link linkat symlink symlinkat readlink readlinkat		\
 	unlink unlinkat rmdir						\
-	ftw ftw64 fts poll ppoll					\
+	poll ppoll							\
 	posix_fadvise posix_fadvise64					\
 	posix_fallocate posix_fallocate64				\
 	sendfile sendfile64 \
 	utimensat futimens
+routines-$(OPTION_EGLIBC_BSD) += lchmod
+routines-$(OPTION_EGLIBC_FTRAVERSE) += ftw ftw64 fts
 
 aux := have_o_cloexec
 
@@ -63,14 +67,16 @@
 		       fstatat fstatat64 mknod mknodat
 
 others		:= pwd
-test-srcs	:= ftwtest
+test-srcs-$(OPTION_EGLIBC_FTRAVERSE) := ftwtest
 tests		:= test-utime test-stat test-stat2 test-lfs tst-getcwd \
-		   tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \
+		   tst-fcntl tst-statvfs \
 		   tst-openat tst-unlinkat tst-fstatat tst-futimesat \
 		   tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
 		   tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
-		   tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
+		   tst-mknodat tst-mkfifoat tst-ttyname_r \
 		   tst-posix_fallocate
+tests-$(OPTION_EGLIBC_FTRAVERSE) += bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 \
+				    bug-ftw5
 
 distribute	:= ftwtest-sh
 
@@ -98,10 +104,23 @@
 
 tst-statvfs-ARGS = $(objpfx)tst-statvfs tst-statvfs.c /tmp
 
-ifeq ($(cross-compiling),no)
+# eglibc: ifeq ($(cross-compiling),no)
+ifeq (y,$(OPTION_EGLIBC_FTRAVERSE))
 tests: $(objpfx)ftwtest.out
+endif
 
+ifeq ($(cross-compiling),yes)
+# EGLIBC's cross-testing support does not require the build and host
+# machines to share a /tmp directory, so when cross-testing, construct
+# the sample directory tree for these tests in the build tree.
+ftwtest-tmpdir = TMPDIR=$(common-objpfx)
+endif
+
 $(objpfx)ftwtest.out: $(objpfx)ftwtest
+	$(ftwtest-tmpdir) \
 	$(SHELL) -e ftwtest-sh $(shell cd $(common-objpfx). && pwd)/ \
+		 '$(cross-test-wrapper)' \
+		 $(shell cd $(..)scripts && pwd)/run-with-env.sh \
 		 $(shell cd $(<D) && pwd)/$(<F) > $@
-endif
+
+# eglibc: endif
Index: libc/io/ftwtest-sh
===================================================================
--- libc/io/ftwtest-sh	(.../fsf/trunk)	(revision 8411)
+++ libc/io/ftwtest-sh	(.../trunk)	(revision 8411)
@@ -3,6 +3,12 @@
 # The common objpfx, used to find libraries and the dynamic loader.
 objpfx=$1
 
+# The cross-testing wrapper.
+cross_test_wrapper="$2"
+
+# The environment-setting wrapper.
+run_with_env="$3"
+
 # We expect one parameter which is the test program.  This must understand
 # a number options:
 #   --phys		use the FTW_PHYS flag
@@ -11,7 +17,7 @@
 #   --depth		use the FTW_DEPTH flag
 #   --early-exit 	print file@2 item only and return non-zero from the
 #			callback when it is seen
-testprogram=$2
+testprogram=$4
 
 # We cannot test this as root.
 if test `id | sed "s/uid=\([0-9]*\).*/\1/"` = 0; then
@@ -29,6 +35,7 @@
 tmpdir=$tmp/ftwtest.d
 
 [ -f ${objpfx}elf/ld.so ] && ldso=${objpfx}elf/ld.so
+ldso="${cross_test_wrapper:+$cross_test_wrapper }$run_with_env $ldso"
 
 trap 'chmod -fR a+x $tmpdir; rm -fr $tmpdir $testout' 1 2 3 15
 
@@ -54,7 +61,7 @@
 
 testout=${TMPDIR:-/tmp}/ftwtest.out
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram $tmpdir |
     sort > $testout
 
 cat <<EOF | cmp $testout - || exit 1
@@ -73,7 +80,7 @@
 EOF
 rm $testout
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --depth $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --depth $tmpdir |
     sort > $testout
 
 cat <<EOF | cmp $testout - || exit 1
@@ -92,7 +99,7 @@
 EOF
 rm $testout
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --phys $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --phys $tmpdir |
     sort > $testout
 
 cat <<EOF | cmp $testout - || exit 1
@@ -116,7 +123,7 @@
 # For the next test everything must be readable.
 chmod -fR a+x $tmpdir
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir $tmpdir |
     sort > $testout
 
 # perhaps $tmp involves some symlinks...
@@ -140,7 +147,7 @@
 
 curwd=`/bin/pwd 2>/dev/null || /usr/bin/pwd`
 cd "$tmp"
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d |
     sort > $testout
 cd "$curwd"
 
@@ -162,7 +169,7 @@
 
 curwd=`/bin/pwd 2>/dev/null || /usr/bin/pwd`
 cd "$tmp"
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d/. |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d/. |
     sort > $testout
 cd "$curwd"
 
@@ -184,7 +191,7 @@
 
 curwd=`/bin/pwd 2>/dev/null || /usr/bin/pwd`
 cd "$tmp"
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d/foo/lvl1/link@1 |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --chdir ftwtest.d/foo/lvl1/link@1 |
     sort > $testout
 cd "$curwd"
 
@@ -193,7 +200,7 @@
 EOF
 rm $testout
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --early-exit $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --early-exit $tmpdir |
     sort > $testout
 
 cat <<EOF | cmp $testout - || exit 1
@@ -207,7 +214,7 @@
 echo > $tmpdir/foo/lvl1b/file2@1b
 echo > $tmpdir/foo/lvl1b/file3@1b
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-subtree=lvl1 $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-subtree=lvl1 $tmpdir |
     sort > $testout
 
 cat <<EOF | diff -u $testout - || exit 1
@@ -224,7 +231,7 @@
 EOF
 rm $testout
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=lvl1 $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=lvl1 $tmpdir |
     sort > $testout
 
 # The filesystem is not required to put lvl1 before lvl1b.
@@ -248,7 +255,7 @@
 EOF
 rm $testout
 
-LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=file@1b $tmpdir |
+EGLIBC_TEST_LD_LIBRARY_PATH=$objpfx $ldso $testprogram --skip-siblings=file@1b $tmpdir |
     sort > $testout
 
 # The filesystem is not required to put file2@1b and file3@1b after file@1b.
Index: libc/EGLIBC.option-groups
===================================================================
--- libc/EGLIBC.option-groups	(.../fsf/trunk)	(revision 0)
+++ libc/EGLIBC.option-groups	(.../trunk)	(revision 8411)
@@ -0,0 +1,153 @@
+                                                        -*- mode: text -*-
+
+              The EGLIBC Component Configuration System
+                  Jim Blandy <jimb@codesourcery.com>
+
+Introduction
+
+The GNU C library (GLIBC) provides a broad range of functionality,
+ranging from internationalization support to transcendental
+mathematical functions.  Its website boasts that "nearly all known and
+useful functions from any other C library are available."  This
+exhaustive approach has been one of GLIBC's strengths on desktop and
+server systems, but it has also given GLIBC a large footprint, both in
+memory and on disk, making it a challenge to use in embedded systems
+with limited resources.
+
+The Embedded GNU C library (EGLIBC) is a variant of the GNU C library
+designed to work well on embedded systems.  In particular, EGLIBC's
+component configuration system allows embedded developers to build
+customized versions of the library that include only the features
+their application uses, reducing its space requirements.
+
+EGLIBC's component configuration system categorizes the library's
+functions into "option groups", and allows you to include or exclude
+option groups individually.  Some option groups depend on others;
+EGLIBC tracks these relationships, and ensures that the selected
+configuration yields a functioning library.
+
+
+Consistent and Predictable Behavior
+
+A flexible configuration system is a mixed blessing: if the options
+offered are poorly designed, it can be hard to see which choices will
+have the desired effects, and choices with obscure consequences can
+make debugging difficult.  EGLIBC's configuration follows some general
+principles to reduce these risks:
+
+- EGLIBC has a single default configuration for each target
+  architecture.
+
+- In the default configuration, all option groups are enabled, and
+  EGLIBC is upwardly API- and ABI-compatible with GLIBC.
+
+- As much as possible, configurations only affect what functions are
+  present, not how they behave.  If the system works with an option
+  group disabled, it will still work with it enabled.
+
+- As much as possible, configurations only select option groups ---
+  they do not describe characteristics of the target architecture.
+
+These rules mean that you have a simple debugging strategy available
+if you suspect that your EGLIBC configuration might be the source of a
+problem: fall back to the default configuration, re-test, and then
+disable option groups one by one, until the problem reappears.
+
+
+The Option Groups
+
+EGLIBC currently implements the following option groups, also
+documented in the file 'option-groups.def':
+
+OPTION_EGLIBC_CATGETS
+       This option group includes functions for accessing message
+       catalogs: catopen, catclose, and catgets.
+
+OPTION_EGLIBC_LOCALES
+       This option group includes all locale definitions other than
+       those for the "C" locale.  If this option group is omitted, then
+       only the "C" locale is supported.
+
+OPTION_EGLIBC_LIBM
+       This option group includes the 'libm' library, containing
+       mathematical functions.  If this option group is omitted, then
+       an EGLIBC installation does not include shared or unshared versions
+       of the math library.
+
+       Note that this does not remove all floating-point related
+       functionality from EGLIBC; for example, 'printf' and 'scanf'
+       can still print and read floating-point values with this option
+       group disabled.
+
+       Note that the ISO Standard C++ library 'libstdc++' depends on
+       EGLIBC's math library 'libm'.  If you disable this option
+       group, you will not be able to build 'libstdc++' against the
+       resulting EGLIBC installation.
+
+The POSIX.1-2001 specification includes a suggested partition of all
+the functions in the POSIX C API into option groups: math functions
+like 'sin' and 'cos'; networking functions like 'socket' and
+'connect'; and so on.  EGLIBC could use this partitioning as the basis
+for future option groups.
+
+
+Implementation
+
+The EGLIBC component configuration system resembles the approach used
+by the Linux kernel to select device drivers, network protocols, and
+other features.  A file named 'option-groups.config' in the top-level
+build directory contains assignments to Make variables, each of which
+enables or disables a particular option group.  If the variable's
+value is set to 'y', then the option group is enabled; if it set to
+anything else, the option group is omitted.  The file
+'option-groups.defaults', at the top of the source tree, establishes
+default values for all variables; all option groups are enabled by
+default.
+
+For example, the following 'option-groups.config' would omit locale
+data, but include mathematical functions, and everything else:
+
+   OPTION_EGLIBC_LOCALES = n
+   OPTION_EGLIBC_LIBM = y
+
+In general, each option group variable controls whether a given set of
+object files in EGLIBC is compiled and included in the final
+libraries, or omitted from the build.
+
+Each subdirectory's Makefile categorizes its routines, libraries, and
+executables by option group.  For example, EGLIBC's 'math/Makefile'
+places the 'libm' library in the OPTION_EGLIBC_LIBM group as follows:
+
+   extra-libs-$(OPTION_EGLIBC_LIBM) := libm
+
+Finally, common code in 'Makerules' cites the value of the variable
+'extra-libs-y', selecting only those libraries that belong to enabled
+option groups to be built.
+
+
+Current Status and Future Directions
+
+The EGLIBC component configuration system described here is still
+under development.
+
+We have used the system to subset some portions of EGLIBC's
+functionality.  It needs to be extended to cover more of the library.
+
+At the moment, EGLIBC performs no sanity checks on the contents of
+'option-groups.config'; if an option group's name is mistyped, the
+option group is silently included in the build.  EGLIBC should check
+that all variables set in 'option-groups.config' are proper option
+group names, and that their values are appropriate.
+
+Some portions of EGLIBC depend on others; for example, the Sun Remote
+Procedure Call functions in 'sunrpc' depend on the networking
+functions in 'inet'.  The sanity checking described above should check
+that the selection configuration satisfies dependencies within EGLIBC,
+and produce a legible error message if it does not.  At the moment,
+inconsistent configurations produce link errors late in the build
+process.
+
+The Linux kernel's configuration system provides interactive
+interfaces for creating and modifying configuration files (which also
+perform the sanity checking and dependency tracking described above).
+EGLIBC should provide similar interfaces.
