summaryrefslogtreecommitdiff
path: root/string
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-12-14 15:06:39 +0000
committerUlrich Drepper <drepper@redhat.com>2005-12-14 15:06:39 +0000
commit9d13fb2413921c713f83efe331e8e4d219c62c6b (patch)
tree2d44d7ac45ab2d147eb8361bbff880c365aa8ad5 /string
parentb6ab06cef4670e02756bcdd4d2c33a49369a4346 (diff)
Moved to csu/errno-loc.c.
Diffstat (limited to 'string')
-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.c190
-rw-r--r--string/strchrnul.c170
-rw-r--r--string/strcmp.c47
-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/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/wordcopy.c413
-rw-r--r--string/xpg-strerror.c57
40 files changed, 4133 insertions, 0 deletions
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..c8b7969e85
--- /dev/null
+++ b/string/strchr.c
@@ -0,0 +1,190 @@
+/* Copyright (C) 1991,93,94,95,96,97,99,2000,03 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 = 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/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/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/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;
+}