summary refs log tree commit diff
path: root/string
diff options
context:
space:
mode:
Diffstat (limited to 'string')
-rw-r--r--string/Makefile10
-rw-r--r--string/_strerror.c68
-rw-r--r--string/argz-replace.c5
-rw-r--r--string/bcopy.c29
-rw-r--r--string/bits/string3.h87
-rw-r--r--string/bug-envz1.c76
-rw-r--r--string/bug-strtok1.c45
-rw-r--r--string/bzero.c83
-rw-r--r--string/envz.c4
-rw-r--r--string/ffs.c55
-rw-r--r--string/ffsll.c42
-rw-r--r--string/memccpy.c46
-rw-r--r--string/memchr.c215
-rw-r--r--string/memcmp.c381
-rw-r--r--string/memcpy.c65
-rw-r--r--string/memmem.c58
-rw-r--r--string/memmove.c112
-rw-r--r--string/mempcpy.c69
-rw-r--r--string/memrchr.c210
-rw-r--r--string/memset.c91
-rw-r--r--string/rawmemchr.c189
-rw-r--r--string/stpcpy.c55
-rw-r--r--string/stpncpy.c100
-rw-r--r--string/strcasecmp.c74
-rw-r--r--string/strcasecmp_l.c23
-rw-r--r--string/strcasestr.c142
-rw-r--r--string/strcat.c52
-rw-r--r--string/strchr.c191
-rw-r--r--string/strchrnul.c170
-rw-r--r--string/strcmp.c47
-rw-r--r--string/strcoll.c6
-rw-r--r--string/strcpy.c50
-rw-r--r--string/strcspn.c51
-rw-r--r--string/string-inlines.c35
-rw-r--r--string/strlen.c153
-rw-r--r--string/strncase.c76
-rw-r--r--string/strncase_l.c25
-rw-r--r--string/strncat.c85
-rw-r--r--string/strncmp.c73
-rw-r--r--string/strncpy.c87
-rw-r--r--string/strnlen.c161
-rw-r--r--string/strpbrk.c46
-rw-r--r--string/strrchr.c50
-rw-r--r--string/strsep.c70
-rw-r--r--string/strsignal.c6
-rw-r--r--string/strspn.c47
-rw-r--r--string/strstr.c123
-rw-r--r--string/strtok.c66
-rw-r--r--string/strtok_r.c79
-rw-r--r--string/strxfrm_l.c17
-rw-r--r--string/test-memccpy.c6
-rw-r--r--string/test-memchr.c13
-rw-r--r--string/test-memcmp.c8
-rw-r--r--string/test-memcpy.c10
-rw-r--r--string/test-memmove.c10
-rw-r--r--string/test-memset.c16
-rw-r--r--string/test-strcat.c9
-rw-r--r--string/test-strchr.c14
-rw-r--r--string/test-strcmp.c8
-rw-r--r--string/test-strcpy.c9
-rw-r--r--string/test-strlen.c9
-rw-r--r--string/test-strncmp.c85
-rw-r--r--string/test-strncpy.c10
-rw-r--r--string/test-strpbrk.c19
-rw-r--r--string/test-strrchr.c16
-rw-r--r--string/test-strspn.c14
-rw-r--r--string/tester.c37
-rw-r--r--string/tst-strfry.c15
-rw-r--r--string/tst-strxfrm2.c83
-rw-r--r--string/wordcopy.c413
-rw-r--r--string/xpg-strerror.c57
71 files changed, 4818 insertions, 143 deletions
diff --git a/string/Makefile b/string/Makefile
index 66469f586e..f087022b3c 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-1999,2000,2001,2002 Free Software Foundation, Inc.
+# Copyright (C) 1991-2002, 2005, 2006, 2007 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -52,8 +52,9 @@ strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
-		   tst-strtok tst-strxfrm bug-strcoll1			\
-		   $(addprefix test-,$(strop-tests))
+		   tst-strtok tst-strxfrm bug-strcoll1 tst-strfry	\
+		   bug-strtok1 $(addprefix test-,$(strop-tests))	\
+		   bug-envz1 tst-strxfrm2
 distribute	:= memcopy.h pagecopy.h tst-svc.expect test-string.h
 
 
@@ -63,11 +64,14 @@ tester-ENV = LANGUAGE=C
 inl-tester-ENV = LANGUAGE=C
 noinl-tester-ENV = LANGUAGE=C
 tst-strxfrm-ENV = LOCPATH=$(common-objpfx)localedata
+tst-strxfrm2-ENV = LOCPATH=$(common-objpfx)localedata
 bug-strcoll1-ENV = LOCPATH=$(common-objpfx)localedata
+CFLAGS-inl-tester.c = -fno-builtin
 CFLAGS-noinl-tester.c = -fno-builtin
 CFLAGS-tst-strlen.c = -fno-builtin
 CFLAGS-stratcliff.c = -fno-builtin
 CFLAGS-test-ffs.c = -fno-builtin
+CFLAGS-tst-inlcall.c = -fno-builtin
 
 ifeq ($(cross-compiling),no)
 tests: $(objpfx)tst-svc.out
diff --git a/string/_strerror.c b/string/_strerror.c
new file mode 100644
index 0000000000..cb5d9e3609
--- /dev/null
+++ b/string/_strerror.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1991,93,95,96,97,98,2000,2002,2006
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <libintl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <stdio-common/_itoa.h>
+
+/* It is critical here that we always use the `dcgettext' function for
+   the message translation.  Since <libintl.h> only defines the macro
+   `dgettext' to use `dcgettext' for optimizing programs this is not
+   always guaranteed.  */
+#ifndef dgettext
+# include <locale.h>		/* We need LC_MESSAGES.  */
+# define dgettext(domainname, msgid) dcgettext (domainname, msgid, LC_MESSAGES)
+#endif
+
+/* Return a string describing the errno code in ERRNUM.  */
+char *
+__strerror_r (int errnum, char *buf, size_t buflen)
+{
+  if (__builtin_expect (errnum < 0 || errnum >= _sys_nerr_internal
+			|| _sys_errlist_internal[errnum] == NULL, 0))
+    {
+      /* Buffer we use to print the number in.  For a maximum size for
+	 `int' of 8 bytes we never need more than 20 digits.  */
+      char numbuf[21];
+      const char *unk = _("Unknown error ");
+      const size_t unklen = strlen (unk);
+      char *p, *q;
+
+      numbuf[20] = '\0';
+      p = _itoa_word (errnum, &numbuf[20], 10, 0);
+
+      /* Now construct the result while taking care for the destination
+	 buffer size.  */
+      q = __mempcpy (buf, unk, MIN (unklen, buflen));
+      if (unklen < buflen)
+	memcpy (q, p, MIN ((size_t) (&numbuf[21] - p), buflen - unklen));
+
+      /* Terminate the string in any case.  */
+      if (buflen > 0)
+	buf[buflen - 1] = '\0';
+
+      return buf;
+    }
+
+  return (char *) _(_sys_errlist_internal[errnum]);
+}
+weak_alias (__strerror_r, strerror_r)
+libc_hidden_def (__strerror_r)
diff --git a/string/argz-replace.c b/string/argz-replace.c
index 3c4062488e..1b0eb15fd7 100644
--- a/string/argz-replace.c
+++ b/string/argz-replace.c
@@ -1,5 +1,5 @@
 /* String replacement in an argz vector
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>
 
@@ -121,8 +121,7 @@ __argz_replace (char **argz, size_t *argz_len, const char *str, const char *with
 	  if (! delayed_copy)
 	    /* We never found any instances of str.  */
 	    {
-	      if (src)
-		free (src);
+	      free (src);
 	      *argz = dst;
 	      *argz_len = dst_len;
 	    }
diff --git a/string/bcopy.c b/string/bcopy.c
new file mode 100644
index 0000000000..3f16b884ac
--- /dev/null
+++ b/string/bcopy.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1991, 1992, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#define	memmove		bcopy
+#define	rettype		void
+#define	RETURN(s)	return
+#define	a1		src
+#define	a1const		const
+#define	a2		dest
+#define	a2const
+
+#include <memmove.c>
diff --git a/string/bits/string3.h b/string/bits/string3.h
index 87cbe35bb1..041ac11259 100644
--- a/string/bits/string3.h
+++ b/string/bits/string3.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -44,10 +44,9 @@
   ((__bos0 (dest) != (size_t) -1)					\
    ? __builtin___memcpy_chk (dest, src, len, __bos0 (dest))		\
    : __memcpy_ichk (dest, src, len))
-static __inline__ void *
-__attribute__ ((__always_inline__))
-__memcpy_ichk (void *__restrict __dest, const void *__restrict __src,
-	       size_t __len)
+static __always_inline void *
+__NTH (__memcpy_ichk (void *__restrict __dest, __const void *__restrict __src,
+		      size_t __len))
 {
   return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
 }
@@ -57,9 +56,8 @@ __memcpy_ichk (void *__restrict __dest, const void *__restrict __src,
   ((__bos0 (dest) != (size_t) -1)					\
    ? __builtin___memmove_chk (dest, src, len, __bos0 (dest))		\
    : __memmove_ichk (dest, src, len))
-static __inline__ void *
-__attribute__ ((__always_inline__))
-__memmove_ichk (void *__dest, const void *__src, size_t __len)
+static __always_inline void *
+__NTH (__memmove_ichk (void *__dest, __const void *__src, size_t __len))
 {
   return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
 }
@@ -70,23 +68,30 @@ __memmove_ichk (void *__dest, const void *__src, size_t __len)
   ((__bos0 (dest) != (size_t) -1)					\
    ? __builtin___mempcpy_chk (dest, src, len, __bos0 (dest))		\
    : __mempcpy_ichk (dest, src, len))
-static __inline__ void *
-__attribute__ ((__always_inline__))
-__mempcpy_ichk (void *__restrict __dest, const void *__restrict __src,
-		size_t __len)
+static __always_inline void *
+__NTH (__mempcpy_ichk (void *__restrict __dest,
+		       __const void *__restrict __src, size_t __len))
 {
   return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
 }
 #endif
 
 
+/* The first two tests here help to catch a somewhat common problem
+   where the second and third parameter are transposed.  This is
+   especially problematic if the intended fill value is zero.  In this
+   case no work is done at all.  We detect these problems by referring
+   non-existing functions.  */
+__warndecl (__warn_memset_zero_len,
+	    "memset used with constant zero length parameter; this could be due to transposed parameters");
 #define memset(dest, ch, len) \
-  ((__bos0 (dest) != (size_t) -1)					\
-   ? __builtin___memset_chk (dest, ch, len, __bos0 (dest))		\
-   : __memset_ichk (dest, ch, len))
-static __inline__ void *
-__attribute__ ((__always_inline__))
-__memset_ichk (void *__dest, int __ch, size_t __len)
+  (__builtin_constant_p (len) && (len) == 0				      \
+   ? (__warn_memset_zero_len (), (void) (ch), (void) (len), (void *) (dest))  \
+   : ((__bos0 (dest) != (size_t) -1)					      \
+      ? __builtin___memset_chk (dest, ch, len, __bos0 (dest))		      \
+      : __memset_ichk (dest, ch, len)))
+static __always_inline void *
+__NTH (__memset_ichk (void *__dest, int __ch, size_t __len))
 {
   return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
 }
@@ -107,9 +112,8 @@ __memset_ichk (void *__dest, int __ch, size_t __len)
   ((__bos (dest) != (size_t) -1)					\
    ? __builtin___strcpy_chk (dest, src, __bos (dest))			\
    : __strcpy_ichk (dest, src))
-static __inline__ char *
-__attribute__ ((__always_inline__))
-__strcpy_ichk (char *__restrict __dest, const char *__restrict __src)
+static __always_inline char *
+__NTH (__strcpy_ichk (char *__restrict __dest, __const char *__restrict __src))
 {
   return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
 }
@@ -120,9 +124,8 @@ __strcpy_ichk (char *__restrict __dest, const char *__restrict __src)
   ((__bos (dest) != (size_t) -1)					\
    ? __builtin___stpcpy_chk (dest, src, __bos (dest))			\
    : __stpcpy_ichk (dest, src))
-static __inline__ char *
-__attribute__ ((__always_inline__))
-__stpcpy_ichk (char *__restrict __dest, const char *__restrict __src)
+static __always_inline char *
+__NTH (__stpcpy_ichk (char *__restrict __dest, __const char *__restrict __src))
 {
   return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
 }
@@ -133,22 +136,37 @@ __stpcpy_ichk (char *__restrict __dest, const char *__restrict __src)
   ((__bos (dest) != (size_t) -1)					\
    ? __builtin___strncpy_chk (dest, src, len, __bos (dest))		\
    : __strncpy_ichk (dest, src, len))
-static __inline__ char *
-__attribute__ ((__always_inline__))
-__strncpy_ichk (char *__restrict __dest, const char *__restrict __src,
-		size_t __len)
+static __always_inline char *
+__NTH (__strncpy_ichk (char *__restrict __dest, __const char *__restrict __src,
+		       size_t __len))
 {
   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
 }
 
 
+// XXX We have no corresponding builtin yet.
+extern char *__stpncpy_chk (char *__dest, __const char *__src, size_t __n,
+			    size_t __destlen) __THROW;
+extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest,
+					       __const char *__src,
+					       size_t __n), stpncpy);
+
+extern __always_inline char *
+__NTH (stpncpy (char *__dest, __const char *__src, size_t __n))
+{
+  if (__bos (__dest) != (size_t) -1
+      && (!__builtin_constant_p (__n) || __n <= __bos (__dest)))
+    return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+  return __stpncpy_alias (__dest, __src, __n);
+}
+
+
 #define strcat(dest, src) \
   ((__bos (dest) != (size_t) -1)					\
    ? __builtin___strcat_chk (dest, src, __bos (dest))			\
    : __strcat_ichk (dest, src))
-static __inline__ char *
-__attribute__ ((__always_inline__))
-__strcat_ichk (char *__restrict __dest, const char *__restrict __src)
+static __always_inline char *
+__NTH (__strcat_ichk (char *__restrict __dest, __const char *__restrict __src))
 {
   return __builtin___strcat_chk (__dest, __src, __bos (__dest));
 }
@@ -158,10 +176,9 @@ __strcat_ichk (char *__restrict __dest, const char *__restrict __src)
   ((__bos (dest) != (size_t) -1)					\
    ? __builtin___strncat_chk (dest, src, len, __bos (dest))		\
    : __strncat_ichk (dest, src, len))
-static __inline__ char *
-__attribute__ ((__always_inline__))
-__strncat_ichk (char *__restrict __dest, const char *__restrict __src,
-		size_t __len)
+static __always_inline char *
+__NTH (__strncat_ichk (char *__restrict __dest, __const char *__restrict __src,
+		       size_t __len))
 {
   return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
 }
diff --git a/string/bug-envz1.c b/string/bug-envz1.c
new file mode 100644
index 0000000000..e8a60972b5
--- /dev/null
+++ b/string/bug-envz1.c
@@ -0,0 +1,76 @@
+/* Test for bug BZ #2703.  */
+#include <stdio.h>
+#include <envz.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const struct
+{
+  const char *s;
+  int in_result;
+} strs[] =
+{
+  { "a=1", 1 },
+  { "b=2", 1 },
+  { "(*)", 0 },
+  { "(*)", 0 },
+  { "e=5", 1 },
+  { "f=", 1 },
+  { "(*)", 0 },
+  { "h=8", 1 },
+  { "i=9", 1 },
+  { "j", 0 }
+};
+
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+
+
+static int
+do_test (void)
+{
+
+  size_t size = 0;
+  char *str = malloc (100);
+  if (str == NULL)
+    {
+      puts ("out of memory");
+      return 1;
+    }
+
+  char **argz = &str;
+
+  for (int i = 0; i < nstrs; ++i)
+    argz_add_sep (argz, &size, strs[i].s, '\0');
+
+  printf ("calling envz_strip with size=%zu\n", size);
+  envz_strip (argz, &size);
+
+  int result = 0;
+  printf ("new size=%zu\n", size);
+  for (int i = 0; i < nstrs; ++i)
+    if (strs[i].in_result)
+      {
+        char name[2];
+        name[0] = strs[i].s[0];
+        name[1] = '\0';
+
+        char *e = envz_entry (*argz, size, name);
+        if (e == NULL)
+          {
+            printf ("entry '%s' not found\n", name);
+            result = 1;
+          }
+        else if (strcmp (e, strs[i].s) != 0)
+          {
+            printf ("entry '%s' does not match: is '%s', expected '%s'\n",
+                    name, e, strs[i].s);
+            result = 1;
+          }
+      }
+
+  free (*argz);
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/bug-strtok1.c b/string/bug-strtok1.c
new file mode 100644
index 0000000000..da30acf2e6
--- /dev/null
+++ b/string/bug-strtok1.c
@@ -0,0 +1,45 @@
+/* See BZ #2126.  */
+#include <string.h>
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+  const char str[] = "axaaba";
+  char *token;
+  char *cp;
+  char *l;
+  int result = 0;
+
+  puts ("test strtok");
+  cp = strdupa (str);
+  printf ("cp = %p, len = %zu\n", cp, strlen (cp));
+  token = strtok (cp, "ab");
+  result |= token == NULL || strcmp (token, "x");
+  printf ("token: %s (%d)\n", token ? token : "NULL", result);
+  token = strtok(0, "ab");
+  result |= token != NULL;
+  printf ("token: %s (%d)\n", token ? token : "NULL", result);
+  token = strtok(0, "a");
+  result |= token != NULL;
+  printf ("token: %s (%d)\n", token ? token : "NULL", result);
+
+  puts ("test strtok_r");
+  cp = strdupa (str);
+  size_t len = strlen (cp);
+  printf ("cp = %p, len = %zu\n", cp, len);
+  token = strtok_r (cp, "ab", &l);
+  result |= token == NULL || strcmp (token, "x");
+  printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
+  token = strtok_r(0, "ab", &l);
+  result |= token != NULL || l != cp + len;
+  printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
+  token = strtok_r(0, "a", &l);
+  result |= token != NULL || l != cp + len;
+  printf ("token: %s,  next = %p (%d)\n", token ? token : "NULL", l, result);
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/bzero.c b/string/bzero.c
new file mode 100644
index 0000000000..c6ede14139
--- /dev/null
+++ b/string/bzero.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 1991, 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef __bzero
+
+/* Set N bytes of S to 0.  */
+void
+__bzero (s, len)
+     void *s;
+     size_t len;
+{
+  long int dstp = (long int) s;
+  const op_t zero = 0;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+
+      /* There are at least some bytes to zero.  No need to test
+	 for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+	{
+	  ((byte *) dstp)[0] = 0;
+	  dstp += 1;
+	  len -= 1;
+	}
+
+      /* Write 8 op_t per iteration until less than 8 op_t remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen != 0)
+	{
+	  ((op_t *) dstp)[0] = zero;
+	  ((op_t *) dstp)[1] = zero;
+	  ((op_t *) dstp)[2] = zero;
+	  ((op_t *) dstp)[3] = zero;
+	  ((op_t *) dstp)[4] = zero;
+	  ((op_t *) dstp)[5] = zero;
+	  ((op_t *) dstp)[6] = zero;
+	  ((op_t *) dstp)[7] = zero;
+	  dstp += 8 * OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ * 8;
+
+      /* Write 1 op_t per iteration until less than op_t remain.  */
+      xlen = len / OPSIZ;
+      while (xlen != 0)
+	{
+	  ((op_t *) dstp)[0] = zero;
+	  dstp += OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len != 0)
+    {
+      ((byte *) dstp)[0] = 0;
+      dstp += 1;
+      len -= 1;
+    }
+}
+weak_alias (__bzero, bzero)
diff --git a/string/envz.c b/string/envz.c
index 5c5804c12b..a9d420212f 100644
--- a/string/envz.c
+++ b/string/envz.c
@@ -1,5 +1,5 @@
 /* Routines for dealing with '\0' separated environment vectors
-   Copyright (C) 1995,96,97,98,2001,02 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998,2001,2002,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.org>
 
@@ -165,7 +165,7 @@ envz_strip (char **envz, size_t *envz_len)
       left -= entry_len;
       if (! strchr (entry, SEP))
 	/* Null entry. */
-	memmove (entry + entry_len, entry, left);
+	memmove (entry, entry + entry_len, left);
       else
 	entry += entry_len;
     }
diff --git a/string/ffs.c b/string/ffs.c
new file mode 100644
index 0000000000..06a1542bd9
--- /dev/null
+++ b/string/ffs.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1991, 1992, 1997, 1998, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <limits.h>
+#define ffsl __something_else
+#include <string.h>
+
+#undef	ffs
+
+/* Find the first bit set in I.  */
+int
+__ffs (i)
+     int i;
+{
+  static const unsigned char table[] =
+    {
+      0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+      6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+      7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+      7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+      8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+      8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+      8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+      8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+    };
+  unsigned int a;
+  unsigned int x = i & -i;
+
+  a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ?  16 : 24);
+
+  return table[x >> a] + a;
+}
+weak_alias (__ffs, ffs)
+libc_hidden_builtin_def (ffs)
+
+#if ULONG_MAX == UINT_MAX
+#undef ffsl
+weak_alias (__ffs, ffsl)
+#endif
diff --git a/string/ffsll.c b/string/ffsll.c
new file mode 100644
index 0000000000..9dd269afb7
--- /dev/null
+++ b/string/ffsll.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991, 1992, 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <limits.h>
+#define ffsl __something_else
+#include <string.h>
+
+#undef	ffsll
+
+/* Find the first bit set in I.  */
+int
+ffsll (i)
+     long long int i;
+{
+  unsigned long long int x = i & -i;
+
+  if (x <= 0xffffffff)
+    return ffs (i);
+  else
+    return 32 + ffs (i >> 32);
+}
+
+#if ULONG_MAX != UINT_MAX
+#undef ffsl
+weak_alias (ffsll, ffsl)
+#endif
diff --git a/string/memccpy.c b/string/memccpy.c
new file mode 100644
index 0000000000..9ffdc335d4
--- /dev/null
+++ b/string/memccpy.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 1995, 1997, 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#undef __memccpy
+#undef memccpy
+
+/* Copy no more than N bytes of SRC to DEST, stopping when C is found.
+   Return the position in DEST one byte past where C was copied, or
+   NULL if C was not found in the first N bytes of SRC.  */
+void *
+__memccpy (dest, src, c, n)
+      void *dest;
+      const void *src;
+      int c;
+      size_t n;
+{
+  register const char *s = src;
+  register char *d = dest;
+  register const char x = c;
+  register size_t i = n;
+
+  while (i-- > 0)
+    if ((*d++ = *s++) == x)
+      return d;
+
+  return NULL;
+}
+
+weak_alias (__memccpy, memccpy)
diff --git a/string/memchr.c b/string/memchr.c
new file mode 100644
index 0000000000..f3098c775a
--- /dev/null
+++ b/string/memchr.c
@@ -0,0 +1,215 @@
+/* Copyright (C) 1991,93,96,97,99,2000,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef __ptr_t
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+# define __ptr_t void *
+#else /* Not C++ or ANSI C.  */
+# define __ptr_t char *
+#endif /* C++ or ANSI C.  */
+
+#if defined _LIBC
+# include <string.h>
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#if HAVE_STDLIB_H || defined _LIBC
+# include <stdlib.h>
+#endif
+
+#if HAVE_LIMITS_H || defined _LIBC
+# include <limits.h>
+#endif
+
+#define LONG_MAX_32_BITS 2147483647
+
+#ifndef LONG_MAX
+#define LONG_MAX LONG_MAX_32_BITS
+#endif
+
+#include <sys/types.h>
+#if HAVE_BP_SYM_H || defined _LIBC
+#include <bp-sym.h>
+#else
+# define BP_SYM(sym) sym
+#endif
+
+#undef memchr
+#undef __memchr
+
+/* Search no more than N bytes of S for C.  */
+__ptr_t
+__memchr (s, c_in, n)
+     const __ptr_t s;
+     int c_in;
+     size_t n;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       n > 0 && ((unsigned long int) char_ptr
+		 & (sizeof (longword) - 1)) != 0;
+       --n, ++char_ptr)
+    if (*char_ptr == c)
+      return (__ptr_t) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+
+  if (sizeof (longword) != 4 && sizeof (longword) != 8)
+    abort ();
+
+#if LONG_MAX <= LONG_MAX_32_BITS
+  magic_bits = 0x7efefeff;
+#else
+  magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
+#endif
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+#if LONG_MAX > LONG_MAX_32_BITS
+  charmask |= charmask << 32;
+#endif
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (n >= sizeof (longword))
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *longword_ptr++ ^ charmask;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+	  if (cp[0] == c)
+	    return (__ptr_t) cp;
+	  if (cp[1] == c)
+	    return (__ptr_t) &cp[1];
+	  if (cp[2] == c)
+	    return (__ptr_t) &cp[2];
+	  if (cp[3] == c)
+	    return (__ptr_t) &cp[3];
+#if LONG_MAX > 2147483647
+	  if (cp[4] == c)
+	    return (__ptr_t) &cp[4];
+	  if (cp[5] == c)
+	    return (__ptr_t) &cp[5];
+	  if (cp[6] == c)
+	    return (__ptr_t) &cp[6];
+	  if (cp[7] == c)
+	    return (__ptr_t) &cp[7];
+#endif
+	}
+
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  while (n-- > 0)
+    {
+      if (*char_ptr == c)
+	return (__ptr_t) char_ptr;
+      else
+	++char_ptr;
+    }
+
+  return 0;
+}
+#ifdef weak_alias
+weak_alias (__memchr, BP_SYM (memchr))
+#endif
+libc_hidden_builtin_def (memchr)
diff --git a/string/memcmp.c b/string/memcmp.c
new file mode 100644
index 0000000000..2f8cf344af
--- /dev/null
+++ b/string/memcmp.c
@@ -0,0 +1,381 @@
+/* Copyright (C) 1991,1993,1995,1997,1998,2003,2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#undef	__ptr_t
+#if defined __cplusplus || (defined __STDC__ && __STDC__)
+# define __ptr_t	void *
+#else /* Not C++ or ANSI C.  */
+# undef	const
+# define const
+# define __ptr_t	char *
+#endif /* C++ or ANSI C.  */
+
+#if defined HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#endif
+
+#undef memcmp
+
+#ifdef _LIBC
+
+# include <memcopy.h>
+# include <endian.h>
+
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN
+# endif
+
+#else	/* Not in the GNU C library.  */
+
+# include <sys/types.h>
+
+/* Type to use for aligned memory operations.
+   This should normally be the biggest type supported by a single load
+   and store.  Must be an unsigned type.  */
+# define op_t	unsigned long int
+# define OPSIZ	(sizeof(op_t))
+
+/* Threshold value for when to enter the unrolled loops.  */
+# define OP_T_THRES	16
+
+/* Type to use for unaligned operations.  */
+typedef unsigned char byte;
+
+# ifndef WORDS_BIGENDIAN
+#  define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
+# else
+#  define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
+# endif
+
+#endif	/* In the GNU C library.  */
+
+#ifdef WORDS_BIGENDIAN
+# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
+#else
+# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
+#endif
+
+/* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
+
+/* The strategy of this memcmp is:
+
+   1. Compare bytes until one of the block pointers is aligned.
+
+   2. Compare using memcmp_common_alignment or
+      memcmp_not_common_alignment, regarding the alignment of the other
+      block after the initial byte operations.  The maximum number of
+      full words (of type op_t) are compared in this way.
+
+   3. Compare the few remaining bytes.  */
+
+#ifndef WORDS_BIGENDIAN
+/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine.
+   A and B are known to be different.
+   This is needed only on little-endian machines.  */
+
+static int memcmp_bytes (op_t, op_t) __THROW;
+
+# ifdef  __GNUC__
+__inline
+# endif
+static int
+memcmp_bytes (a, b)
+     op_t a, b;
+{
+  long int srcp1 = (long int) &a;
+  long int srcp2 = (long int) &b;
+  op_t a0, b0;
+
+  do
+    {
+      a0 = ((byte *) srcp1)[0];
+      b0 = ((byte *) srcp2)[0];
+      srcp1 += 1;
+      srcp2 += 1;
+    }
+  while (a0 == b0);
+  return a0 - b0;
+}
+#endif
+
+static int memcmp_common_alignment (long, long, size_t) __THROW;
+
+/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
+   objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
+   memory operations on `op_t's.  */
+static int
+memcmp_common_alignment (srcp1, srcp2, len)
+     long int srcp1;
+     long int srcp2;
+     size_t len;
+{
+  op_t a0, a1;
+  op_t b0, b1;
+
+  switch (len % 4)
+    {
+    default: /* Avoid warning about uninitialized local variables.  */
+    case 2:
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      srcp1 -= 2 * OPSIZ;
+      srcp2 -= 2 * OPSIZ;
+      len += 2;
+      goto do1;
+    case 3:
+      a1 = ((op_t *) srcp1)[0];
+      b1 = ((op_t *) srcp2)[0];
+      srcp1 -= OPSIZ;
+      srcp2 -= OPSIZ;
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return 0;
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      goto do3;
+    case 1:
+      a1 = ((op_t *) srcp1)[0];
+      b1 = ((op_t *) srcp2)[0];
+      srcp1 += OPSIZ;
+      srcp2 += OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      /* Fall through.  */
+    }
+
+  do
+    {
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      if (a1 != b1)
+	return CMP_LT_OR_GT (a1, b1);
+
+    do3:
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[1];
+      if (a0 != b0)
+	return CMP_LT_OR_GT (a0, b0);
+
+    do2:
+      a0 = ((op_t *) srcp1)[2];
+      b0 = ((op_t *) srcp2)[2];
+      if (a1 != b1)
+	return CMP_LT_OR_GT (a1, b1);
+
+    do1:
+      a1 = ((op_t *) srcp1)[3];
+      b1 = ((op_t *) srcp2)[3];
+      if (a0 != b0)
+	return CMP_LT_OR_GT (a0, b0);
+
+      srcp1 += 4 * OPSIZ;
+      srcp2 += 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  if (a1 != b1)
+    return CMP_LT_OR_GT (a1, b1);
+  return 0;
+}
+
+static int memcmp_not_common_alignment (long, long, size_t) __THROW;
+
+/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
+   `op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
+   operations on `op_t', but SRCP1 *should be unaligned*.  */
+static int
+memcmp_not_common_alignment (srcp1, srcp2, len)
+     long int srcp1;
+     long int srcp2;
+     size_t len;
+{
+  op_t a0, a1, a2, a3;
+  op_t b0, b1, b2, b3;
+  op_t x;
+  int shl, shr;
+
+  /* Calculate how to shift a word read at the memory operation
+     aligned srcp1 to make it aligned for comparison.  */
+
+  shl = 8 * (srcp1 % OPSIZ);
+  shr = 8 * OPSIZ - shl;
+
+  /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
+     it points in the middle of.  */
+  srcp1 &= -OPSIZ;
+
+  switch (len % 4)
+    {
+    default: /* Avoid warning about uninitialized local variables.  */
+    case 2:
+      a1 = ((op_t *) srcp1)[0];
+      a2 = ((op_t *) srcp1)[1];
+      b2 = ((op_t *) srcp2)[0];
+      srcp1 -= 1 * OPSIZ;
+      srcp2 -= 2 * OPSIZ;
+      len += 2;
+      goto do1;
+    case 3:
+      a0 = ((op_t *) srcp1)[0];
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[0];
+      srcp2 -= 1 * OPSIZ;
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return 0;
+      a3 = ((op_t *) srcp1)[0];
+      a0 = ((op_t *) srcp1)[1];
+      b0 = ((op_t *) srcp2)[0];
+      srcp1 += 1 * OPSIZ;
+      goto do3;
+    case 1:
+      a2 = ((op_t *) srcp1)[0];
+      a3 = ((op_t *) srcp1)[1];
+      b3 = ((op_t *) srcp2)[0];
+      srcp1 += 2 * OPSIZ;
+      srcp2 += 1 * OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      /* Fall through.  */
+    }
+
+  do
+    {
+      a0 = ((op_t *) srcp1)[0];
+      b0 = ((op_t *) srcp2)[0];
+      x = MERGE(a2, shl, a3, shr);
+      if (x != b3)
+	return CMP_LT_OR_GT (x, b3);
+
+    do3:
+      a1 = ((op_t *) srcp1)[1];
+      b1 = ((op_t *) srcp2)[1];
+      x = MERGE(a3, shl, a0, shr);
+      if (x != b0)
+	return CMP_LT_OR_GT (x, b0);
+
+    do2:
+      a2 = ((op_t *) srcp1)[2];
+      b2 = ((op_t *) srcp2)[2];
+      x = MERGE(a0, shl, a1, shr);
+      if (x != b1)
+	return CMP_LT_OR_GT (x, b1);
+
+    do1:
+      a3 = ((op_t *) srcp1)[3];
+      b3 = ((op_t *) srcp2)[3];
+      x = MERGE(a1, shl, a2, shr);
+      if (x != b2)
+	return CMP_LT_OR_GT (x, b2);
+
+      srcp1 += 4 * OPSIZ;
+      srcp2 += 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  x = MERGE(a2, shl, a3, shr);
+  if (x != b3)
+    return CMP_LT_OR_GT (x, b3);
+  return 0;
+}
+
+int
+memcmp (s1, s2, len)
+     const __ptr_t s1;
+     const __ptr_t s2;
+     size_t len;
+{
+  op_t a0;
+  op_t b0;
+  long int srcp1 = (long int) s1;
+  long int srcp2 = (long int) s2;
+  op_t res;
+
+  if (len >= OP_T_THRES)
+    {
+      /* There are at least some bytes to compare.  No need to test
+	 for LEN == 0 in this alignment loop.  */
+      while (srcp2 % OPSIZ != 0)
+	{
+	  a0 = ((byte *) srcp1)[0];
+	  b0 = ((byte *) srcp2)[0];
+	  srcp1 += 1;
+	  srcp2 += 1;
+	  res = a0 - b0;
+	  if (res != 0)
+	    return res;
+	  len -= 1;
+	}
+
+      /* SRCP2 is now aligned for memory operations on `op_t'.
+	 SRCP1 alignment determines if we can do a simple,
+	 aligned compare or need to shuffle bits.  */
+
+      if (srcp1 % OPSIZ == 0)
+	res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
+      else
+	res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
+      if (res != 0)
+	return res;
+
+      /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
+      srcp1 += len & -OPSIZ;
+      srcp2 += len & -OPSIZ;
+      len %= OPSIZ;
+    }
+
+  /* There are just a few bytes to compare.  Use byte memory operations.  */
+  while (len != 0)
+    {
+      a0 = ((byte *) srcp1)[0];
+      b0 = ((byte *) srcp2)[0];
+      srcp1 += 1;
+      srcp2 += 1;
+      res = a0 - b0;
+      if (res != 0)
+	return res;
+      len -= 1;
+    }
+
+  return 0;
+}
+libc_hidden_builtin_def(memcmp)
+#ifdef weak_alias
+# undef bcmp
+weak_alias (memcmp, bcmp)
+#endif
diff --git a/string/memcpy.c b/string/memcpy.c
new file mode 100644
index 0000000000..e167e85d7b
--- /dev/null
+++ b/string/memcpy.c
@@ -0,0 +1,65 @@
+/* Copy memory to memory until the specified number of bytes
+   has been copied.  Overlap is NOT handled correctly.
+   Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+#include <pagecopy.h>
+
+#undef memcpy
+
+void *
+memcpy (dstpp, srcpp, len)
+     void *dstpp;
+     const void *srcpp;
+     size_t len;
+{
+  unsigned long int dstp = (long int) dstpp;
+  unsigned long int srcp = (long int) srcpp;
+
+  /* Copy from the beginning to the end.  */
+
+  /* If there not too few bytes to copy, use word copy.  */
+  if (len >= OP_T_THRES)
+    {
+      /* Copy just a few bytes to make DSTP aligned.  */
+      len -= (-dstp) % OPSIZ;
+      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
+
+      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
+	 as much as possible.  */
+
+      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
+
+      /* Copy from SRCP to DSTP taking advantage of the known alignment of
+	 DSTP.  Number of bytes remaining is put in the third argument,
+	 i.e. in LEN.  This number may vary from machine to machine.  */
+
+      WORD_COPY_FWD (dstp, srcp, len, len);
+
+      /* Fall out and copy the tail.  */
+    }
+
+  /* There are just a few bytes to copy.  Use byte memory operations.  */
+  BYTE_COPY_FWD (dstp, srcp, len);
+
+  return dstpp;
+}
+libc_hidden_builtin_def (memcpy)
diff --git a/string/memmem.c b/string/memmem.c
new file mode 100644
index 0000000000..c40462104a
--- /dev/null
+++ b/string/memmem.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1991,92,93,94,96,97,98,2000,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stddef.h>
+#include <string.h>
+
+#ifndef _LIBC
+# define __builtin_expect(expr, val)   (expr)
+#endif
+
+#undef memmem
+
+/* Return the first occurrence of NEEDLE in HAYSTACK.  */
+void *
+memmem (haystack, haystack_len, needle, needle_len)
+     const void *haystack;
+     size_t haystack_len;
+     const void *needle;
+     size_t needle_len;
+{
+  const char *begin;
+  const char *const last_possible
+    = (const char *) haystack + haystack_len - needle_len;
+
+  if (needle_len == 0)
+    /* The first occurrence of the empty string is deemed to occur at
+       the beginning of the string.  */
+    return (void *) haystack;
+
+  /* Sanity check, otherwise the loop might search through the whole
+     memory.  */
+  if (__builtin_expect (haystack_len < needle_len, 0))
+    return NULL;
+
+  for (begin = (const char *) haystack; begin <= last_possible; ++begin)
+    if (begin[0] == ((const char *) needle)[0] &&
+	!memcmp ((const void *) &begin[1],
+		 (const void *) ((const char *) needle + 1),
+		 needle_len - 1))
+      return (void *) begin;
+
+  return NULL;
+}
diff --git a/string/memmove.c b/string/memmove.c
new file mode 100644
index 0000000000..16671f7bb5
--- /dev/null
+++ b/string/memmove.c
@@ -0,0 +1,112 @@
+/* Copy memory to memory until the specified number of bytes
+   has been copied.  Overlap is handled correctly.
+   Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+#include <pagecopy.h>
+
+/* All this is so that bcopy.c can #include
+   this file after defining some things.  */
+#ifndef	a1
+#define	a1	dest	/* First arg is DEST.  */
+#define	a1const
+#define	a2	src	/* Second arg is SRC.  */
+#define	a2const	const
+#undef memmove
+#endif
+#if	!defined(RETURN) || !defined(rettype)
+#define	RETURN(s)	return (s)	/* Return DEST.  */
+#define	rettype		void *
+#endif
+
+
+rettype
+memmove (a1, a2, len)
+     a1const void *a1;
+     a2const void *a2;
+     size_t len;
+{
+  unsigned long int dstp = (long int) dest;
+  unsigned long int srcp = (long int) src;
+
+  /* This test makes the forward copying code be used whenever possible.
+     Reduces the working set.  */
+  if (dstp - srcp >= len)	/* *Unsigned* compare!  */
+    {
+      /* Copy from the beginning to the end.  */
+
+      /* If there not too few bytes to copy, use word copy.  */
+      if (len >= OP_T_THRES)
+	{
+	  /* Copy just a few bytes to make DSTP aligned.  */
+	  len -= (-dstp) % OPSIZ;
+	  BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
+
+	  /* Copy whole pages from SRCP to DSTP by virtual address
+	     manipulation, as much as possible.  */
+
+	  PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
+
+	  /* Copy from SRCP to DSTP taking advantage of the known
+	     alignment of DSTP.  Number of bytes remaining is put
+	     in the third argument, i.e. in LEN.  This number may
+	     vary from machine to machine.  */
+
+	  WORD_COPY_FWD (dstp, srcp, len, len);
+
+	  /* Fall out and copy the tail.  */
+	}
+
+      /* There are just a few bytes to copy.  Use byte memory operations.  */
+      BYTE_COPY_FWD (dstp, srcp, len);
+    }
+  else
+    {
+      /* Copy from the end to the beginning.  */
+      srcp += len;
+      dstp += len;
+
+      /* If there not too few bytes to copy, use word copy.  */
+      if (len >= OP_T_THRES)
+	{
+	  /* Copy just a few bytes to make DSTP aligned.  */
+	  len -= dstp % OPSIZ;
+	  BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ);
+
+	  /* Copy from SRCP to DSTP taking advantage of the known
+	     alignment of DSTP.  Number of bytes remaining is put
+	     in the third argument, i.e. in LEN.  This number may
+	     vary from machine to machine.  */
+
+	  WORD_COPY_BWD (dstp, srcp, len, len);
+
+	  /* Fall out and copy the tail.  */
+	}
+
+      /* There are just a few bytes to copy.  Use byte memory operations.  */
+      BYTE_COPY_BWD (dstp, srcp, len);
+    }
+
+  RETURN (dest);
+}
+#ifndef memmove
+libc_hidden_builtin_def (memmove)
+#endif
diff --git a/string/mempcpy.c b/string/mempcpy.c
new file mode 100644
index 0000000000..a72617e86f
--- /dev/null
+++ b/string/mempcpy.c
@@ -0,0 +1,69 @@
+/* Copy memory to memory until the specified number of bytes
+   has been copied, return pointer to following byte.
+   Overlap is NOT handled correctly.
+   Copyright (C) 1991, 1997, 1998, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+#include <pagecopy.h>
+
+#undef mempcpy
+#undef __mempcpy
+
+void *
+__mempcpy (dstpp, srcpp, len)
+     void *dstpp;
+     const void *srcpp;
+     size_t len;
+{
+  unsigned long int dstp = (long int) dstpp;
+  unsigned long int srcp = (long int) srcpp;
+
+  /* Copy from the beginning to the end.  */
+
+  /* If there not too few bytes to copy, use word copy.  */
+  if (len >= OP_T_THRES)
+    {
+      /* Copy just a few bytes to make DSTP aligned.  */
+      len -= (-dstp) % OPSIZ;
+      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
+
+      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
+	 as much as possible.  */
+
+      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
+
+      /* Copy from SRCP to DSTP taking advantage of the known alignment of
+	 DSTP.  Number of bytes remaining is put in the third argument,
+	 i.e. in LEN.  This number may vary from machine to machine.  */
+
+      WORD_COPY_FWD (dstp, srcp, len, len);
+
+      /* Fall out and copy the tail.  */
+    }
+
+  /* There are just a few bytes to copy.  Use byte memory operations.  */
+  BYTE_COPY_FWD (dstp, srcp, len);
+
+  return (void *) dstp;
+}
+libc_hidden_def (__mempcpy)
+weak_alias (__mempcpy, mempcpy)
+libc_hidden_builtin_def (mempcpy)
diff --git a/string/memrchr.c b/string/memrchr.c
new file mode 100644
index 0000000000..21662b1bd7
--- /dev/null
+++ b/string/memrchr.c
@@ -0,0 +1,210 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+   Copyright (C) 1991, 93, 96, 97, 99, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef __ptr_t
+#if defined __cplusplus || (defined __STDC__ && __STDC__)
+# define __ptr_t void *
+#else /* Not C++ or ANSI C.  */
+# define __ptr_t char *
+#endif /* C++ or ANSI C.  */
+
+#if defined _LIBC
+# include <string.h>
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#if defined HAVE_LIMITS_H || defined _LIBC
+# include <limits.h>
+#endif
+
+#define LONG_MAX_32_BITS 2147483647
+
+#ifndef LONG_MAX
+# define LONG_MAX LONG_MAX_32_BITS
+#endif
+
+#include <sys/types.h>
+
+#undef __memrchr
+#undef memrchr
+
+#ifndef weak_alias
+# define __memrchr memrchr
+#endif
+
+/* Search no more than N bytes of S for C.  */
+__ptr_t
+__memrchr (s, c_in, n)
+     const __ptr_t s;
+     int c_in;
+     size_t n;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the last few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s + n;
+       n > 0 && ((unsigned long int) char_ptr
+		 & (sizeof (longword) - 1)) != 0;
+       --n)
+    if (*--char_ptr == c)
+      return (__ptr_t) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (const unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+
+  if (sizeof (longword) != 4 && sizeof (longword) != 8)
+    abort ();
+
+#if LONG_MAX <= LONG_MAX_32_BITS
+  magic_bits = 0x7efefeff;
+#else
+  magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
+#endif
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+#if LONG_MAX > LONG_MAX_32_BITS
+  charmask |= charmask << 32;
+#endif
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (n >= sizeof (longword))
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *--longword_ptr ^ charmask;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) longword_ptr;
+
+#if LONG_MAX > 2147483647
+	  if (cp[7] == c)
+	    return (__ptr_t) &cp[7];
+	  if (cp[6] == c)
+	    return (__ptr_t) &cp[6];
+	  if (cp[5] == c)
+	    return (__ptr_t) &cp[5];
+	  if (cp[4] == c)
+	    return (__ptr_t) &cp[4];
+#endif
+	  if (cp[3] == c)
+	    return (__ptr_t) &cp[3];
+	  if (cp[2] == c)
+	    return (__ptr_t) &cp[2];
+	  if (cp[1] == c)
+	    return (__ptr_t) &cp[1];
+	  if (cp[0] == c)
+	    return (__ptr_t) cp;
+	}
+
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  while (n-- > 0)
+    {
+      if (*--char_ptr == c)
+	return (__ptr_t) char_ptr;
+    }
+
+  return 0;
+}
+#ifdef weak_alias
+weak_alias (__memrchr, memrchr)
+#endif
diff --git a/string/memset.c b/string/memset.c
new file mode 100644
index 0000000000..592b11e435
--- /dev/null
+++ b/string/memset.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef memset
+
+void *
+memset (dstpp, c, len)
+     void *dstpp;
+     int c;
+     size_t len;
+{
+  long int dstp = (long int) dstpp;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+      op_t cccc;
+
+      cccc = (unsigned char) c;
+      cccc |= cccc << 8;
+      cccc |= cccc << 16;
+      if (OPSIZ > 4)
+	/* Do the shift in two steps to avoid warning if long has 32 bits.  */
+	cccc |= (cccc << 16) << 16;
+
+      /* There are at least some bytes to set.
+	 No need to test for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+	{
+	  ((byte *) dstp)[0] = c;
+	  dstp += 1;
+	  len -= 1;
+	}
+
+      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  ((op_t *) dstp)[1] = cccc;
+	  ((op_t *) dstp)[2] = cccc;
+	  ((op_t *) dstp)[3] = cccc;
+	  ((op_t *) dstp)[4] = cccc;
+	  ((op_t *) dstp)[5] = cccc;
+	  ((op_t *) dstp)[6] = cccc;
+	  ((op_t *) dstp)[7] = cccc;
+	  dstp += 8 * OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ * 8;
+
+      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
+      xlen = len / OPSIZ;
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  dstp += OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len > 0)
+    {
+      ((byte *) dstp)[0] = c;
+      dstp += 1;
+      len -= 1;
+    }
+
+  return dstpp;
+}
+libc_hidden_builtin_def (memset)
diff --git a/string/rawmemchr.c b/string/rawmemchr.c
new file mode 100644
index 0000000000..cb00ad7e90
--- /dev/null
+++ b/string/rawmemchr.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 1991,93,96,97,99,2000,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef __ptr_t
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+# define __ptr_t void *
+#else /* Not C++ or ANSI C.  */
+# define __ptr_t char *
+#endif /* C++ or ANSI C.  */
+
+#if defined (_LIBC)
+# include <string.h>
+# include <memcopy.h>
+# include <stdlib.h>
+#else
+# define reg_char char
+#endif
+
+#if defined (HAVE_LIMITS_H) || defined (_LIBC)
+# include <limits.h>
+#endif
+
+#define LONG_MAX_32_BITS 2147483647
+
+#ifndef LONG_MAX
+#define LONG_MAX LONG_MAX_32_BITS
+#endif
+
+#include <sys/types.h>
+
+#undef memchr
+
+
+/* Find the first occurrence of C in S.  */
+__ptr_t
+__rawmemchr (s, c_in)
+     const __ptr_t s;
+     int c_in;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == c)
+      return (__ptr_t) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+
+  if (sizeof (longword) != 4 && sizeof (longword) != 8)
+    abort ();
+
+#if LONG_MAX <= LONG_MAX_32_BITS
+  magic_bits = 0x7efefeff;
+#else
+  magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
+#endif
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+#if LONG_MAX > LONG_MAX_32_BITS
+  charmask |= charmask << 32;
+#endif
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (1)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C, not zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *longword_ptr++ ^ charmask;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+	  if (cp[0] == c)
+	    return (__ptr_t) cp;
+	  if (cp[1] == c)
+	    return (__ptr_t) &cp[1];
+	  if (cp[2] == c)
+	    return (__ptr_t) &cp[2];
+	  if (cp[3] == c)
+	    return (__ptr_t) &cp[3];
+#if LONG_MAX > 2147483647
+	  if (cp[4] == c)
+	    return (__ptr_t) &cp[4];
+	  if (cp[5] == c)
+	    return (__ptr_t) &cp[5];
+	  if (cp[6] == c)
+	    return (__ptr_t) &cp[6];
+	  if (cp[7] == c)
+	    return (__ptr_t) &cp[7];
+#endif
+	}
+    }
+}
+libc_hidden_def (__rawmemchr)
+weak_alias (__rawmemchr, rawmemchr)
diff --git a/string/stpcpy.c b/string/stpcpy.c
new file mode 100644
index 0000000000..6e42911fde
--- /dev/null
+++ b/string/stpcpy.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1992, 1995, 1997, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#undef __stpcpy
+#undef stpcpy
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
+char *
+__stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  register char *d = dest;
+  register const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__stpcpy)
+#endif
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
+#ifdef libc_hidden_builtin_def
+libc_hidden_builtin_def (stpcpy)
+#endif
diff --git a/string/stpncpy.c b/string/stpncpy.c
new file mode 100644
index 0000000000..164d0f1747
--- /dev/null
+++ b/string/stpncpy.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This is almost copied from strncpy.c, written by Torbjorn Granlund.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <string.h>
+#else
+# include <sys/types.h>
+#endif
+
+#ifndef weak_alias
+# define __stpncpy stpncpy
+#endif
+
+/* Copy no more than N characters of SRC to DEST, returning the address of
+   the terminating '\0' in DEST, if any, or else DEST + N.  */
+char *
+__stpncpy (dest, src, n)
+     char *dest;
+     const char *src;
+     size_t n;
+{
+  char c;
+  char *s = dest;
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+
+      for (;;)
+	{
+	  c = *src++;
+	  *dest++ = c;
+	  if (c == '\0')
+	    break;
+	  c = *src++;
+	  *dest++ = c;
+	  if (c == '\0')
+	    break;
+	  c = *src++;
+	  *dest++ = c;
+	  if (c == '\0')
+	    break;
+	  c = *src++;
+	  *dest++ = c;
+	  if (c == '\0')
+	    break;
+	  if (--n4 == 0)
+	    goto last_chars;
+	}
+      n -= dest - s;
+      goto zero_fill;
+    }
+
+ last_chars:
+  n &= 3;
+  if (n == 0)
+    return dest;
+
+  for (;;)
+    {
+      c = *src++;
+      --n;
+      *dest++ = c;
+      if (c == '\0')
+	break;
+      if (n == 0)
+	return dest;
+    }
+
+ zero_fill:
+  while (n-- > 0)
+    dest[n] = '\0';
+
+  return dest - 1;
+}
+#ifdef weak_alias
+libc_hidden_def (__stpncpy)
+weak_alias (__stpncpy, stpncpy)
+#endif
diff --git a/string/strcasecmp.c b/string/strcasecmp.c
new file mode 100644
index 0000000000..3ae3d67d04
--- /dev/null
+++ b/string/strcasecmp.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991,1992,1995,1996,1997,2001,2002, 2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <string.h>
+
+#ifndef _LIBC
+# define __strcasecmp strcasecmp
+# define TOLOWER(Ch) tolower (Ch)
+#else
+# include <locale/localeinfo.h>
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define __strcasecmp __strcasecmp_l
+# endif
+# define TOLOWER(Ch) __tolower_l ((Ch), loc)
+#endif
+
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_DECL __locale_t loc;
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_DECL
+#endif
+
+/* Compare S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than,
+   equal to or greater than S2.  */
+int
+__strcasecmp (s1, s2 LOCALE_PARAM)
+     const char *s1;
+     const char *s2;
+     LOCALE_PARAM_DECL
+{
+#if defined _LIBC && !defined USE_IN_EXTENDED_LOCALE_MODEL
+  __locale_t loc = _NL_CURRENT_LOCALE;
+#endif
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  int result;
+
+  if (p1 == p2)
+    return 0;
+
+  while ((result = TOLOWER (*p1) - TOLOWER (*p2++)) == 0)
+    if (*p1++ == '\0')
+      break;
+
+  return result;
+}
+#ifndef __strcasecmp
+libc_hidden_def (__strcasecmp)
+weak_alias (__strcasecmp, strcasecmp)
+#endif
diff --git a/string/strcasecmp_l.c b/string/strcasecmp_l.c
new file mode 100644
index 0000000000..498a27d975
--- /dev/null
+++ b/string/strcasecmp_l.c
@@ -0,0 +1,23 @@
+/* Copyright (C) 1997, 2002, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#include "strcasecmp.c"
+
+libc_hidden_def (__strcasecmp_l)
+weak_alias (__strcasecmp_l, strcasecmp_l)
diff --git a/string/strcasestr.c b/string/strcasestr.c
new file mode 100644
index 0000000000..1dde43c606
--- /dev/null
+++ b/string/strcasestr.c
@@ -0,0 +1,142 @@
+/* Return the offset of one string within another.
+   Copyright (C) 1994, 1996-2000, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*
+ * My personal strstr() implementation that beats most other algorithms.
+ * Until someone tells me otherwise, I assume that this is the
+ * fastest implementation of strstr() in C.
+ * I deliberately chose not to comment it.  You should have at least
+ * as much fun trying to understand it, as I had to write it :-).
+ *
+ * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de	*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef _LIBC
+# include <locale/localeinfo.h>
+# define TOLOWER(c) __tolower_l ((unsigned char) c, loc)
+#else
+# define TOLOWER(c) _tolower (c)
+#endif
+
+typedef unsigned chartype;
+
+#undef strcasestr
+#undef __strcasestr
+
+char *
+__strcasestr (phaystack, pneedle)
+     const char *phaystack;
+     const char *pneedle;
+{
+  register const unsigned char *haystack, *needle;
+  register chartype b, c;
+#ifdef _LIBC
+  __locale_t loc = _NL_CURRENT_LOCALE;
+#endif
+
+  haystack = (const unsigned char *) phaystack;
+  needle = (const unsigned char *) pneedle;
+
+  b = TOLOWER (*needle);
+  if (b != '\0')
+    {
+      haystack--;				/* possible ANSI violation */
+      do
+	{
+	  c = *++haystack;
+	  if (c == '\0')
+	    goto ret0;
+	}
+      while (TOLOWER (c) != (int) b);
+
+      c = TOLOWER (*++needle);
+      if (c == '\0')
+	goto foundneedle;
+      ++needle;
+      goto jin;
+
+      for (;;)
+        {
+          register chartype a;
+	  register const unsigned char *rhaystack, *rneedle;
+
+	  do
+	    {
+	      a = *++haystack;
+	      if (a == '\0')
+		goto ret0;
+	      if (TOLOWER (a) == (int) b)
+		break;
+	      a = *++haystack;
+	      if (a == '\0')
+		goto ret0;
+shloop:
+	      ;
+	    }
+          while (TOLOWER (a) != (int) b);
+
+jin:	  a = *++haystack;
+	  if (a == '\0')
+	    goto ret0;
+
+	  if (TOLOWER (a) != (int) c)
+	    goto shloop;
+
+	  rhaystack = haystack-- + 1;
+	  rneedle = needle;
+	  a = TOLOWER (*rneedle);
+
+	  if (TOLOWER (*rhaystack) == (int) a)
+	    do
+	      {
+		if (a == '\0')
+		  goto foundneedle;
+		++rhaystack;
+		a = TOLOWER (*++needle);
+		if (TOLOWER (*rhaystack) != (int) a)
+		  break;
+		if (a == '\0')
+		  goto foundneedle;
+		++rhaystack;
+		a = TOLOWER (*++needle);
+	      }
+	    while (TOLOWER (*rhaystack) == (int) a);
+
+	  needle = rneedle;		/* took the register-poor approach */
+
+	  if (a == '\0')
+	    break;
+        }
+    }
+foundneedle:
+  return (char*) haystack;
+ret0:
+  return 0;
+}
+
+weak_alias (__strcasestr, strcasestr)
diff --git a/string/strcat.c b/string/strcat.c
new file mode 100644
index 0000000000..eef22add36
--- /dev/null
+++ b/string/strcat.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef strcat
+
+/* Append SRC on the end of DEST.  */
+char *
+strcat (dest, src)
+     char *dest;
+     const char *src;
+{
+  char *s1 = dest;
+  const char *s2 = src;
+  reg_char c;
+
+  /* Find the end of the string.  */
+  do
+    c = *s1++;
+  while (c != '\0');
+
+  /* Make S1 point before the next character, so we can increment
+     it while memory is read (wins on pipelined cpus).  */
+  s1 -= 2;
+
+  do
+    {
+      c = *s2++;
+      *++s1 = c;
+    }
+  while (c != '\0');
+
+  return dest;
+}
+libc_hidden_builtin_def (strcat)
diff --git a/string/strchr.c b/string/strchr.c
new file mode 100644
index 0000000000..5afd364533
--- /dev/null
+++ b/string/strchr.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 1991,1993-1997,1999,2000,2003,2006
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   bug fix and commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+#include <stdlib.h>
+
+#undef strchr
+
+/* Find the first occurrence of C in S.  */
+char *
+strchr (s, c_in)
+     const char *s;
+     int c_in;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == c)
+      return (void *) char_ptr;
+    else if (*char_ptr == '\0')
+      return NULL;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  switch (sizeof (longword))
+    {
+    case 4: magic_bits = 0x7efefeffL; break;
+    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
+    default:
+      abort ();
+    }
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+  if (sizeof (longword) > 4)
+    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+    charmask |= (charmask << 16) << 16;
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  for (;;)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C as well as zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *longword_ptr++;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0 ||
+
+	  /* That caught zeroes.  Now test for C.  */
+	  ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C or zero?
+	     If none of them were, it was a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+	  if (*cp == c)
+	    return (char *) cp;
+	  else if (*cp == '\0')
+	    return NULL;
+	  if (*++cp == c)
+	    return (char *) cp;
+	  else if (*cp == '\0')
+	    return NULL;
+	  if (*++cp == c)
+	    return (char *) cp;
+	  else if (*cp == '\0')
+	    return NULL;
+	  if (*++cp == c)
+	    return (char *) cp;
+	  else if (*cp == '\0')
+	    return NULL;
+	  if (sizeof (longword) > 4)
+	    {
+	      if (*++cp == c)
+		return (char *) cp;
+	      else if (*cp == '\0')
+		return NULL;
+	      if (*++cp == c)
+		return (char *) cp;
+	      else if (*cp == '\0')
+		return NULL;
+	      if (*++cp == c)
+		return (char *) cp;
+	      else if (*cp == '\0')
+		return NULL;
+	      if (*++cp == c)
+		return (char *) cp;
+	      else if (*cp == '\0')
+		return NULL;
+	    }
+	}
+    }
+
+  return NULL;
+}
+
+#ifdef weak_alias
+#undef index
+weak_alias (strchr, index)
+#endif
+libc_hidden_builtin_def (strchr)
diff --git a/string/strchrnul.c b/string/strchrnul.c
new file mode 100644
index 0000000000..88b96dd126
--- /dev/null
+++ b/string/strchrnul.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 1991,1993-1997,99,2000,2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se) and
+   bug fix and commentary by Jim Blandy (jimb@ai.mit.edu);
+   adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+   and implemented by Roland McGrath (roland@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+#include <stdlib.h>
+
+#undef __strchrnul
+#undef strchrnul
+
+/* Find the first occurrence of C in S or the final NUL byte.  */
+char *
+__strchrnul (s, c_in)
+     const char *s;
+     int c_in;
+{
+  const unsigned char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, charmask;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == c || *char_ptr == '\0')
+      return (void *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  switch (sizeof (longword))
+    {
+    case 4: magic_bits = 0x7efefeffL; break;
+    case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break;
+    default:
+      abort ();
+    }
+
+  /* Set up a longword, each of whose bytes is C.  */
+  charmask = c | (c << 8);
+  charmask |= charmask << 16;
+  if (sizeof (longword) > 4)
+    /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+    charmask |= (charmask << 16) << 16;
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  for (;;)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.
+
+	 3) But wait!  Aren't we looking for C as well as zero?
+	 Good point.  So what we do is XOR LONGWORD with a longword,
+	 each of whose bytes is C.  This turns each byte that is C
+	 into a zero.  */
+
+      longword = *longword_ptr++;
+
+      /* Add MAGIC_BITS to LONGWORD.  */
+      if ((((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits) != 0 ||
+
+	  /* That caught zeroes.  Now test for C.  */
+	  ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask))
+	   & ~magic_bits) != 0)
+	{
+	  /* Which of the bytes was C or zero?
+	     If none of them were, it was a misfire; continue the search.  */
+
+	  const unsigned char *cp = (const unsigned char *) (longword_ptr - 1);
+
+	  if (*cp == c || *cp == '\0')
+	    return (char *) cp;
+	  if (*++cp == c || *cp == '\0')
+	    return (char *) cp;
+	  if (*++cp == c || *cp == '\0')
+	    return (char *) cp;
+	  if (*++cp == c || *cp == '\0')
+	    return (char *) cp;
+	  if (sizeof (longword) > 4)
+	    {
+	      if (*++cp == c || *cp == '\0')
+		return (char *) cp;
+	      if (*++cp == c || *cp == '\0')
+		return (char *) cp;
+	      if (*++cp == c || *cp == '\0')
+		return (char *) cp;
+	      if (*++cp == c || *cp == '\0')
+		return (char *) cp;
+	    }
+	}
+    }
+
+  /* This should never happen.  */
+  return NULL;
+}
+
+weak_alias (__strchrnul, strchrnul)
diff --git a/string/strcmp.c b/string/strcmp.c
new file mode 100644
index 0000000000..bd53c05c6e
--- /dev/null
+++ b/string/strcmp.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef strcmp
+
+/* Compare S1 and S2, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than,
+   equal to or greater than S2.  */
+int
+strcmp (p1, p2)
+     const char *p1;
+     const char *p2;
+{
+  register const unsigned char *s1 = (const unsigned char *) p1;
+  register const unsigned char *s2 = (const unsigned char *) p2;
+  unsigned reg_char c1, c2;
+
+  do
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0')
+	return c1 - c2;
+    }
+  while (c1 == c2);
+
+  return c1 - c2;
+}
+libc_hidden_builtin_def (strcmp)
diff --git a/string/strcoll.c b/string/strcoll.c
index 8a73cae564..8e8fdc7792 100644
--- a/string/strcoll.c
+++ b/string/strcoll.c
@@ -23,6 +23,7 @@
 # define STRING_TYPE char
 # define STRCOLL strcoll
 # define STRCOLL_L __strcoll_l
+# define USE_HIDDEN_DEF
 #endif
 
 #include "../locale/localeinfo.h"
@@ -35,6 +36,7 @@ STRCOLL (s1, s2)
 {
   return STRCOLL_L (s1, s2, _NL_CURRENT_LOCALE);
 }
-#if !defined WIDE_CHAR_VERSION
-libc_hidden_def (strcoll)
+
+#ifdef USE_HIDDEN_DEF
+libc_hidden_def (STRCOLL)
 #endif
diff --git a/string/strcpy.c b/string/strcpy.c
new file mode 100644
index 0000000000..c736a60762
--- /dev/null
+++ b/string/strcpy.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1991, 1997, 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stddef.h>
+#include <string.h>
+#include <memcopy.h>
+#include <bp-checks.h>
+
+#undef strcpy
+
+/* Copy SRC to DEST.  */
+char *
+strcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  reg_char c;
+  char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
+  const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
+  size_t n;
+
+  do
+    {
+      c = *s++;
+      s[off] = c;
+    }
+  while (c != '\0');
+
+  n = s - src;
+  (void) CHECK_BOUNDS_HIGH (src + n);
+  (void) CHECK_BOUNDS_HIGH (dest + n);
+
+  return dest;
+}
+libc_hidden_builtin_def (strcpy)
diff --git a/string/strcspn.c b/string/strcspn.c
new file mode 100644
index 0000000000..f359d578f7
--- /dev/null
+++ b/string/strcspn.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1991, 1994, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined _LIBC || HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+# ifndef strchr
+#  define strchr index
+# endif
+#endif
+
+#undef strcspn
+
+/* Return the length of the maximum initial segment of S
+   which contains no characters from REJECT.  */
+size_t
+strcspn (s, reject)
+     const char *s;
+     const char *reject;
+{
+  size_t count = 0;
+
+  while (*s != '\0')
+    if (strchr (reject, *s++) == NULL)
+      ++count;
+    else
+      return count;
+
+  return count;
+}
+libc_hidden_builtin_def (strcspn)
diff --git a/string/string-inlines.c b/string/string-inlines.c
new file mode 100644
index 0000000000..89a5baab5d
--- /dev/null
+++ b/string/string-inlines.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*  <bits/string.h> and <bits/string2.h> declare some extern inline
+    functions.  These functions are declared additionally here if
+    inlining is not possible.  */
+
+#undef __USE_STRING_INLINES
+#define __USE_STRING_INLINES
+#define _FORCE_INLINES
+#define __STRING_INLINE /* empty */
+#define __NO_INLINE__
+
+#include <string.h>
+#undef index
+#undef rindex
+
+#undef __NO_INLINE__
+#include <bits/string.h>
+#include <bits/string2.h>
diff --git a/string/strlen.c b/string/strlen.c
new file mode 100644
index 0000000000..9bc9db68f7
--- /dev/null
+++ b/string/strlen.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se);
+   commentary by Jim Blandy (jimb@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <stdlib.h>
+
+#undef strlen
+
+/* Return the length of the null-terminated string STR.  Scan for
+   the null terminator quickly by testing four bytes at a time.  */
+size_t
+strlen (str)
+     const char *str;
+{
+  const char *char_ptr;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, himagic, lomagic;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = str; ((unsigned long int) char_ptr
+			& (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == '\0')
+      return char_ptr - str;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  magic_bits = 0x7efefeffL;
+  himagic = 0x80808080L;
+  lomagic = 0x01010101L;
+  if (sizeof (longword) > 4)
+    {
+      /* 64-bit version of the magic.  */
+      /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+      magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
+      himagic = ((himagic << 16) << 16) | himagic;
+      lomagic = ((lomagic << 16) << 16) | lomagic;
+    }
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  for (;;)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.  */
+
+      longword = *longword_ptr++;
+
+      if (
+#if 0
+	  /* Add MAGIC_BITS to LONGWORD.  */
+	  (((longword + magic_bits)
+
+	    /* Set those bits that were unchanged by the addition.  */
+	    ^ ~longword)
+
+	   /* Look at only the hole bits.  If any of the hole bits
+	      are unchanged, most likely one of the bytes was a
+	      zero.  */
+	   & ~magic_bits)
+#else
+	  ((longword - lomagic) & himagic)
+#endif
+	  != 0)
+	{
+	  /* Which of the bytes was the zero?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const char *cp = (const char *) (longword_ptr - 1);
+
+	  if (cp[0] == 0)
+	    return cp - str;
+	  if (cp[1] == 0)
+	    return cp - str + 1;
+	  if (cp[2] == 0)
+	    return cp - str + 2;
+	  if (cp[3] == 0)
+	    return cp - str + 3;
+	  if (sizeof (longword) > 4)
+	    {
+	      if (cp[4] == 0)
+		return cp - str + 4;
+	      if (cp[5] == 0)
+		return cp - str + 5;
+	      if (cp[6] == 0)
+		return cp - str + 6;
+	      if (cp[7] == 0)
+		return cp - str + 7;
+	    }
+	}
+    }
+}
+libc_hidden_builtin_def (strlen)
diff --git a/string/strncase.c b/string/strncase.c
new file mode 100644
index 0000000000..a55aaf6a3a
--- /dev/null
+++ b/string/strncase.c
@@ -0,0 +1,76 @@
+/* Compare at most N characters of two strings without taking care for
+   the case.
+   Copyright (C) 1992, 1996, 1997, 2001, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#ifndef weak_alias
+# define __strncasecmp strncasecmp
+# define TOLOWER(Ch) tolower (Ch)
+#else
+# include <locale/localeinfo.h>
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define __strncasecmp __strncasecmp_l
+# endif
+# define TOLOWER(Ch) __tolower_l ((Ch), loc)
+#endif
+
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_DECL __locale_t loc;
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_DECL
+#endif
+
+/* Compare no more than N characters of S1 and S2,
+   ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexicographically less
+   than, equal to or greater than S2.  */
+int
+__strncasecmp (s1, s2, n LOCALE_PARAM)
+     const char *s1;
+     const char *s2;
+     size_t n;
+     LOCALE_PARAM_DECL
+{
+#if defined _LIBC && !defined USE_IN_EXTENDED_LOCALE_MODEL
+  __locale_t loc = _NL_CURRENT_LOCALE;
+#endif
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  int result;
+
+  if (p1 == p2 || n == 0)
+    return 0;
+
+  while ((result = TOLOWER (*p1) - TOLOWER (*p2++)) == 0)
+    if (*p1++ == '\0' || --n == 0)
+      break;
+
+  return result;
+}
+#ifndef __strncasecmp
+weak_alias (__strncasecmp, strncasecmp)
+#endif
diff --git a/string/strncase_l.c b/string/strncase_l.c
new file mode 100644
index 0000000000..0f22b46de1
--- /dev/null
+++ b/string/strncase_l.c
@@ -0,0 +1,25 @@
+/* Compare at most N characters of two strings without taking care for
+   the case using given locale.
+   Copyright (C) 1997, 2002, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#include "strncase.c"
+
+libc_hidden_def (__strncasecmp_l)
+weak_alias (__strncasecmp_l, strncasecmp_l)
diff --git a/string/strncat.c b/string/strncat.c
new file mode 100644
index 0000000000..2e2de11508
--- /dev/null
+++ b/string/strncat.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#ifdef _LIBC
+# include <memcopy.h>
+#else
+typedef char reg_char;
+#endif
+
+#undef strncat
+
+char *
+strncat (s1, s2, n)
+     char *s1;
+     const char *s2;
+     size_t n;
+{
+  reg_char c;
+  char *s = s1;
+
+  /* Find the end of S1.  */
+  do
+    c = *s1++;
+  while (c != '\0');
+
+  /* Make S1 point before next character, so we can increment
+     it while memory is read (wins on pipelined cpus).  */
+  s1 -= 2;
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+      do
+	{
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    return s;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    return s;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    return s;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    return s;
+	} while (--n4 > 0);
+      n &= 3;
+    }
+
+  while (n > 0)
+    {
+      c = *s2++;
+      *++s1 = c;
+      if (c == '\0')
+	return s;
+      n--;
+    }
+
+  if (c != '\0')
+    *++s1 = '\0';
+
+  return s;
+}
diff --git a/string/strncmp.c b/string/strncmp.c
new file mode 100644
index 0000000000..1adb2c0ebd
--- /dev/null
+++ b/string/strncmp.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef strncmp
+
+/* Compare no more than N characters of S1 and S2,
+   returning less than, equal to or greater than zero
+   if S1 is lexicographically less than, equal to or
+   greater than S2.  */
+int
+strncmp (s1, s2, n)
+     const char *s1;
+     const char *s2;
+     size_t n;
+{
+  unsigned reg_char c1 = '\0';
+  unsigned reg_char c2 = '\0';
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+      do
+	{
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	} while (--n4 > 0);
+      n &= 3;
+    }
+
+  while (n > 0)
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0' || c1 != c2)
+	return c1 - c2;
+      n--;
+    }
+
+  return c1 - c2;
+}
+libc_hidden_builtin_def (strncmp)
diff --git a/string/strncpy.c b/string/strncpy.c
new file mode 100644
index 0000000000..f32612e1cf
--- /dev/null
+++ b/string/strncpy.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef strncpy
+
+char *
+strncpy (s1, s2, n)
+     char *s1;
+     const char *s2;
+     size_t n;
+{
+  reg_char c;
+  char *s = s1;
+
+  --s1;
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+
+      for (;;)
+	{
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    break;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    break;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    break;
+	  c = *s2++;
+	  *++s1 = c;
+	  if (c == '\0')
+	    break;
+	  if (--n4 == 0)
+	    goto last_chars;
+	}
+      n = n - (s1 - s) - 1;
+      if (n == 0)
+	return s;
+      goto zero_fill;
+    }
+
+ last_chars:
+  n &= 3;
+  if (n == 0)
+    return s;
+
+  do
+    {
+      c = *s2++;
+      *++s1 = c;
+      if (--n == 0)
+	return s;
+    }
+  while (c != '\0');
+
+ zero_fill:
+  do
+    *++s1 = '\0';
+  while (--n > 0);
+
+  return s;
+}
+libc_hidden_builtin_def (strncpy)
diff --git a/string/strnlen.c b/string/strnlen.c
new file mode 100644
index 0000000000..454257b2bc
--- /dev/null
+++ b/string/strnlen.c
@@ -0,0 +1,161 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+   Copyright (C) 1991,1993,1997,2000,2001,2005 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+   Based on strlen written by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se);
+   commentary by Jim Blandy (jimb@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <string.h>
+#include <stdlib.h>
+
+/* Find the length of S, but scan at most MAXLEN characters.  If no
+   '\0' terminator is found in that many characters, return MAXLEN.  */
+size_t
+__strnlen (const char *str, size_t maxlen)
+{
+  const char *char_ptr, *end_ptr = str + maxlen;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, himagic, lomagic;
+
+  if (maxlen == 0)
+    return 0;
+
+  if (__builtin_expect (end_ptr < str, 0))
+    end_ptr = (const char *) ~0UL;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = str; ((unsigned long int) char_ptr
+			& (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == '\0')
+      {
+	if (char_ptr > end_ptr)
+	  char_ptr = end_ptr;
+	return char_ptr - str;
+      }
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  magic_bits = 0x7efefeffL;
+  himagic = 0x80808080L;
+  lomagic = 0x01010101L;
+  if (sizeof (longword) > 4)
+    {
+      /* 64-bit version of the magic.  */
+      /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+      magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
+      himagic = ((himagic << 16) << 16) | himagic;
+      lomagic = ((lomagic << 16) << 16) | lomagic;
+    }
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (longword_ptr < (unsigned long int *) end_ptr)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.  */
+
+      longword = *longword_ptr++;
+
+      if ((longword - lomagic) & himagic)
+	{
+	  /* Which of the bytes was the zero?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const char *cp = (const char *) (longword_ptr - 1);
+
+	  char_ptr = cp;
+	  if (cp[0] == 0)
+	    break;
+	  char_ptr = cp + 1;
+	  if (cp[1] == 0)
+	    break;
+	  char_ptr = cp + 2;
+	  if (cp[2] == 0)
+	    break;
+	  char_ptr = cp + 3;
+	  if (cp[3] == 0)
+	    break;
+	  if (sizeof (longword) > 4)
+	    {
+	      char_ptr = cp + 4;
+	      if (cp[4] == 0)
+		break;
+	      char_ptr = cp + 5;
+	      if (cp[5] == 0)
+		break;
+	      char_ptr = cp + 6;
+	      if (cp[6] == 0)
+		break;
+	      char_ptr = cp + 7;
+	      if (cp[7] == 0)
+		break;
+	    }
+	}
+      char_ptr = end_ptr;
+    }
+
+  if (char_ptr > end_ptr)
+    char_ptr = end_ptr;
+  return char_ptr - str;
+}
+weak_alias (__strnlen, strnlen)
+libc_hidden_def (strnlen)
diff --git a/string/strpbrk.c b/string/strpbrk.c
new file mode 100644
index 0000000000..620cfab7f9
--- /dev/null
+++ b/string/strpbrk.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 1994, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined _LIBC || defined HAVE_CONFIG_H
+# include <string.h>
+#endif
+
+#undef strpbrk
+
+/* Find the first occurrence in S of any character in ACCEPT.  */
+char *
+strpbrk (s, accept)
+     const char *s;
+     const char *accept;
+{
+  while (*s != '\0')
+    {
+      const char *a = accept;
+      while (*a != '\0')
+	if (*a++ == *s)
+	  return (char *) s;
+      ++s;
+    }
+
+  return NULL;
+}
+libc_hidden_builtin_def (strpbrk)
diff --git a/string/strrchr.c b/string/strrchr.c
new file mode 100644
index 0000000000..64118b87ef
--- /dev/null
+++ b/string/strrchr.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#undef strrchr
+
+/* Find the last occurrence of C in S.  */
+char *
+strrchr (const char *s, int c)
+{
+  register const char *found, *p;
+
+  c = (unsigned char) c;
+
+  /* Since strchr is fast, we use it rather than the obvious loop.  */
+
+  if (c == '\0')
+    return strchr (s, '\0');
+
+  found = NULL;
+  while ((p = strchr (s, c)) != NULL)
+    {
+      found = p;
+      s = p + 1;
+    }
+
+  return (char *) found;
+}
+
+#ifdef weak_alias
+#undef rindex
+weak_alias (strrchr, rindex)
+#endif
+libc_hidden_builtin_def (strrchr)
diff --git a/string/strsep.c b/string/strsep.c
new file mode 100644
index 0000000000..e5342f7a22
--- /dev/null
+++ b/string/strsep.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1992, 93, 96, 97, 98, 99, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#undef __strsep
+#undef strsep
+
+char *
+__strsep (char **stringp, const char *delim)
+{
+  char *begin, *end;
+
+  begin = *stringp;
+  if (begin == NULL)
+    return NULL;
+
+  /* A frequent case is when the delimiter string contains only one
+     character.  Here we don't need to call the expensive `strpbrk'
+     function and instead work using `strchr'.  */
+  if (delim[0] == '\0' || delim[1] == '\0')
+    {
+      char ch = delim[0];
+
+      if (ch == '\0')
+	end = NULL;
+      else
+	{
+	  if (*begin == ch)
+	    end = begin;
+	  else if (*begin == '\0')
+	    end = NULL;
+	  else
+	    end = strchr (begin + 1, ch);
+	}
+    }
+  else
+    /* Find the end of the token.  */
+    end = strpbrk (begin, delim);
+
+  if (end)
+    {
+      /* Terminate the token and set *STRINGP past NUL character.  */
+      *end++ = '\0';
+      *stringp = end;
+    }
+  else
+    /* No more delimiters; this is the last token.  */
+    *stringp = NULL;
+
+  return begin;
+}
+weak_alias (__strsep, strsep)
+strong_alias (__strsep, __strsep_g)
+libc_hidden_def (__strsep_g)
diff --git a/string/strsignal.c b/string/strsignal.c
index 8ff01a4731..8c5ed1e621 100644
--- a/string/strsignal.c
+++ b/string/strsignal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1994-2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1994-2002, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -24,10 +24,6 @@
 #include <bits/libc-lock.h>
 
 
-#ifndef	HAVE_GNU_LD
-#define	_sys_siglist	sys_siglist
-#endif
-
 /* Defined in siglist.c.  */
 extern const char *const _sys_siglist[];
 extern const char *const _sys_siglist_internal[] attribute_hidden;
diff --git a/string/strspn.c b/string/strspn.c
new file mode 100644
index 0000000000..dc17ea8cbc
--- /dev/null
+++ b/string/strspn.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+#undef strspn
+
+/* Return the length of the maximum initial segment
+   of S which contains only characters in ACCEPT.  */
+size_t
+strspn (s, accept)
+     const char *s;
+     const char *accept;
+{
+  const char *p;
+  const char *a;
+  size_t count = 0;
+
+  for (p = s; *p != '\0'; ++p)
+    {
+      for (a = accept; *a != '\0'; ++a)
+	if (*p == *a)
+	  break;
+      if (*a == '\0')
+	return count;
+      else
+	++count;
+    }
+
+  return count;
+}
+libc_hidden_builtin_def (strspn)
diff --git a/string/strstr.c b/string/strstr.c
new file mode 100644
index 0000000000..fce1f2a756
--- /dev/null
+++ b/string/strstr.c
@@ -0,0 +1,123 @@
+/* Return the offset of one string within another.
+   Copyright (C) 1994,1996,1997,2000,2001,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*
+ * My personal strstr() implementation that beats most other algorithms.
+ * Until someone tells me otherwise, I assume that this is the
+ * fastest implementation of strstr() in C.
+ * I deliberately chose not to comment it.  You should have at least
+ * as much fun trying to understand it, as I had to write it :-).
+ *
+ * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de	*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+#endif
+
+typedef unsigned chartype;
+
+#undef strstr
+
+char *
+strstr (phaystack, pneedle)
+     const char *phaystack;
+     const char *pneedle;
+{
+  const unsigned char *haystack, *needle;
+  chartype b;
+  const unsigned char *rneedle;
+
+  haystack = (const unsigned char *) phaystack;
+
+  if ((b = *(needle = (const unsigned char *) pneedle)))
+    {
+      chartype c;
+      haystack--;		/* possible ANSI violation */
+
+      {
+	chartype a;
+	do
+	  if (!(a = *++haystack))
+	    goto ret0;
+	while (a != b);
+      }
+
+      if (!(c = *++needle))
+	goto foundneedle;
+      ++needle;
+      goto jin;
+
+      for (;;)
+	{
+	  {
+	    chartype a;
+	    if (0)
+	    jin:{
+		if ((a = *++haystack) == c)
+		  goto crest;
+	      }
+	    else
+	      a = *++haystack;
+	    do
+	      {
+		for (; a != b; a = *++haystack)
+		  {
+		    if (!a)
+		      goto ret0;
+		    if ((a = *++haystack) == b)
+		      break;
+		    if (!a)
+		      goto ret0;
+		  }
+	      }
+	    while ((a = *++haystack) != c);
+	  }
+	crest:
+	  {
+	    chartype a;
+	    {
+	      const unsigned char *rhaystack;
+	      if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle)))
+		do
+		  {
+		    if (!a)
+		      goto foundneedle;
+		    if (*++rhaystack != (a = *++needle))
+		      break;
+		    if (!a)
+		      goto foundneedle;
+		  }
+		while (*++rhaystack == (a = *++needle));
+	      needle = rneedle;	/* took the register-poor aproach */
+	    }
+	    if (!a)
+	      break;
+	  }
+	}
+    }
+foundneedle:
+  return (char *) haystack;
+ret0:
+  return 0;
+}
+libc_hidden_builtin_def (strstr)
diff --git a/string/strtok.c b/string/strtok.c
new file mode 100644
index 0000000000..f45b760f74
--- /dev/null
+++ b/string/strtok.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 1991,1996,1997,1999,2000,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <string.h>
+
+
+static char *olds;
+
+#undef strtok
+
+/* Parse S into tokens separated by characters in DELIM.
+   If S is NULL, the last string strtok() was called with is
+   used.  For example:
+	char s[] = "-abc-=-def";
+	x = strtok(s, "-");		// x = "abc"
+	x = strtok(NULL, "-=");		// x = "def"
+	x = strtok(NULL, "=");		// x = NULL
+		// s = "abc\0-def\0"
+*/
+char *
+strtok (s, delim)
+     char *s;
+     const char *delim;
+{
+  char *token;
+
+  if (s == NULL)
+    s = olds;
+
+  /* Scan leading delimiters.  */
+  s += strspn (s, delim);
+  if (*s == '\0')
+    {
+      olds = s;
+      return NULL;
+    }
+
+  /* Find the end of the token.  */
+  token = s;
+  s = strpbrk (token, delim);
+  if (s == NULL)
+    /* This token finishes the string.  */
+    olds = __rawmemchr (token, '\0');
+  else
+    {
+      /* Terminate the token and make OLDS point past it.  */
+      *s = '\0';
+      olds = s + 1;
+    }
+  return token;
+}
diff --git a/string/strtok_r.c b/string/strtok_r.c
new file mode 100644
index 0000000000..b11cb520f6
--- /dev/null
+++ b/string/strtok_r.c
@@ -0,0 +1,79 @@
+/* Reentrant string tokenizer.  Generic version.
+   Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#undef strtok_r
+#undef __strtok_r
+
+#ifndef _LIBC
+/* Get specification.  */
+# include "strtok_r.h"
+# define __strtok_r strtok_r
+# define __rawmemchr strchr
+#endif
+
+/* Parse S into tokens separated by characters in DELIM.
+   If S is NULL, the saved pointer in SAVE_PTR is used as
+   the next starting point.  For example:
+	char s[] = "-abc-=-def";
+	char *sp;
+	x = strtok_r(s, "-", &sp);	// x = "abc", sp = "=-def"
+	x = strtok_r(NULL, "-=", &sp);	// x = "def", sp = NULL
+	x = strtok_r(NULL, "=", &sp);	// x = NULL
+		// s = "abc\0-def\0"
+*/
+char *
+__strtok_r (char *s, const char *delim, char **save_ptr)
+{
+  char *token;
+
+  if (s == NULL)
+    s = *save_ptr;
+
+  /* Scan leading delimiters.  */
+  s += strspn (s, delim);
+  if (*s == '\0')
+    {
+      *save_ptr = s;
+      return NULL;
+    }
+
+  /* Find the end of the token.  */
+  token = s;
+  s = strpbrk (token, delim);
+  if (s == NULL)
+    /* This token finishes the string.  */
+    *save_ptr = __rawmemchr (token, '\0');
+  else
+    {
+      /* Terminate the token and make *SAVE_PTR point past it.  */
+      *s = '\0';
+      *save_ptr = s + 1;
+    }
+  return token;
+}
+#ifdef weak_alias
+libc_hidden_def (__strtok_r)
+weak_alias (__strtok_r, strtok_r)
+#endif
diff --git a/string/strxfrm_l.c b/string/strxfrm_l.c
index 44b605168a..20f2f149bd 100644
--- a/string/strxfrm_l.c
+++ b/string/strxfrm_l.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1995,96,97,2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 2002, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Ulrich Drepper <drepper@gnu.org>, 1995.
 
@@ -96,6 +97,7 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
   const int32_t *indirect;
   uint_fast32_t pass;
   size_t needed;
+  size_t last_needed;
   const USTRING_TYPE *usrc;
   size_t srclen = STRLEN (src);
   int32_t *idxarr;
@@ -197,6 +199,7 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
 	 this is true for all of them.  */
       int position = rule & sort_position;
 
+      last_needed = needed;
       if (position == 0)
 	{
 	  for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
@@ -210,8 +213,9 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
 		      /* Handle the pushed elements now.  */
 		      size_t backw;
 
-		      for (backw = idxcnt - 1; backw >= backw_stop; --backw)
+		      for (backw = idxcnt; backw > backw_stop; )
 			{
+			  --backw;
 			  len = weights[idxarr[backw]++];
 
 			  if (needed + len < n)
@@ -293,8 +297,9 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
 		     /* Handle the pushed elements now.  */
 		      size_t backw;
 
-		      for (backw = idxcnt - 1; backw >= backw_stop; --backw)
+		      for (backw = idxcnt; backw > backw_stop; )
 			{
+			  --backw;
 			  len = weights[idxarr[backw]++];
 			  if (len != 0)
 			    {
@@ -424,11 +429,11 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
      a `position' rule at the end and if no non-ignored character
      is found the last \1 byte is immediately followed by a \0 byte
      signalling this.  We can avoid the \1 byte(s).  */
-  if (needed <= n && needed > 2 && dest[needed - 2] == L('\1'))
+  if (needed > 2 && needed == last_needed + 1)
     {
       /* Remove the \1 byte.  */
-      --needed;
-      dest[needed - 1] = L('\0');
+      if (--needed <= n)
+	dest[needed - 1] = L('\0');
     }
 
   /* Free the memory if needed.  */
diff --git a/string/test-memccpy.c b/string/test-memccpy.c
index b581408f37..26532633df 100644
--- a/string/test-memccpy.c
+++ b/string/test-memccpy.c
@@ -1,5 +1,5 @@
 /* Test and measure memccpy functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -109,8 +109,8 @@ do_test (size_t align1, size_t align2, int c, size_t len, size_t n,
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len - 1; ++i)
     {
diff --git a/string/test-memchr.c b/string/test-memchr.c
index df866fe2d7..c233ead5dd 100644
--- a/string/test-memchr.c
+++ b/string/test-memchr.c
@@ -1,5 +1,5 @@
 /* Test and measure memchr functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -89,7 +89,7 @@ do_test (size_t align, size_t pos, size_t len, int seek_char)
     {
       buf1[align + pos] = seek_char;
       buf1[align + len] = -seek_char;
-      result = buf1 + align + pos;
+      result = (char *) (buf1 + align + pos);
     }
   else
     {
@@ -101,7 +101,7 @@ do_test (size_t align, size_t pos, size_t len, int seek_char)
     printf ("Length %4zd, alignment %2zd:", pos, align);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, buf1 + align, seek_char, len, result);
+    do_one_test (impl, (char *) (buf1 + align), seek_char, len, result);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -144,16 +144,17 @@ do_random_tests (void)
 	}
 
       if (pos < len)
-	result = p + pos + align;
+	result = (char *) (p + pos + align);
       else
 	result = NULL;
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align, seek_char, len) != result)
+	if (CALL (impl, (char *) (p + align), seek_char, len) != result)
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
 		   n, impl->name, align, seek_char, len, pos,
-		   CALL (impl, p + align, seek_char, len), result, p);
+		   CALL (impl, (char *) (p + align), seek_char, len),
+		   result, p);
 	    ret = 1;
 	  }
     }
diff --git a/string/test-memcmp.c b/string/test-memcmp.c
index 89c104386b..af07a5e599 100644
--- a/string/test-memcmp.c
+++ b/string/test-memcmp.c
@@ -1,5 +1,5 @@
 /* Test and measure memcmp functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -88,8 +88,8 @@ do_test (size_t align1, size_t align2, size_t len, int exp_result)
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len; i++)
     s1[i] = s2[i] = 1 + 23 * i % 255;
@@ -161,7 +161,7 @@ do_random_tests (void)
 
       FOR_EACH_IMPL (impl, 1)
 	{
-	  r = CALL (impl, p1 + align1, p2 + align2, len);
+	  r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2), len);
 	  /* Test whether on 64-bit architectures where ABI requires
 	     callee to promote has the promotion been done.  */
 	  asm ("" : "=g" (r) : "0" (r));
diff --git a/string/test-memcpy.c b/string/test-memcpy.c
index adc90da767..7b0723a65a 100644
--- a/string/test-memcpy.c
+++ b/string/test-memcpy.c
@@ -1,5 +1,5 @@
 /* Test and measure memcpy functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -102,8 +102,8 @@ do_test (size_t align1, size_t align2, size_t len)
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0, j = 1; i < len; i++, j += 23)
     s1[i] = j;
@@ -190,7 +190,9 @@ do_random_tests (void)
 	  if (j > size2)
 	    j = size2;
 	  memset (p2, c, j);
-	  res = CALL (impl, p2 + align2, p1 + align1, len);
+	  res = (unsigned char *) CALL (impl,
+					(char *) (p2 + align2),
+					(char *) (p1 + align1), len);
 	  if (res != MEMCPY_RESULT (p2 + align2, len))
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
diff --git a/string/test-memmove.c b/string/test-memmove.c
index 9531aa82d8..2f3a8f7631 100644
--- a/string/test-memmove.c
+++ b/string/test-memmove.c
@@ -101,8 +101,8 @@ do_test (size_t align1, size_t align2, size_t len)
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0, j = 1; i < len; i++, j += 23)
     s1[i] = j;
@@ -111,7 +111,7 @@ do_test (size_t align1, size_t align2, size_t len)
     printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, s2, buf2 + align1, s1, len);
+    do_one_test (impl, s2, (char *) (buf2 + align1), s1, len);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -179,7 +179,9 @@ do_random_tests (void)
 	{
 	  memset (p2 + dststart, c, dstend - dststart);
 	  memcpy (p2 + srcstart, p1 + srcstart, srcend - srcstart);
-	  res = CALL (impl, p2 + align2, p2 + align1, len);
+	  res = (unsigned char *) CALL (impl,
+					(char *) (p2 + align2),
+					(char *) (p2 + align1), len);
 	  if (res != p2 + align2)
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
diff --git a/string/test-memset.c b/string/test-memset.c
index 9ae774162f..601ace4195 100644
--- a/string/test-memset.c
+++ b/string/test-memset.c
@@ -1,5 +1,5 @@
 /* Test and measure memset functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -49,10 +49,12 @@ static void
 do_one_test (impl_t *impl, char *s, int c, size_t n)
 {
   char *res = CALL (impl, s, c, n);
-  if (res != s)
+  char tstbuf[n];
+  if (res != s
+      || simple_memset (tstbuf, c, n) != tstbuf
+      || memcmp (s, tstbuf, n) != 0)
     {
-      error (0, 0, "Wrong result in function %s %p != %p", impl->name,
-	     res, s);
+      error (0, 0, "Wrong result in function %s", impl->name);
       ret = 1;
       return;
     }
@@ -87,7 +89,7 @@ do_test (size_t align, int c, size_t len)
     printf ("Length %4zd, alignment %2zd, c %2d:", len, align, c);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, buf1 + align, c, len);
+    do_one_test (impl, (char *) buf1 + align, c, len);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -143,7 +145,7 @@ do_random_tests (void)
 	      if (p[i + align] == c)
 		p[i + align] = o;
 	    }
-	  res = CALL (impl, p + align, c, len);
+	  res = (unsigned char *) CALL (impl, (char *) p + align, c, len);
 	  if (res != p + align)
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p",
@@ -191,7 +193,7 @@ test_main (void)
     printf ("\t%s", impl->name);
   putchar ('\n');
 
-  for (c = 0; c <= 65; c += 65)
+  for (c = -65; c <= 130; c += 65)
     {
       for (i = 0; i < 18; ++i)
 	do_test (0, c, 1 << i);
diff --git a/string/test-strcat.c b/string/test-strcat.c
index 53c8462839..443752069c 100644
--- a/string/test-strcat.c
+++ b/string/test-strcat.c
@@ -1,5 +1,5 @@
 /* Test and measure strcat functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -91,8 +91,8 @@ do_test (size_t align1, size_t align2, size_t len1, size_t len2, int max_char)
   if (align2 + len1 + len2 >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len1; ++i)
     s1[i] = 32 + 23 * i % (max_char - 32);
@@ -175,7 +175,8 @@ do_random_tests (void)
 	  memset (p2 - 64, '\1', align2 + 64);
 	  memset (p2 + align2 + len2 + 1, '\1', 512 - align2 - len2 - 1);
 	  memcpy (p2 + align2, buf1, len2 + 1);
-	  res = CALL (impl, p2 + align2, p1 + align1);
+	  res = (unsigned char *) CALL (impl, (char *) (p2 + align2),
+					(char *) (p1 + align1));
 	  if (res != p2 + align2)
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd %zd) %p != %p",
diff --git a/string/test-strchr.c b/string/test-strchr.c
index 1333ebc8bc..cf25b449d9 100644
--- a/string/test-strchr.c
+++ b/string/test-strchr.c
@@ -101,10 +101,10 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
   if (pos < len)
     {
       buf1[align + pos] = seek_char;
-      result = buf1 + align + pos;
+      result = (char *) (buf1 + align + pos);
     }
   else if (seek_char == 0)
-    result = buf1 + align + len;
+    result = (char *) (buf1 + align + len);
   else
     result = NULL;
 
@@ -112,7 +112,7 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
     printf ("Length %4zd, alignment %2zd:", pos, align);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, buf1 + align, seek_char, result);
+    do_one_test (impl, (char *) (buf1 + align), seek_char, result);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -166,18 +166,18 @@ do_random_tests (void)
 	}
 
       if (pos <= len)
-	result = p + pos + align;
+	result = (char *) (p + pos + align);
       else if (seek_char == 0)
-	result = p + len + align;
+	result = (char *) (p + len + align);
       else
 	result = NULL;
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align, seek_char) != result)
+	if (CALL (impl, (char *) (p + align), seek_char) != result)
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
 		   n, impl->name, align, seek_char, len, pos,
-		   CALL (impl, p + align, seek_char), result, p);
+		   CALL (impl, (char *) (p + align), seek_char), result, p);
 	    ret = 1;
 	  }
     }
diff --git a/string/test-strcmp.c b/string/test-strcmp.c
index af49f14fe1..769e9828fd 100644
--- a/string/test-strcmp.c
+++ b/string/test-strcmp.c
@@ -1,5 +1,5 @@
 /* Test and measure strcmp functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -103,8 +103,8 @@ do_test (size_t align1, size_t align2, size_t len, int max_char,
   if (align2 + len + 1 >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len; i++)
     s1[i] = s2[i] = 1 + 23 * i % max_char;
@@ -198,7 +198,7 @@ do_random_tests (void)
 
       FOR_EACH_IMPL (impl, 1)
 	{
-	  r = CALL (impl, p1 + align1, p2 + align2);
+	  r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2));
 	  /* Test whether on 64-bit architectures where ABI requires
 	     callee to promote has the promotion been done.  */
 	  asm ("" : "=g" (r) : "0" (r));
diff --git a/string/test-strcpy.c b/string/test-strcpy.c
index dbfbb9294d..6a2ea2510e 100644
--- a/string/test-strcpy.c
+++ b/string/test-strcpy.c
@@ -1,5 +1,5 @@
 /* Test and measure strcpy functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -92,8 +92,8 @@ do_test (size_t align1, size_t align2, size_t len, int max_char)
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len; i++)
     s1[i] = 32 + 23 * i % (max_char - 32);
@@ -148,7 +148,8 @@ do_random_tests (void)
       FOR_EACH_IMPL (impl, 1)
 	{
 	  memset (p2 - 64, '\1', 512 + 64);
-	  res = CALL (impl, p2 + align2, p1 + align1);
+	  res = (unsigned char *) CALL (impl, (char *) (p2 + align2),
+					(char *) (p1 + align1));
 	  if (res != STRCPY_RESULT (p2 + align2, len))
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
diff --git a/string/test-strlen.c b/string/test-strlen.c
index 82ad95e5cc..e01befbf46 100644
--- a/string/test-strlen.c
+++ b/string/test-strlen.c
@@ -1,5 +1,5 @@
 /* Test and measure strlen functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -92,7 +92,7 @@ do_test (size_t align, size_t len, int max_char)
     printf ("Length %4zd, alignment %2zd:", len, align);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, buf1 + align, len);
+    do_one_test (impl, (char *) (buf1 + align), len);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -127,10 +127,11 @@ do_random_tests (void)
 	}
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align) != len)
+	if (CALL (impl, (char *) (p + align)) != len)
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd) %zd != %zd, p %p",
-		   n, impl->name, align, CALL (impl, p + align), len, p);
+		   n, impl->name, align, CALL (impl, (char *) (p + align)),
+		   len, p);
 	    ret = 1;
 	  }
     }
diff --git a/string/test-strncmp.c b/string/test-strncmp.c
index 431b64d6af..5adf0eb311 100644
--- a/string/test-strncmp.c
+++ b/string/test-strncmp.c
@@ -86,6 +86,65 @@ do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
 }
 
 static void
+do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
+	 int exp_result)
+{
+  size_t i, align_n;
+  char *s1, *s2;
+
+  if (n == 0)
+    {
+      s1 = (char*)(buf1 + page_size);
+      s2 = (char*)(buf2 + page_size);
+      if (HP_TIMING_AVAIL)
+	printf ("Length %4zd/%4zd:", len, n);
+	
+      FOR_EACH_IMPL (impl, 0)
+	do_one_test (impl, s1, s2, n, 0);
+
+      if (HP_TIMING_AVAIL)
+	putchar ('\n');
+	
+      return;
+    }
+
+  align1 &= 15;
+  align2 &= 15;
+  align_n = (page_size - n) & 15;
+
+  s1 = (char*)(buf1 + page_size - n);
+  s2 = (char*)(buf2 + page_size - n);
+  
+  if (align1 < align_n)
+    s1 -= (align_n - align1);
+    
+  if (align2 < align_n)
+    s2 -= (align_n - align2);
+    
+  for (i = 0; i < n; i++)
+    s1[i] = s2[i] = 1 + 23 * i % max_char;
+
+  if (len < n)
+    {
+      s1[len] = 0;
+      s2[len] = 0;
+      if (exp_result < 0)
+	s2[len] = 32;
+      else if (exp_result > 0)
+	s1[len] = 64;
+    }
+
+  if (HP_TIMING_AVAIL)
+    printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2);
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, s1, s2, n, exp_result);
+
+  if (HP_TIMING_AVAIL)
+    putchar ('\n');
+}
+
+static void
 do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
 	 int exp_result)
 {
@@ -103,8 +162,8 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
   if (align2 + n + 1 >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char*)(buf1 + align1);
+  s2 = (char*)(buf2 + align2);
 
   for (i = 0; i < n; i++)
     s1[i] = s2[i] = 1 + 23 * i % max_char;
@@ -124,7 +183,7 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
     printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, s1, s2, n, exp_result);
+    do_one_test (impl, (char*)s1, (char*)s2, n, exp_result);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -208,7 +267,7 @@ do_random_tests (void)
 
       FOR_EACH_IMPL (impl, 1)
 	{
-	  r = CALL (impl, p1 + align1, p2 + align2, size);
+	  r = CALL (impl, (char*)(p1 + align1), (char*)(p2 + align2), size);
 	  /* Test whether on 64-bit architectures where ABI requires
 	     callee to promote has the promotion been done.  */
 	  asm ("" : "=g" (r) : "0" (r));
@@ -271,6 +330,24 @@ test_main (void)
       do_test (2 * i, i, 8 << i, 16 << i, 255, 0);
       do_test (2 * i, i, 8 << i, 16 << i, 255, 1);
     }
+    
+  do_test_limit (0, 0, 0, 0, 127, 0);
+  do_test_limit (4, 0, 21, 20, 127, 0);
+  do_test_limit (0, 4, 21, 20, 127, 0);
+  do_test_limit (8, 0, 25, 24, 127, 0);
+  do_test_limit (0, 8, 25, 24, 127, 0);
+
+  for (i = 0; i < 8; ++i)
+    {
+      do_test_limit (0, 0, 17 - i, 16 - i, 127, 0);
+      do_test_limit (0, 0, 17 - i, 16 - i, 255, 0);
+      do_test_limit (0, 0, 15 - i, 16 - i, 127, 0);
+      do_test_limit (0, 0, 15 - i, 16 - i, 127, 1);
+      do_test_limit (0, 0, 15 - i, 16 - i, 127, -1);
+      do_test_limit (0, 0, 15 - i, 16 - i, 255, 0);
+      do_test_limit (0, 0, 15 - i, 16 - i, 255, 1);
+      do_test_limit (0, 0, 15 - i, 16 - i, 255, -1);
+    }
 
   do_random_tests ();
   return ret;
diff --git a/string/test-strncpy.c b/string/test-strncpy.c
index 62b83166a3..d7a714cef1 100644
--- a/string/test-strncpy.c
+++ b/string/test-strncpy.c
@@ -1,5 +1,5 @@
 /* Test and measure strncpy functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -124,8 +124,8 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
   if (align2 + len >= page_size)
     return;
 
-  s1 = buf1 + align1;
-  s2 = buf2 + align2;
+  s1 = (char *) (buf1 + align1);
+  s2 = (char *) (buf2 + align2);
 
   for (i = 0; i < len; ++i)
     s1[i] = 32 + 23 * i % (max_char - 32);
@@ -215,7 +215,9 @@ do_random_tests (void)
       FOR_EACH_IMPL (impl, 1)
 	{
 	  memset (p2 - 64, '\1', 512 + 64);
-	  res = CALL (impl, p2 + align2, p1 + align1, size);
+	  res = (unsigned char *) CALL (impl,
+					(char *) (p2 + align2),
+					(char *) (p1 + align1), size);
 	  if (res != STRNCPY_RESULT (p2 + align2, len, size))
 	    {
 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c
index 2ec52fd286..f3ed2080bc 100644
--- a/string/test-strpbrk.c
+++ b/string/test-strpbrk.c
@@ -1,5 +1,5 @@
 /* Test and measure strpbrk functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -102,8 +102,8 @@ do_test (size_t align, size_t pos, size_t len)
   if (align + pos + 10 >= page_size || len > 240)
     return;
 
-  rej = buf2 + (random () & 255);
-  s = buf1 + align;
+  rej = (char *) (buf2 + (random () & 255));
+  s = (char *) (buf1 + align);
 
   for (i = 0; i < len; ++i)
     {
@@ -182,7 +182,7 @@ do_random_tests (void)
 	}
       rej[i] = '\0';
       for (c = 1; c <= 255; ++c)
-	if (strchr (rej, c) == NULL)
+	if (strchr ((char *) rej, c) == NULL)
 	  break;
       j = (pos > len ? pos : len) + align + 64;
       if (j > 512)
@@ -199,23 +199,24 @@ do_random_tests (void)
 	  else
 	    {
 	      p[i] = random () & 255;
-	      if (strchr (rej, p[i]))
+	      if (strchr ((char *) rej, p[i]))
 		{
 		  p[i] = random () & 255;
-		  if (strchr (rej, p[i]))
+		  if (strchr ((char *) rej, p[i]))
 		    p[i] = c;
 		}
 	    }
 	}
 
-      result = STRPBRK_RESULT (p + align, pos < len ? pos : len);
+      result = STRPBRK_RESULT ((char *) (p + align), pos < len ? pos : len);
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align, rej) != result)
+	if (CALL (impl, (char *) (p + align), (char *) rej) != result)
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd, %zd) %p != %p",
 		   n, impl->name, align, rej, rlen, pos, len,
-		   (void *) CALL (impl, p + align, rej), (void *) result);
+		   (void *) CALL (impl, (char *) (p + align), (char *) rej),
+		   (void *) result);
 	    ret = 1;
 	  }
     }
diff --git a/string/test-strrchr.c b/string/test-strrchr.c
index 5aff75aeba..92e8ab1bb1 100644
--- a/string/test-strrchr.c
+++ b/string/test-strrchr.c
@@ -1,5 +1,5 @@
 /* Test and measure strrchr functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -95,10 +95,10 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
   if (pos < len)
     {
       buf1[align + pos] = seek_char;
-      result = buf1 + align + pos;
+      result = (char *) (buf1 + align + pos);
     }
   else if (seek_char == 0)
-    result = buf1 + align + len;
+    result = (char *) (buf1 + align + len);
   else
     result = NULL;
 
@@ -106,7 +106,7 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
     printf ("Length %4zd, alignment %2zd:", pos, align);
 
   FOR_EACH_IMPL (impl, 0)
-    do_one_test (impl, buf1 + align, seek_char, result);
+    do_one_test (impl, (char *) (buf1 + align), seek_char, result);
 
   if (HP_TIMING_AVAIL)
     putchar ('\n');
@@ -165,18 +165,18 @@ do_random_tests (void)
 	}
 
       if (pos <= len)
-	result = p + pos + align;
+	result = (char *) (p + pos + align);
       else if (seek_char == 0)
-        result = p + len + align;
+        result = (char *) (p + len + align);
       else
 	result = NULL;
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align, seek_char) != result)
+	if (CALL (impl, (char *) (p + align), seek_char) != result)
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
 		   n, impl->name, align, seek_char, len, pos,
-		   CALL (impl, p + align, seek_char), result, p);
+		   CALL (impl, (char *) (p + align), seek_char), result, p);
 	    ret = 1;
 	  }
     }
diff --git a/string/test-strspn.c b/string/test-strspn.c
index de7351fe8c..15cf4923f0 100644
--- a/string/test-strspn.c
+++ b/string/test-strspn.c
@@ -1,5 +1,5 @@
 /* Test and measure strspn functions.
-   Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999,2002,2003,2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -104,8 +104,8 @@ do_test (size_t align, size_t pos, size_t len)
   if (align + pos + 10 >= page_size || len > 240 || ! len)
     return;
 
-  acc = buf2 + (random () & 255);
-  s = buf1 + align;
+  acc = (char *) (buf2 + (random () & 255));
+  s = (char *) (buf1 + align);
 
   for (i = 0; i < len; ++i)
     {
@@ -183,7 +183,7 @@ do_random_tests (void)
 	  else if (i == pos + align)
 	    {
 	      p[i] = random () & 255;
-	      if (strchr (acc, p[i]))
+	      if (strchr ((char *) acc, p[i]))
 		p[i] = '\0';
 	    }
 	  else if (i < align || i > pos + align)
@@ -193,11 +193,13 @@ do_random_tests (void)
 	}
 
       FOR_EACH_IMPL (impl, 1)
-	if (CALL (impl, p + align, acc) != (pos < len ? pos : len))
+	if (CALL (impl, (char *) (p + align),
+		  (char *) acc) != (pos < len ? pos : len))
 	  {
 	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd, %zd) %zd != %zd",
 		   n, impl->name, align, acc, alen, pos, len,
-		   CALL (impl, p + align, acc), (pos < len ? pos : len));
+		   CALL (impl, (char *) (p + align), (char *) acc),
+		   (pos < len ? pos : len));
 	    ret = 1;
 	  }
     }
diff --git a/string/tester.c b/string/tester.c
index 5f0a851104..cccef3ad9d 100644
--- a/string/tester.c
+++ b/string/tester.c
@@ -1,5 +1,5 @@
 /* Tester for string functions.
-   Copyright (C) 1995-2000, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2001, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -34,10 +34,6 @@
 #include <strings.h>
 #include <fcntl.h>
 
-#ifndef HAVE_GNU_LD
-#define _sys_nerr	sys_nerr
-#define _sys_errlist	sys_errlist
-#endif
 
 #define	STREQ(a, b)	(strcmp((a), (b)) == 0)
 
@@ -348,6 +344,9 @@ test_strncat (void)
 
   (void) strncat (one, "gh", 2);
   equal (one, "abcdgh", 12);		/* Count and length equal. */
+
+  (void) strncat (one, "ij", (size_t)-1);	/* set sign bit in count */
+  equal (one, "abcdghij", 13);
 }
 
 static void
@@ -368,6 +367,8 @@ test_strncmp (void)
   check (strncmp ("abce", "abc", 3) == 0, 11);	/* Count == length. */
   check (strncmp ("abcd", "abce", 4) < 0, 12);	/* Nudging limit. */
   check (strncmp ("abc", "def", 0) == 0, 13);	/* Zero count. */
+  check (strncmp ("abc", "", (size_t)-1) > 0, 14);	/* set sign bit in count */
+  check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
 }
 
 static void
@@ -434,6 +435,29 @@ test_strlen (void)
 }
 
 static void
+test_strnlen (void)
+{
+  it = "strnlen";
+  check (strnlen ("", 10) == 0, 1);		/* Empty. */
+  check (strnlen ("a", 10) == 1, 2);		/* Single char. */
+  check (strnlen ("abcd", 10) == 4, 3);		/* Multiple chars. */
+  check (strnlen ("foo", (size_t)-1) == 3, 4);	/* limits of n. */
+
+  {
+    char buf[4096];
+    int i;
+    char *p;
+    for (i=0; i < 0x100; i++)
+      {
+	p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
+	strcpy (p, "OK");
+	strcpy (p+3, "BAD/WRONG");
+	check (strnlen (p, 100) == 2, 5+i);
+      }
+   }
+}
+
+static void
 test_strchr (void)
 {
   it = "strchr";
@@ -1386,6 +1410,9 @@ main (void)
   /* strlen.  */
   test_strlen ();
 
+  /* strnlen.  */
+  test_strnlen ();
+
   /* strchr.  */
   test_strchr ();
 
diff --git a/string/tst-strfry.c b/string/tst-strfry.c
new file mode 100644
index 0000000000..2b40a39b13
--- /dev/null
+++ b/string/tst-strfry.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+  char str[] = "this is a test";
+
+  strfry (str);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/tst-strxfrm2.c b/string/tst-strxfrm2.c
new file mode 100644
index 0000000000..d5a1115338
--- /dev/null
+++ b/string/tst-strxfrm2.c
@@ -0,0 +1,83 @@
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+static int
+do_test (void)
+{
+  int res = 0;
+
+  char buf[20];
+  size_t l1 = strxfrm (NULL, "ab", 0);
+  size_t l2 = strxfrm (buf, "ab", 1);
+  size_t l3 = strxfrm (buf, "ab", sizeof (buf));
+  if (l3 < sizeof (buf) && strlen (buf) != l3)
+    {
+      puts ("C locale l3 test failed");
+      res = 1;
+    }
+
+  size_t l4 = strxfrm (buf, "ab", l1 + 1);
+  if (l4 < l1 + 1 && strlen (buf) != l4)
+    {
+      puts ("C locale l4 test failed");
+      res = 1;
+    }
+
+  buf[l1] = 'Z';
+  size_t l5 = strxfrm (buf, "ab", l1);
+  if (buf[l1] != 'Z')
+    {
+      puts ("C locale l5 test failed");
+      res = 1;
+    }
+
+  if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
+    {
+      puts ("C locale retval test failed");
+      res = 1;
+    }
+
+  if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
+    {
+      puts ("setlocale failed");
+      res = 1;
+    }
+  else
+    {
+      l1 = strxfrm (NULL, "ab", 0);
+      l2 = strxfrm (buf, "ab", 1);
+      l3 = strxfrm (buf, "ab", sizeof (buf));
+      if (l3 < sizeof (buf) && strlen (buf) != l3)
+	{
+	  puts ("UTF-8 locale l3 test failed");
+	  res = 1;
+	}
+
+      l4 = strxfrm (buf, "ab", l1 + 1);
+      if (l4 < l1 + 1 && strlen (buf) != l4)
+	{
+	  puts ("UTF-8 locale l4 test failed");
+	  res = 1;
+	}
+
+      buf[l1] = 'Z';
+      l5 = strxfrm (buf, "ab", l1);
+      if (buf[l1] != 'Z')
+	{
+	  puts ("UTF-8 locale l5 test failed");
+	  res = 1;
+	}
+
+      if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
+	{
+	  puts ("UTF-8 locale retval test failed");
+	  res = 1;
+	}
+    }
+
+  return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/string/wordcopy.c b/string/wordcopy.c
new file mode 100644
index 0000000000..0c9a4be4f6
--- /dev/null
+++ b/string/wordcopy.c
@@ -0,0 +1,413 @@
+/* _memcopy.c -- subroutines for memory copy functions.
+   Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
+
+#include <stddef.h>
+#include <memcopy.h>
+
+/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
+   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
+   Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
+
+void
+_wordcopy_fwd_aligned (dstp, srcp, len)
+     long int dstp;
+     long int srcp;
+     size_t len;
+{
+  op_t a0, a1;
+
+  switch (len % 8)
+    {
+    case 2:
+      a0 = ((op_t *) srcp)[0];
+      srcp -= 6 * OPSIZ;
+      dstp -= 7 * OPSIZ;
+      len += 6;
+      goto do1;
+    case 3:
+      a1 = ((op_t *) srcp)[0];
+      srcp -= 5 * OPSIZ;
+      dstp -= 6 * OPSIZ;
+      len += 5;
+      goto do2;
+    case 4:
+      a0 = ((op_t *) srcp)[0];
+      srcp -= 4 * OPSIZ;
+      dstp -= 5 * OPSIZ;
+      len += 4;
+      goto do3;
+    case 5:
+      a1 = ((op_t *) srcp)[0];
+      srcp -= 3 * OPSIZ;
+      dstp -= 4 * OPSIZ;
+      len += 3;
+      goto do4;
+    case 6:
+      a0 = ((op_t *) srcp)[0];
+      srcp -= 2 * OPSIZ;
+      dstp -= 3 * OPSIZ;
+      len += 2;
+      goto do5;
+    case 7:
+      a1 = ((op_t *) srcp)[0];
+      srcp -= 1 * OPSIZ;
+      dstp -= 2 * OPSIZ;
+      len += 1;
+      goto do6;
+
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return;
+      a0 = ((op_t *) srcp)[0];
+      srcp -= 0 * OPSIZ;
+      dstp -= 1 * OPSIZ;
+      goto do7;
+    case 1:
+      a1 = ((op_t *) srcp)[0];
+      srcp -=-1 * OPSIZ;
+      dstp -= 0 * OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      goto do8;			/* No-op.  */
+    }
+
+  do
+    {
+    do8:
+      a0 = ((op_t *) srcp)[0];
+      ((op_t *) dstp)[0] = a1;
+    do7:
+      a1 = ((op_t *) srcp)[1];
+      ((op_t *) dstp)[1] = a0;
+    do6:
+      a0 = ((op_t *) srcp)[2];
+      ((op_t *) dstp)[2] = a1;
+    do5:
+      a1 = ((op_t *) srcp)[3];
+      ((op_t *) dstp)[3] = a0;
+    do4:
+      a0 = ((op_t *) srcp)[4];
+      ((op_t *) dstp)[4] = a1;
+    do3:
+      a1 = ((op_t *) srcp)[5];
+      ((op_t *) dstp)[5] = a0;
+    do2:
+      a0 = ((op_t *) srcp)[6];
+      ((op_t *) dstp)[6] = a1;
+    do1:
+      a1 = ((op_t *) srcp)[7];
+      ((op_t *) dstp)[7] = a0;
+
+      srcp += 8 * OPSIZ;
+      dstp += 8 * OPSIZ;
+      len -= 8;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  ((op_t *) dstp)[0] = a1;
+}
+
+/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
+   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
+   DSTP should be aligned for memory operations on `op_t's, but SRCP must
+   *not* be aligned.  */
+
+void
+_wordcopy_fwd_dest_aligned (dstp, srcp, len)
+     long int dstp;
+     long int srcp;
+     size_t len;
+{
+  op_t a0, a1, a2, a3;
+  int sh_1, sh_2;
+
+  /* Calculate how to shift a word read at the memory operation
+     aligned srcp to make it aligned for copy.  */
+
+  sh_1 = 8 * (srcp % OPSIZ);
+  sh_2 = 8 * OPSIZ - sh_1;
+
+  /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
+     it points in the middle of.  */
+  srcp &= -OPSIZ;
+
+  switch (len % 4)
+    {
+    case 2:
+      a1 = ((op_t *) srcp)[0];
+      a2 = ((op_t *) srcp)[1];
+      srcp -= 1 * OPSIZ;
+      dstp -= 3 * OPSIZ;
+      len += 2;
+      goto do1;
+    case 3:
+      a0 = ((op_t *) srcp)[0];
+      a1 = ((op_t *) srcp)[1];
+      srcp -= 0 * OPSIZ;
+      dstp -= 2 * OPSIZ;
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return;
+      a3 = ((op_t *) srcp)[0];
+      a0 = ((op_t *) srcp)[1];
+      srcp -=-1 * OPSIZ;
+      dstp -= 1 * OPSIZ;
+      len += 0;
+      goto do3;
+    case 1:
+      a2 = ((op_t *) srcp)[0];
+      a3 = ((op_t *) srcp)[1];
+      srcp -=-2 * OPSIZ;
+      dstp -= 0 * OPSIZ;
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      goto do4;			/* No-op.  */
+    }
+
+  do
+    {
+    do4:
+      a0 = ((op_t *) srcp)[0];
+      ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
+    do3:
+      a1 = ((op_t *) srcp)[1];
+      ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2);
+    do2:
+      a2 = ((op_t *) srcp)[2];
+      ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2);
+    do1:
+      a3 = ((op_t *) srcp)[3];
+      ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2);
+
+      srcp += 4 * OPSIZ;
+      dstp += 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
+}
+
+/* _wordcopy_bwd_aligned -- Copy block finishing right before
+   SRCP to block finishing right before DSTP with LEN `op_t' words
+   (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
+   operations on `op_t's.  */
+
+void
+_wordcopy_bwd_aligned (dstp, srcp, len)
+     long int dstp;
+     long int srcp;
+     size_t len;
+{
+  op_t a0, a1;
+
+  switch (len % 8)
+    {
+    case 2:
+      srcp -= 2 * OPSIZ;
+      dstp -= 1 * OPSIZ;
+      a0 = ((op_t *) srcp)[1];
+      len += 6;
+      goto do1;
+    case 3:
+      srcp -= 3 * OPSIZ;
+      dstp -= 2 * OPSIZ;
+      a1 = ((op_t *) srcp)[2];
+      len += 5;
+      goto do2;
+    case 4:
+      srcp -= 4 * OPSIZ;
+      dstp -= 3 * OPSIZ;
+      a0 = ((op_t *) srcp)[3];
+      len += 4;
+      goto do3;
+    case 5:
+      srcp -= 5 * OPSIZ;
+      dstp -= 4 * OPSIZ;
+      a1 = ((op_t *) srcp)[4];
+      len += 3;
+      goto do4;
+    case 6:
+      srcp -= 6 * OPSIZ;
+      dstp -= 5 * OPSIZ;
+      a0 = ((op_t *) srcp)[5];
+      len += 2;
+      goto do5;
+    case 7:
+      srcp -= 7 * OPSIZ;
+      dstp -= 6 * OPSIZ;
+      a1 = ((op_t *) srcp)[6];
+      len += 1;
+      goto do6;
+
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return;
+      srcp -= 8 * OPSIZ;
+      dstp -= 7 * OPSIZ;
+      a0 = ((op_t *) srcp)[7];
+      goto do7;
+    case 1:
+      srcp -= 9 * OPSIZ;
+      dstp -= 8 * OPSIZ;
+      a1 = ((op_t *) srcp)[8];
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      goto do8;			/* No-op.  */
+    }
+
+  do
+    {
+    do8:
+      a0 = ((op_t *) srcp)[7];
+      ((op_t *) dstp)[7] = a1;
+    do7:
+      a1 = ((op_t *) srcp)[6];
+      ((op_t *) dstp)[6] = a0;
+    do6:
+      a0 = ((op_t *) srcp)[5];
+      ((op_t *) dstp)[5] = a1;
+    do5:
+      a1 = ((op_t *) srcp)[4];
+      ((op_t *) dstp)[4] = a0;
+    do4:
+      a0 = ((op_t *) srcp)[3];
+      ((op_t *) dstp)[3] = a1;
+    do3:
+      a1 = ((op_t *) srcp)[2];
+      ((op_t *) dstp)[2] = a0;
+    do2:
+      a0 = ((op_t *) srcp)[1];
+      ((op_t *) dstp)[1] = a1;
+    do1:
+      a1 = ((op_t *) srcp)[0];
+      ((op_t *) dstp)[0] = a0;
+
+      srcp -= 8 * OPSIZ;
+      dstp -= 8 * OPSIZ;
+      len -= 8;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  ((op_t *) dstp)[7] = a1;
+}
+
+/* _wordcopy_bwd_dest_aligned -- Copy block finishing right
+   before SRCP to block finishing right before DSTP with LEN `op_t'
+   words (not LEN bytes!).  DSTP should be aligned for memory
+   operations on `op_t', but SRCP must *not* be aligned.  */
+
+void
+_wordcopy_bwd_dest_aligned (dstp, srcp, len)
+     long int dstp;
+     long int srcp;
+     size_t len;
+{
+  op_t a0, a1, a2, a3;
+  int sh_1, sh_2;
+
+  /* Calculate how to shift a word read at the memory operation
+     aligned srcp to make it aligned for copy.  */
+
+  sh_1 = 8 * (srcp % OPSIZ);
+  sh_2 = 8 * OPSIZ - sh_1;
+
+  /* Make srcp aligned by rounding it down to the beginning of the op_t
+     it points in the middle of.  */
+  srcp &= -OPSIZ;
+  srcp += OPSIZ;
+
+  switch (len % 4)
+    {
+    case 2:
+      srcp -= 3 * OPSIZ;
+      dstp -= 1 * OPSIZ;
+      a2 = ((op_t *) srcp)[2];
+      a1 = ((op_t *) srcp)[1];
+      len += 2;
+      goto do1;
+    case 3:
+      srcp -= 4 * OPSIZ;
+      dstp -= 2 * OPSIZ;
+      a3 = ((op_t *) srcp)[3];
+      a2 = ((op_t *) srcp)[2];
+      len += 1;
+      goto do2;
+    case 0:
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	return;
+      srcp -= 5 * OPSIZ;
+      dstp -= 3 * OPSIZ;
+      a0 = ((op_t *) srcp)[4];
+      a3 = ((op_t *) srcp)[3];
+      goto do3;
+    case 1:
+      srcp -= 6 * OPSIZ;
+      dstp -= 4 * OPSIZ;
+      a1 = ((op_t *) srcp)[5];
+      a0 = ((op_t *) srcp)[4];
+      len -= 1;
+      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
+	goto do0;
+      goto do4;			/* No-op.  */
+    }
+
+  do
+    {
+    do4:
+      a3 = ((op_t *) srcp)[3];
+      ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
+    do3:
+      a2 = ((op_t *) srcp)[2];
+      ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2);
+    do2:
+      a1 = ((op_t *) srcp)[1];
+      ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2);
+    do1:
+      a0 = ((op_t *) srcp)[0];
+      ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
+
+      srcp -= 4 * OPSIZ;
+      dstp -= 4 * OPSIZ;
+      len -= 4;
+    }
+  while (len != 0);
+
+  /* This is the right position for do0.  Please don't move
+     it into the loop.  */
+ do0:
+  ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
+}
diff --git a/string/xpg-strerror.c b/string/xpg-strerror.c
new file mode 100644
index 0000000000..5cb56cdfb8
--- /dev/null
+++ b/string/xpg-strerror.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2002, 2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <stdio-common/_itoa.h>
+
+/* It is critical here that we always use the `dcgettext' function for
+   the message translation.  Since <libintl.h> only defines the macro
+   `dgettext' to use `dcgettext' for optimizing programs this is not
+   always guaranteed.  */
+#ifndef dgettext
+# include <locale.h>		/* We need LC_MESSAGES.  */
+# define dgettext(domainname, msgid) dcgettext (domainname, msgid, LC_MESSAGES)
+#endif
+
+/* Fill buf with a string describing the errno code in ERRNUM.  */
+int
+__xpg_strerror_r (int errnum, char *buf, size_t buflen)
+{
+  if (errnum < 0 || errnum >= _sys_nerr_internal
+      || _sys_errlist_internal[errnum] == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+  const char *estr = (const char *) _(_sys_errlist_internal[errnum]);
+  size_t estrlen = strlen (estr) + 1;
+
+  if (buflen < estrlen)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+
+  memcpy (buf, estr, estrlen);
+  return 0;
+}