about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-12-18 19:45:25 +0000
committerUlrich Drepper <drepper@redhat.com>1999-12-18 19:45:25 +0000
commitb85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a (patch)
tree6aec765390be55804ecbe7c1bde6c79dda2e1dc2
parent440a52ea7b427b7a5668c77283825cae20d7fc3c (diff)
downloadglibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.tar.gz
glibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.tar.xz
glibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.zip
Update.
1999-12-17  Ulrich Drepper  <drepper@cygnus.com>

	* string/bits/string2.h (__strtok_r_1c): Help gcc optimizing string
	access.

	* locale/programs/ld-collate.c: Implement handling of absolute
	ellipsis.  Parsing of file and constructing the internal data
	structures should now be complete.
	(collate_finish): Start adding support to generate the data
	structures which are written out to the file.

	* intl/dcgettext.c: Rewrite to handle caching of previous results here
	instead of in the dcgettext macro.
	* intl/libintl.h (dcgettext): Don't define for systems using this
	glibc or systems with tsearch.

	* sysdeps/generic/mathdef.h: Protect definitions for math.h
	against double inclusion.
	* sysdeps/alpha/fpu/bits/mathdef.h: Likewise.
	* sysdeps/i386/fpu/bits/mathdef.h: Likewise.
	* sysdeps/m68k/fpu/bits/mathdef.h: Likewise.
	* sysdeps/powerpc/fpu/bits/mathdef.h: Likewise.

	* sysdeps/i386/fpu/libm-test-ulps: Add more deltas (are mobile PIIs
	that different?).

1999-12-17  Andreas Jaeger  <aj@suse.de>

	* rt/aio.h (struct aiocb64): Add member __next_prio to sync the
	struct with aiocb.

	* rt/Makefile (tests): Added tst-aio64.
	Added dependency rules for tst-aio64.

	* rt/tst-aio64.c: New file, copied from tst-aio.c and changed for
	64bit tests.

1999-12-15  Thorsten Kukuk  <kukuk@suse.de>

	* sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/bits/resource.h: Change RLIM_INFINITY back to
	old value (signed long).
	* sysdeps/unix/sysv/linux/i386/bits/resource.h: New, with unsigned
	long RLIM_INFINITY.
	* sysdeps/unix/sysv/linux/getrlimit.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/getrlimit.c: ... here.
	* sysdeps/unix/sysv/linux/getrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/getrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/oldgetrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/oldsetrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/setrlimit.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/setrlimit.c: ... here.
	* sysdeps/unix/sysv/linux/setrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/setrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/sparc/bits/resource.h: New.
	* sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c: Removed.

1999-12-17  Andreas Jaeger  <aj@suse.de>

	* elf/ldconfig.c: Add new option -l to manualy link shared
	libraries.
	(options): Added option.
	(parse_opt): Set option.
	(main): Handle option.
	(manual_link): New function.

1999-12-17  Thorsten Kukuk  <kukuk@suse.de>

	* string/bits/string2.h: Fix patch from 1999-12-07.

1999-12-16  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/generic/strsep.c: If delim string has only one character
	don't run over end of string.

	* locale/programs/ld-collate.c (insert_weights): Also update next
	pointer of last cursor element.
	(insert_value): Return nonzero value if nothing got inserted.
	(handle_ellipsis): Don't do anything if to-value cannot be inserted.

1999-12-10  Jakub Jelinek  <jakub@redhat.com>

	* stdlib/longlong.h (__sparc_v9__): Use %rDIGIT instead of %DIGIT
	where appropriate.

1999-12-10  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c (__sigaction):
	Copy sa_flags into kernel sigaction structure.

1999-12-14  Andreas Jaeger  <aj@suse.de>

	* string/tester.c (test_strsep): More tests for access beyond
	the final NUL.  The first two tests come from PR libc/1486 by
	martinea@iro.umontreal.ca.

1999-12-14  Thorsten Kukuk  <kukuk@suse.de>

	* nis/ypclnt.c: Correct handling of cached client handles.
	(__xdr_ypresp_all): Call callback function for errors, too,
	like Solaris does.
	* nis/nss_compat/compat-grp.c: Make sure errno is always set correct.
	* nis/nss_compat/compat-initgroups.c: Likewise.
	* nis/nss_compat/compat-spwd.c: Likewise.
	* nis/nss_nis/nis-alias.c: Likewise.
	* nis/nss_nis/nis-ethers.c: Likewise.
	* nis/nss_nis/nis-grp.c: Likewise.
	* nis/nss_nis/nis-hosts.c: Likewise.
	* nis/nss_nis/nis-netgrp.c: Likewise.
	* nis/nss_nis/nis-publickey.c: Likewise.
	* nis/nss_nis/nis-service.c: Likewise. Also use services.byservicename
	Map if available, optimize query if name/port and protocol is known.
-rw-r--r--ChangeLog117
-rw-r--r--bits/mathdef.h4
-rw-r--r--elf/ldconfig.c93
-rw-r--r--intl/dcgettext.c175
-rw-r--r--intl/libintl.h2
-rw-r--r--linuxthreads/ChangeLog8
-rw-r--r--linuxthreads/manager.c22
-rw-r--r--linuxthreads/pthread.c5
-rw-r--r--locale/programs/ld-collate.c317
-rw-r--r--nis/nss_compat/compat-grp.c12
-rw-r--r--nis/nss_compat/compat-initgroups.c6
-rw-r--r--nis/nss_compat/compat-spwd.c23
-rw-r--r--nis/nss_nis/nis-alias.c5
-rw-r--r--nis/nss_nis/nis-ethers.c9
-rw-r--r--nis/nss_nis/nis-grp.c6
-rw-r--r--nis/nss_nis/nis-hosts.c6
-rw-r--r--nis/nss_nis/nis-netgrp.c9
-rw-r--r--nis/nss_nis/nis-publickey.c33
-rw-r--r--nis/nss_nis/nis-service.c115
-rw-r--r--nis/ypclnt.c358
-rw-r--r--rt/Makefile6
-rw-r--r--rt/aio.h4
-rw-r--r--rt/tst-aio64.c196
-rw-r--r--stdlib/longlong.h8
-rw-r--r--string/bits/string2.h8
-rw-r--r--string/tester.c27
-rw-r--r--sysdeps/alpha/fpu/bits/mathdef.h4
-rw-r--r--sysdeps/generic/bits/mathdef.h4
-rw-r--r--sysdeps/generic/strsep.c4
-rw-r--r--sysdeps/i386/fpu/bits/mathdef.h4
-rw-r--r--sysdeps/i386/fpu/libm-test-ulps63
-rw-r--r--sysdeps/m68k/fpu/bits/mathdef.h4
-rw-r--r--sysdeps/powerpc/fpu/bits/mathdef.h4
-rw-r--r--sysdeps/sparc/fpu/bits/mathdef.h4
-rw-r--r--sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c1
-rw-r--r--sysdeps/unix/sysv/linux/bits/resource.h6
-rw-r--r--sysdeps/unix/sysv/linux/i386/bits/resource.h227
-rw-r--r--sysdeps/unix/sysv/linux/i386/getrlimit.c (renamed from sysdeps/unix/sysv/linux/getrlimit.c)0
-rw-r--r--sysdeps/unix/sysv/linux/i386/getrlimit64.c (renamed from sysdeps/unix/sysv/linux/getrlimit64.c)0
-rw-r--r--sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c (renamed from sysdeps/unix/sysv/linux/oldgetrlimit64.c)0
-rw-r--r--sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c (renamed from sysdeps/unix/sysv/linux/oldsetrlimit64.c)0
-rw-r--r--sysdeps/unix/sysv/linux/i386/setrlimit.c (renamed from sysdeps/unix/sysv/linux/setrlimit.c)0
-rw-r--r--sysdeps/unix/sysv/linux/i386/setrlimit64.c (renamed from sysdeps/unix/sysv/linux/setrlimit64.c)0
-rw-r--r--sysdeps/unix/sysv/linux/sparc/bits/resource.h243
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c1
48 files changed, 1830 insertions, 316 deletions
diff --git a/ChangeLog b/ChangeLog
index e08445df95..f3b284705f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,120 @@
+1999-12-17  Ulrich Drepper  <drepper@cygnus.com>
+
+	* string/bits/string2.h (__strtok_r_1c): Help gcc optimizing string
+	access.
+
+	* locale/programs/ld-collate.c: Implement handling of absolute
+	ellipsis.  Parsing of file and constructing the internal data
+	structures should now be complete.
+	(collate_finish): Start adding support to generate the data
+	structures which are written out to the file.
+
+	* intl/dcgettext.c: Rewrite to handle caching of previous results here
+	instead of in the dcgettext macro.
+	* intl/libintl.h (dcgettext): Don't define for systems using this
+	glibc or systems with tsearch.
+
+	* sysdeps/generic/mathdef.h: Protect definitions for math.h
+	against double inclusion.
+	* sysdeps/alpha/fpu/bits/mathdef.h: Likewise.
+	* sysdeps/i386/fpu/bits/mathdef.h: Likewise.
+	* sysdeps/m68k/fpu/bits/mathdef.h: Likewise.
+	* sysdeps/powerpc/fpu/bits/mathdef.h: Likewise.
+
+	* sysdeps/i386/fpu/libm-test-ulps: Add more deltas (are mobile PIIs
+	that different?).
+
+1999-12-17  Andreas Jaeger  <aj@suse.de>
+
+	* rt/aio.h (struct aiocb64): Add member __next_prio to sync the
+	struct with aiocb.
+
+	* rt/Makefile (tests): Added tst-aio64.
+	Added dependency rules for tst-aio64.
+
+	* rt/tst-aio64.c: New file, copied from tst-aio.c and changed for
+	64bit tests.
+
+1999-12-15  Thorsten Kukuk  <kukuk@suse.de>
+
+	* sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c: Removed.
+	* sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c: Removed.
+	* sysdeps/unix/sysv/linux/bits/resource.h: Change RLIM_INFINITY back to
+	old value (signed long).
+	* sysdeps/unix/sysv/linux/i386/bits/resource.h: New, with unsigned
+	long RLIM_INFINITY.
+	* sysdeps/unix/sysv/linux/getrlimit.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/getrlimit.c: ... here.
+	* sysdeps/unix/sysv/linux/getrlimit64.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/getrlimit64.c: ... here.
+	* sysdeps/unix/sysv/linux/oldgetrlimit64.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c: ... here.
+	* sysdeps/unix/sysv/linux/oldsetrlimit64.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c: ... here.
+	* sysdeps/unix/sysv/linux/setrlimit.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/setrlimit.c: ... here.
+	* sysdeps/unix/sysv/linux/setrlimit64.c: Moved from here to ...
+	* sysdeps/unix/sysv/linux/i386/setrlimit64.c: ... here.
+	* sysdeps/unix/sysv/linux/sparc/bits/resource.h: New.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c: Removed.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c: Removed.
+
+1999-12-17  Andreas Jaeger  <aj@suse.de>
+
+	* elf/ldconfig.c: Add new option -l to manualy link shared
+	libraries.
+	(options): Added option.
+	(parse_opt): Set option.
+	(main): Handle option.
+	(manual_link): New function.
+
+1999-12-17  Thorsten Kukuk  <kukuk@suse.de>
+
+	* string/bits/string2.h: Fix patch from 1999-12-07.
+
+1999-12-16  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/generic/strsep.c: If delim string has only one character
+	don't run over end of string.
+
+	* locale/programs/ld-collate.c (insert_weights): Also update next
+	pointer of last cursor element.
+	(insert_value): Return nonzero value if nothing got inserted.
+	(handle_ellipsis): Don't do anything if to-value cannot be inserted.
+
+1999-12-10  Jakub Jelinek  <jakub@redhat.com>
+
+	* stdlib/longlong.h (__sparc_v9__): Use %rDIGIT instead of %DIGIT
+	where appropriate.
+
+1999-12-10  Jakub Jelinek  <jakub@redhat.com>
+
+	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c (__sigaction):
+	Copy sa_flags into kernel sigaction structure.
+
+1999-12-14  Andreas Jaeger  <aj@suse.de>
+
+	* string/tester.c (test_strsep): More tests for access beyond
+	the final NUL.  The first two tests come from PR libc/1486 by
+	martinea@iro.umontreal.ca.
+
+1999-12-14  Thorsten Kukuk  <kukuk@suse.de>
+
+	* nis/ypclnt.c: Correct handling of cached client handles.
+	(__xdr_ypresp_all): Call callback function for errors, too,
+	like Solaris does.
+	* nis/nss_compat/compat-grp.c: Make sure errno is always set correct.
+	* nis/nss_compat/compat-initgroups.c: Likewise.
+	* nis/nss_compat/compat-spwd.c: Likewise.
+	* nis/nss_nis/nis-alias.c: Likewise.
+	* nis/nss_nis/nis-ethers.c: Likewise.
+	* nis/nss_nis/nis-grp.c: Likewise.
+	* nis/nss_nis/nis-hosts.c: Likewise.
+	* nis/nss_nis/nis-netgrp.c: Likewise.
+	* nis/nss_nis/nis-publickey.c: Likewise.
+	* nis/nss_nis/nis-service.c: Likewise. Also use services.byservicename
+	Map if available, optimize query if name/port and protocol is known.
+
 1999-12-12  Ulrich Drepper  <drepper@cygnus.com>
 
 	* locale/programs/ld-collate.c (collate_read): Make symbolic
diff --git a/bits/mathdef.h b/bits/mathdef.h
index d306e54366..0c30b01f52 100644
--- a/bits/mathdef.h
+++ b/bits/mathdef.h
@@ -20,7 +20,9 @@
 # error "Never use <bits/mathdef.h> directly; include <math.h> instead"
 #endif
 
-#if defined  __USE_ISOC99 && defined _MATH_H
+#if defined  __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 /* Normally, there is no long double type and the `float' and `double'
    expressions are evaluated as `double'.  */
 typedef double float_t;		/* `float' expressions are evaluated as
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 6c2bcb2d4f..98a4817202 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -97,6 +97,9 @@ static int opt_only_cline = 0;
 /* Path to root for chroot.  */
 static char *opt_chroot;
 
+/* Manually link given shared libraries.  */
+static int opt_manual_link = 0;
+
 /* Cache file to use.  */
 static const char *cache_file;
 
@@ -119,6 +122,7 @@ static const struct argp_option options[] =
   { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
   { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
+  { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
   { NULL, 0, NULL, 0, NULL, 0 }
 };
 
@@ -148,6 +152,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'f':
       config_file = arg;
       break;
+    case 'l':
+      opt_manual_link = 1;
+      break;
     case 'N':
       opt_build_cache = 0;
       break;
@@ -323,6 +330,75 @@ create_links (const char *path, const char *libname, const char *soname)
     fputs ("\n", stdout);
 }
 
+/* Manually link the given library.  */
+static void
+manual_link (char *library)
+{
+  char *path;
+  char *libname;
+  char *soname;
+  struct stat stat_buf;
+  int flag;
+
+  /* Prepare arguments for create_links call.  Split library name in
+     directory and filename first.  Since path is allocated, we've got
+     to be careful to free at the end.  */
+  path = xstrdup (library);
+  libname = strrchr (path, '/');
+
+  if (libname)
+    {
+      /* Successfully split names.  Check if path is just "/" to avoid
+         an empty path.  */
+      if (libname == path)
+	{
+	  libname = library + 1;
+	  path = xrealloc (path, 2);
+	  strcpy (path, "/");
+	}
+      else
+	{
+	  *libname = '\0';
+	  ++libname;
+	}
+    }
+  else
+    {
+      /* There's no path, construct one. */
+      libname = library;
+      path = xrealloc (path, 2);
+      strcpy (path, ".");
+    }
+
+  /* Do some sanity checks first.  */
+  if (lstat (library, &stat_buf))
+    {
+      error (0, errno, _("Can't lstat %s"), library);
+      free (path);
+      return;
+    }
+  /* We don't want links here!  */
+  else if (!S_ISREG (stat_buf.st_mode))
+    {
+      error (0, 0, _("Ignored file %s since it is not a regular file."),
+	     library);
+      free (path);
+      return;
+    }
+  libname = basename (library);
+  if (process_file (library, libname, &flag, &soname, 0))
+    {
+      error (0, 0, _("No link created since soname could not be found for %s"),
+	     library);
+      free (path);
+      return;
+    }
+  create_links (path, libname, soname);
+  free (soname);
+  free (path);
+}
+
+
 /* Read a whole directory and search for libraries.
    The purpose is two-fold:
    - search for libraries which will be added to the cache
@@ -595,8 +671,9 @@ main (int argc, char **argv)
   /* Parse and process arguments.  */
   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
-  /* Remaining arguments are additional libraries.  */
-  if (remaining != argc)
+  /* Remaining arguments are additional libraries if opt_manual_link
+     is not set.  */
+  if (remaining != argc && !opt_manual_link)
     {
       int i;
       for (i = remaining; i < argc; ++i)
@@ -626,6 +703,18 @@ main (int argc, char **argv)
       exit (0);
     }
 
+  if (opt_manual_link)
+    {
+      /* Link all given libraries manually.  */
+      int i;
+
+      for (i = remaining; i < argc; ++i)
+	manual_link (argv [i]);
+
+      exit (0);
+    }
+  
+  
   if (opt_build_cache)
     init_cache ();
 
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index d482da39b8..8e51970495 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -121,6 +121,9 @@ char *getcwd ();
 # ifndef HAVE_STPCPY
 static char *stpcpy PARAMS ((char *dest, const char *src));
 # endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
+# endif
 #endif
 
 /* Amount to increase buffer size by in each try.  */
@@ -130,7 +133,7 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
    PATH_MAX but might cause redefinition warnings when sys/param.h is
    later included (as on MORE/BSD 4.3).  */
-#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
 # include <limits.h>
 #endif
 
@@ -138,16 +141,16 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 # define _POSIX_PATH_MAX 255
 #endif
 
-#if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
+#if !defined PATH_MAX && defined _PC_PATH_MAX
 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
 #endif
 
 /* Don't include sys/param.h if it already has been.  */
-#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
 # include <sys/param.h>
 #endif
 
-#if !defined(PATH_MAX) && defined(MAXPATHLEN)
+#if !defined PATH_MAX && defined MAXPATHLEN
 # define PATH_MAX MAXPATHLEN
 #endif
 
@@ -165,6 +168,68 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 # define HAVE_LOCALE_NULL
 #endif
 
+/* We want to allocate a string at the end of the struct.  gcc makes
+   this easy.  */
+#ifdef __GNUC__
+# define ZERO 0
+#else
+# define ZERO 1
+#endif
+
+/* This is the type used for the search tree where known translations
+   are stored.  */
+struct known_translation_t
+{
+  /* Domain in which to search.  */
+  char *domain;
+
+  /* The category.  */
+  int category;
+
+  /* State of the catalog counter at the point the string was found.  */
+  int counter;
+
+  /* And finally the translation.  */
+  const char *translation;
+
+  /* Pointer to the string in question.  */
+  char msgid[ZERO];
+};
+
+/* Root of the search tree with known translations.  We can use this
+   only if the system provides the `tsearch' function family.  */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+
+static void *root;
+
+# ifdef _LIBC
+#  define tsearch __tsearch
+# endif
+
+/* Function to compare two entries in the table of known translations.  */
+static int
+transcmp (const void *p1, const void *p2)
+{
+  struct known_translation_t *s1 = (struct known_translation_t *) p1;
+  struct known_translation_t *s2 = (struct known_translation_t *) p2;
+  int result;
+
+  result = strcmp (s1->msgid, s2->msgid);
+  if (result == 0)
+    {
+      result = strcmp (s1->msgid, s2->msgid);
+      if (result == 0)
+	/* We compare the category last (though this is the cheapest
+	   operation) since it is hopefully always the same (namely
+	   LC_MESSAGES).  */
+	result = s1->category - s2->category;
+    }
+
+  return result;
+}
+#endif
+
 /* Name of the default domain used for gettext(3) prior any call to
    textdomain(3).  The default value for this is "messages".  */
 const char _nl_default_default_domain[] = "messages";
@@ -268,12 +333,34 @@ DCGETTEXT (domainname, msgid, category)
   char *dirname, *xdomainname;
   char *single_locale;
   char *retval;
-  int saved_errno = errno;
+  int saved_errno;
+#if defined HAVE_TSEARCH || defined _LIBC
+  struct known_translation_t *search;
+  struct known_translation_t **foundp;
+  size_t msgid_len = strlen (msgid) + 1;
+#endif
+  size_t domainname_len;
 
   /* If no real MSGID is given return NULL.  */
   if (msgid == NULL)
     return NULL;
 
+#if defined HAVE_TSEARCH || defined _LIBC
+  /* Try to find the translation among those which we found at some time.  */
+  search = (struct known_translation_t *) alloca (sizeof (*search)
+						  + msgid_len);
+  memcpy (search->msgid, msgid, msgid_len);
+  search->domain = (char *) domainname;
+  search->category = category;
+
+  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+    return (char *) (*foundp)->translation;
+#endif
+
+  /* Preserve the `errno' value.  */
+  saved_errno = errno;
+
   /* See whether this is a SUID binary or not.  */
   DETERMINE_SECURE;
 
@@ -340,12 +427,13 @@ DCGETTEXT (domainname, msgid, category)
   categoryname = category_to_name (category);
   categoryvalue = guess_category_value (category, categoryname);
 
+  domainname_len = strlen (domainname);
   xdomainname = (char *) alloca (strlen (categoryname)
-				 + strlen (domainname) + 5);
+				 + domainname_len + 5);
   ADD_BLOCK (block_list, xdomainname);
 
-  stpcpy (stpcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
-		  domainname),
+  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+		  domainname, domainname_len),
 	  ".mo");
 
   /* Creating working area.  */
@@ -422,6 +510,38 @@ DCGETTEXT (domainname, msgid, category)
 	    {
 	      FREE_BLOCKS (block_list);
 	      __set_errno (saved_errno);
+#if defined HAVE_TSEARCH || defined _LIBC
+	      if (foundp == NULL)
+		{
+		  /* Create a new entry and add it to the search tree.  */
+		  struct known_translation_t *newp;
+
+		  newp = (struct known_translation_t *)
+		    malloc (sizeof (*newp) + msgid_len
+			    + domainname_len + 1 - ZERO);
+		  if (newp != NULL)
+		    {
+		      newp->domain = mempcpy (newp->msgid, msgid, msgid_len);
+		      memcpy (newp->domain, domainname, domainname_len + 1);
+		      newp->category = category;
+		      newp->counter = _nl_msg_cat_cntr;
+		      newp->translation = retval;
+
+		      /* Insert the entry in the search tree.  */
+		      foundp = (struct known_translation_t **)
+			tsearch (newp, &root, transcmp);
+		      if (&newp != foundp)
+			/* The insert failed.  */
+			free (newp);
+		    }
+		}
+	      else
+		{
+		  /* We can update the existing entry.  */
+		  (*foundp)->counter = _nl_msg_cat_cntr;
+		  (*foundp)->translation = retval;
+		}
+#endif
 	      return retval;
 	    }
 	}
@@ -571,12 +691,13 @@ _nl_find_msg (domain_file, msgid)
 	    return NULL;
 
 	  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
-	      && strcmp (msgid,
-			 domain->data + W (domain->must_swap,
-					   domain->orig_tab[nstr - 1].offset))
-	         == 0)
-	    return (char *) domain->data
-	      + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
+	      && (strcmp (msgid,
+			  domain->data + W (domain->must_swap,
+					    domain->orig_tab[nstr - 1].offset))
+		  == 0))
+	    return ((char *) domain->data
+		    + W (domain->must_swap,
+			 domain->trans_tab[nstr - 1].offset));
 	}
       /* NOTREACHED */
     }
@@ -590,9 +711,9 @@ _nl_find_msg (domain_file, msgid)
       int cmp_val;
 
       act = (bottom + top) / 2;
-      cmp_val = strcmp (msgid, domain->data
-			       + W (domain->must_swap,
-				    domain->orig_tab[act].offset));
+      cmp_val = strcmp (msgid, (domain->data
+				+ W (domain->must_swap,
+				     domain->orig_tab[act].offset)));
       if (cmp_val < 0)
 	top = act;
       else if (cmp_val > 0)
@@ -602,9 +723,9 @@ _nl_find_msg (domain_file, msgid)
     }
 
   /* If an translation is found return this.  */
-  return bottom >= top ? NULL : (char *) domain->data
-                                + W (domain->must_swap,
-				     domain->trans_tab[act].offset);
+  return bottom >= top ? NULL : ((char *) domain->data
+				 + W (domain->must_swap,
+				      domain->trans_tab[act].offset));
 }
 
 
@@ -728,6 +849,17 @@ stpcpy (dest, src)
 }
 #endif
 
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (dest, src, n)
+     void *dest;
+     const void *src;
+     size_t n;
+{
+  return (void *) ((char *) memcpy (dst, src, n) + n);
+}
+#endif
+
 
 #ifdef _LIBC
 /* If we want to free all resources we have to do some work at
@@ -748,6 +880,9 @@ free_mem (void)
   if (_nl_current_default_domain != _nl_default_default_domain)
     /* Yes, again a pointer comparison.  */
     free ((char *) _nl_current_default_domain);
+
+  /* Remove the search tree with the know translations.  */
+  __tdestroy (root, free);
 }
 
 text_set_element (__libc_subfreeres, free_mem);
diff --git a/intl/libintl.h b/intl/libintl.h
index aec7ea4b27..0c987e7d73 100644
--- a/intl/libintl.h
+++ b/intl/libintl.h
@@ -82,7 +82,7 @@ extern char *bindtextdomain (__const char *__domainname,
 # define dgettext(domainname, msgid)					      \
   dcgettext (domainname, msgid, LC_MESSAGES)
 
-# if __GNUC_PREREQ (2,7)
+# if __GLIBC__ >= 2 && __GNUC_PREREQ (2,7)
 /* Variable defined in loadmsgcat.c which gets incremented every time a
    new catalog is loaded.  */
 extern int _nl_msg_cat_cntr;
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 7d161b8254..9bdf83e951 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,11 @@
+1999-12-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* manager.c (pthread_allocate_stack): Correct computation of
+	new_thread_bottom.  Correct handling of stack size and when the
+	rlimit method to guard for stack growth is used.
+	* pthread.c (pthread_initialize): Stack limit must be STACK_SIZE
+	minus one pagesize (not two).
+
 1999-12-03  Andreas Jaeger  <aj@suse.de>
 
 	* Versions: Add __res_state with version GLIBC_2.2.
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c
index 307ce63721..0cbb426c9d 100644
--- a/linuxthreads/manager.c
+++ b/linuxthreads/manager.c
@@ -289,9 +289,12 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
     }
   else
     {
+      stacksize = STACK_SIZE - pagesize;
+      if (attr != NULL)
+        stacksize = MIN (stacksize, roundup(attr->__stacksize, pagesize));
       /* Allocate space for stack and thread descriptor at default address */
       new_thread = default_new_thread;
-      new_thread_bottom = (char *) new_thread - STACK_SIZE;
+      new_thread_bottom = (char *) (new_thread + 1) - stacksize;
       if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE),
                INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
                MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
@@ -300,14 +303,10 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
         return -1;
       /* We manage to get a stack.  Now see whether we need a guard
          and allocate it if necessary.  Notice that the default
-         attributes (stack_size = STACK_SIZE - pagesize and
-         guardsize = pagesize) do not need a guard page, since
-         the RLIMIT_STACK soft limit prevents stacks from
-         running into one another. */
-      if (attr == NULL ||
-          attr->__guardsize == 0 ||
-          (attr->__guardsize == pagesize &&
-           attr->__stacksize == STACK_SIZE - pagesize))
+         attributes (stack_size = STACK_SIZE - pagesize) do not need
+	 a guard page, since the RLIMIT_STACK soft limit prevents stacks
+	 from running into one another. */
+      if (stacksize == STACK_SIZE - pagesize)
         {
           /* We don't need a guard page. */
           guardaddr = NULL;
@@ -316,10 +315,7 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
       else
         {
           /* Put a bad page at the bottom of the stack */
-          stacksize = roundup(attr->__stacksize, pagesize);
-          if (stacksize >= STACK_SIZE - pagesize)
-            stacksize = STACK_SIZE - pagesize;
-          guardaddr = (void *)new_thread - stacksize;
+          guardaddr = (void *)new_thread_bottom - stacksize;
           guardsize = attr->__guardsize;
           if (mmap ((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0)
               == MAP_FAILED)
diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c
index 41d09a833c..a9083635b6 100644
--- a/linuxthreads/pthread.c
+++ b/linuxthreads/pthread.c
@@ -300,10 +300,9 @@ static void pthread_initialize(void)
   __pthread_initial_thread_bos =
     (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
   /* Play with the stack size limit to make sure that no stack ever grows
-     beyond STACK_SIZE minus two pages (one page for the thread descriptor
-     immediately beyond, and one page to act as a guard page). */
+     beyond STACK_SIZE minus one page (to act as a guard page). */
   getrlimit(RLIMIT_STACK, &limit);
-  max_stack = STACK_SIZE - 2 * __getpagesize();
+  max_stack = STACK_SIZE - __getpagesize();
   if (limit.rlim_cur > max_stack) {
     limit.rlim_cur = max_stack;
     setrlimit(RLIMIT_STACK, &limit);
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index 42fd601064..87005e86ab 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -73,7 +73,8 @@ struct element_t
 
   const char *mbs;
   const uint32_t *wcs;
-  int order;
+  int mborder;
+  int wcorder;
 
   struct element_list_t *weights;
 
@@ -87,6 +88,9 @@ struct element_t
   /* Predecessor and successor in the order list.  */
   struct element_t *last;
   struct element_t *next;
+
+  /* Next element in multibyte output list.  */
+  struct element_t *mbnext;
 };
 
 /* Special element value.  */
@@ -151,6 +155,10 @@ struct locale_collate_t
      that the definitions from more than one input file contains information.
      Therefore we keep all relevant input in a list.  */
   struct locale_collate_t *next;
+
+  /* Arrays with heads of the list for each of the leading bytes in
+     the multibyte sequences.  */
+  struct element_t *mbheads[256];
 };
 
 
@@ -176,7 +184,7 @@ make_seclist_elem (struct locale_collate_t *collate, const char *string,
 
 
 static struct element_t *
-new_element (struct locale_collate_t *collate, const char *mbs,
+new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
 	     const uint32_t *wcs, const char *name, size_t namelen)
 {
   struct element_t *newp;
@@ -185,7 +193,10 @@ new_element (struct locale_collate_t *collate, const char *mbs,
 					     sizeof (*newp));
   newp->name = name == NULL ? NULL : obstack_copy (&collate->mempool,
 						   name, namelen);
-  newp->mbs = mbs;
+  if (mbs != NULL)
+    newp->mbs = obstack_copy0 (&collate->mempool, mbs, mbslen);
+  else
+    newp->mbs = NULL;
   if (wcs != NULL)
     {
       size_t nwcs = wcslen ((wchar_t *) wcs) + 1;
@@ -196,7 +207,8 @@ new_element (struct locale_collate_t *collate, const char *mbs,
     }
   else
     newp->wcs = NULL;
-  newp->order = 0;
+  newp->mborder = 0;
+  newp->wcorder = 0;
 
   /* Will be allocated later.  */
   newp->weights = NULL;
@@ -209,6 +221,8 @@ new_element (struct locale_collate_t *collate, const char *mbs,
   newp->last = NULL;
   newp->next = NULL;
 
+  newp->mbnext = NULL;
+
   return newp;
 }
 
@@ -457,14 +471,15 @@ find_element (struct linereader *ldfile, struct locale_collate_t *collate,
 	  result = sym->order;
 
 	  if (result == NULL)
-	    result = sym->order = new_element (collate, NULL, NULL, NULL, 0);
+	    result = sym->order = new_element (collate, NULL, 0, NULL,
+					       NULL, 0);
 	}
       else if (find_entry (&collate->elem_table, str, len,
 			   (void **) &result) != 0)
 	{
 	  /* It's also no collation element.  So it is an character
 	     element defined later.  */
-	  result = new_element (collate, NULL, NULL, str, len);
+	  result = new_element (collate, NULL, 0, NULL, str, len);
 	  if (result != NULL)
 	    /* Insert it into the sequence table.  */
 	    insert_entry (&collate->seq_table, str, len, result);
@@ -499,6 +514,8 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
   elem->line = ldfile->lineno;
   elem->last = collate->cursor;
   elem->next = collate->cursor ? collate->cursor->next : NULL;
+  if (collate->cursor != NULL)
+    collate->cursor->next = elem;
   elem->weights = (struct element_list_t *)
     obstack_alloc (&collate->mempool, nrules * sizeof (struct element_list_t));
   memset (elem->weights, '\0', nrules * sizeof (struct element_list_t));
@@ -683,7 +700,7 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
 }
 
 
-static void
+static int
 insert_value (struct linereader *ldfile, struct token *arg,
 	      struct charmap_t *charmap, struct repertoire_t *repertoire,
 	      struct locale_collate_t *collate)
@@ -721,14 +738,14 @@ insert_value (struct linereader *ldfile, struct token *arg,
 	  elem = sym->order;
 
 	  if (elem == NULL)
-	    elem = sym->order = new_element (collate, NULL, NULL, NULL, 0);
+	    elem = sym->order = new_element (collate, NULL, 0, NULL, NULL, 0);
 	}
       else if (find_entry (&collate->elem_table, arg->val.str.startmb,
 			   arg->val.str.lenmb, (void **) &elem) != 0)
 	{
 	  /* It's also no collation element.  Therefore ignore it.  */
 	  lr_ignore_rest (ldfile, 0);
-	  return;
+	  return 1;
 	}
     }
   else
@@ -741,6 +758,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
 
 	  /* We have to allocate an entry.  */
 	  elem = new_element (collate, seq != NULL ? seq->bytes : NULL,
+			      seq != NULL ? seq->nbytes : 0,
 			      wcs, arg->val.str.startmb, arg->val.str.lenmb);
 
 	  /* And add it to the table.  */
@@ -755,14 +773,16 @@ insert_value (struct linereader *ldfile, struct token *arg,
   if (elem->next != NULL || (collate->cursor != NULL
 			     && elem->next == collate->cursor))
     {
-      lr_error (ldfile, _("order for `%.*s' already defined at %s:%Z"),
+      lr_error (ldfile, _("order for `%.*s' already defined at %s:%zu"),
 		arg->val.str.lenmb, arg->val.str.startmb,
 		elem->file, elem->line);
       lr_ignore_rest (ldfile, 0);
-      return;
+      return 1;
     }
 
   insert_weights (ldfile, elem, charmap, repertoire, collate, tok_none);
+
+  return 0;
 }
 
 
@@ -780,8 +800,11 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
   startp = collate->cursor;
 
   /* Process and add the end-entry.  */
-  if (arg != NULL)
-    insert_value (ldfile, arg, charmap, repertoire, collate);
+  if (arg != NULL
+      && insert_value (ldfile, arg, charmap, repertoire, collate))
+    /* Something went wrong with inserting the to-value.  This means
+       we cannot process the ellipsis.  */
+    return;
 
   /* Reset the cursor.  */
   collate->cursor = startp;
@@ -805,7 +828,168 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
 
   if (ellipsis == tok_ellipsis3)
     {
-      /* XXX */
+      /* One requirement we make here: the length of the byte
+	 sequences for the first and end character must be the same.
+	 This is mainly to prevent unwanted effects and this is often
+	 not what is wanted.  */
+      size_t len = (startp->mbs != NULL ? strlen (startp->mbs)
+		    : (endp->mbs != NULL ? strlen (endp->mbs) : 0));
+      char mbcnt[len + 1];
+      char mbend[len + 1];
+
+      /* Well, this should be caught somewhere else already.  Just to
+	 make sure.  */
+      assert (startp == NULL || startp->wcs == NULL || startp->wcs[1] == 0);
+      assert (endp == NULL || endp->wcs == NULL || endp->wcs[1] == 0);
+
+      if (startp != NULL && endp != NULL
+	  && startp->mbs != NULL && endp->mbs != NULL
+	  && strlen (startp->mbs) != strlen (endp->mbs))
+	{
+	  lr_error (ldfile, _("\
+%s: byte sequences of first and last character must have the same length"),
+		    "LC_COLLATE");
+	  return;
+	}
+
+      /* Determine whether we have to generate multibyte sequences.  */
+      if ((startp == NULL || startp->mbs != NULL)
+	  && (endp == NULL || endp->mbs != NULL))
+	{
+	  int cnt;
+	  int ret;
+
+	  /* Prepare the beginning byte sequence.  This is either from the
+	     beginning byte sequence or it is all nulls if it was an
+	     initial ellipsis.  */
+	  if (startp == NULL || startp->mbs == NULL)
+	    memset (mbcnt, '\0', len);
+	  else
+	    {
+	      memcpy (mbcnt, startp->mbs, len);
+
+	      /* And increment it so that the value is the first one we will
+		 try to insert.  */
+	      for (cnt = len - 1; cnt >= 0; --cnt)
+		if (++mbcnt[cnt] != '\0')
+		  break;
+	    }
+	  mbcnt[len] = '\0';
+
+	  /* And the end sequence.  */
+	  if (endp == NULL || endp->mbs == NULL)
+	    memset (mbend, '\0', len);
+	  else
+	    memcpy (mbend, endp->mbs, len);
+	  mbend[len] = '\0';
+
+	  /* Test whether we have a correct range.  */
+	  ret = memcmp (mbcnt, mbend, len);
+	  if (ret >= 0)
+	    {
+	      if (ret > 0)
+		lr_error (ldfile, _("%s: byte sequence of first character of \
+sequence is not lower than that of the last character"), "LC_COLLATE");
+	      return;
+	    }
+
+	  /* Generate the byte sequences data.  */
+	  while (1)
+	    {
+	      struct charseq *seq;
+
+	      /* Quite a bit of work ahead.  We have to find the character
+		 definition for the byte sequence and then determine the
+		 wide character belonging to it.  */
+	      seq = charmap_find_symbol (charmap, mbcnt, len);
+	      if (seq != NULL)
+		{
+		  struct element_t *elem;
+		  size_t namelen;
+
+		  if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
+		    seq->ucs4 = repertoire_find_value (repertoire, seq->name,
+						       strlen (seq->name));
+
+		  /* I don't this this can ever happen.  */
+		  assert (seq->name != NULL);
+		  namelen = strlen (seq->name);
+
+		  /* Now we are ready to insert the new value in the
+		     sequence.  Find out whether the element is
+		     already known.  */
+		  if (find_entry (&collate->seq_table, seq->name, namelen,
+				  (void **) &elem) != 0)
+		    {
+		      uint32_t wcs[2] = { seq->ucs4, 0 };
+
+		      /* We have to allocate an entry.  */
+		      elem = new_element (collate, mbcnt, len, wcs, seq->name,
+					  namelen);
+
+		      /* And add it to the table.  */
+		      if (insert_entry (&collate->seq_table, seq->name,
+					namelen, elem) != 0)
+			/* This cannot happen.  */
+			assert (! "Internal error");
+		    }
+
+		  /* Test whether this element is not already in the list.  */
+		  if (elem->next != NULL || (collate->cursor != NULL
+					     && elem->next == collate->cursor))
+		    {
+		      lr_error (ldfile, _("\
+order for `%.*s' already defined at %s:%zu"),
+				namelen, seq->name, elem->file, elem->line);
+		      goto increment;
+		    }
+
+		  /* Enqueue the new element.  */
+		  elem->last = collate->cursor;
+		  elem->next = collate->cursor->next;
+		  elem->last->next = elem;
+		  if (elem->next != NULL)
+		    elem->next->last = elem;
+		  collate->cursor = elem;
+
+		 /* Add the weight value.  We take them from the
+		    `ellipsis_weights' member of `collate'.  */
+		  elem->weights = (struct element_list_t *)
+		    obstack_alloc (&collate->mempool,
+				   nrules * sizeof (struct element_list_t));
+		  for (cnt = 0; cnt < nrules; ++cnt)
+		    if (collate->ellipsis_weight.weights[cnt].cnt == 1
+			&& (collate->ellipsis_weight.weights[cnt].w[0]
+			    == ELEMENT_ELLIPSIS2))
+		      {
+			elem->weights[cnt].w = (struct element_t **)
+			  obstack_alloc (&collate->mempool,
+					 sizeof (struct element_t *));
+			elem->weights[cnt].w[0] = elem;
+			elem->weights[cnt].cnt = 1;
+		      }
+		    else
+		      {
+			/* Simly use the weight from `ellipsis_weight'.  */
+			elem->weights[cnt].w =
+			  collate->ellipsis_weight.weights[cnt].w;
+			elem->weights[cnt].cnt =
+			  collate->ellipsis_weight.weights[cnt].cnt;
+		      }
+		}
+
+	      /* Increment for the next round.  */
+	    increment:
+	      for (cnt = len - 1; cnt >= 0; --cnt)
+		if (++mbcnt[cnt] != '\0')
+		  break;
+
+	      /* Find out whether this was all.  */
+	      if (cnt < 0 || memcmp (mbcnt, mbend, len) >= 0)
+		/* Yep, that's all.  */
+		break;
+	    }
+	}
     }
   else
     {
@@ -883,7 +1067,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
 					     && elem->next == collate->cursor))
 		    {
 		      lr_error (ldfile, _("\
-%s: order for `%.*s' already defined at %s:%Z"),
+%s: order for `%.*s' already defined at %s:%zu"),
 				"LC_COLLATE", lenfrom, buf,
 				elem->file, elem->line);
 		      continue;
@@ -923,6 +1107,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
 		      /* We have to allocate an entry.  */
 		      elem = new_element (collate,
 					  seq != NULL ? seq->bytes : NULL,
+					  seq != NULL ? seq->nbytes : 0,
 					  wc == ILLEGAL_CHAR_VALUE
 					  ? NULL : wcs,
 					  buf, lenfrom);
@@ -1023,6 +1208,67 @@ collate_startup (struct linereader *ldfile, struct localedef_t *locale,
 void
 collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
 {
+  /* Now is the time when we can assign the individual collation
+     values for all the symbols.  We have possibly different values
+     for the wide- and the multibyte-character symbols.  This is done
+     since it might make a difference in the encoding if there is in
+     some cases no multibyte-character but there are wide-characters.
+     (The other way around it is not important since theencoded
+     collation value in the wide-character case is 32 bits wide and
+     therefore requires no encoding).
+
+     The lowest collation value assigned is 2.  Zero is reserved for
+     the NUL byte terminating the strings in the `strxfrm'/`wcsxfrm'
+     functions and 1 is used to separate the individual passes for the
+     different rules.
+
+     We also have to construct is list with all the bytes/words which
+     can come first in a sequence, followed by all the elements which
+     also start with this byte/word.  The order is reverse which has
+     among others the important effect that longer strings are located
+     first in the list.  This is required for the output data since
+     the algorithm used in `strcoll' etc depends on this.
+
+     The multibyte case is easy.  We simply sort into an array with
+     256 elements.  */
+  struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
+  int mbact = 2;
+  int wcact = 2;
+  struct element_t *runp = collate->start;
+
+  while (runp != NULL)
+    {
+      if (runp->mbs != NULL)
+	{
+	  struct element_t **eptr;
+
+	  /* Determine the order.  */
+	  runp->mborder = mbact++;
+
+	  /* Find the point where to insert in the list.  */
+	  eptr = &collate->mbheads[(unsigned int) runp->mbs[0]];
+	  while (*eptr != NULL)
+	    {
+	      /* Check which string is larger, the one we want to insert
+		 or the current element of the list we are looking at.  */
+	      assert (runp->mbs[0] == (*eptr)->mbs[0]);
+	      if (strcmp (runp->mbs, (*eptr)->mbs) > 0)
+		break;
+
+	      eptr = &(*eptr)->mbnext;
+	    }
+
+	  /* Set the pointers.  */
+	  runp->mbnext = *eptr;
+	  *eptr = runp;
+	}
+
+      if (runp->wcs != NULL)
+	runp->wcorder = wcact++;
+
+      /* Up to the next entry.  */
+      runp = runp->next;
+    }
 }
 
 
@@ -1257,7 +1503,8 @@ collate_read (struct linereader *ldfile, struct localedef_t *result,
 		      if (insert_entry (&collate->elem_table,
 					symbol, symbol_len,
 					new_element (collate,
-						     NULL, NULL, NULL, 0)) < 0)
+						     NULL, 0, NULL, symbol,
+						     symbol_len)) < 0)
 			lr_error (ldfile, _("\
 error while adding collating element"));
 		    }
@@ -1519,9 +1766,12 @@ error while adding equivalent collating symbol"));
 	    goto err_label;
 
 	  /* Handle ellipsis at end of list.  */
-	  if (was_ellipsis)
-	    /* XXX */
-	    abort ();
+	  if (was_ellipsis != tok_none)
+	    {
+	      handle_ellipsis (ldfile, NULL, was_ellipsis, charmap, repertoire,
+			       collate);
+	      was_ellipsis = tok_none;
+	    }
 
 	  state = 2;
 	  lr_ignore_rest (ldfile, 1);
@@ -1543,9 +1793,12 @@ error while adding equivalent collating symbol"));
 	      state = 2;
 
 	      /* Handle ellipsis at end of list.  */
-	      if (was_ellipsis)
-		/* XXX */
-		abort ();
+	      if (was_ellipsis != tok_none)
+		{
+		  handle_ellipsis (ldfile, arg, was_ellipsis, charmap,
+				   repertoire, collate);
+		  was_ellipsis = tok_none;
+		}
 	    }
 	  else if (state != 2 && state != 3)
 	    goto err_label;
@@ -1610,9 +1863,12 @@ error while adding equivalent collating symbol"));
 	      state = 2;
 
 	      /* Handle ellipsis at end of list.  */
-	      if (was_ellipsis)
-		/* XXX */
-		abort ();
+	      if (was_ellipsis != tok_none)
+		{
+		  handle_ellipsis (ldfile, NULL, was_ellipsis, charmap,
+				   repertoire, collate);
+		  was_ellipsis = tok_none;
+		}
 	    }
 	  else if (state == 3)
 	    {
@@ -1848,7 +2104,7 @@ error while adding equivalent collating symbol"));
 		  && collate->undefined.next == collate->cursor))
 	    {
 	      lr_error (ldfile,
-			_("%s: order for `%.*s' already defined at %s:%Z"),
+			_("%s: order for `%.*s' already defined at %s:%zu"),
 			"LC_COLLATE", 9, "UNDEFINED", collate->undefined.file,
 			collate->undefined.line);
 	      lr_ignore_rest (ldfile, 0);
@@ -1892,9 +2148,12 @@ error while adding equivalent collating symbol"));
 			    "LC_COLLATE");
 
 		  /* Handle ellipsis at end of list.  */
-		  if (was_ellipsis)
-		    /* XXX */
-		    abort ();
+		  if (was_ellipsis != tok_none)
+		    {
+		      handle_ellipsis (ldfile, NULL, was_ellipsis, charmap,
+				       repertoire, collate);
+		      was_ellipsis = tok_none;
+		    }
 		}
 	      else if (state == 3)
 		error (0, 0, _("%s: missing `reorder-end' keyword"),
diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c
index ac56f6fbec..2de46088df 100644
--- a/nis/nss_compat/compat-grp.c
+++ b/nis/nss_compat/compat-grp.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -730,7 +730,10 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp,
   enum nss_status status;
 
   if (name[0] == '-' || name[0] == '+')
-    return NSS_STATUS_NOTFOUND;
+    {
+      *errnop = ENOENT;
+      return NSS_STATUS_NOTFOUND;
+    }
 
   __libc_lock_lock (lock);
 
@@ -915,7 +918,10 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
 
 	  status = getgrgid_plusgroup (gid, result, buffer, buflen, errnop);
 	  if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
-	    return NSS_STATUS_NOTFOUND;
+	    {
+	      *errnop = ENOENT;
+	      return NSS_STATUS_NOTFOUND;
+	    }
 	  else
 	    return status;
 	}
diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c
index 47b395ede6..d4c3422bd4 100644
--- a/nis/nss_compat/compat-initgroups.c
+++ b/nis/nss_compat/compat-initgroups.c
@@ -263,6 +263,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer,
   if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
     {
       ent->nis = 0;
+      *errnop = ENOENT;
       return NSS_STATUS_NOTFOUND;
     }
 
@@ -445,7 +446,10 @@ getgrnam_plusgroup (const char *name, struct group *result, char *buffer,
         ++p;
       parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop);
       if (parse_res == -1)
-	return NSS_STATUS_TRYAGAIN;
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
     }
 
   if (parse_res)
diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c
index 1290346881..f254fadf5c 100644
--- a/nis/nss_compat/compat-spwd.c
+++ b/nis/nss_compat/compat-spwd.c
@@ -383,6 +383,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent,
       if (parse_res == -1)
 	{
 	  ent->netgrdata.cursor = saved_cursor;
+	  *errnop = ERANGE;
 	  return NSS_STATUS_TRYAGAIN;
 	}
 
@@ -1112,7 +1113,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
 	  && result->sp_namp[1] != '@')
 	{
 	  if (strcmp (&result->sp_namp[1], name) == 0)
-	    return NSS_STATUS_NOTFOUND;
+	    {
+	      *errnop = ENOENT;
+	      return NSS_STATUS_NOTFOUND;
+	    }
 	  else
 	    continue;
 	}
@@ -1128,8 +1132,11 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
 	      status = getspnam_plususer (name, result, buffer, buflen,
 					  errnop);
 	      if (status == NSS_STATUS_RETURN)
-		/* We couldn't parse the entry */
-		return NSS_STATUS_NOTFOUND;
+		{
+		  /* We couldn't parse the entry */
+		  *errnop = ENOENT;
+		  return NSS_STATUS_NOTFOUND;
+		}
 	      else
 		return status;
 	    }
@@ -1142,7 +1149,10 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
 
 	  status = getspnam_plususer (name, result, buffer, buflen, errnop);
 	  if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
-	    return NSS_STATUS_NOTFOUND;
+	    {
+	      *errnop = ENOENT;
+	      return NSS_STATUS_NOTFOUND;
+	    }
 	  else
 	    return status;
 	}
@@ -1159,7 +1169,10 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
   enum nss_status status;
 
   if (name[0] == '-' || name[0] == '+')
-    return NSS_STATUS_NOTFOUND;
+    {
+      *errnop = ENOENT;
+      return NSS_STATUS_NOTFOUND;
+    }
 
   if (ni == NULL)
     {
diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c
index 64d0bf8de5..e6e2386547 100644
--- a/nis/nss_nis/nis-alias.c
+++ b/nis/nss_nis/nis-alias.c
@@ -278,7 +278,10 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
       if (parse_res == -1)
 	return NSS_STATUS_TRYAGAIN;
       else
-	return NSS_STATUS_NOTFOUND;
+	{
+	  *errnop = ENOENT;
+	  return NSS_STATUS_NOTFOUND;
+	}
     }
 
   return NSS_STATUS_SUCCESS;
diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c
index c95f766469..c1ea32adc5 100644
--- a/nis/nss_nis/nis-ethers.c
+++ b/nis/nss_nis/nis-ethers.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -241,7 +241,10 @@ _nss_nis_gethostton_r (const char *name, struct ether *eth,
       if (parse_res == -1)
 	return NSS_STATUS_TRYAGAIN;
       else
-	return NSS_STATUS_NOTFOUND;
+	{
+	  *errnop = ENOENT;
+	  return NSS_STATUS_NOTFOUND;
+	}
     }
   return NSS_STATUS_SUCCESS;
 }
diff --git a/nis/nss_nis/nis-grp.c b/nis/nss_nis/nis-grp.c
index 6dca66e4df..62e6b475b7 100644
--- a/nis/nss_nis/nis-grp.c
+++ b/nis/nss_nis/nis-grp.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -207,7 +207,7 @@ _nss_nis_getgrnam_r (const char *name, struct group *grp,
 	return NSS_STATUS_TRYAGAIN;
       else
 	{
-	  *errnop = EAGAIN;
+	  *errnop = ENOENT;
 	  return NSS_STATUS_NOTFOUND;
 	}
     }
diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c
index 0ddc930687..15aff251e5 100644
--- a/nis/nss_nis/nis-hosts.c
+++ b/nis/nss_nis/nis-hosts.c
@@ -321,6 +321,7 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
       else
 	{
 	  *h_errnop = HOST_NOT_FOUND;
+	  *errnop = ENOENT;
 	  return NSS_STATUS_NOTFOUND;
 	}
     }
@@ -392,7 +393,10 @@ _nss_nis_gethostbyaddr_r (char *addr, size_t addrlen, int af,
 	  *errnop = errno;
 	}
       if (retval == NSS_STATUS_NOTFOUND)
-	*h_errnop = HOST_NOT_FOUND;
+	{
+	  *h_errnop = HOST_NOT_FOUND;
+	  *errnop = ENOENT;
+	}
       return retval;
     }
 
diff --git a/nis/nss_nis/nis-netgrp.c b/nis/nss_nis/nis-netgrp.c
index d170b56f50..0d3ed44d3f 100644
--- a/nis/nss_nis/nis-netgrp.c
+++ b/nis/nss_nis/nis-netgrp.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -117,7 +117,10 @@ _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen,
   enum nss_status status;
 
   if (cursor == NULL)
-    return NSS_STATUS_NOTFOUND;
+    {
+      *errnop = ENOENT;
+      return NSS_STATUS_NOTFOUND;
+    }
 
   __libc_lock_lock (lock);
 
diff --git a/nis/nss_nis/nis-publickey.c b/nis/nss_nis/nis-publickey.c
index 73afd442a9..821accfbae 100644
--- a/nis/nss_nis/nis-publickey.c
+++ b/nis/nss_nis/nis-publickey.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -50,8 +50,11 @@ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop)
 
   domain = strchr (netname, '@');
   if (!domain)
-    return NSS_STATUS_UNAVAIL;
-  domain++;
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  ++domain;
 
   retval = yperr2nss (yp_match (domain, "publickey.byname", netname,
 				strlen (netname), &result, &len));
@@ -95,8 +98,11 @@ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd,
 
   domain = strchr (netname, '@');
   if (!domain)
-    return NSS_STATUS_UNAVAIL;
-  domain++;
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  ++domain;
 
   retval = yperr2nss (yp_match (domain, "publickey.byname", netname,
 				strlen (netname), &result, &len));
@@ -196,10 +202,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
 
   domain = strchr (netname, '@');
   if (!domain)
-    return NSS_STATUS_UNAVAIL;
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
 
   /* Point past the '@' character */
-  domain++;
+  ++domain;
   lookup = NULL;
   yperr = yp_match (domain, "netid.byname", netname, strlen (netname),
 		    &lookup, &len);
@@ -209,11 +218,13 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
       break;			/* the successful case */
     case YPERR_DOMAIN:
     case YPERR_KEY:
+      *errnop = ENOENT;
       return NSS_STATUS_NOTFOUND;
     case YPERR_MAP:
     default:
       return NSS_STATUS_UNAVAIL;
     }
+
   if (lookup)
     {
       enum nss_status err;
@@ -224,7 +235,9 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
       return err;
     }
   else
-    return NSS_STATUS_NOTFOUND;
-
+    {
+      *errnop = ENOENT;
+      return NSS_STATUS_NOTFOUND;
+    }
   return NSS_STATUS_SUCCESS;
 }
diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c
index 103b1e4115..cece55c283 100644
--- a/nis/nss_nis/nis-service.c
+++ b/nis/nss_nis/nis-service.c
@@ -172,7 +172,7 @@ internal_nis_getservent_r (struct servent *serv, char *buffer,
 	  return NSS_STATUS_NOTFOUND;
 	}
       p = strncpy (buffer, data->next->val, buflen);
-           while (isspace (*p))
+      while (isspace (*p))
         ++p;
 
       parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
@@ -215,6 +215,63 @@ _nss_nis_getservbyname_r (const char *name, char *protocol,
       return NSS_STATUS_UNAVAIL;
     }
 
+  /* If the protocol is given, we could try if our NIS server knows
+     about services.byservicename map. If yes, we only need one query */
+  if (protocol != NULL)
+    {
+      char key[strlen (name) + strlen (protocol) + 2];
+      char *cp, *domain, *result;
+      size_t keylen, len;
+
+      /* If this fails, the other solution will also fail. */
+      if (yp_get_default_domain (&domain))
+	return NSS_STATUS_UNAVAIL;
+
+      /* key is: "name/protocol" */
+      cp = stpcpy (key, name);
+      *cp++ = '/';
+      stpcpy (cp, protocol);
+      keylen = strlen (key);
+      status = yperr2nss (yp_match (domain, "services.byservicename", key,
+				    keylen, &result, &len));
+
+      /* If we found the key, it's ok and parse the result. If not,
+	 fall through and parse the complete table. */
+      if (status == NSS_STATUS_SUCCESS)
+	{
+	  struct parser_data *pdata = (void *) buffer;
+	  int parse_res;
+	  char *p;
+
+	  if ((size_t) (len + 1) > buflen)
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  p = strncpy (buffer, result, len);
+	  buffer[len] = '\0';
+	  while (isspace (*p))
+	    ++p;
+	  free (result);
+	  parse_res = _nss_files_parse_servent (p, serv, pdata,
+						buflen, errnop);
+	  if (parse_res < 0)
+	    {
+	      if (parse_res == -1)
+		return NSS_STATUS_TRYAGAIN;
+	      else
+		{
+		  *errnop = ENOENT;
+		  return NSS_STATUS_NOTFOUND;
+		}
+	    }
+	  else
+	    return NSS_STATUS_SUCCESS;
+	}
+    }
+
   status = internal_nis_setservent (&data);
   if (status != NSS_STATUS_SUCCESS)
     return status;
@@ -256,10 +313,57 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv,
   enum nss_status status;
   int found;
 
-  if (protocol == NULL)
+  /* If the protocol is given, we only need one query */
+  if (protocol != NULL)
     {
-      *errnop = EINVAL;
-      return NSS_STATUS_UNAVAIL;
+      char key[100 + strlen (protocol) + 2];
+      char *domain, *result;
+      size_t keylen, len;
+
+      /* If this fails, the other solution will also fail. */
+      if (yp_get_default_domain (&domain))
+	return NSS_STATUS_UNAVAIL;
+
+      /* key is: "port/protocol" */
+      keylen = snprintf (key, sizeof (key), "%d/%s", port, protocol);
+      status = yperr2nss (yp_match (domain, "services.byname", key,
+				    keylen, &result, &len));
+
+      /* If we found the key, it's ok and parse the result. If not,
+	 fall through and parse the complete table. */
+      if (status == NSS_STATUS_SUCCESS)
+	{
+	  struct parser_data *pdata = (void *) buffer;
+	  int parse_res;
+	  char *p;
+
+	  if ((size_t) (len + 1) > buflen)
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  p = strncpy (buffer, result, len);
+	  buffer[len] = '\0';
+	  while (isspace (*p))
+	    ++p;
+	  free (result);
+	  parse_res = _nss_files_parse_servent (p, serv, pdata,
+						buflen, errnop);
+	  if (parse_res < 0)
+	    {
+	      if (parse_res == -1)
+		return NSS_STATUS_TRYAGAIN;
+	      else
+		{
+		  *errnop = ENOENT;
+		  return NSS_STATUS_NOTFOUND;
+		}
+	    }
+	  else
+	    return NSS_STATUS_SUCCESS;
+	}
     }
 
   status = internal_nis_setservent (&data);
@@ -270,7 +374,8 @@ _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv,
   while (!found &&
          ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
 					       &data)) == NSS_STATUS_SUCCESS))
-    if (serv->s_port == port && strcmp (serv->s_proto, protocol) == 0)
+    if (serv->s_port == port &&
+	(protocol == NULL || strcmp (serv->s_proto, protocol) == 0))
       found = 1;
 
   internal_nis_endservent (&data);
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 1dc9ca3126..00d0f8b4c8 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -1,6 +1,6 @@
 /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -42,7 +42,6 @@ struct dom_binding
     struct sockaddr_in dom_server_addr;
     int dom_socket;
     CLIENT *dom_client;
-    long int dom_vers;
   };
 typedef struct dom_binding dom_binding;
 
@@ -63,7 +62,6 @@ __yp_bind (const char *domain, dom_binding **ypdb)
   int clnt_sock;
   CLIENT *client;
   int is_new = 0;
-  int try;
 
   if (domain == NULL || domain[0] == '\0')
     return YPERR_BADARGS;
@@ -83,137 +81,127 @@ __yp_bind (const char *domain, dom_binding **ypdb)
     {
       is_new = 1;
       ysd = (dom_binding *) calloc (1, sizeof *ysd);
-      ysd->dom_socket = -1;
-      ysd->dom_vers = -1;
     }
 
-  try = 0;
-
-  do
-    {
-      ++try;
-      if (try > MAXTRIES)
-        {
-          if (is_new)
-            free (ysd);
-          return YPERR_YPBIND;
-        }
-
 #if USE_BINDINGDIR
-      if (ysd->dom_vers < 1 && try == 1) /* Try binding dir only first time */
+  if (ysd->dom_client == NULL)
+    {
+      /* Try binding dir at first if we have no binding */
+      char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
+      struct iovec vec[2];
+      unsigned short port;
+      int fd;
+
+      sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
+      fd = open (path, O_RDONLY);
+      if (fd >= 0)
 	{
-	  char path[sizeof (BINDINGDIR) - 1 + strlen (domain) + 10];
-	  struct iovec vec[2];
-	  unsigned short port;
-	  int fd;
-
-	  sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
-	  fd = open (path, O_RDONLY);
-	  if (fd >= 0)
+	  /* We have a binding file and could save a RPC call */
+	  vec[0].iov_base = &port;
+	  vec[0].iov_len = sizeof (port);
+	  vec[1].iov_base = &ypbr;
+	  vec[1].iov_len = sizeof (ypbr);
+
+	  if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
 	    {
-	      /* We have a binding file and could save a RPC call */
-	      vec[0].iov_base = &port;
-	      vec[0].iov_len = sizeof (port);
-	      vec[1].iov_base = &ypbr;
-	      vec[1].iov_len = sizeof (ypbr);
-
-	      if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
-		{
-		  ysd->dom_server_addr.sin_family = AF_INET;
-		  memcpy (&ysd->dom_server_addr.sin_port,
-			  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
-			  sizeof (ysd->dom_server_addr.sin_port));
-		  memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
-			  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
-			  sizeof (ysd->dom_server_addr.sin_addr.s_addr));
-		  ysd->dom_vers = YPVERS;
-		  strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
-		  ysd->dom_domain[YPMAXDOMAIN] = '\0';
-		}
-	      close (fd);
+	      ysd->dom_server_addr.sin_family = AF_INET;
+	      memcpy (&ysd->dom_server_addr.sin_port,
+		      ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+		      sizeof (ysd->dom_server_addr.sin_port));
+	      memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
+		      ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+		      sizeof (ysd->dom_server_addr.sin_addr.s_addr));
+	      strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
+	      ysd->dom_domain[YPMAXDOMAIN] = '\0';
+
+	      ysd->dom_socket = RPC_ANYSOCK;
+	      ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
+						YPVERS, UDPTIMEOUT,
+						&ysd->dom_socket);
+
+	      if (ysd->dom_client != NULL)
+		/* If the program exits, close the socket */
+		if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
+		  perror ("fcntl: F_SETFD");
 	    }
+	  close (fd);
 	}
+    }
 #endif /* USE_BINDINGDIR */
 
-      if (ysd->dom_vers == -1)
+  if (ysd->dom_client == NULL)
+    {
+      memset (&clnt_saddr, '\0', sizeof clnt_saddr);
+      clnt_saddr.sin_family = AF_INET;
+      clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+      clnt_sock = RPC_ANYSOCK;
+      client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
+			       &clnt_sock, 0, 0);
+      if (client == NULL)
 	{
-	  if (ysd->dom_client)
-	    {
-	      clnt_destroy (ysd->dom_client);
-	      ysd->dom_client = NULL;
-	      ysd->dom_socket = -1;
-	    }
-          memset (&clnt_saddr, '\0', sizeof clnt_saddr);
-          clnt_saddr.sin_family = AF_INET;
-          clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-          clnt_sock = RPC_ANYSOCK;
-          client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
-                                   &clnt_sock, 0, 0);
-          if (client == NULL)
-            {
-              if (is_new)
-                free (ysd);
-              return YPERR_YPBIND;
-            }
-          /*
-          ** Check the port number -- should be < IPPORT_RESERVED.
-          ** If not, it's possible someone has registered a bogus
-          ** ypbind with the portmapper and is trying to trick us.
-          */
-          if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
-            {
-              clnt_destroy (client);
-              if (is_new)
-                free (ysd);
-              return YPERR_YPBIND;
-            }
-
-          if (clnt_call (client, YPBINDPROC_DOMAIN,
-                         (xdrproc_t) xdr_domainname, (caddr_t) &domain,
-                         (xdrproc_t) xdr_ypbind_resp,
-                         (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
-            {
-              clnt_destroy (client);
-              if (is_new)
-                free (ysd);
-              return YPERR_YPBIND;
-            }
-
-          clnt_destroy (client);
-
-          if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
-            {
-	      fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
-		       ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
-	      if (is_new)
-		free (ysd);
-	      return YPERR_DOMAIN;
-	    }
-          memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
-          ysd->dom_server_addr.sin_family = AF_INET;
-          memcpy (&ysd->dom_server_addr.sin_port,
-                  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
-                  sizeof (ysd->dom_server_addr.sin_port));
-          memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
-                  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
-                  sizeof (ysd->dom_server_addr.sin_addr.s_addr));
-          ysd->dom_vers = YPVERS;
-          strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
-	  ysd->dom_domain[YPMAXDOMAIN] = '\0';
-        }
+	  if (is_new)
+	    free (ysd);
+	  return YPERR_YPBIND;
+	}
+      /* Check the port number -- should be < IPPORT_RESERVED.
+	 If not, it's possible someone has registered a bogus
+	 ypbind with the portmapper and is trying to trick us. */
+      if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
+	{
+	  clnt_destroy (client);
+	  if (is_new)
+	    free (ysd);
+	  return YPERR_YPBIND;
+	}
+
+      if (clnt_call (client, YPBINDPROC_DOMAIN,
+		     (xdrproc_t) xdr_domainname, (caddr_t) &domain,
+		     (xdrproc_t) xdr_ypbind_resp,
+		     (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
+	{
+	  clnt_destroy (client);
+	  if (is_new)
+	    free (ysd);
+	  return YPERR_YPBIND;
+	}
+
+      clnt_destroy (client);
+
+      if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
+	{
+	  fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
+		   ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
+	  if (is_new)
+	    free (ysd);
+	  return YPERR_DOMAIN;
+	}
+      memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
+      ysd->dom_server_addr.sin_family = AF_INET;
+      memcpy (&ysd->dom_server_addr.sin_port,
+	      ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+	      sizeof (ysd->dom_server_addr.sin_port));
+      memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
+	      ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+	      sizeof (ysd->dom_server_addr.sin_addr.s_addr));
+      strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
+      ysd->dom_domain[YPMAXDOMAIN] = '\0';
 
       ysd->dom_socket = RPC_ANYSOCK;
       ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
                                         UDPTIMEOUT, &ysd->dom_socket);
-      if (ysd->dom_client == NULL)
-        ysd->dom_vers = -1;
 
+      if (ysd->dom_client != NULL)
+	/* If the program exits, close the socket */
+	if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
+	  perror ("fcntl: F_SETFD");
     }
-  while (ysd->dom_client == NULL);
 
-  /* If the program exists, close the socket */
-  if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
-    perror ("fcntl: F_SETFD");
+  if (ysd->dom_client == NULL)
+    {
+      if (is_new)
+	free (ysd);
+      return YPERR_YPSERV;
+    }
 
   if (is_new && ypdb != NULL)
     {
@@ -229,7 +217,60 @@ __yp_unbind (dom_binding *ydb)
 {
   clnt_destroy (ydb->dom_client);
   ydb->dom_client = NULL;
-  ydb->dom_socket = -1;
+}
+
+int
+yp_bind (const char *indomain)
+{
+  int status;
+
+  __libc_lock_lock (ypbindlist_lock);
+
+  status = __yp_bind (indomain, &__ypbindlist);
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return status;
+}
+
+static void
+yp_unbind_locked (const char *indomain)
+{
+  dom_binding *ydbptr, *ydbptr2;
+
+  ydbptr2 = NULL;
+  ydbptr = __ypbindlist;
+
+  while (ydbptr != NULL)
+    {
+      if (strcmp (ydbptr->dom_domain, indomain) == 0)
+	{
+	  dom_binding *work;
+
+	  work = ydbptr;
+	  if (ydbptr2 == NULL)
+	    __ypbindlist = __ypbindlist->dom_pnext;
+	  else
+	    ydbptr2 = ydbptr->dom_pnext;
+	  __yp_unbind (work);
+	  free (work);
+	  break;
+	}
+      ydbptr2 = ydbptr;
+      ydbptr = ydbptr->dom_pnext;
+    }
+}
+
+void
+yp_unbind (const char *indomain)
+{
+  __libc_lock_lock (ypbindlist_lock);
+
+  yp_unbind_locked (indomain);
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return;
 }
 
 static int
@@ -278,14 +319,26 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
 
       if (result != RPC_SUCCESS)
 	{
-	  clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
-	  ydb->dom_vers = -1;
-	  if (!use_ypbindlist)
+	  /* Don't print the error message on the first try. It
+	     could be that we use cached data which is now invalid. */
+	  if (try != 0)
+	    clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
+
+	  if (use_ypbindlist)
+	    {
+	      /* We use ypbindlist, and the old cached data is
+		 invalid. unbind now and create a new binding */
+	      yp_unbind_locked (domain);
+	      __libc_lock_unlock (ypbindlist_lock);
+	      use_ypbindlist = FALSE;
+	    }
+	  else
 	    {
 	      __yp_unbind (ydb);
 	      free (ydb);
-	      ydb = NULL;
 	    }
+
+	  ydb = NULL;
 	  status = YPERR_RPC;
 	}
       else
@@ -311,52 +364,6 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
   return status;
 }
 
-int
-yp_bind (const char *indomain)
-{
-  int status;
-
-  __libc_lock_lock (ypbindlist_lock);
-
-  status = __yp_bind (indomain, &__ypbindlist);
-
-  __libc_lock_unlock (ypbindlist_lock);
-
-  return status;
-}
-
-void
-yp_unbind (const char *indomain)
-{
-  dom_binding *ydbptr, *ydbptr2;
-
-  __libc_lock_lock (ypbindlist_lock);
-
-  ydbptr2 = NULL;
-  ydbptr = __ypbindlist;
-  while (ydbptr != NULL)
-    {
-      if (strcmp (ydbptr->dom_domain, indomain) == 0)
-	{
-	  dom_binding *work;
-
-	  work = ydbptr;
-	  if (ydbptr2 == NULL)
-	    __ypbindlist = __ypbindlist->dom_pnext;
-	  else
-	    ydbptr2 = ydbptr->dom_pnext;
-	  __yp_unbind (work);
-	  free (work);
-	  break;
-	}
-      ydbptr2 = ydbptr;
-      ydbptr = ydbptr->dom_pnext;
-    }
-
-  __libc_lock_unlock (ypbindlist_lock);
-
-  return;
-}
 
 __libc_lock_define_initialized (static, domainname_lock)
 
@@ -374,7 +381,7 @@ yp_get_default_domain (char **outdomain)
 	result = YPERR_NODOM;
       else if (strcmp (__ypdomainname, "(none)") == 0)
 	{
-	  /* If domainname is not set, some Systems will return "(none)" */
+	  /* If domainname is not set, some systems will return "(none)" */
 	  __ypdomainname[0] = '\0';
 	  result = YPERR_NODOM;
 	}
@@ -629,6 +636,10 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp)
 	    int keylen = resp.ypresp_all_u.val.key.keydat_len;
 	    int vallen = resp.ypresp_all_u.val.val.valdat_len;
 
+	    /* We are not allowed to modify the key and val data.
+	       But we are allowed to add data behind the buffer,
+	       if we don't modify the length. So add an extra NUL
+	       character to avoid trouble with broken code. */
 	    *objp = YP_TRUE;
 	    memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
 	    key[keylen] = '\0';
@@ -640,14 +651,13 @@ __xdr_ypresp_all (XDR *xdrs, u_long *objp)
 	      return TRUE;
 	  }
 	  break;
-	case YP_NOMORE:
-	  *objp = YP_NOMORE;
-	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
-	  return TRUE;
-	  break;
 	default:
 	  *objp = resp.ypresp_all_u.val.stat;
 	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  /* Sun says we don't need to make this call, but must return
+	     immediatly. Since Solaris makes this call, we will call
+	     the callback function, too. */
+	  (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data);
 	  return TRUE;
 	}
     }
diff --git a/rt/Makefile b/rt/Makefile
index b102cc834e..2044eb4bf6 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -35,7 +35,7 @@ include ../Makeconfig
 
 ifeq ($(have-thread-library),yes)
 
-tests := tst-aio
+tests := tst-aio tst-aio64
 
 extra-libs := librt
 extra-libs-others := $(extra-libs)
@@ -51,6 +51,8 @@ $(objpfx)librt.so: $(common-objpfx)libc.so $(shared-thread-library)
 
 ifeq (yes,$(build-shared))
 $(objpfx)tst-aio: $(objpfx)librt.so $(shared-thread-library)
+$(objpfx)tst-aio64: $(objpfx)librt.so $(shared-thread-library)
 else
 $(objpfx)tst-aio: $(objpfx)librt.a $(static-thread-library)
-endif
\ No newline at end of file
+$(objpfx)tst-aio64: $(objpfx)librt.a $(static-thread-library)
+endif
diff --git a/rt/aio.h b/rt/aio.h
index 0190ce9cd5..205d63afe7 100644
--- a/rt/aio.h
+++ b/rt/aio.h
@@ -57,7 +57,8 @@ struct aiocb
   char __unused[32];
 };
 
-/* The same for the 64bit offsets.  */
+/* The same for the 64bit offsets.  Please note that the members aio_fildes
+   to __return_value have to be the same in aiocb and aiocb64.  */
 #ifdef __USE_LARGEFILE64
 struct aiocb64
 {
@@ -69,6 +70,7 @@ struct aiocb64
   struct sigevent aio_sigevent;	/* Signal number and value.  */
 
   /* Internal members.  */
+  struct aiocb *__next_prio;
   int __abs_prio;
   int __policy;
   int __error_code;
diff --git a/rt/tst-aio64.c b/rt/tst-aio64.c
new file mode 100644
index 0000000000..60db0dd1aa
--- /dev/null
+++ b/rt/tst-aio64.c
@@ -0,0 +1,196 @@
+/* Tests for 64bit AIO in librt.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define _LARGEFILE_SOURCE 1
+#include <aio.h>
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+/* Prototype for our test function.  */
+extern void do_prepare (int argc, char *argv[]);
+extern int do_test (int argc, char *argv[]);
+
+/* We have a preparation function.  */
+#define PREPARE do_prepare
+
+/* We might need a bit longer timeout.  */
+#define TIMEOUT 20 /* sec */
+
+/* This defines the `main' function and some more.  */
+#include <test-skeleton.c>
+
+
+/* These are for the temporary file we generate.  */
+char *name;
+int fd;
+
+void
+do_prepare (int argc, char *argv[])
+{
+  char name_len;
+
+  name_len = strlen (test_dir);
+  name = malloc (name_len + sizeof ("/aioXXXXXX"));
+  mempcpy (mempcpy (name, test_dir, name_len),
+	   "/aioXXXXXX", sizeof ("/aioXXXXXX"));
+  add_temp_file (name);
+
+  /* Open our test file.   */
+  fd = mkstemp (name);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
+}
+
+
+int
+test_file (const void *buf, size_t size, int fd, const char *msg)
+{
+  struct stat st;
+  char tmp[size];
+
+  errno = 0;
+  if (fstat (fd, &st) < 0)
+    {
+      error (0, errno, "%s: failed stat", msg);
+      return 1;
+    }
+
+  if (st.st_size != size)
+    {
+      error (0, errno, "%s: wrong size: %lu, should be %lu",
+	     msg, (unsigned long int) st.st_size, (unsigned long int) size);
+      return 1;
+    }
+
+  if (pread (fd, tmp, size, 0) != size)
+    {
+      error (0, errno, "%s: failed stat", msg);
+      return 1;
+    }
+
+  if (memcmp (buf, tmp, size) != 0)
+    {
+      error (0, errno, "%s: failed comparison", msg);
+      return 1;
+    }
+
+  printf ("%s test ok\n", msg);
+
+  return 0;
+}
+
+
+void
+do_wait (struct aiocb64 **cbp, size_t nent)
+{
+  int go_on;
+  do
+    {
+      size_t cnt;
+
+      aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL);
+      go_on = 0;
+      for (cnt = 0; cnt < nent; ++cnt)
+	if (cbp[cnt] != NULL && aio_error64 (cbp[cnt]) == EINPROGRESS)
+	  go_on = 1;
+	else
+	  cbp[cnt] = NULL;
+    }
+  while (go_on);
+}
+
+
+int
+do_test (int argc, char *argv[])
+{
+  struct aiocb64 cbs[10];
+  struct aiocb64 *cbp[10];
+  char buf[1000];
+  size_t cnt;
+  int result = 0;
+
+  /* Preparation.  */
+  for (cnt = 0; cnt < 10; ++cnt)
+    {
+      cbs[cnt].aio_fildes = fd;
+      cbs[cnt].aio_reqprio = 0;
+      cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100);
+      cbs[cnt].aio_nbytes = 100;
+      cbs[cnt].aio_offset = cnt * 100;
+      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;
+
+      cbp[cnt] = &cbs[cnt];
+    }
+
+  /* First a simple test.  */
+  for (cnt = 10; cnt > 0; )
+    aio_write64 (cbp[--cnt]);
+  /* Wait 'til the results are there.  */
+  do_wait (cbp, 10);
+  /* Test this.  */
+  result |= test_file (buf, sizeof (buf), fd, "aio_write");
+
+  /* Read now as we've written it.  */
+  memset (buf, '\0', sizeof (buf));
+  /* Issue the commands.  */
+  for (cnt = 10; cnt > 0; )
+    {
+      --cnt;
+      cbp[cnt] = &cbs[cnt];
+      aio_read64 (cbp[cnt]);
+    }
+  /* Wait 'til the results are there.  */
+  do_wait (cbp, 10);
+  /* Test this.  */
+  for (cnt = 0; cnt < 1000; ++cnt)
+    if (buf[cnt] != '0' + (cnt / 100))
+      {
+	result = 1;
+	error (0, 0, "comparison failed for aio_read test");
+	break;
+      }
+
+  if (cnt == 1000)
+    puts ("aio_read test ok");
+
+  /* Remove the test file contents.  */
+  if (ftruncate64 (fd, 0) < 0)
+    {
+      error (0, errno, "ftruncate failed\n");
+      result = 1;
+    }
+
+  /* Test lio_listio.  */
+  for (cnt = 0; cnt < 10; ++cnt)
+    {
+      cbs[cnt].aio_lio_opcode = LIO_WRITE;
+      cbp[cnt] = &cbs[cnt];
+    }
+  /* Issue the command.  */
+  lio_listio64 (LIO_WAIT, cbp, 10, NULL);
+  /* ...and immediately test it since we started it in wait mode.  */
+  result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");
+
+  return result;
+}
diff --git a/stdlib/longlong.h b/stdlib/longlong.h
index f76f4799c7..a2e56c4c67 100644
--- a/stdlib/longlong.h
+++ b/stdlib/longlong.h
@@ -1185,8 +1185,8 @@ UDItype __umulsidi3 (USItype, USItype);
 #if (defined (__sparc_v9__) || (defined (__sparc__) && defined (__arch64__)) \
     || defined (__sparcv9)) && W_TYPE_SIZE == 64
 #define add_ssaaaa(sh, sl, ah, al, bh, bl)				\
-  __asm__ ("addcc %4,%5,%1
-  	    add %2,%3,%0
+  __asm__ ("addcc %r4,%5,%1
+  	    add %r2,%3,%0
   	    bcs,a,pn %%xcc, 1f
   	    add %0, 1, %0
   	    1:"								\
@@ -1199,8 +1199,8 @@ UDItype __umulsidi3 (USItype, USItype);
 	   __CLOBBER_CC)
 
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) 				\
-  __asm__ ("subcc %4,%5,%1
-  	    sub %2,%3,%0
+  __asm__ ("subcc %r4,%5,%1
+  	    sub %r2,%3,%0
   	    bcs,a,pn %%xcc, 1f
   	    sub %0, 1, %0
   	    1:"								\
diff --git a/string/bits/string2.h b/string/bits/string2.h
index 4d1baa2062..336aafef9a 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -118,7 +118,7 @@ __STRING2_COPY_TYPE (8);
      __uint8_t __c = (__uint8_t) (c);					      \
 									      \
      /* This `switch' statement will be removed at compile-time.  */	      \
-     switch ((unsigned int) n)						      \
+     switch ((unsigned int) (n))					      \
        {								      \
        case 15:								      \
 	 __u->__ui = __c * 0x01010101;					      \
@@ -1078,8 +1078,10 @@ __strtok_r_1c (char *__s, char __sep, char **__nextp)
   __extension__								      \
   ({ char __r0, __r1, __r2;						      \
      (__builtin_constant_p (reject) && __string2_1bptr_p (reject)	      \
-      && (__r0 = ((__const char *) (reject))[0], __r0 != '\0')		      \
-      ? ((__r1 = ((__const char *) (reject))[1], __r1 == '\0')		      \
+      && (__r0 = ((__const char *) (reject))[0],			      \
+	  ((__const char *) (reject))[0] != '\0')			      \
+      ? ((__r1 = ((__const char *) (reject))[1],			      \
+	 ((__const char *) (reject))[1] == '\0')			      \
 	 ? __strsep_1c (s, __r0)					      \
 	 : ((__r2 = ((__const char *) (reject))[2], __r2 == '\0')	      \
 	    ? __strsep_2c (s, __r0, __r1)				      \
diff --git a/string/tester.c b/string/tester.c
index 4fed10e4b4..d9043e046f 100644
--- a/string/tester.c
+++ b/string/tester.c
@@ -807,6 +807,7 @@ test_strtok_r (void)
 void
 test_strsep (void)
 {
+  char *ptr;
   it = "strsep";
   cp = strcpy(one, "first, second, third");
   equal(strsep(&cp, ", "), "first", 1);	/* Basic test. */
@@ -901,6 +902,32 @@ test_strsep (void)
   equal(strsep(&cp, "xy,"), "", 71);
   check(strsep(&cp, "x,y") == NULL, 72);
   check(strsep(&cp, ",xy") == NULL, 73);	/* Persistence. */
+
+  cp = strcpy(one, "ABC");
+  one[4] = ':';
+  equal(strsep(&cp, "C"), "AB", 74);	/* Access beyond NUL.  */
+  ptr = strsep(&cp, ":");
+  equal(ptr, "", 75);
+  check(ptr == one + 3, 76);
+  check(cp == NULL, 77);
+
+  cp = strcpy(one, "ABC");
+  one[4] = ':';
+  equal(strsep(&cp, "CD"), "AB", 78);	/* Access beyond NUL.  */
+  ptr = strsep(&cp, ":.");
+  equal(ptr, "", 79);
+  check(ptr == one + 3, 80);
+
+  cp = strcpy(one, "ABC");		/* No token in string.  */
+  equal(strsep(&cp, ","), "ABC", 81);
+  check(cp == NULL, 82);
+
+  *one = '\0';				/* Empty string. */
+  cp = one;
+  ptr = strsep(&cp, ",");
+  equal(ptr, "", 83);
+  check(ptr == one, 84);
+  check(cp == NULL, 85);
 }
 
 void
diff --git a/sysdeps/alpha/fpu/bits/mathdef.h b/sysdeps/alpha/fpu/bits/mathdef.h
index f5d5de8b12..30f93dda1c 100644
--- a/sysdeps/alpha/fpu/bits/mathdef.h
+++ b/sysdeps/alpha/fpu/bits/mathdef.h
@@ -23,7 +23,9 @@
 /* FIXME! This file describes properties of the compiler, not the machine;
    it should not be part of libc!  */
 
-#if defined __USE_ISOC99 && defined _MATH_H
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 # ifdef __GNUC__
 #  if __STDC__ == 1
 
diff --git a/sysdeps/generic/bits/mathdef.h b/sysdeps/generic/bits/mathdef.h
index d306e54366..0c30b01f52 100644
--- a/sysdeps/generic/bits/mathdef.h
+++ b/sysdeps/generic/bits/mathdef.h
@@ -20,7 +20,9 @@
 # error "Never use <bits/mathdef.h> directly; include <math.h> instead"
 #endif
 
-#if defined  __USE_ISOC99 && defined _MATH_H
+#if defined  __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 /* Normally, there is no long double type and the `float' and `double'
    expressions are evaluated as `double'.  */
 typedef double float_t;		/* `float' expressions are evaluated as
diff --git a/sysdeps/generic/strsep.c b/sysdeps/generic/strsep.c
index 7ca44f3c3a..004d8d8ac2 100644
--- a/sysdeps/generic/strsep.c
+++ b/sysdeps/generic/strsep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1993, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -43,6 +43,8 @@ __strsep (char **stringp, const char *delim)
 	{
 	  if (*begin == ch)
 	    end = begin;
+	  else if (*begin == '\0')
+	    end = NULL;
 	  else
 	    end = strchr (begin + 1, ch);
 	}
diff --git a/sysdeps/i386/fpu/bits/mathdef.h b/sysdeps/i386/fpu/bits/mathdef.h
index ba5129895d..9436877a77 100644
--- a/sysdeps/i386/fpu/bits/mathdef.h
+++ b/sysdeps/i386/fpu/bits/mathdef.h
@@ -20,7 +20,9 @@
 # error "Never use <bits/mathdef.h> directly; include <math.h> instead"
 #endif
 
-#if defined __USE_ISOC99 && defined _MATH_H
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 /* The ix87 FPUs evaluate all values in the 80 bit floating-point format
    which is also available for the user as `long double'.  Therefore we
    define:  */
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 443117da63..195bcca168 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -488,10 +488,14 @@ Test "Real part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383
 ildouble: 2
 ldouble: 2
 Test "Imaginary part of: ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i":
+float: 1
+ifloat: 1
 ildouble: 23
 ldouble: 23
 Test "Real part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
 Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
 double: 0.5
 idouble: 0.5
 Test "Real part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i":
@@ -636,6 +640,9 @@ idouble: 1
 Test "j0 (8.0) == 0.17165080713755390609":
 float: 1
 ifloat: 1
+Test "j0 (10.0) == -0.24593576445134833520":
+double: 2
+idouble: 2
 
 # j1
 Test "j1 (10.0) == 0.043472746168861436670":
@@ -654,6 +661,8 @@ ifloat: 1
 Test "jn (0, 10.0) == -0.24593576445134833520":
 float: 1
 ifloat: 1
+double: 2
+idouble: 2
 Test "jn (0, 2.0) == 0.22389077914123566805":
 float: 1
 ifloat: 1
@@ -673,33 +682,46 @@ idouble: 1
 Test "jn (1, 8.0) == 0.23463634685391462438":
 float: 1
 ifloat: 1
+Test "jn (10, -1.0) == 0.26306151236874532070e-9":
+float: 1
+ifloat: 1
 Test "jn (10, 0.1) == 0.26905328954342155795e-19":
 double: 4
 float: 2
 idouble: 4
 ifloat: 2
 Test "jn (10, 0.7) == 0.75175911502153953928e-11":
-double: 3
+double: 4
 float: 1
-idouble: 3
+idouble: 4
 ifloat: 1
-Test "jn (10, 2.0) == 0.25153862827167367096e-6":
+Test "jn (10, 1.0) == 0.26306151236874532070e-9":
 float: 1
 ifloat: 1
-double: 1
-idouble: 1
-Test "jn (10, 10.0) == 0.20748610663335885770":
+Test "jn (10, 2.0) == 0.25153862827167367096e-6":
 float: 1
 ifloat: 1
+double: 2
+idouble: 2
+Test "jn (10, 10.0) == 0.20748610663335885770":
+float: 2
+ifloat: 2
+double: 4
+idouble: 4
 Test "jn (3, 0.1) == 0.000020820315754756261429":
 double: 1
 idouble: 1
 Test "jn (3, 0.7) == 0.0069296548267508408077":
 double: 2
 idouble: 2
+Test "jn (3, 2.0) == 0.12894324947440205110":
+double: 1
+idouble: 1
 Test "jn (3, 10.0) == 0.058379379305186812343":
 float: 1
 ifloat: 1
+double: 3
+idouble: 3
 
 # lgamma
 Test "lgamma (-0.5) == log(2*sqrt(pi))":
@@ -847,6 +869,8 @@ float: 1
 idouble: 1
 ifloat: 1
 Test "y0 (0.7) == -0.19066492933739506743":
+float: 1
+ifloat: 1
 double: 2
 idouble: 2
 Test "y0 (1.0) == 0.088256964215676957983":
@@ -857,6 +881,8 @@ ifloat: 1
 Test "y0 (1.5) == 0.38244892379775884396":
 float: 1
 ifloat: 1
+double: 1
+idouble: 1
 Test "y0 (2.0) == 0.51037567264974511960":
 double: 1
 idouble: 1
@@ -891,9 +917,9 @@ idouble: 3
 ifloat: 2
 Test "y1 (2.0) == -0.10703243154093754689":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "y1 (8.0) == -0.15806046173124749426":
 float: 2
 ifloat: 2
@@ -905,6 +931,8 @@ float: 1
 idouble: 1
 ifloat: 1
 Test "yn (0, 0.7) == -0.19066492933739506743":
+float: 1
+ifloat: 1
 double: 2
 idouble: 2
 Test "yn (0, 1.0) == 0.088256964215676957983":
@@ -915,6 +943,8 @@ ifloat: 1
 Test "yn (0, 1.5) == 0.38244892379775884396":
 float: 1
 ifloat: 1
+double: 1
+idouble: 1
 Test "yn (0, 2.0) == 0.51037567264974511960":
 double: 1
 idouble: 1
@@ -947,9 +977,9 @@ idouble: 3
 ifloat: 2
 Test "yn (1, 2.0) == -0.10703243154093754689":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 Test "yn (1, 8.0) == -0.15806046173124749426":
 float: 2
 ifloat: 2
@@ -974,8 +1004,8 @@ ifloat: 1
 Test "yn (10, 2.0) == -129184.54220803928264":
 float: 1
 ifloat: 1
-double: 1
-idouble: 1
+double: 2
+idouble: 2
 Test "yn (3, 0.1) == -5099.3323786129048894":
 double: 1
 float: 1
@@ -984,6 +1014,9 @@ ifloat: 1
 Test "yn (3, 0.7) == -15.819479052819633505":
 double: 2
 idouble: 2
+Test "yn (3, 2.0) == -1.1277837768404277861":
+double: 1
+idouble: 1
 Test "yn (3, 10.0) == -0.25136265718383732978":
 double: 1
 float: 1
@@ -1263,6 +1296,8 @@ ildouble: 286
 ldouble: 286
 
 Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
 double: 1
 idouble: 1
 ildouble: 3074
@@ -1313,8 +1348,8 @@ ldouble: 560
 Function: "j0":
 float: 1
 ifloat: 1
-double: 1
-idouble: 1
+double: 2
+idouble: 2
 
 Function: "j1":
 double: 1
diff --git a/sysdeps/m68k/fpu/bits/mathdef.h b/sysdeps/m68k/fpu/bits/mathdef.h
index 2f650ec8b5..c80dad3fe1 100644
--- a/sysdeps/m68k/fpu/bits/mathdef.h
+++ b/sysdeps/m68k/fpu/bits/mathdef.h
@@ -20,7 +20,9 @@
 # error "Never use <bits/mathdef.h> directly; include <math.h> instead"
 #endif
 
-#if defined __USE_ISOC99 && defined _MATH_H
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 /* The m68k FPUs evaluate all values in the 96 bit floating-point format
    which is also available for the user as `long double'.  Therefore we
    define: */
diff --git a/sysdeps/powerpc/fpu/bits/mathdef.h b/sysdeps/powerpc/fpu/bits/mathdef.h
index 71378c8458..577a596843 100644
--- a/sysdeps/powerpc/fpu/bits/mathdef.h
+++ b/sysdeps/powerpc/fpu/bits/mathdef.h
@@ -27,7 +27,9 @@
    FIXME! This file does not deal with the -fshort-double option of
    gcc! */
 
-#if defined __USE_ISOC99 && defined _MATH_H
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 # ifdef __GNUC__
 #  if __STDC__ == 1
 
diff --git a/sysdeps/sparc/fpu/bits/mathdef.h b/sysdeps/sparc/fpu/bits/mathdef.h
index c58167ce83..9477790654 100644
--- a/sysdeps/sparc/fpu/bits/mathdef.h
+++ b/sysdeps/sparc/fpu/bits/mathdef.h
@@ -25,7 +25,9 @@
 /* FIXME! This file describes properties of the compiler, not the machine;
    it should not be part of libc!  */
 
-#if defined __USE_ISOC99 && defined _MATH_H
+#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF
+# define _MATH_H_MATHDEF	1
+
 # ifdef __GNUC__
 #  if __STDC__ == 1
 
diff --git a/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c
deleted file mode 100644
index 9feab0e6b8..0000000000
--- a/sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* getrlimit64 is the same as getrlimit. */
diff --git a/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c
deleted file mode 100644
index 8edcff0086..0000000000
--- a/sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* setrlimit64 is the same as setrlimit. */
diff --git a/sysdeps/unix/sysv/linux/bits/resource.h b/sysdeps/unix/sysv/linux/bits/resource.h
index fcff605892..6a3d86ce18 100644
--- a/sysdeps/unix/sysv/linux/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/bits/resource.h
@@ -106,13 +106,13 @@ enum __rlimit_resource
 
 /* Value to indicate that there is no limit.  */
 #ifndef __USE_FILE_OFFSET64
-# define RLIM_INFINITY ((unsigned long int)(~0UL))
+# define RLIM_INFINITY ((long int)(~0UL >> 1))
 #else
-# define RLIM_INFINITY 0xffffffffffffffffuLL
+# define RLIM_INFINITY 0x7fffffffffffffffLL
 #endif
 
 #ifdef __USE_LARGEFILE64
-# define RLIM64_INFINITY 0xffffffffffffffffuLL
+# define RLIM64_INFINITY 0x7fffffffffffffffLL
 #endif
 
 /* We can represent all limits.  */
diff --git a/sysdeps/unix/sysv/linux/i386/bits/resource.h b/sysdeps/unix/sysv/linux/i386/bits/resource.h
new file mode 100644
index 0000000000..fcff605892
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/bits/resource.h
@@ -0,0 +1,227 @@
+/* Bit values & structures for resource limits.  Linux version.
+   Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _SYS_RESOURCE_H
+# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
+#endif
+
+#include <asm/resource.h>
+#include <bits/types.h>
+
+/* Transmute defines to enumerations.  The macro re-definitions are
+   necessary because some programs want to test for operating system
+   features with #ifdef RUSAGE_SELF.  In ISO C the reflexive
+   definition is a no-op.  */
+
+/* Kinds of resource limit.  */
+enum __rlimit_resource
+{
+  /* Per-process CPU limit, in seconds.  */
+  _RLIMIT_CPU = RLIMIT_CPU,
+#undef RLIMIT_CPU
+  RLIMIT_CPU = _RLIMIT_CPU,
+#define RLIMIT_CPU RLIMIT_CPU
+
+  /* Largest file that can be created, in bytes.  */
+  _RLIMIT_FSIZE = RLIMIT_FSIZE,
+#undef RLIMIT_FSIZE
+  RLIMIT_FSIZE = _RLIMIT_FSIZE,
+#define	RLIMIT_FSIZE RLIMIT_FSIZE
+
+  /* Maximum size of data segment, in bytes.  */
+  _RLIMIT_DATA = RLIMIT_DATA,
+#undef RLIMIT_DATA
+  RLIMIT_DATA = _RLIMIT_DATA,
+#define	RLIMIT_DATA RLIMIT_DATA
+
+  /* Maximum size of stack segment, in bytes.  */
+  _RLIMIT_STACK = RLIMIT_STACK,
+#undef RLIMIT_STACK
+  RLIMIT_STACK = _RLIMIT_STACK,
+#define	RLIMIT_STACK RLIMIT_STACK
+
+  /* Largest core file that can be created, in bytes.  */
+  _RLIMIT_CORE = RLIMIT_CORE,
+#undef RLIMIT_CORE
+  RLIMIT_CORE = _RLIMIT_CORE,
+#define	RLIMIT_CORE RLIMIT_CORE
+
+  /* Largest resident set size, in bytes.
+     This affects swapping; processes that are exceeding their
+     resident set size will be more likely to have physical memory
+     taken from them.  */
+  _RLIMIT_RSS = RLIMIT_RSS,
+#undef RLIMIT_RSS
+  RLIMIT_RSS = _RLIMIT_RSS,
+#define	RLIMIT_RSS RLIMIT_RSS
+
+  /* Number of open files.  */
+  _RLIMIT_NOFILE = RLIMIT_NOFILE,
+#undef RLIMIT_NOFILE
+  RLIMIT_NOFILE = _RLIMIT_NOFILE,
+  RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
+#define RLIMIT_NOFILE RLIMIT_NOFILE
+#define RLIMIT_OFILE RLIMIT_OFILE
+
+  /* Address space limit (?) */
+  _RLIMIT_AS = RLIMIT_AS,
+#undef RLIMIT_AS
+  RLIMIT_AS = _RLIMIT_AS,
+#define RLIMIT_AS RLIMIT_AS
+
+  /* Number of processes.  */
+  _RLIMIT_NPROC = RLIMIT_NPROC,
+#undef RLIMIT_NPROC
+  RLIMIT_NPROC = _RLIMIT_NPROC,
+#define RLIMIT_NPROC RLIMIT_NPROC
+
+  /* Locked-in-memory address space.  */
+  _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK,
+#undef RLIMIT_MEMLOCK
+  RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK,
+#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
+
+  RLIMIT_NLIMITS = RLIM_NLIMITS,
+#undef RLIM_NLIMITS
+  RLIM_NLIMITS = RLIMIT_NLIMITS
+#define RLIMIT_NLIMITS RLIMIT_NLIMITS
+#define RLIM_NLIMITS RLIM_NLIMITS
+};
+
+/* Value to indicate that there is no limit.  */
+#ifndef __USE_FILE_OFFSET64
+# define RLIM_INFINITY ((unsigned long int)(~0UL))
+#else
+# define RLIM_INFINITY 0xffffffffffffffffuLL
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define RLIM64_INFINITY 0xffffffffffffffffuLL
+#endif
+
+/* We can represent all limits.  */
+#define RLIM_SAVED_MAX	RLIM_INFINITY
+#define RLIM_SAVED_CUR	RLIM_INFINITY
+
+
+/* Type for resource quantity measurement.  */
+#ifndef __USE_FILE_OFFSET64
+typedef __rlim_t rlim_t;
+#else
+typedef __rlim64_t rlim_t;
+#endif
+#ifdef __USE_LARGEFILE64
+typedef __rlim64_t rlim64_t;
+#endif
+
+struct rlimit
+  {
+    /* The current (soft) limit.  */
+    rlim_t rlim_cur;
+    /* The hard limit.  */
+    rlim_t rlim_max;
+  };
+
+#ifdef __USE_LARGEFILE64
+struct rlimit64
+  {
+    /* The current (soft) limit.  */
+    rlim64_t rlim_cur;
+    /* The hard limit.  */
+    rlim64_t rlim_max;
+ };
+#endif
+
+/* Whose usage statistics do you want?  */
+enum __rusage_who
+{
+  /* The calling process.  */
+  RUSAGE_SELF = 0,
+#define RUSAGE_SELF RUSAGE_SELF
+
+  /* All of its terminated child processes.  */
+  RUSAGE_CHILDREN = -1,
+#define RUSAGE_CHILDREN RUSAGE_CHILDREN
+
+  /* Both.  */
+  RUSAGE_BOTH = -2
+#define RUSAGE_BOTH RUSAGE_BOTH
+};
+
+#define __need_timeval
+#include <bits/time.h>		/* For `struct timeval'.  */
+
+/* Structure which says how much of each resource has been used.  */
+struct rusage
+  {
+    /* Total amount of user time used.  */
+    struct timeval ru_utime;
+    /* Total amount of system time used.  */
+    struct timeval ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    long int ru_maxrss;
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    long int ru_ixrss;
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    long int ru_idrss;
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    long int ru_isrss;
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    long int ru_minflt;
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    long int ru_majflt;
+    /* Number of times a process was swapped out of physical memory.  */
+    long int ru_nswap;
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    long int ru_inblock;
+    /* Number of output operations via the file system.  */
+    long int ru_oublock;
+    /* Number of IPC messages sent.  */
+    long int ru_msgsnd;
+    /* Number of IPC messages received.  */
+    long int ru_msgrcv;
+    /* Number of signals delivered.  */
+    long int ru_nsignals;
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    long int ru_nvcsw;
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    long int ru_nivcsw;
+  };
+
+/* Priority limits.  */
+#define PRIO_MIN	-20	/* Minimum priority a process can have.  */
+#define PRIO_MAX	20	/* Maximum priority a process can have.  */
+
+/* The type of the WHICH argument to `getpriority' and `setpriority',
+   indicating what flavor of entity the WHO argument specifies.  */
+enum __priority_which
+{
+  PRIO_PROCESS = 0,		/* WHO is a process ID.  */
+#define PRIO_PROCESS PRIO_PROCESS
+  PRIO_PGRP = 1,		/* WHO is a process group ID.  */
+#define PRIO_PGRP PRIO_PGRP
+  PRIO_USER = 2			/* WHO is a user ID.  */
+#define PRIO_USER PRIO_USER
+};
diff --git a/sysdeps/unix/sysv/linux/getrlimit.c b/sysdeps/unix/sysv/linux/i386/getrlimit.c
index 14a879c5df..14a879c5df 100644
--- a/sysdeps/unix/sysv/linux/getrlimit.c
+++ b/sysdeps/unix/sysv/linux/i386/getrlimit.c
diff --git a/sysdeps/unix/sysv/linux/getrlimit64.c b/sysdeps/unix/sysv/linux/i386/getrlimit64.c
index 602dd28d8a..602dd28d8a 100644
--- a/sysdeps/unix/sysv/linux/getrlimit64.c
+++ b/sysdeps/unix/sysv/linux/i386/getrlimit64.c
diff --git a/sysdeps/unix/sysv/linux/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c
index 5fb0becfbe..5fb0becfbe 100644
--- a/sysdeps/unix/sysv/linux/oldgetrlimit64.c
+++ b/sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c
diff --git a/sysdeps/unix/sysv/linux/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c
index c5448dcdce..c5448dcdce 100644
--- a/sysdeps/unix/sysv/linux/oldsetrlimit64.c
+++ b/sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c
diff --git a/sysdeps/unix/sysv/linux/setrlimit.c b/sysdeps/unix/sysv/linux/i386/setrlimit.c
index 2123360fc9..2123360fc9 100644
--- a/sysdeps/unix/sysv/linux/setrlimit.c
+++ b/sysdeps/unix/sysv/linux/i386/setrlimit.c
diff --git a/sysdeps/unix/sysv/linux/setrlimit64.c b/sysdeps/unix/sysv/linux/i386/setrlimit64.c
index 3e7e5cc0e0..3e7e5cc0e0 100644
--- a/sysdeps/unix/sysv/linux/setrlimit64.c
+++ b/sysdeps/unix/sysv/linux/i386/setrlimit64.c
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/resource.h b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
new file mode 100644
index 0000000000..abfe433c59
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
@@ -0,0 +1,243 @@
+/* Bit values & structures for resource limits.  Linux version.
+   Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _SYS_RESOURCE_H
+# error "Never use <bits/resource.h> directly; include <sys/resource.h> instead."
+#endif
+
+#include <asm/resource.h>
+#include <bits/types.h>
+
+/* Transmute defines to enumerations.  The macro re-definitions are
+   necessary because some programs want to test for operating system
+   features with #ifdef RUSAGE_SELF.  In ISO C the reflexive
+   definition is a no-op.  */
+
+/* Kinds of resource limit.  */
+enum __rlimit_resource
+{
+  /* Per-process CPU limit, in seconds.  */
+  _RLIMIT_CPU = RLIMIT_CPU,
+#undef RLIMIT_CPU
+  RLIMIT_CPU = _RLIMIT_CPU,
+#define RLIMIT_CPU RLIMIT_CPU
+
+  /* Largest file that can be created, in bytes.  */
+  _RLIMIT_FSIZE = RLIMIT_FSIZE,
+#undef RLIMIT_FSIZE
+  RLIMIT_FSIZE = _RLIMIT_FSIZE,
+#define	RLIMIT_FSIZE RLIMIT_FSIZE
+
+  /* Maximum size of data segment, in bytes.  */
+  _RLIMIT_DATA = RLIMIT_DATA,
+#undef RLIMIT_DATA
+  RLIMIT_DATA = _RLIMIT_DATA,
+#define	RLIMIT_DATA RLIMIT_DATA
+
+  /* Maximum size of stack segment, in bytes.  */
+  _RLIMIT_STACK = RLIMIT_STACK,
+#undef RLIMIT_STACK
+  RLIMIT_STACK = _RLIMIT_STACK,
+#define	RLIMIT_STACK RLIMIT_STACK
+
+  /* Largest core file that can be created, in bytes.  */
+  _RLIMIT_CORE = RLIMIT_CORE,
+#undef RLIMIT_CORE
+  RLIMIT_CORE = _RLIMIT_CORE,
+#define	RLIMIT_CORE RLIMIT_CORE
+
+  /* Largest resident set size, in bytes.
+     This affects swapping; processes that are exceeding their
+     resident set size will be more likely to have physical memory
+     taken from them.  */
+  _RLIMIT_RSS = RLIMIT_RSS,
+#undef RLIMIT_RSS
+  RLIMIT_RSS = _RLIMIT_RSS,
+#define	RLIMIT_RSS RLIMIT_RSS
+
+  /* Number of open files.  */
+  _RLIMIT_NOFILE = RLIMIT_NOFILE,
+#undef RLIMIT_NOFILE
+  RLIMIT_NOFILE = _RLIMIT_NOFILE,
+  RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same.  */
+#define RLIMIT_NOFILE RLIMIT_NOFILE
+#define RLIMIT_OFILE RLIMIT_OFILE
+
+  /* Address space limit (?) */
+  _RLIMIT_AS = RLIMIT_AS,
+#undef RLIMIT_AS
+  RLIMIT_AS = _RLIMIT_AS,
+#define RLIMIT_AS RLIMIT_AS
+
+  /* Number of processes.  */
+  _RLIMIT_NPROC = RLIMIT_NPROC,
+#undef RLIMIT_NPROC
+  RLIMIT_NPROC = _RLIMIT_NPROC,
+#define RLIMIT_NPROC RLIMIT_NPROC
+
+  /* Locked-in-memory address space.  */
+  _RLIMIT_MEMLOCK = RLIMIT_MEMLOCK,
+#undef RLIMIT_MEMLOCK
+  RLIMIT_MEMLOCK = _RLIMIT_MEMLOCK,
+#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
+
+  RLIMIT_NLIMITS = RLIM_NLIMITS,
+#undef RLIM_NLIMITS
+  RLIM_NLIMITS = RLIMIT_NLIMITS
+#define RLIMIT_NLIMITS RLIMIT_NLIMITS
+#define RLIM_NLIMITS RLIM_NLIMITS
+};
+
+/* Value to indicate that there is no limit.  */
+#if __WORDSIZE == 64
+
+#ifndef __USE_FILE_OFFSET64
+# define RLIM_INFINITY ((unsigned long int)(~0UL))
+#else
+# define RLIM_INFINITY 0xffffffffffffffffuLL
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define RLIM64_INFINITY 0xffffffffffffffffuLL
+#endif
+
+#else
+
+#ifndef __USE_FILE_OFFSET64
+# define RLIM_INFINITY ((long int)(~0UL >> 1))
+#else
+# define RLIM_INFINITY 0x7fffffffffffffffLL
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define RLIM64_INFINITY 0x7fffffffffffffffLL
+#endif
+
+#endif
+
+/* We can represent all limits.  */
+#define RLIM_SAVED_MAX	RLIM_INFINITY
+#define RLIM_SAVED_CUR	RLIM_INFINITY
+
+
+/* Type for resource quantity measurement.  */
+#ifndef __USE_FILE_OFFSET64
+typedef __rlim_t rlim_t;
+#else
+typedef __rlim64_t rlim_t;
+#endif
+#ifdef __USE_LARGEFILE64
+typedef __rlim64_t rlim64_t;
+#endif
+
+struct rlimit
+  {
+    /* The current (soft) limit.  */
+    rlim_t rlim_cur;
+    /* The hard limit.  */
+    rlim_t rlim_max;
+  };
+
+#ifdef __USE_LARGEFILE64
+struct rlimit64
+  {
+    /* The current (soft) limit.  */
+    rlim64_t rlim_cur;
+    /* The hard limit.  */
+    rlim64_t rlim_max;
+ };
+#endif
+
+/* Whose usage statistics do you want?  */
+enum __rusage_who
+{
+  /* The calling process.  */
+  RUSAGE_SELF = 0,
+#define RUSAGE_SELF RUSAGE_SELF
+
+  /* All of its terminated child processes.  */
+  RUSAGE_CHILDREN = -1,
+#define RUSAGE_CHILDREN RUSAGE_CHILDREN
+
+  /* Both.  */
+  RUSAGE_BOTH = -2
+#define RUSAGE_BOTH RUSAGE_BOTH
+};
+
+#define __need_timeval
+#include <bits/time.h>		/* For `struct timeval'.  */
+
+/* Structure which says how much of each resource has been used.  */
+struct rusage
+  {
+    /* Total amount of user time used.  */
+    struct timeval ru_utime;
+    /* Total amount of system time used.  */
+    struct timeval ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    long int ru_maxrss;
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    long int ru_ixrss;
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    long int ru_idrss;
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    long int ru_isrss;
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    long int ru_minflt;
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    long int ru_majflt;
+    /* Number of times a process was swapped out of physical memory.  */
+    long int ru_nswap;
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    long int ru_inblock;
+    /* Number of output operations via the file system.  */
+    long int ru_oublock;
+    /* Number of IPC messages sent.  */
+    long int ru_msgsnd;
+    /* Number of IPC messages received.  */
+    long int ru_msgrcv;
+    /* Number of signals delivered.  */
+    long int ru_nsignals;
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    long int ru_nvcsw;
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    long int ru_nivcsw;
+  };
+
+/* Priority limits.  */
+#define PRIO_MIN	-20	/* Minimum priority a process can have.  */
+#define PRIO_MAX	20	/* Maximum priority a process can have.  */
+
+/* The type of the WHICH argument to `getpriority' and `setpriority',
+   indicating what flavor of entity the WHO argument specifies.  */
+enum __priority_which
+{
+  PRIO_PROCESS = 0,		/* WHO is a process ID.  */
+#define PRIO_PROCESS PRIO_PROCESS
+  PRIO_PGRP = 1,		/* WHO is a process group ID.  */
+#define PRIO_PGRP PRIO_PGRP
+  PRIO_USER = 2			/* WHO is a user ID.  */
+#define PRIO_USER PRIO_USER
+};
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c b/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c
deleted file mode 100644
index 9feab0e6b8..0000000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* getrlimit64 is the same as getrlimit. */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c b/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c
deleted file mode 100644
index 8edcff0086..0000000000
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* setrlimit64 is the same as setrlimit. */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
index cbfc248c8e..34d3c62e86 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c
@@ -44,6 +44,7 @@ __sigaction (int sig, __const struct sigaction *act, struct sigaction *oact)
     {
       kact.k_sa_handler = act->sa_handler;
       memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
+      kact.sa_flags = act->sa_flags;
       kact.sa_restorer = NULL;
     }