aboutsummaryrefslogtreecommitdiff
path: root/REORG.TODO/string
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/string')
-rw-r--r--REORG.TODO/string/Depend1
-rw-r--r--REORG.TODO/string/Makefile109
-rw-r--r--REORG.TODO/string/Versions88
-rw-r--r--REORG.TODO/string/_strerror.c74
-rw-r--r--REORG.TODO/string/argz-addsep.c58
-rw-r--r--REORG.TODO/string/argz-append.c49
-rw-r--r--REORG.TODO/string/argz-count.c38
-rw-r--r--REORG.TODO/string/argz-create.c53
-rw-r--r--REORG.TODO/string/argz-ctsep.c70
-rw-r--r--REORG.TODO/string/argz-delete.c41
-rw-r--r--REORG.TODO/string/argz-extract.c36
-rw-r--r--REORG.TODO/string/argz-insert.c63
-rw-r--r--REORG.TODO/string/argz-next.c39
-rw-r--r--REORG.TODO/string/argz-replace.c134
-rw-r--r--REORG.TODO/string/argz-stringify.c40
-rw-r--r--REORG.TODO/string/argz.h182
-rw-r--r--REORG.TODO/string/basename.c29
-rw-r--r--REORG.TODO/string/bcopy.c24
-rw-r--r--REORG.TODO/string/bits/string2.h119
-rw-r--r--REORG.TODO/string/bits/string3.h156
-rw-r--r--REORG.TODO/string/bits/strings_fortified.h34
-rw-r--r--REORG.TODO/string/bug-envz1.c75
-rw-r--r--REORG.TODO/string/bug-strcoll1.c24
-rw-r--r--REORG.TODO/string/bug-strcoll2.c91
-rw-r--r--REORG.TODO/string/bug-strncat1.c31
-rw-r--r--REORG.TODO/string/bug-strpbrk1.c19
-rw-r--r--REORG.TODO/string/bug-strspn1.c19
-rw-r--r--REORG.TODO/string/bug-strtok1.c44
-rw-r--r--REORG.TODO/string/byteswap.h39
-rw-r--r--REORG.TODO/string/bzero.c29
-rw-r--r--REORG.TODO/string/endian.h97
-rw-r--r--REORG.TODO/string/envz.c172
-rw-r--r--REORG.TODO/string/envz.h73
-rw-r--r--REORG.TODO/string/explicit_bzero.c38
-rw-r--r--REORG.TODO/string/ffs.c54
-rw-r--r--REORG.TODO/string/ffsll.c40
-rw-r--r--REORG.TODO/string/inl-tester.c6
-rw-r--r--REORG.TODO/string/memccpy.c42
-rw-r--r--REORG.TODO/string/memchr.c162
-rw-r--r--REORG.TODO/string/memcmp.c364
-rw-r--r--REORG.TODO/string/memcpy.c60
-rw-r--r--REORG.TODO/string/memfrob.c29
-rw-r--r--REORG.TODO/string/memmem.c81
-rw-r--r--REORG.TODO/string/memmove.c115
-rw-r--r--REORG.TODO/string/memory.h33
-rw-r--r--REORG.TODO/string/mempcpy.c39
-rw-r--r--REORG.TODO/string/memrchr.c200
-rw-r--r--REORG.TODO/string/memset.c88
-rw-r--r--REORG.TODO/string/noinl-tester.c4
-rw-r--r--REORG.TODO/string/rawmemchr.c41
-rw-r--r--REORG.TODO/string/stpcpy.c41
-rw-r--r--REORG.TODO/string/stpncpy.c51
-rw-r--r--REORG.TODO/string/str-two-way.h527
-rw-r--r--REORG.TODO/string/stratcliff.c561
-rw-r--r--REORG.TODO/string/strcasecmp.c67
-rw-r--r--REORG.TODO/string/strcasecmp_l.c22
-rw-r--r--REORG.TODO/string/strcasestr.c104
-rw-r--r--REORG.TODO/string/strcat.c33
-rw-r--r--REORG.TODO/string/strchr.c185
-rw-r--r--REORG.TODO/string/strchrnul.c166
-rw-r--r--REORG.TODO/string/strcmp.c47
-rw-r--r--REORG.TODO/string/strcoll.c39
-rw-r--r--REORG.TODO/string/strcoll_l.c363
-rw-r--r--REORG.TODO/string/strcpy.c33
-rw-r--r--REORG.TODO/string/strcspn.c72
-rw-r--r--REORG.TODO/string/strdup.c54
-rw-r--r--REORG.TODO/string/strerror.c43
-rw-r--r--REORG.TODO/string/strerror_l.c71
-rw-r--r--REORG.TODO/string/strfry.c52
-rw-r--r--REORG.TODO/string/string-inlines.c570
-rw-r--r--REORG.TODO/string/string.h544
-rw-r--r--REORG.TODO/string/strings.h147
-rw-r--r--REORG.TODO/string/strlen.c109
-rw-r--r--REORG.TODO/string/strncase.c69
-rw-r--r--REORG.TODO/string/strncase_l.c24
-rw-r--r--REORG.TODO/string/strncat.c39
-rw-r--r--REORG.TODO/string/strncmp.c74
-rw-r--r--REORG.TODO/string/strncpy.c34
-rw-r--r--REORG.TODO/string/strndup.c56
-rw-r--r--REORG.TODO/string/strnlen.c166
-rw-r--r--REORG.TODO/string/strpbrk.c33
-rw-r--r--REORG.TODO/string/strrchr.c53
-rw-r--r--REORG.TODO/string/strsep.c49
-rw-r--r--REORG.TODO/string/strsignal.c125
-rw-r--r--REORG.TODO/string/strspn.c76
-rw-r--r--REORG.TODO/string/strstr.c92
-rw-r--r--REORG.TODO/string/strtok.c35
-rw-r--r--REORG.TODO/string/strtok_r.c79
-rw-r--r--REORG.TODO/string/strverscmp.c107
-rw-r--r--REORG.TODO/string/strxfrm.c32
-rw-r--r--REORG.TODO/string/strxfrm_l.c747
-rw-r--r--REORG.TODO/string/swab.c33
-rw-r--r--REORG.TODO/string/test-bcopy.c20
-rw-r--r--REORG.TODO/string/test-bzero.c19
-rw-r--r--REORG.TODO/string/test-endian-types.c49
-rw-r--r--REORG.TODO/string/test-explicit_bzero.c20
-rw-r--r--REORG.TODO/string/test-ffs.c65
-rw-r--r--REORG.TODO/string/test-memccpy.c269
-rw-r--r--REORG.TODO/string/test-memchr.c227
-rw-r--r--REORG.TODO/string/test-memcmp.c525
-rw-r--r--REORG.TODO/string/test-memcpy.c259
-rw-r--r--REORG.TODO/string/test-memmem.c184
-rw-r--r--REORG.TODO/string/test-memmove.c290
-rw-r--r--REORG.TODO/string/test-mempcpy.c38
-rw-r--r--REORG.TODO/string/test-memrchr.c186
-rw-r--r--REORG.TODO/string/test-memset.c267
-rw-r--r--REORG.TODO/string/test-rawmemchr.c165
-rw-r--r--REORG.TODO/string/test-stpcpy.c52
-rw-r--r--REORG.TODO/string/test-stpncpy.c79
-rw-r--r--REORG.TODO/string/test-strcasecmp.c270
-rw-r--r--REORG.TODO/string/test-strcasestr.c194
-rw-r--r--REORG.TODO/string/test-strcat.c272
-rw-r--r--REORG.TODO/string/test-strchr.c296
-rw-r--r--REORG.TODO/string/test-strchrnul.c21
-rw-r--r--REORG.TODO/string/test-strcmp.c409
-rw-r--r--REORG.TODO/string/test-strcpy.c245
-rw-r--r--REORG.TODO/string/test-strcspn.c81
-rw-r--r--REORG.TODO/string/test-string.h219
-rw-r--r--REORG.TODO/string/test-strlen.c167
-rw-r--r--REORG.TODO/string/test-strncasecmp.c353
-rw-r--r--REORG.TODO/string/test-strncat.c322
-rw-r--r--REORG.TODO/string/test-strncmp.c479
-rw-r--r--REORG.TODO/string/test-strncpy.c323
-rw-r--r--REORG.TODO/string/test-strnlen.c248
-rw-r--r--REORG.TODO/string/test-strpbrk.c267
-rw-r--r--REORG.TODO/string/test-strrchr.c247
-rw-r--r--REORG.TODO/string/test-strspn.c245
-rw-r--r--REORG.TODO/string/test-strstr.c212
-rw-r--r--REORG.TODO/string/testcopy.c107
-rw-r--r--REORG.TODO/string/tester.c1685
-rw-r--r--REORG.TODO/string/tst-bswap.c75
-rw-r--r--REORG.TODO/string/tst-cmp.c212
-rw-r--r--REORG.TODO/string/tst-endian.c134
-rw-r--r--REORG.TODO/string/tst-inlcall.c84
-rw-r--r--REORG.TODO/string/tst-strcoll-overflow.c54
-rw-r--r--REORG.TODO/string/tst-strfry.c14
-rw-r--r--REORG.TODO/string/tst-strlen.c57
-rw-r--r--REORG.TODO/string/tst-strtok.c25
-rw-r--r--REORG.TODO/string/tst-strtok_r.c38
-rw-r--r--REORG.TODO/string/tst-strxfrm.c73
-rw-r--r--REORG.TODO/string/tst-strxfrm2.c84
-rw-r--r--REORG.TODO/string/tst-svc.c47
-rw-r--r--REORG.TODO/string/tst-svc.expect33
-rw-r--r--REORG.TODO/string/tst-svc.input33
-rw-r--r--REORG.TODO/string/tst-svc2.c61
-rw-r--r--REORG.TODO/string/tst-xbzero-opt.c298
-rw-r--r--REORG.TODO/string/wordcopy.c416
-rw-r--r--REORG.TODO/string/xpg-strerror.c53
148 files changed, 20537 insertions, 0 deletions
diff --git a/REORG.TODO/string/Depend b/REORG.TODO/string/Depend
new file mode 100644
index 0000000000..f3e1156a4e
--- /dev/null
+++ b/REORG.TODO/string/Depend
@@ -0,0 +1 @@
+localedata
diff --git a/REORG.TODO/string/Makefile b/REORG.TODO/string/Makefile
new file mode 100644
index 0000000000..f317d02a8c
--- /dev/null
+++ b/REORG.TODO/string/Makefile
@@ -0,0 +1,109 @@
+# Copyright (C) 1991-2017 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, see
+# <http://www.gnu.org/licenses/>.
+
+#
+# Sub-makefile for string portion of library.
+#
+subdir := string
+
+include ../Makeconfig
+
+headers := string.h strings.h memory.h endian.h bits/endian.h \
+ argz.h envz.h byteswap.h bits/byteswap.h bits/byteswap-16.h \
+ bits/string.h bits/string2.h bits/string3.h \
+ bits/strings_fortified.h bits/uintn-identity.h
+
+routines := strcat strchr strcmp strcoll strcpy strcspn \
+ strverscmp strdup strndup \
+ strerror _strerror strlen strnlen \
+ strncat strncmp strncpy \
+ strrchr strpbrk strsignal strspn strstr strtok \
+ strtok_r strxfrm memchr memcmp memmove memset \
+ mempcpy bcopy bzero ffs ffsll stpcpy stpncpy \
+ strcasecmp strncase strcasecmp_l strncase_l \
+ memccpy memcpy wordcopy strsep strcasestr \
+ swab strfry memfrob memmem rawmemchr strchrnul \
+ $(addprefix argz-,append count create ctsep next \
+ delete extract insert stringify \
+ addsep replace) \
+ envz basename \
+ strcoll_l strxfrm_l string-inlines memrchr \
+ xpg-strerror strerror_l explicit_bzero
+
+strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \
+ stpcpy stpncpy strcat strchr strcmp strcpy strcspn \
+ strlen strncmp strncpy strpbrk strrchr strspn memmem \
+ strstr strcasestr strnlen strcasecmp strncasecmp \
+ strncat rawmemchr strchrnul bcopy bzero memrchr \
+ explicit_bzero
+tests := tester inl-tester noinl-tester testcopy test-ffs \
+ tst-strlen stratcliff tst-svc tst-inlcall \
+ bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
+ tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
+ bug-strtok1 $(addprefix test-,$(strop-tests)) \
+ bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \
+ tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt \
+ test-endian-types
+
+# This test allocates a lot of memory and can run for a long time.
+xtests = tst-strcoll-overflow
+
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-svc-cmp.out
+endif
+
+include ../Rules
+
+CFLAGS-inl-tester.c = -fno-builtin
+CFLAGS-noinl-tester.c = -fno-builtin
+CFLAGS-tst-strlen.c = -fno-builtin
+CFLAGS-stratcliff.c = -fno-builtin
+CFLAGS-test-ffs.c = -fno-builtin
+CFLAGS-tst-inlcall.c = -fno-builtin
+CFLAGS-tst-xbzero-opt.c = -O3
+# BZ 21006: Resolve all functions but at least explicit_bzero at startup.
+# Otherwise the test fails on s390x as the memcpy in prepare_test_buffer is
+# done by loading r4 / r5 with the test_pattern and using store multiple
+# instruction to store r4 / r5 to buf. If explicit_bzero would be resolved in
+# setup_explicit_clear, r4 / r5 would be stored to stack by _dl_runtime_resolve
+# and the call to memmem in count_test_patterns will find a hit of the
+# test_pattern on the stack.
+LDFLAGS-tst-xbzero-opt = -z now
+
+# Called during TLS initialization.
+CFLAGS-memcpy.c = $(no-stack-protector)
+CFLAGS-wordcopy.c = $(no-stack-protector)
+
+ifeq ($(run-built-tests),yes)
+$(objpfx)tst-svc-cmp.out: tst-svc.expect $(objpfx)tst-svc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+
+LOCALES := de_DE.UTF-8 en_US.ISO-8859-1 en_US.UTF-8 \
+ tr_TR.ISO-8859-9 tr_TR.UTF-8 cs_CZ.UTF-8 \
+ da_DK.ISO-8859-1 en_GB.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)test-strcasecmp.out: $(gen-locales)
+$(objpfx)test-strncasecmp.out: $(gen-locales)
+$(objpfx)tst-strxfrm.out: $(gen-locales)
+$(objpfx)tst-strxfrm2.out: $(gen-locales)
+# bug-strcoll2 needs cs_CZ.UTF-8 and da_DK.ISO-8859-1.
+$(objpfx)bug-strcoll2.out: $(gen-locales)
+$(objpfx)tst-strcoll-overflow.out: $(gen-locales)
+
+endif
diff --git a/REORG.TODO/string/Versions b/REORG.TODO/string/Versions
new file mode 100644
index 0000000000..9b709d12a9
--- /dev/null
+++ b/REORG.TODO/string/Versions
@@ -0,0 +1,88 @@
+libc {
+ GLIBC_2.0 {
+ # functions with required interface outside normal name space
+ __argz_count; __argz_stringify; __argz_next;
+
+ # functions used in inline functions or macros
+ __bzero; __strtok_r;
+
+ # functions used in other libraries
+ __ffs; __mempcpy; __stpncpy; __stpcpy; __strcasecmp; __strdup;
+ __strerror_r;
+
+ # a*
+ argz_add; argz_add_sep; argz_append; argz_count; argz_create;
+ argz_create_sep; argz_delete; argz_extract; argz_insert; argz_next;
+ argz_replace; argz_stringify;
+
+ # b*
+ basename; bcmp; bcopy; bzero;
+
+ # e*
+ envz_add; envz_entry; envz_get; envz_merge; envz_remove;
+ envz_strip;
+
+ # f*
+ ffs;
+
+ # i*
+ index;
+
+ # m*
+ memccpy; memchr; memcmp; memcpy; memfrob; memmem; memmove; memset;
+
+ # r*
+ rindex;
+
+ # s*
+ stpcpy; stpncpy; strcasecmp; strcat; strchr; strcmp; strcoll; strcpy;
+ strcspn; strdup; strerror; strerror_r; strfry; strlen; strncasecmp;
+ strncat; strncmp; strncpy; strndup; strnlen; strpbrk; strrchr; strsep;
+ strsignal; strspn; strstr; strtok; strtok_r; strxfrm; swab;
+ }
+ GLIBC_2.1 {
+ # functions used in macros and other libraries
+ __rawmemchr; __strcasestr;
+
+ # f*
+ ffsl; ffsll;
+
+ # m*
+ mempcpy;
+
+ # r*
+ rawmemchr;
+
+ # s*
+ strcasestr; strverscmp;
+ }
+ GLIBC_2.1.1 {
+ # extern inline functions used by <bits/string2.h>
+ __mempcpy_small; __stpcpy_small; __strcspn_c1; __strcspn_c2; __strcspn_c3;
+ __strcpy_small; __strspn_c1; __strspn_c2; __strspn_c3; __strpbrk_c2;
+ __strpbrk_c3; __strsep_1c; __strsep_2c; __strsep_3c; __strsep_g;
+ __strtok_r_1c;
+
+ # s*
+ strchrnul; __strverscmp;
+ }
+ GLIBC_2.2 {
+ # functions used in macros.
+ __strndup;
+
+ # m*
+ memrchr;
+ }
+ GLIBC_2.3.4 {
+ # x*
+ __xpg_strerror_r;
+ }
+ GLIBC_2.6 {
+ strerror_l;
+ }
+ GLIBC_2.24 {
+ }
+ GLIBC_2.25 {
+ explicit_bzero;
+ }
+}
diff --git a/REORG.TODO/string/_strerror.c b/REORG.TODO/string/_strerror.c
new file mode 100644
index 0000000000..4d3a52d906
--- /dev/null
+++ b/REORG.TODO/string/_strerror.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <_itoa.h>
+
+/* It is critical here that we always use the `dcgettext' function for
+ the message translation. Since <libintl.h> only defines the macro
+ `dgettext' to use `dcgettext' for optimizing programs this is not
+ always guaranteed. */
+#ifndef dgettext
+# include <locale.h> /* We need LC_MESSAGES. */
+# define dgettext(domainname, msgid) dcgettext (domainname, msgid, LC_MESSAGES)
+#endif
+
+/* Return a string describing the errno code in ERRNUM. */
+char *
+__strerror_r (int errnum, char *buf, size_t buflen)
+{
+ if (__builtin_expect (errnum < 0 || errnum >= _sys_nerr_internal
+ || _sys_errlist_internal[errnum] == NULL, 0))
+ {
+ /* Buffer we use to print the number in. For a maximum size for
+ `int' of 8 bytes we never need more than 20 digits. */
+ char numbuf[21];
+ const char *unk = _("Unknown error ");
+ size_t unklen = strlen (unk);
+ char *p, *q;
+ bool negative = errnum < 0;
+
+ numbuf[20] = '\0';
+ p = _itoa_word (abs (errnum), &numbuf[20], 10, 0);
+
+ /* Now construct the result while taking care for the destination
+ buffer size. */
+ q = __mempcpy (buf, unk, MIN (unklen, buflen));
+ if (negative && unklen < buflen)
+ {
+ *q++ = '-';
+ ++unklen;
+ }
+ if (unklen < buflen)
+ memcpy (q, p, MIN ((size_t) (&numbuf[21] - p), buflen - unklen));
+
+ /* Terminate the string in any case. */
+ if (buflen > 0)
+ buf[buflen - 1] = '\0';
+
+ return buf;
+ }
+
+ return (char *) _(_sys_errlist_internal[errnum]);
+}
+weak_alias (__strerror_r, strerror_r)
+libc_hidden_def (__strerror_r)
diff --git a/REORG.TODO/string/argz-addsep.c b/REORG.TODO/string/argz-addsep.c
new file mode 100644
index 0000000000..eab6d3ef17
--- /dev/null
+++ b/REORG.TODO/string/argz-addsep.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+error_t
+__argz_add_sep (char **argz, size_t *argz_len, const char *string, int delim)
+{
+ size_t nlen = strlen (string) + 1;
+
+ if (nlen > 1)
+ {
+ const char *rp;
+ char *wp;
+
+ *argz = (char *) realloc (*argz, *argz_len + nlen);
+ if (*argz == NULL)
+ return ENOMEM;
+
+ wp = *argz + *argz_len;
+ rp = string;
+ do
+ if (*rp == delim)
+ {
+ if (wp > *argz && wp[-1] != '\0')
+ *wp++ = '\0';
+ else
+ --nlen;
+ }
+ else
+ *wp++ = *rp;
+ while (*rp++ != '\0');
+
+ *argz_len += nlen;
+ }
+
+ return 0;
+}
+weak_alias (__argz_add_sep, argz_add_sep)
diff --git a/REORG.TODO/string/argz-append.c b/REORG.TODO/string/argz-append.c
new file mode 100644
index 0000000000..09015016e6
--- /dev/null
+++ b/REORG.TODO/string/argz-append.c
@@ -0,0 +1,49 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
+error_t
+__argz_append (char **argz, size_t *argz_len, const char *buf, size_t buf_len)
+{
+ size_t new_argz_len = *argz_len + buf_len;
+ char *new_argz = realloc (*argz, new_argz_len);
+ if (new_argz)
+ {
+ memcpy (new_argz + *argz_len, buf, buf_len);
+ *argz = new_argz;
+ *argz_len = new_argz_len;
+ return 0;
+ }
+ else
+ return ENOMEM;
+}
+weak_alias (__argz_append, argz_append)
+
+/* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into
+ argz.c in libshouldbelibc. */
+error_t
+__argz_add (char **argz, size_t *argz_len, const char *str)
+{
+ return __argz_append (argz, argz_len, str, strlen (str) + 1);
+}
+weak_alias (__argz_add, argz_add)
diff --git a/REORG.TODO/string/argz-count.c b/REORG.TODO/string/argz-count.c
new file mode 100644
index 0000000000..64e2e69b12
--- /dev/null
+++ b/REORG.TODO/string/argz-count.c
@@ -0,0 +1,38 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+
+/* Returns the number of strings in ARGZ. */
+size_t
+__argz_count (const char *argz, size_t len)
+{
+ size_t count = 0;
+ while (len > 0)
+ {
+ size_t part_len = strlen(argz);
+ argz += part_len + 1;
+ len -= part_len + 1;
+ count++;
+ }
+ return count;
+}
+libc_hidden_def (__argz_count)
+weak_alias (__argz_count, argz_count)
diff --git a/REORG.TODO/string/argz-create.c b/REORG.TODO/string/argz-create.c
new file mode 100644
index 0000000000..f7d429b5b6
--- /dev/null
+++ b/REORG.TODO/string/argz-create.c
@@ -0,0 +1,53 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Make a '\0' separated arg vector from a unix argv vector, returning it in
+ ARGZ, and the total length in LEN. If a memory allocation error occurs,
+ ENOMEM is returned, otherwise 0. */
+error_t
+__argz_create (char *const argv[], char **argz, size_t *len)
+{
+ int argc;
+ size_t tlen = 0;
+ char *const *ap;
+ char *p;
+
+ for (argc = 0; argv[argc] != NULL; ++argc)
+ tlen += strlen (argv[argc]) + 1;
+
+ if (tlen == 0)
+ *argz = NULL;
+ else
+ {
+ *argz = malloc (tlen);
+ if (*argz == NULL)
+ return ENOMEM;
+
+ for (p = *argz, ap = argv; *ap; ++ap, ++p)
+ p = __stpcpy (p, *ap);
+ }
+ *len = tlen;
+
+ return 0;
+}
+weak_alias (__argz_create, argz_create)
diff --git a/REORG.TODO/string/argz-ctsep.c b/REORG.TODO/string/argz-ctsep.c
new file mode 100644
index 0000000000..7fc1511a4b
--- /dev/null
+++ b/REORG.TODO/string/argz-ctsep.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+error_t
+__argz_create_sep (const char *string, int delim, char **argz, size_t *len)
+{
+ size_t nlen = strlen (string) + 1;
+
+ if (nlen > 1)
+ {
+ const char *rp;
+ char *wp;
+
+ *argz = (char *) malloc (nlen);
+ if (*argz == NULL)
+ return ENOMEM;
+
+ rp = string;
+ wp = *argz;
+ do
+ if (*rp == delim)
+ {
+ if (wp > *argz && wp[-1] != '\0')
+ *wp++ = '\0';
+ else
+ --nlen;
+ }
+ else
+ *wp++ = *rp;
+ while (*rp++ != '\0');
+
+ if (nlen == 0)
+ {
+ free (*argz);
+ *argz = NULL;
+ *len = 0;
+ }
+
+ *len = nlen;
+ }
+ else
+ {
+ *argz = NULL;
+ *len = 0;
+ }
+
+ return 0;
+}
+weak_alias (__argz_create_sep, argz_create_sep)
diff --git a/REORG.TODO/string/argz-delete.c b/REORG.TODO/string/argz-delete.c
new file mode 100644
index 0000000000..183ac0d43c
--- /dev/null
+++ b/REORG.TODO/string/argz-delete.c
@@ -0,0 +1,41 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */
+void
+argz_delete (char **argz, size_t *argz_len, char *entry)
+{
+ if (entry)
+ /* Get rid of the old value for NAME. */
+ {
+ size_t entry_len = strlen (entry) + 1;
+ *argz_len -= entry_len;
+ memmove (entry, entry + entry_len, *argz_len - (entry - *argz));
+ if (*argz_len == 0)
+ {
+ free (*argz);
+ *argz = 0;
+ }
+ }
+}
+libc_hidden_def (argz_delete)
diff --git a/REORG.TODO/string/argz-extract.c b/REORG.TODO/string/argz-extract.c
new file mode 100644
index 0000000000..13345e894f
--- /dev/null
+++ b/REORG.TODO/string/argz-extract.c
@@ -0,0 +1,36 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+
+/* Puts pointers to each string in ARGZ, plus a terminating 0 element, into
+ ARGV, which must be large enough to hold them all. */
+void
+__argz_extract (const char *argz, size_t len, char **argv)
+{
+ while (len > 0)
+ {
+ size_t part_len = strlen (argz);
+ *argv++ = (char *) argz;
+ argz += part_len + 1;
+ len -= part_len + 1;
+ }
+ *argv = 0;
+}
+weak_alias (__argz_extract, argz_extract)
diff --git a/REORG.TODO/string/argz-insert.c b/REORG.TODO/string/argz-insert.c
new file mode 100644
index 0000000000..e4c78407ff
--- /dev/null
+++ b/REORG.TODO/string/argz-insert.c
@@ -0,0 +1,63 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
+ existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
+ Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
+ ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
+ in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
+ ARGZ, ENOMEM is returned, else 0. */
+error_t
+__argz_insert (char **argz, size_t *argz_len, char *before, const char *entry)
+{
+ if (! before)
+ return __argz_add (argz, argz_len, entry);
+
+ if (before < *argz || before >= *argz + *argz_len)
+ return EINVAL;
+
+ if (before > *argz)
+ /* Make sure before is actually the beginning of an entry. */
+ while (before[-1])
+ before--;
+
+ {
+ size_t after_before = *argz_len - (before - *argz);
+ size_t entry_len = strlen (entry) + 1;
+ size_t new_argz_len = *argz_len + entry_len;
+ char *new_argz = realloc (*argz, new_argz_len);
+
+ if (new_argz)
+ {
+ before = new_argz + (before - *argz);
+ memmove (before + entry_len, before, after_before);
+ memmove (before, entry, entry_len);
+ *argz = new_argz;
+ *argz_len = new_argz_len;
+ return 0;
+ }
+ else
+ return ENOMEM;
+ }
+}
+weak_alias (__argz_insert, argz_insert)
diff --git a/REORG.TODO/string/argz-next.c b/REORG.TODO/string/argz-next.c
new file mode 100644
index 0000000000..9c2fa33cc2
--- /dev/null
+++ b/REORG.TODO/string/argz-next.c
@@ -0,0 +1,39 @@
+/* Iterate through the elements of an argz block.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+
+char *
+__argz_next (const char *argz, size_t argz_len, const char *entry)
+{
+ if (entry)
+ {
+ if (entry < argz + argz_len)
+ entry = strchr (entry, '\0') + 1;
+
+ return entry >= argz + argz_len ? NULL : (char *) entry;
+ }
+ else
+ if (argz_len > 0)
+ return (char *) argz;
+ else
+ return NULL;
+}
+weak_alias (__argz_next, argz_next)
diff --git a/REORG.TODO/string/argz-replace.c b/REORG.TODO/string/argz-replace.c
new file mode 100644
index 0000000000..6464e9bdbb
--- /dev/null
+++ b/REORG.TODO/string/argz-replace.c
@@ -0,0 +1,134 @@
+/* String replacement in an argz vector
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <argz.h>
+
+/* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and
+ updating *TO & *TO_LEN appropriately. If an allocation error occurs,
+ *TO's old value is freed, and *TO is set to 0. */
+static void
+str_append (char **to, size_t *to_len, const char *buf, const size_t buf_len)
+{
+ size_t new_len = *to_len + buf_len;
+ char *new_to = realloc (*to, new_len + 1);
+
+ if (new_to)
+ {
+ *((char *) __mempcpy (new_to + *to_len, buf, buf_len)) = '\0';
+ *to = new_to;
+ *to_len = new_len;
+ }
+ else
+ {
+ free (*to);
+ *to = 0;
+ }
+}
+
+/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
+ ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
+ incremented by number of replacements performed. */
+error_t
+__argz_replace (char **argz, size_t *argz_len, const char *str, const char *with,
+ unsigned *replace_count)
+{
+ error_t err = 0;
+
+ if (str && *str)
+ {
+ char *arg = 0;
+ char *src = *argz;
+ size_t src_len = *argz_len;
+ char *dst = 0;
+ size_t dst_len = 0;
+ int delayed_copy = 1; /* True while we've avoided copying anything. */
+ size_t str_len = strlen (str), with_len = strlen (with);
+
+ while (!err && (arg = argz_next (src, src_len, arg)))
+ {
+ char *match = strstr (arg, str);
+ if (match)
+ {
+ char *from = match + str_len;
+ size_t to_len = match - arg;
+ char *to = __strndup (arg, to_len);
+
+ while (to && from)
+ {
+ str_append (&to, &to_len, with, with_len);
+ if (to)
+ {
+ match = strstr (from, str);
+ if (match)
+ {
+ str_append (&to, &to_len, from, match - from);
+ from = match + str_len;
+ }
+ else
+ {
+ str_append (&to, &to_len, from, strlen (from));
+ from = 0;
+ }
+ }
+ }
+
+ if (to)
+ {
+ if (delayed_copy)
+ /* We avoided copying SRC to DST until we found a match;
+ now that we've done so, copy everything from the start
+ of SRC. */
+ {
+ if (arg > src)
+ err = __argz_append (&dst, &dst_len, src, (arg - src));
+ delayed_copy = 0;
+ }
+ if (! err)
+ err = __argz_add (&dst, &dst_len, to);
+ free (to);
+ }
+ else
+ err = ENOMEM;
+
+ if (replace_count)
+ (*replace_count)++;
+ }
+ else if (! delayed_copy)
+ err = __argz_add (&dst, &dst_len, arg);
+ }
+
+ if (! err)
+ {
+ if (! delayed_copy)
+ /* We never found any instances of str. */
+ {
+ free (src);
+ *argz = dst;
+ *argz_len = dst_len;
+ }
+ }
+ else if (dst_len > 0)
+ free (dst);
+ }
+
+ return err;
+}
+weak_alias (__argz_replace, argz_replace)
diff --git a/REORG.TODO/string/argz-stringify.c b/REORG.TODO/string/argz-stringify.c
new file mode 100644
index 0000000000..5499264d38
--- /dev/null
+++ b/REORG.TODO/string/argz-stringify.c
@@ -0,0 +1,40 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <argz.h>
+#include <string.h>
+
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+ except the last into the character SEP. */
+void
+__argz_stringify (char *argz, size_t len, int sep)
+{
+ if (len > 0)
+ while (1)
+ {
+ size_t part_len = __strnlen (argz, len);
+ argz += part_len;
+ len -= part_len;
+ if (len-- <= 1) /* includes final '\0' we want to stop at */
+ break;
+ *argz++ = sep;
+ }
+}
+libc_hidden_def (__argz_stringify)
+weak_alias (__argz_stringify, argz_stringify)
diff --git a/REORG.TODO/string/argz.h b/REORG.TODO/string/argz.h
new file mode 100644
index 0000000000..f9d0ac9950
--- /dev/null
+++ b/REORG.TODO/string/argz.h
@@ -0,0 +1,182 @@
+/* Routines for dealing with '\0' separated arg vectors.
+ Copyright (C) 1995-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARGZ_H
+#define _ARGZ_H 1
+
+#include <features.h>
+
+#define __need_error_t
+#include <errno.h>
+#include <string.h> /* Need size_t, and strchr is called below. */
+
+#ifndef __error_t_defined
+typedef int error_t;
+#endif
+
+
+__BEGIN_DECLS
+
+/* Make a '\0' separated arg vector from a unix argv vector, returning it in
+ ARGZ, and the total length in LEN. If a memory allocation error occurs,
+ ENOMEM is returned, otherwise 0. The result can be destroyed using free. */
+extern error_t __argz_create (char *const __argv[], char **__restrict __argz,
+ size_t *__restrict __len) __THROW;
+extern error_t argz_create (char *const __argv[], char **__restrict __argz,
+ size_t *__restrict __len) __THROW;
+
+/* Make a '\0' separated arg vector from a SEP separated list in
+ STRING, returning it in ARGZ, and the total length in LEN. If a
+ memory allocation error occurs, ENOMEM is returned, otherwise 0.
+ The result can be destroyed using free. */
+extern error_t __argz_create_sep (const char *__restrict __string,
+ int __sep, char **__restrict __argz,
+ size_t *__restrict __len) __THROW;
+extern error_t argz_create_sep (const char *__restrict __string,
+ int __sep, char **__restrict __argz,
+ size_t *__restrict __len) __THROW;
+
+/* Returns the number of strings in ARGZ. */
+extern size_t __argz_count (const char *__argz, size_t __len)
+ __THROW __attribute_pure__;
+extern size_t argz_count (const char *__argz, size_t __len)
+ __THROW __attribute_pure__;
+
+/* Puts pointers to each string in ARGZ into ARGV, which must be large enough
+ to hold them all. */
+extern void __argz_extract (const char *__restrict __argz, size_t __len,
+ char **__restrict __argv) __THROW;
+extern void argz_extract (const char *__restrict __argz, size_t __len,
+ char **__restrict __argv) __THROW;
+
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+ except the last into the character SEP. */
+extern void __argz_stringify (char *__argz, size_t __len, int __sep) __THROW;
+extern void argz_stringify (char *__argz, size_t __len, int __sep) __THROW;
+
+/* Append BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
+extern error_t __argz_append (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __buf, size_t __buf_len)
+ __THROW;
+extern error_t argz_append (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __buf, size_t __buf_len)
+ __THROW;
+
+/* Append STR to the argz vector in ARGZ & ARGZ_LEN. */
+extern error_t __argz_add (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __str) __THROW;
+extern error_t argz_add (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __str) __THROW;
+
+/* Append SEP separated list in STRING to the argz vector in ARGZ &
+ ARGZ_LEN. */
+extern error_t __argz_add_sep (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __string, int __delim)
+ __THROW;
+extern error_t argz_add_sep (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __string, int __delim)
+ __THROW;
+
+/* Delete ENTRY from ARGZ & ARGZ_LEN, if it appears there. */
+extern void __argz_delete (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ char *__restrict __entry) __THROW;
+extern void argz_delete (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ char *__restrict __entry) __THROW;
+
+/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
+ existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
+ Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
+ ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
+ in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
+ ARGZ, ENOMEM is returned, else 0. */
+extern error_t __argz_insert (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ char *__restrict __before,
+ const char *__restrict __entry) __THROW;
+extern error_t argz_insert (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ char *__restrict __before,
+ const char *__restrict __entry) __THROW;
+
+/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
+ ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
+ incremented by number of replacements performed. */
+extern error_t __argz_replace (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __str,
+ const char *__restrict __with,
+ unsigned int *__restrict __replace_count);
+extern error_t argz_replace (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __str,
+ const char *__restrict __with,
+ unsigned int *__restrict __replace_count);
+
+/* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there
+ are no more. If entry is NULL, then the first entry is returned. This
+ behavior allows two convenient iteration styles:
+
+ char *entry = 0;
+ while ((entry = argz_next (argz, argz_len, entry)))
+ ...;
+
+ or
+
+ char *entry;
+ for (entry = argz; entry; entry = argz_next (argz, argz_len, entry))
+ ...;
+*/
+extern char *__argz_next (const char *__restrict __argz, size_t __argz_len,
+ const char *__restrict __entry) __THROW;
+extern char *argz_next (const char *__restrict __argz, size_t __argz_len,
+ const char *__restrict __entry) __THROW;
+
+#ifdef __USE_EXTERN_INLINES
+__extern_inline char *
+__NTH (__argz_next (const char *__argz, size_t __argz_len,
+ const char *__entry))
+{
+ if (__entry)
+ {
+ if (__entry < __argz + __argz_len)
+ __entry = strchr (__entry, '\0') + 1;
+
+ return __entry >= __argz + __argz_len ? (char *) NULL : (char *) __entry;
+ }
+ else
+ return __argz_len > 0 ? (char *) __argz : 0;
+}
+__extern_inline char *
+__NTH (argz_next (const char *__argz, size_t __argz_len,
+ const char *__entry))
+{
+ return __argz_next (__argz, __argz_len, __entry);
+}
+#endif /* Use extern inlines. */
+
+__END_DECLS
+
+#endif /* argz.h */
diff --git a/REORG.TODO/string/basename.c b/REORG.TODO/string/basename.c
new file mode 100644
index 0000000000..0f379680b7
--- /dev/null
+++ b/REORG.TODO/string/basename.c
@@ -0,0 +1,29 @@
+/* Return the name-within-directory of a file name.
+ Copyright (C) 1996-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+char *
+__basename (const char *filename)
+{
+ char *p = strrchr (filename, '/');
+ return p ? p + 1 : (char *) filename;
+}
+libc_hidden_def (__basename)
+weak_alias (__basename, basename)
+libc_hidden_weak (basename)
diff --git a/REORG.TODO/string/bcopy.c b/REORG.TODO/string/bcopy.c
new file mode 100644
index 0000000000..24fe494fec
--- /dev/null
+++ b/REORG.TODO/string/bcopy.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+void
+bcopy (const void *src, void *dest, size_t len)
+{
+ memmove (dest, src, len);
+}
diff --git a/REORG.TODO/string/bits/string2.h b/REORG.TODO/string/bits/string2.h
new file mode 100644
index 0000000000..6a26e2bc68
--- /dev/null
+++ b/REORG.TODO/string/bits/string2.h
@@ -0,0 +1,119 @@
+/* Machine-independant string function optimizations.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRING_H
+# error "Never use <bits/string2.h> directly; include <string.h> instead."
+#endif
+
+#ifndef __NO_STRING_INLINES
+
+/* Unlike the definitions in the header <bits/string.h> the
+ definitions contained here are not optimized down to assembler
+ level. Those optimizations are not always a good idea since this
+ means the code size increases a lot. Instead the definitions here
+ optimize some functions in a way which do not dramatically
+ increase the code size and which do not use assembler. The main
+ trick is to use GCC's `__builtin_constant_p' function.
+
+ Every function XXX which has a defined version in
+ <bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX
+ to make sure we don't get redefinitions.
+
+ We must use here macros instead of inline functions since the
+ trick won't work with the latter. */
+
+#ifndef __STRING_INLINE
+# ifdef __cplusplus
+# define __STRING_INLINE inline
+# else
+# define __STRING_INLINE __extern_inline
+# endif
+#endif
+
+/* Dereferencing a pointer arg to run sizeof on it fails for the void
+ pointer case, so we use this instead.
+ Note that __x is evaluated twice. */
+#define __string2_1bptr_p(__x) \
+ ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
+
+/* Set N bytes of S to 0. */
+#if !defined _HAVE_STRING_ARCH_memset
+# define __bzero(s, n) __builtin_memset (s, '\0', n)
+#endif
+
+
+/* Copy SRC to DEST, returning pointer to final NUL byte. */
+#ifdef __USE_GNU
+# ifndef _HAVE_STRING_ARCH_stpcpy
+# define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
+/* In glibc we use this function frequently but for namespace reasons
+ we have to use the name `__stpcpy'. */
+# define stpcpy(dest, src) __stpcpy (dest, src)
+# endif
+#endif
+
+
+/* Copy no more than N characters of SRC to DEST. */
+#ifndef _HAVE_STRING_ARCH_strncpy
+# define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)
+#endif
+
+
+/* Append no more than N characters from SRC onto DEST. */
+#ifndef _HAVE_STRING_ARCH_strncat
+# ifdef _USE_STRING_ARCH_strchr
+# define strncat(dest, src, n) \
+ (__extension__ ({ char *__dest = (dest); \
+ __builtin_constant_p (src) && __builtin_constant_p (n) \
+ ? (strlen (src) < ((size_t) (n)) \
+ ? strcat (__dest, src) \
+ : (*((char *) __mempcpy (strchr (__dest, '\0'), \
+ src, n)) = '\0', __dest)) \
+ : strncat (dest, src, n); }))
+# else
+# define strncat(dest, src, n) __builtin_strncat (dest, src, n)
+# endif
+#endif
+
+
+/* Return the length of the initial segment of S which
+ consists entirely of characters not in REJECT. */
+#ifndef _HAVE_STRING_ARCH_strcspn
+# define strcspn(s, reject) __builtin_strcspn (s, reject)
+#endif
+
+
+/* Return the length of the initial segment of S which
+ consists entirely of characters in ACCEPT. */
+#ifndef _HAVE_STRING_ARCH_strspn
+# define strspn(s, accept) __builtin_strspn (s, accept)
+#endif
+
+
+/* Find the first occurrence in S of any character in ACCEPT. */
+#ifndef _HAVE_STRING_ARCH_strpbrk
+# define strpbrk(s, accept) __builtin_strpbrk (s, accept)
+#endif
+
+
+#ifndef _FORCE_INLINES
+# undef __STRING_INLINE
+#endif
+
+#endif /* No string inlines. */
diff --git a/REORG.TODO/string/bits/string3.h b/REORG.TODO/string/bits/string3.h
new file mode 100644
index 0000000000..738226d49b
--- /dev/null
+++ b/REORG.TODO/string/bits/string3.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 2004-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRING_H
+# error "Never use <bits/string3.h> directly; include <string.h> instead."
+#endif
+
+#if !__GNUC_PREREQ (5,0)
+__warndecl (__warn_memset_zero_len,
+ "memset used with constant zero length parameter; this could be due to transposed parameters");
+#endif
+
+#ifndef __cplusplus
+/* XXX This is temporarily. We should not redefine any of the symbols
+ and instead integrate the error checking into the original
+ definitions. */
+# undef memcpy
+# undef memmove
+# undef memset
+# undef strcat
+# undef strcpy
+# undef strncat
+# undef strncpy
+# ifdef __USE_GNU
+# undef mempcpy
+# undef stpcpy
+# endif
+# ifdef __USE_MISC
+# undef bcopy
+# undef bzero
+# endif
+#endif
+
+
+__fortify_function void *
+__NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
+ size_t __len))
+{
+ return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+__fortify_function void *
+__NTH (memmove (void *__dest, const void *__src, size_t __len))
+{
+ return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+#ifdef __USE_GNU
+__fortify_function void *
+__NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
+ size_t __len))
+{
+ return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+#endif
+
+
+/* The first two tests here help to catch a somewhat common problem
+ where the second and third parameter are transposed. This is
+ especially problematic if the intended fill value is zero. In this
+ case no work is done at all. We detect these problems by referring
+ non-existing functions. */
+__fortify_function void *
+__NTH (memset (void *__dest, int __ch, size_t __len))
+{
+ /* GCC-5.0 and newer implements these checks in the compiler, so we don't
+ need them here. */
+#if !__GNUC_PREREQ (5,0)
+ if (__builtin_constant_p (__len) && __len == 0
+ && (!__builtin_constant_p (__ch) || __ch != 0))
+ {
+ __warn_memset_zero_len ();
+ return __dest;
+ }
+#endif
+ return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
+}
+
+#ifdef __USE_MISC
+# include <bits/strings_fortified.h>
+
+void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen)
+ __THROW __nonnull ((1));
+
+__fortify_function void
+__NTH (explicit_bzero (void *__dest, size_t __len))
+{
+ __explicit_bzero_chk (__dest, __len, __bos0 (__dest));
+}
+#endif
+
+__fortify_function char *
+__NTH (strcpy (char *__restrict __dest, const char *__restrict __src))
+{
+ return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
+}
+
+#ifdef __USE_GNU
+__fortify_function char *
+__NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
+{
+ return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
+}
+#endif
+
+
+__fortify_function char *
+__NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
+ size_t __len))
+{
+ return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
+}
+
+/* XXX We have no corresponding builtin yet. */
+extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
+ size_t __destlen) __THROW;
+extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src,
+ size_t __n), stpncpy);
+
+__fortify_function char *
+__NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+{
+ if (__bos (__dest) != (size_t) -1
+ && (!__builtin_constant_p (__n) || __n > __bos (__dest)))
+ return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+ return __stpncpy_alias (__dest, __src, __n);
+}
+
+
+__fortify_function char *
+__NTH (strcat (char *__restrict __dest, const char *__restrict __src))
+{
+ return __builtin___strcat_chk (__dest, __src, __bos (__dest));
+}
+
+
+__fortify_function char *
+__NTH (strncat (char *__restrict __dest, const char *__restrict __src,
+ size_t __len))
+{
+ return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
+}
diff --git a/REORG.TODO/string/bits/strings_fortified.h b/REORG.TODO/string/bits/strings_fortified.h
new file mode 100644
index 0000000000..411e7863d6
--- /dev/null
+++ b/REORG.TODO/string/bits/strings_fortified.h
@@ -0,0 +1,34 @@
+/* Fortify macros for strings.h functions.
+ Copyright (C) 2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __STRINGS_FORTIFIED
+# define __STRINGS_FORTIFIED 1
+
+__fortify_function void
+__NTH (bcopy (const void *__src, void *__dest, size_t __len))
+{
+ (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+__fortify_function void
+__NTH (bzero (void *__dest, size_t __len))
+{
+ (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
+}
+
+#endif
diff --git a/REORG.TODO/string/bug-envz1.c b/REORG.TODO/string/bug-envz1.c
new file mode 100644
index 0000000000..931a0559fe
--- /dev/null
+++ b/REORG.TODO/string/bug-envz1.c
@@ -0,0 +1,75 @@
+/* Test for bug BZ #2703. */
+#include <stdio.h>
+#include <envz.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const struct
+{
+ const char *s;
+ int in_result;
+} strs[] =
+{
+ { "a=1", 1 },
+ { "b=2", 1 },
+ { "(*)", 0 },
+ { "(*)", 0 },
+ { "e=5", 1 },
+ { "f=", 1 },
+ { "(*)", 0 },
+ { "h=8", 1 },
+ { "i=9", 1 },
+ { "j", 0 }
+};
+
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+
+
+int
+do_test (void)
+{
+
+ size_t size = 0;
+ char *str = malloc (100);
+ if (str == NULL)
+ {
+ puts ("out of memory");
+ return 1;
+ }
+
+ char **argz = &str;
+
+ for (int i = 0; i < nstrs; ++i)
+ argz_add_sep (argz, &size, strs[i].s, '\0');
+
+ printf ("calling envz_strip with size=%zu\n", size);
+ envz_strip (argz, &size);
+
+ int result = 0;
+ printf ("new size=%zu\n", size);
+ for (int i = 0; i < nstrs; ++i)
+ if (strs[i].in_result)
+ {
+ char name[2];
+ name[0] = strs[i].s[0];
+ name[1] = '\0';
+
+ char *e = envz_entry (*argz, size, name);
+ if (e == NULL)
+ {
+ printf ("entry '%s' not found\n", name);
+ result = 1;
+ }
+ else if (strcmp (e, strs[i].s) != 0)
+ {
+ printf ("entry '%s' does not match: is '%s', expected '%s'\n",
+ name, e, strs[i].s);
+ result = 1;
+ }
+ }
+
+ free (*argz);
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/bug-strcoll1.c b/REORG.TODO/string/bug-strcoll1.c
new file mode 100644
index 0000000000..b6510d926f
--- /dev/null
+++ b/REORG.TODO/string/bug-strcoll1.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+
+int
+main (void)
+{
+ const char t1[] = "0-0-0-0-0-0-0-0-0-0.COM";
+ const char t2[] = "00000-00000.COM";
+ int res1;
+ int res2;
+
+ setlocale (LC_ALL, "en_US.ISO-8859-1");
+
+ res1 = strcoll (t1, t2);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, res1);
+ res2 = strcoll (t2, t1);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, res2);
+
+ return ((res1 == 0 && res2 != 0)
+ || (res1 != 0 && res2 == 0)
+ || (res1 < 0 && res2 < 0)
+ || (res1 > 0 && res2 > 0));
+}
diff --git a/REORG.TODO/string/bug-strcoll2.c b/REORG.TODO/string/bug-strcoll2.c
new file mode 100644
index 0000000000..ff33007df6
--- /dev/null
+++ b/REORG.TODO/string/bug-strcoll2.c
@@ -0,0 +1,91 @@
+/* Bug 18589: sort-test.sh fails at random.
+ Copyright (C) 2015-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+
+/* An incorrect strcoll optimization resulted in incorrect
+ results from strcoll for cs_CZ and da_DK. */
+
+int
+test_cs_CZ (void)
+{
+ const char t1[] = "config";
+ const char t2[] = "choose";
+ if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
+ {
+ perror ("setlocale");
+ return 1;
+ }
+ /* In Czech the digraph ch sorts after c, therefore we expect
+ config to sort before choose. */
+ int a = strcoll (t1, t2);
+ int b = strcoll (t2, t1);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
+ if (a < 0 && b > 0)
+ {
+ puts ("PASS: config < choose");
+ return 0;
+ }
+ else
+ {
+ puts ("FAIL: Wrong sorting in cs_CZ.UTF-8.");
+ return 1;
+ }
+}
+
+int
+test_da_DK (void)
+{
+ const char t1[] = "AS";
+ const char t2[] = "AA";
+ if (setlocale (LC_ALL, "da_DK.ISO-8859-1") == NULL)
+ {
+ perror ("setlocale");
+ return 1;
+ }
+ /* AA should be treated as the last letter of the Danish alphabet,
+ hence sorting after AS. */
+ int a = strcoll (t1, t2);
+ int b = strcoll (t2, t1);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
+ if (a < 0 && b > 0)
+ {
+ puts ("PASS: AS < AA");
+ return 0;
+ }
+ else
+ {
+ puts ("FAIL: Wrong sorting in da_DK.ISO-8859-1");
+ return 1;
+ }
+}
+
+int
+do_test (void)
+{
+ int err = 0;
+ err |= test_cs_CZ ();
+ err |= test_da_DK ();
+ return err;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/bug-strncat1.c b/REORG.TODO/string/bug-strncat1.c
new file mode 100644
index 0000000000..f1b5c37c5c
--- /dev/null
+++ b/REORG.TODO/string/bug-strncat1.c
@@ -0,0 +1,31 @@
+/* Test case by Joseph S. Myers <jsm28@cam.ac.uk>. */
+#undef __USE_STRING_INLINES
+#define __USE_STRING_INLINES
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char d[3] = "\0\1\2";
+
+int
+main (void)
+{
+ strncat (d, "\5\6", 1);
+ if (d[0] != '\5')
+ {
+ puts ("d[0] != '\\5'");
+ exit (1);
+ }
+ if (d[1] != '\0')
+ {
+ puts ("d[1] != '\\0'");
+ exit (1);
+ }
+ if (d[2] != '\2')
+ {
+ puts ("d[2] != '\\2'");
+ exit (1);
+ }
+
+ return 0;
+}
diff --git a/REORG.TODO/string/bug-strpbrk1.c b/REORG.TODO/string/bug-strpbrk1.c
new file mode 100644
index 0000000000..28238b0f50
--- /dev/null
+++ b/REORG.TODO/string/bug-strpbrk1.c
@@ -0,0 +1,19 @@
+/* Test case by Joseph S. Myers <jsm28@cam.ac.uk>. */
+#undef __USE_STRING_INLINES
+#define __USE_STRING_INLINES
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+ const char *a = "abc";
+ const char *b = a;
+
+ strpbrk (b++, "");
+ if (b != a + 1)
+ return 1;
+
+ return 0;
+}
diff --git a/REORG.TODO/string/bug-strspn1.c b/REORG.TODO/string/bug-strspn1.c
new file mode 100644
index 0000000000..a657bafc43
--- /dev/null
+++ b/REORG.TODO/string/bug-strspn1.c
@@ -0,0 +1,19 @@
+/* Test case by Joseph S. Myers <jsm28@cam.ac.uk>. */
+#undef __USE_STRING_INLINES
+#define __USE_STRING_INLINES
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+ const char *a = "abc";
+ const char *b = a;
+
+ strspn (b++, "");
+ if (b != a + 1)
+ return 1;
+
+ return 0;
+}
diff --git a/REORG.TODO/string/bug-strtok1.c b/REORG.TODO/string/bug-strtok1.c
new file mode 100644
index 0000000000..a47b2f3531
--- /dev/null
+++ b/REORG.TODO/string/bug-strtok1.c
@@ -0,0 +1,44 @@
+/* See BZ #2126. */
+#include <string.h>
+#include <stdio.h>
+
+int
+do_test (void)
+{
+ const char str[] = "axaaba";
+ char *token;
+ char *cp;
+ char *l;
+ int result = 0;
+
+ puts ("test strtok");
+ cp = strdupa (str);
+ printf ("cp = %p, len = %zu\n", cp, strlen (cp));
+ token = strtok (cp, "ab");
+ result |= token == NULL || strcmp (token, "x");
+ printf ("token: %s (%d)\n", token ? token : "NULL", result);
+ token = strtok(0, "ab");
+ result |= token != NULL;
+ printf ("token: %s (%d)\n", token ? token : "NULL", result);
+ token = strtok(0, "a");
+ result |= token != NULL;
+ printf ("token: %s (%d)\n", token ? token : "NULL", result);
+
+ puts ("test strtok_r");
+ cp = strdupa (str);
+ size_t len = strlen (cp);
+ printf ("cp = %p, len = %zu\n", cp, len);
+ token = strtok_r (cp, "ab", &l);
+ result |= token == NULL || strcmp (token, "x");
+ printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
+ token = strtok_r(0, "ab", &l);
+ result |= token != NULL || l != cp + len;
+ printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
+ token = strtok_r(0, "a", &l);
+ result |= token != NULL || l != cp + len;
+ printf ("token: %s, next = %p (%d)\n", token ? token : "NULL", l, result);
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/byteswap.h b/REORG.TODO/string/byteswap.h
new file mode 100644
index 0000000000..4ec8ac7713
--- /dev/null
+++ b/REORG.TODO/string/byteswap.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 1997-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BYTESWAP_H
+#define _BYTESWAP_H 1
+
+#include <features.h>
+
+/* Get the machine specific, optimized definitions. */
+#include <bits/byteswap.h>
+
+
+/* The following definitions must all be macros since otherwise some
+ of the possible optimizations are not possible. */
+
+/* Return a value with all bytes in the 16 bit argument swapped. */
+#define bswap_16(x) __bswap_16 (x)
+
+/* Return a value with all bytes in the 32 bit argument swapped. */
+#define bswap_32(x) __bswap_32 (x)
+
+/* Return a value with all bytes in the 64 bit argument swapped. */
+#define bswap_64(x) __bswap_64 (x)
+
+#endif /* byteswap.h */
diff --git a/REORG.TODO/string/bzero.c b/REORG.TODO/string/bzero.c
new file mode 100644
index 0000000000..9de1f89d10
--- /dev/null
+++ b/REORG.TODO/string/bzero.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef __bzero
+
+/* Set N bytes of S to 0. */
+void
+__bzero (void *s, size_t len)
+{
+ memset (s, '\0', len);
+}
+weak_alias (__bzero, bzero)
diff --git a/REORG.TODO/string/endian.h b/REORG.TODO/string/endian.h
new file mode 100644
index 0000000000..dcc9a65df7
--- /dev/null
+++ b/REORG.TODO/string/endian.h
@@ -0,0 +1,97 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ENDIAN_H
+#define _ENDIAN_H 1
+
+#include <features.h>
+
+/* Definitions for byte order, according to significance of bytes,
+ from low addresses to high addresses. The value is what you get by
+ putting '4' in the most significant byte, '3' in the second most
+ significant byte, '2' in the second least significant byte, and '1'
+ in the least significant byte, and then writing down one digit for
+ each byte, starting with the byte at the lowest address at the left,
+ and proceeding to the byte with the highest address at the right. */
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+/* This file defines `__BYTE_ORDER' for the particular machine. */
+#include <bits/endian.h>
+
+/* Some machines may need to use a different endianness for floating point
+ values. */
+#ifndef __FLOAT_WORD_ORDER
+# define __FLOAT_WORD_ORDER __BYTE_ORDER
+#endif
+
+#ifdef __USE_MISC
+# define LITTLE_ENDIAN __LITTLE_ENDIAN
+# define BIG_ENDIAN __BIG_ENDIAN
+# define PDP_ENDIAN __PDP_ENDIAN
+# define BYTE_ORDER __BYTE_ORDER
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define __LONG_LONG_PAIR(HI, LO) LO, HI
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define __LONG_LONG_PAIR(HI, LO) HI, LO
+#endif
+
+
+#if defined __USE_MISC && !defined __ASSEMBLER__
+/* Conversion interfaces. */
+# include <bits/byteswap.h>
+# include <bits/uintn-identity.h>
+
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define htobe16(x) __bswap_16 (x)
+# define htole16(x) __uint16_identity (x)
+# define be16toh(x) __bswap_16 (x)
+# define le16toh(x) __uint16_identity (x)
+
+# define htobe32(x) __bswap_32 (x)
+# define htole32(x) __uint32_identity (x)
+# define be32toh(x) __bswap_32 (x)
+# define le32toh(x) __uint32_identity (x)
+
+# define htobe64(x) __bswap_64 (x)
+# define htole64(x) __uint64_identity (x)
+# define be64toh(x) __bswap_64 (x)
+# define le64toh(x) __uint64_identity (x)
+
+# else
+# define htobe16(x) __uint16_identity (x)
+# define htole16(x) __bswap_16 (x)
+# define be16toh(x) __uint16_identity (x)
+# define le16toh(x) __bswap_16 (x)
+
+# define htobe32(x) __uint32_identity (x)
+# define htole32(x) __bswap_32 (x)
+# define be32toh(x) __uint32_identity (x)
+# define le32toh(x) __bswap_32 (x)
+
+# define htobe64(x) __uint64_identity (x)
+# define htole64(x) __bswap_64 (x)
+# define be64toh(x) __uint64_identity (x)
+# define le64toh(x) __bswap_64 (x)
+# endif
+#endif
+
+#endif /* endian.h */
diff --git a/REORG.TODO/string/envz.c b/REORG.TODO/string/envz.c
new file mode 100644
index 0000000000..02fb5cc28a
--- /dev/null
+++ b/REORG.TODO/string/envz.c
@@ -0,0 +1,172 @@
+/* Routines for dealing with '\0' separated environment vectors
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.org>
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <malloc.h>
+#include <string.h>
+
+#include <envz.h>
+
+/* The character separating names from values in an envz. */
+#define SEP '='
+
+/* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none.
+ If NAME contains the separator character, only the portion before it is
+ used in the comparison. */
+char *
+envz_entry (const char *envz, size_t envz_len, const char *name)
+{
+ while (envz_len)
+ {
+ const char *p = name;
+ const char *entry = envz; /* Start of this entry. */
+
+ /* See how far NAME and ENTRY match. */
+ while (envz_len && *p == *envz && *p && *p != SEP)
+ p++, envz++, envz_len--;
+
+ if ((*envz == '\0' || *envz == SEP) && (*p == '\0' || *p == SEP))
+ /* Bingo! */
+ return (char *) entry;
+
+ /* No match, skip to the next entry. */
+ while (envz_len && *envz)
+ envz++, envz_len--;
+ if (envz_len)
+ envz++, envz_len--; /* skip '\0' */
+ }
+
+ return 0;
+}
+libc_hidden_def (envz_entry)
+
+/* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0
+ if there is none. */
+char *
+envz_get (const char *envz, size_t envz_len, const char *name)
+{
+ char *entry = envz_entry (envz, envz_len, name);
+ if (entry)
+ {
+ while (*entry && *entry != SEP)
+ entry++;
+ if (*entry)
+ entry++;
+ else
+ entry = 0; /* A null entry. */
+ }
+ return entry;
+}
+
+/* Remove the entry for NAME from ENVZ & ENVZ_LEN, if any. */
+void
+envz_remove (char **envz, size_t *envz_len, const char *name)
+{
+ char *entry = envz_entry (*envz, *envz_len, name);
+ if (entry)
+ argz_delete (envz, envz_len, entry);
+}
+libc_hidden_def (envz_remove)
+
+/* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN. If an entry
+ with the same name already exists in ENVZ, it is removed. If VALUE is
+ NULL, then the new entry will a special null one, for which envz_get will
+ return NULL, although envz_entry will still return an entry; this is handy
+ because when merging with another envz, the null entry can override an
+ entry in the other one. Null entries can be removed with envz_strip (). */
+error_t
+envz_add (char **envz, size_t *envz_len, const char *name, const char *value)
+{
+ envz_remove (envz, envz_len, name);
+
+ if (value)
+ /* Add the new value, if there is one. */
+ {
+ size_t name_len = strlen (name);
+ size_t value_len = strlen (value);
+ size_t old_envz_len = *envz_len;
+ size_t new_envz_len = old_envz_len + name_len + 1 + value_len + 1;
+ char *new_envz = realloc (*envz, new_envz_len);
+
+ if (new_envz)
+ {
+ memcpy (new_envz + old_envz_len, name, name_len);
+ new_envz[old_envz_len + name_len] = SEP;
+ memcpy (new_envz + old_envz_len + name_len + 1, value, value_len);
+ new_envz[new_envz_len - 1] = 0;
+
+ *envz = new_envz;
+ *envz_len = new_envz_len;
+
+ return 0;
+ }
+ else
+ return ENOMEM;
+ }
+ else
+ /* Add a null entry. */
+ return __argz_add (envz, envz_len, name);
+}
+
+/* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add(). If
+ OVERRIDE is true, then values in ENVZ2 will supersede those with the same
+ name in ENV, otherwise not. */
+error_t
+envz_merge (char **envz, size_t *envz_len, const char *envz2,
+ size_t envz2_len, int override)
+{
+ error_t err = 0;
+
+ while (envz2_len && ! err)
+ {
+ char *old = envz_entry (*envz, *envz_len, envz2);
+ size_t new_len = strlen (envz2) + 1;
+
+ if (! old)
+ err = __argz_append (envz, envz_len, envz2, new_len);
+ else if (override)
+ {
+ argz_delete (envz, envz_len, old);
+ err = __argz_append (envz, envz_len, envz2, new_len);
+ }
+
+ envz2 += new_len;
+ envz2_len -= new_len;
+ }
+
+ return err;
+}
+
+/* Remove null entries. */
+void
+envz_strip (char **envz, size_t *envz_len)
+{
+ char *entry = *envz;
+ size_t left = *envz_len;
+ while (left)
+ {
+ size_t entry_len = strlen (entry) + 1;
+ left -= entry_len;
+ if (! strchr (entry, SEP))
+ /* Null entry. */
+ memmove (entry, entry + entry_len, left);
+ else
+ entry += entry_len;
+ }
+ *envz_len = entry - *envz;
+}
diff --git a/REORG.TODO/string/envz.h b/REORG.TODO/string/envz.h
new file mode 100644
index 0000000000..330cdd3d8a
--- /dev/null
+++ b/REORG.TODO/string/envz.h
@@ -0,0 +1,73 @@
+/* Routines for dealing with '\0' separated environment vectors
+ Copyright (C) 1995-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ENVZ_H
+#define _ENVZ_H 1
+
+#include <features.h>
+
+#include <errno.h>
+
+/* Envz's are argz's too, and should be created etc., using the same
+ routines. */
+#include <argz.h>
+
+__BEGIN_DECLS
+
+/* Returns a pointer to the entry in ENVZ for NAME, or 0 if there is none. */
+extern char *envz_entry (const char *__restrict __envz, size_t __envz_len,
+ const char *__restrict __name)
+ __THROW __attribute_pure__;
+
+/* Returns a pointer to the value portion of the entry in ENVZ for NAME, or 0
+ if there is none. */
+extern char *envz_get (const char *__restrict __envz, size_t __envz_len,
+ const char *__restrict __name)
+ __THROW __attribute_pure__;
+
+/* Adds an entry for NAME with value VALUE to ENVZ & ENVZ_LEN. If an entry
+ with the same name already exists in ENVZ, it is removed. If VALUE is
+ NULL, then the new entry will a special null one, for which envz_get will
+ return NULL, although envz_entry will still return an entry; this is handy
+ because when merging with another envz, the null entry can override an
+ entry in the other one. Null entries can be removed with envz_strip (). */
+extern error_t envz_add (char **__restrict __envz,
+ size_t *__restrict __envz_len,
+ const char *__restrict __name,
+ const char *__restrict __value) __THROW;
+
+/* Adds each entry in ENVZ2 to ENVZ & ENVZ_LEN, as if with envz_add(). If
+ OVERRIDE is true, then values in ENVZ2 will supersede those with the same
+ name in ENV, otherwise not. */
+extern error_t envz_merge (char **__restrict __envz,
+ size_t *__restrict __envz_len,
+ const char *__restrict __envz2,
+ size_t __envz2_len, int __override) __THROW;
+
+/* Remove the entry for NAME from ENVZ & ENVZ_LEN, if any. */
+extern void envz_remove (char **__restrict __envz,
+ size_t *__restrict __envz_len,
+ const char *__restrict __name) __THROW;
+
+/* Remove null entries. */
+extern void envz_strip (char **__restrict __envz,
+ size_t *__restrict __envz_len) __THROW;
+
+__END_DECLS
+
+#endif /* envz.h */
diff --git a/REORG.TODO/string/explicit_bzero.c b/REORG.TODO/string/explicit_bzero.c
new file mode 100644
index 0000000000..8dadf45ea8
--- /dev/null
+++ b/REORG.TODO/string/explicit_bzero.c
@@ -0,0 +1,38 @@
+/* Erasure of sensitive data, generic implementation.
+ Copyright (C) 2016-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* An assembler implementation of explicit_bzero can be created as an
+ assembler alias of an optimized bzero implementation.
+ Architecture-specific implementations also need to define
+ __explicit_bzero_chk. */
+
+#include <string.h>
+
+/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero
+ redirects to that. */
+#undef explicit_bzero
+
+/* Set LEN bytes of S to 0. The compiler will not delete a call to
+ this function, even if S is dead after the call. */
+void
+explicit_bzero (void *s, size_t len)
+{
+ memset (s, '\0', len);
+ /* Compiler barrier. */
+ asm volatile ("" ::: "memory");
+}
diff --git a/REORG.TODO/string/ffs.c b/REORG.TODO/string/ffs.c
new file mode 100644
index 0000000000..367cbbfb84
--- /dev/null
+++ b/REORG.TODO/string/ffs.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#define ffsl __something_else
+#include <string.h>
+
+#undef ffs
+
+/* Find the first bit set in I. */
+int
+__ffs (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_def (__ffs)
+libc_hidden_builtin_def (ffs)
+
+#if ULONG_MAX == UINT_MAX
+#undef ffsl
+weak_alias (__ffs, ffsl)
+#endif
diff --git a/REORG.TODO/string/ffsll.c b/REORG.TODO/string/ffsll.c
new file mode 100644
index 0000000000..5e403ef938
--- /dev/null
+++ b/REORG.TODO/string/ffsll.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#define ffsl __something_else
+#include <string.h>
+
+#undef ffsll
+
+/* Find the first bit set in I. */
+int
+ffsll (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/REORG.TODO/string/inl-tester.c b/REORG.TODO/string/inl-tester.c
new file mode 100644
index 0000000000..88528e5ed8
--- /dev/null
+++ b/REORG.TODO/string/inl-tester.c
@@ -0,0 +1,6 @@
+/* We want to test the inline functions here. */
+
+#define DO_STRING_INLINES
+#undef __USE_STRING_INLINES
+#define __USE_STRING_INLINES 1
+#include "tester.c"
diff --git a/REORG.TODO/string/memccpy.c b/REORG.TODO/string/memccpy.c
new file mode 100644
index 0000000000..605a453a69
--- /dev/null
+++ b/REORG.TODO/string/memccpy.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef __memccpy
+#undef memccpy
+
+#ifdef MEMCCPY
+# define __memccpy MEMCCPY
+#endif
+
+/* 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 (void *dest, const void *src, int c, size_t n)
+{
+ void *p = memchr (src, c, n);
+
+ if (p != NULL)
+ return __mempcpy (dest, src, p - src + 1);
+
+ memcpy (dest, src, n);
+ return NULL;
+}
+
+weak_alias (__memccpy, memccpy)
diff --git a/REORG.TODO/string/memchr.c b/REORG.TODO/string/memchr.c
new file mode 100644
index 0000000000..f6708fd917
--- /dev/null
+++ b/REORG.TODO/string/memchr.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <stddef.h>
+
+#include <limits.h>
+
+#undef __memchr
+#ifdef _LIBC
+# undef memchr
+#endif
+
+#ifndef weak_alias
+# define __memchr memchr
+#endif
+
+#ifndef MEMCHR
+# define MEMCHR __memchr
+#endif
+
+/* Search no more than N bytes of S for C. */
+void *
+MEMCHR (void const *s, int c_in, size_t n)
+{
+ /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance. On 64-bit hardware, unsigned long is generally 64
+ bits already. Change this typedef to experiment with
+ performance. */
+ typedef unsigned long int longword;
+
+ const unsigned char *char_ptr;
+ const longword *longword_ptr;
+ longword repeated_one;
+ longword repeated_c;
+ unsigned char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
+ --n, ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+
+ longword_ptr = (const longword *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ repeated_one = 0x01010101;
+ repeated_c = c | (c << 8);
+ repeated_c |= repeated_c << 16;
+ if (0xffffffffU < (longword) -1)
+ {
+ repeated_one |= repeated_one << 31 << 1;
+ repeated_c |= repeated_c << 31 << 1;
+ if (8 < sizeof (longword))
+ {
+ size_t i;
+
+ for (i = 64; i < sizeof (longword) * 8; i *= 2)
+ {
+ repeated_one |= repeated_one << i;
+ repeated_c |= repeated_c << i;
+ }
+ }
+ }
+
+ /* Instead of the traditional loop which tests each byte, 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 equal to c. We first use an xor
+ with repeated_c. This reduces the task to testing whether *any of the
+ four* bytes in longword1 is zero.
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ So, the test whether any byte in longword1 is zero is equivalent to
+ testing whether tmp is nonzero. */
+
+ while (n >= sizeof (longword))
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1)
+ & (repeated_one << 7)) != 0)
+ break;
+ longword_ptr++;
+ n -= sizeof (longword);
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ /* At this point, we know that either n < sizeof (longword), or one of the
+ sizeof (longword) bytes starting at char_ptr is == c. On little-endian
+ machines, we could determine the first such byte without any further
+ memory accesses, just by looking at the tmp result from the last loop
+ iteration. But this does not work on big-endian machines. Choose code
+ that works in both cases. */
+
+ for (; n > 0; --n, ++char_ptr)
+ {
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+ }
+
+ return NULL;
+}
+#ifdef weak_alias
+weak_alias (__memchr, memchr)
+#endif
+libc_hidden_builtin_def (memchr)
diff --git a/REORG.TODO/string/memcmp.c b/REORG.TODO/string/memcmp.c
new file mode 100644
index 0000000000..c53ab3185d
--- /dev/null
+++ b/REORG.TODO/string/memcmp.c
@@ -0,0 +1,364 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#undef __ptr_t
+#define __ptr_t void *
+
+#if defined HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#endif
+
+#undef memcmp
+
+#ifndef MEMCMP
+# define MEMCMP memcmp
+#endif
+
+#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;
+
+static int
+memcmp_bytes (op_t a, op_t 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 (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 (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 (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/REORG.TODO/string/memcpy.c b/REORG.TODO/string/memcpy.c
new file mode 100644
index 0000000000..974f65ef94
--- /dev/null
+++ b/REORG.TODO/string/memcpy.c
@@ -0,0 +1,60 @@
+/* Copy memory to memory until the specified number of bytes
+ has been copied. Overlap is NOT handled correctly.
+ Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef memcpy
+
+void *
+memcpy (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/REORG.TODO/string/memfrob.c b/REORG.TODO/string/memfrob.c
new file mode 100644
index 0000000000..91e162e28f
--- /dev/null
+++ b/REORG.TODO/string/memfrob.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+void *
+memfrob (void *s, size_t n)
+{
+ char *p = (char *) s;
+
+ while (n-- > 0)
+ *p++ ^= 42;
+
+ return s;
+}
diff --git a/REORG.TODO/string/memmem.c b/REORG.TODO/string/memmem.c
new file mode 100644
index 0000000000..54fca4966d
--- /dev/null
+++ b/REORG.TODO/string/memmem.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This particular implementation was written by Eric Blake, 2008. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Specification of memmem. */
+#include <string.h>
+
+#ifndef _LIBC
+# define __builtin_expect(expr, val) (expr)
+# define __memmem memmem
+#endif
+
+#define RETURN_TYPE void *
+#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l))
+#include "str-two-way.h"
+
+#undef memmem
+
+/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK
+ if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in
+ HAYSTACK. */
+void *
+__memmem (const void *haystack_start, size_t haystack_len,
+ const void *needle_start, size_t needle_len)
+{
+ /* Abstract memory is considered to be an array of 'unsigned char' values,
+ not an array of 'char' values. See ISO C 99 section 6.2.6.1. */
+ const unsigned char *haystack = (const unsigned char *) haystack_start;
+ const unsigned char *needle = (const unsigned char *) needle_start;
+
+ 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 (__glibc_unlikely (haystack_len < needle_len))
+ return NULL;
+
+ /* Use optimizations in memchr when possible, to reduce the search
+ size of haystack using a linear algorithm with a smaller
+ coefficient. However, avoid memchr for long needles, since we
+ can often achieve sublinear performance. */
+ if (needle_len < LONG_NEEDLE_THRESHOLD)
+ {
+ haystack = memchr (haystack, *needle, haystack_len);
+ if (!haystack || __builtin_expect (needle_len == 1, 0))
+ return (void *) haystack;
+ haystack_len -= haystack - (const unsigned char *) haystack_start;
+ if (haystack_len < needle_len)
+ return NULL;
+ return two_way_short_needle (haystack, haystack_len, needle, needle_len);
+ }
+ else
+ return two_way_long_needle (haystack, haystack_len, needle, needle_len);
+}
+libc_hidden_def (__memmem)
+weak_alias (__memmem, memmem)
+libc_hidden_weak (memmem)
+
+#undef LONG_NEEDLE_THRESHOLD
diff --git a/REORG.TODO/string/memmove.c b/REORG.TODO/string/memmove.c
new file mode 100644
index 0000000000..d8c2116b01
--- /dev/null
+++ b/REORG.TODO/string/memmove.c
@@ -0,0 +1,115 @@
+/* Copy memory to memory until the specified number of bytes
+ has been copied. Overlap is handled correctly.
+ Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <memcopy.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
+
+#ifndef MEMMOVE
+#define MEMMOVE memmove
+#endif
+
+rettype
+inhibit_loop_to_libcall
+MEMMOVE (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 MEMCPY_OK_FOR_FWD_MEMMOVE
+ dest = memcpy (dest, src, len);
+#else
+ /* 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);
+#endif /* MEMCPY_OK_FOR_FWD_MEMMOVE */
+ }
+ 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/REORG.TODO/string/memory.h b/REORG.TODO/string/memory.h
new file mode 100644
index 0000000000..36ad3808f8
--- /dev/null
+++ b/REORG.TODO/string/memory.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * SVID
+ */
+
+#ifndef _MEMORY_H
+#define _MEMORY_H 1
+
+#include <features.h>
+
+
+#ifndef _STRING_H
+# include <string.h>
+#endif /* string.h */
+
+
+#endif /* memory.h */
diff --git a/REORG.TODO/string/mempcpy.c b/REORG.TODO/string/mempcpy.c
new file mode 100644
index 0000000000..7a8718e79f
--- /dev/null
+++ b/REORG.TODO/string/mempcpy.c
@@ -0,0 +1,39 @@
+/* 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-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define NO_MEMPCPY_STPCPY_REDIRECT
+#include <string.h>
+
+#undef mempcpy
+#undef __mempcpy
+
+#ifndef MEMPCPY
+# define MEMPCPY __mempcpy
+#endif
+
+void *
+MEMPCPY (void *dest, const void *src, size_t len)
+{
+ return memcpy (dest, src, len) + len;
+}
+libc_hidden_def (__mempcpy)
+weak_alias (__mempcpy, mempcpy)
+libc_hidden_builtin_def (mempcpy)
diff --git a/REORG.TODO/string/memrchr.c b/REORG.TODO/string/memrchr.c
new file mode 100644
index 0000000000..0ecfe08842
--- /dev/null
+++ b/REORG.TODO/string/memrchr.c
@@ -0,0 +1,200 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+ Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef __ptr_t
+#define __ptr_t void *
+
+#if defined _LIBC
+# include <string.h>
+# include <memcopy.h>
+#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
+#ifndef MEMRCHR
+__memrchr
+#else
+MEMRCHR
+#endif
+ (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 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. */
+ magic_bits = -1;
+ magic_bits = magic_bits / 0xff * 0xfe << 1 >> 1 | 1;
+
+ /* 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;
+}
+#ifndef MEMRCHR
+# ifdef weak_alias
+weak_alias (__memrchr, memrchr)
+# endif
+#endif
diff --git a/REORG.TODO/string/memset.c b/REORG.TODO/string/memset.c
new file mode 100644
index 0000000000..549790c356
--- /dev/null
+++ b/REORG.TODO/string/memset.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef memset
+
+void *
+inhibit_loop_to_libcall
+memset (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/REORG.TODO/string/noinl-tester.c b/REORG.TODO/string/noinl-tester.c
new file mode 100644
index 0000000000..2e994f73f9
--- /dev/null
+++ b/REORG.TODO/string/noinl-tester.c
@@ -0,0 +1,4 @@
+/* We don't want to test any of the inline functions here. */
+
+#define __NO_STRING_INLINES 1
+#include "tester.c"
diff --git a/REORG.TODO/string/rawmemchr.c b/REORG.TODO/string/rawmemchr.c
new file mode 100644
index 0000000000..42a3f8aaba
--- /dev/null
+++ b/REORG.TODO/string/rawmemchr.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <libc-diag.h>
+
+#ifndef RAWMEMCHR
+# define RAWMEMCHR __rawmemchr
+#endif
+
+/* Find the first occurrence of C in S. */
+void *
+RAWMEMCHR (const void *s, int c)
+{
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 8 warns about the size passed to memchr being larger than
+ PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
+ DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-overflow=");
+#endif
+ if (c != '\0')
+ return memchr (s, c, (size_t)-1);
+ DIAG_POP_NEEDS_COMMENT;
+ return (char *)s + strlen (s);
+}
+libc_hidden_def (__rawmemchr)
+weak_alias (__rawmemchr, rawmemchr)
diff --git a/REORG.TODO/string/stpcpy.c b/REORG.TODO/string/stpcpy.c
new file mode 100644
index 0000000000..1603fb319b
--- /dev/null
+++ b/REORG.TODO/string/stpcpy.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define NO_MEMPCPY_STPCPY_REDIRECT
+#include <string.h>
+
+#undef __stpcpy
+#undef stpcpy
+
+#ifndef STPCPY
+# define STPCPY __stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
+char *
+STPCPY (char *dest, const char *src)
+{
+ size_t len = strlen (src);
+ return memcpy (dest, src, len + 1) + len;
+}
+weak_alias (__stpcpy, stpcpy)
+libc_hidden_def (__stpcpy)
+libc_hidden_builtin_def (stpcpy)
diff --git a/REORG.TODO/string/stpncpy.c b/REORG.TODO/string/stpncpy.c
new file mode 100644
index 0000000000..9b8ef348e5
--- /dev/null
+++ b/REORG.TODO/string/stpncpy.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1993-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <string.h>
+#else
+# include <sys/types.h>
+#endif
+
+#ifndef STPNCPY
+# ifdef weak_alias
+# define STPNCPY __stpncpy
+weak_alias (__stpncpy, stpncpy)
+# else
+# define STPNCPY stpncpy
+# endif
+#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 (char *dest, const char *src, size_t n)
+{
+ size_t size = __strnlen (src, n);
+ memcpy (dest, src, size);
+ dest += size;
+ if (size == n)
+ return dest;
+ return memset (dest, '\0', n - size);
+}
+#ifdef weak_alias
+libc_hidden_def (__stpncpy)
+#endif
diff --git a/REORG.TODO/string/str-two-way.h b/REORG.TODO/string/str-two-way.h
new file mode 100644
index 0000000000..599c867ffd
--- /dev/null
+++ b/REORG.TODO/string/str-two-way.h
@@ -0,0 +1,527 @@
+/* Byte-wise substring search, using the Two-Way algorithm.
+ Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Eric Blake <ebb9@byu.net>, 2008.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Before including this file, you need to include <string.h> (and
+ <config.h> before that, if not part of libc), and define:
+ RETURN_TYPE A macro that expands to the return type.
+ AVAILABLE(h, h_l, j, n_l)
+ A macro that returns nonzero if there are
+ at least N_L bytes left starting at H[J].
+ H is 'unsigned char *', H_L, J, and N_L
+ are 'size_t'; H_L is an lvalue. For
+ NUL-terminated searches, H_L can be
+ modified each iteration to avoid having
+ to compute the end of H up front.
+
+ For case-insensitivity, you may optionally define:
+ CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L
+ characters of P1 and P2 are equal.
+ CANON_ELEMENT(c) A macro that canonicalizes an element right after
+ it has been fetched from one of the two strings.
+ The argument is an 'unsigned char'; the result
+ must be an 'unsigned char' as well.
+
+ Other macros you may optionally define:
+ RET0_IF_0(a) Documented below at default definition.
+ CHECK_EOL Same.
+
+ This file undefines the macros listed above, and defines
+ LONG_NEEDLE_THRESHOLD.
+*/
+
+#include <limits.h>
+#include <stdint.h>
+#include <sys/param.h> /* Defines MAX. */
+
+/* We use the Two-Way string matching algorithm, which guarantees
+ linear complexity with constant space. Additionally, for long
+ needles, we also use a bad character shift table similar to the
+ Boyer-Moore algorithm to achieve improved (potentially sub-linear)
+ performance.
+
+ See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260
+ and http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm
+*/
+
+/* Point at which computing a bad-byte shift table is likely to be
+ worthwhile. Small needles should not compute a table, since it
+ adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a
+ speedup no greater than a factor of NEEDLE_LEN. The larger the
+ needle, the better the potential performance gain. On the other
+ hand, on non-POSIX systems with CHAR_BIT larger than eight, the
+ memory required for the table is prohibitive. */
+#if CHAR_BIT < 10
+# define LONG_NEEDLE_THRESHOLD 32U
+#else
+# define LONG_NEEDLE_THRESHOLD SIZE_MAX
+#endif
+
+#ifndef CANON_ELEMENT
+# define CANON_ELEMENT(c) c
+#endif
+#ifndef CMP_FUNC
+# define CMP_FUNC memcmp
+#endif
+
+/* Check for end-of-line in strstr and strcasestr routines.
+ We piggy-back matching procedure for detecting EOL where possible,
+ and use AVAILABLE macro otherwise. */
+#ifndef CHECK_EOL
+# define CHECK_EOL (0)
+#endif
+
+/* Return NULL if argument is '\0'. */
+#ifndef RET0_IF_0
+# define RET0_IF_0(a) /* nothing */
+#endif
+
+/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
+ Return the index of the first byte in the right half, and set
+ *PERIOD to the global period of the right half.
+
+ The global period of a string is the smallest index (possibly its
+ length) at which all remaining bytes in the string are repetitions
+ of the prefix (the last repetition may be a subset of the prefix).
+
+ When NEEDLE is factored into two halves, a local period is the
+ length of the smallest word that shares a suffix with the left half
+ and shares a prefix with the right half. All factorizations of a
+ non-empty NEEDLE have a local period of at least 1 and no greater
+ than NEEDLE_LEN.
+
+ A critical factorization has the property that the local period
+ equals the global period. All strings have at least one critical
+ factorization with the left half smaller than the global period.
+
+ Given an ordered alphabet, a critical factorization can be computed
+ in linear time, with 2 * NEEDLE_LEN comparisons, by computing the
+ larger of two ordered maximal suffixes. The ordered maximal
+ suffixes are determined by lexicographic comparison of
+ periodicity. */
+static size_t
+critical_factorization (const unsigned char *needle, size_t needle_len,
+ size_t *period)
+{
+ /* Index of last byte of left half, or SIZE_MAX. */
+ size_t max_suffix, max_suffix_rev;
+ size_t j; /* Index into NEEDLE for current candidate suffix. */
+ size_t k; /* Offset into current period. */
+ size_t p; /* Intermediate period. */
+ unsigned char a, b; /* Current comparison bytes. */
+
+ /* Invariants:
+ 0 <= j < NEEDLE_LEN - 1
+ -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed)
+ min(max_suffix, max_suffix_rev) < global period of NEEDLE
+ 1 <= p <= global period of NEEDLE
+ p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j]
+ 1 <= k <= p
+ */
+
+ /* Perform lexicographic search. */
+ max_suffix = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix + k]);
+ if (a < b)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* b < a */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix = j++;
+ k = p = 1;
+ }
+ }
+ *period = p;
+
+ /* Perform reverse lexicographic search. */
+ max_suffix_rev = SIZE_MAX;
+ j = 0;
+ k = p = 1;
+ while (j + k < needle_len)
+ {
+ a = CANON_ELEMENT (needle[j + k]);
+ b = CANON_ELEMENT (needle[max_suffix_rev + k]);
+ if (b < a)
+ {
+ /* Suffix is smaller, period is entire prefix so far. */
+ j += k;
+ k = 1;
+ p = j - max_suffix_rev;
+ }
+ else if (a == b)
+ {
+ /* Advance through repetition of the current period. */
+ if (k != p)
+ ++k;
+ else
+ {
+ j += p;
+ k = 1;
+ }
+ }
+ else /* a < b */
+ {
+ /* Suffix is larger, start over from current location. */
+ max_suffix_rev = j++;
+ k = p = 1;
+ }
+ }
+
+ /* Choose the longer suffix. Return the first byte of the right
+ half, rather than the last byte of the left half. */
+ if (max_suffix_rev + 1 < max_suffix + 1)
+ return max_suffix + 1;
+ *period = p;
+ return max_suffix_rev + 1;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 2 * NEEDLE_LEN comparisons.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */
+static RETURN_TYPE
+two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch can only advance by the
+ period, so use memory to avoid rescanning known occurrences
+ of the period. */
+ size_t memory = 0;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ const unsigned char *pneedle;
+ const unsigned char *phaystack;
+
+ /* Scan for matches in right half. */
+ i = MAX (suffix, memory);
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (i < needle_len && (CANON_ELEMENT (*pneedle++)
+ == CANON_ELEMENT (*phaystack++)))
+ ++i;
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (memory < i + 1 && (CANON_ELEMENT (*pneedle--)
+ == CANON_ELEMENT (*phaystack--)))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ const unsigned char *phaystack = &haystack[suffix];
+ /* The comparison always starts from needle[suffix], so cache it
+ and use an optimized first-character loop. */
+ unsigned char needle_suffix = CANON_ELEMENT (needle[suffix]);
+
+#if CHECK_EOL
+ /* We start matching from the SUFFIX'th element, so make sure we
+ don't hit '\0' before that. */
+ if (haystack_len < suffix + 1
+ && !AVAILABLE (haystack, haystack_len, 0, suffix + 1))
+ return NULL;
+#endif
+
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (1
+#if !CHECK_EOL
+ && AVAILABLE (haystack, haystack_len, j, needle_len)
+#endif
+ )
+ {
+ unsigned char haystack_char;
+ const unsigned char *pneedle;
+
+ /* TODO: The first-character loop can be sped up by adapting
+ longword-at-a-time implementation of memchr/strchr. */
+ if (needle_suffix
+ != (haystack_char = CANON_ELEMENT (*phaystack++)))
+ {
+ RET0_IF_0 (haystack_char);
+#if !CHECK_EOL
+ ++j;
+#endif
+ continue;
+ }
+
+#if CHECK_EOL
+ /* Calculate J if it wasn't kept up-to-date in the first-character
+ loop. */
+ j = phaystack - &haystack[suffix] - 1;
+#endif
+
+ /* Scan for matches in right half. */
+ i = suffix + 1;
+ pneedle = &needle[i];
+ while (i < needle_len)
+ {
+ if (CANON_ELEMENT (*pneedle++)
+ != (haystack_char = CANON_ELEMENT (*phaystack++)))
+ {
+ RET0_IF_0 (haystack_char);
+ break;
+ }
+ ++i;
+ }
+ if (needle_len <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (i != SIZE_MAX)
+ {
+ if (CANON_ELEMENT (*pneedle--)
+ != (haystack_char = CANON_ELEMENT (*phaystack--)))
+ {
+ RET0_IF_0 (haystack_char);
+ break;
+ }
+ --i;
+ }
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+
+#if CHECK_EOL
+ if (!AVAILABLE (haystack, haystack_len, j, needle_len))
+ break;
+#endif
+
+ phaystack = &haystack[suffix + j];
+ }
+ }
+ ret0: __attribute__ ((unused))
+ return NULL;
+}
+
+/* Return the first location of non-empty NEEDLE within HAYSTACK, or
+ NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This
+ method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN.
+ Performance is guaranteed to be linear, with an initialization cost
+ of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations.
+
+ If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at
+ most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching,
+ and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible.
+ If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 *
+ HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and
+ sublinear performance is not possible. */
+static RETURN_TYPE
+two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
+ const unsigned char *needle, size_t needle_len)
+{
+ size_t i; /* Index into current byte of NEEDLE. */
+ size_t j; /* Index into current window of HAYSTACK. */
+ size_t period; /* The period of the right half of needle. */
+ size_t suffix; /* The index of the right half of needle. */
+ size_t shift_table[1U << CHAR_BIT]; /* See below. */
+
+ /* Factor the needle into two halves, such that the left half is
+ smaller than the global period, and the right half is
+ periodic (with a period as large as NEEDLE_LEN - suffix). */
+ suffix = critical_factorization (needle, needle_len, &period);
+
+ /* Populate shift_table. For each possible byte value c,
+ shift_table[c] is the distance from the last occurrence of c to
+ the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE.
+ shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */
+ for (i = 0; i < 1U << CHAR_BIT; i++)
+ shift_table[i] = needle_len;
+ for (i = 0; i < needle_len; i++)
+ shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1;
+
+ /* Perform the search. Each iteration compares the right half
+ first. */
+ if (CMP_FUNC (needle, needle + period, suffix) == 0)
+ {
+ /* Entire needle is periodic; a mismatch can only advance by the
+ period, so use memory to avoid rescanning known occurrences
+ of the period. */
+ size_t memory = 0;
+ size_t shift;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ const unsigned char *pneedle;
+ const unsigned char *phaystack;
+
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ if (memory && shift < period)
+ {
+ /* Since needle is periodic, but the last period has
+ a byte out of place, there can be no match until
+ after the mismatch. */
+ shift = needle_len - period;
+ }
+ memory = 0;
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = MAX (suffix, memory);
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (i < needle_len - 1 && (CANON_ELEMENT (*pneedle++)
+ == CANON_ELEMENT (*phaystack++)))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (memory < i + 1 && (CANON_ELEMENT (*pneedle--)
+ == CANON_ELEMENT (*phaystack--)))
+ --i;
+ if (i + 1 < memory + 1)
+ return (RETURN_TYPE) (haystack + j);
+ /* No match, so remember how many repetitions of period
+ on the right half were scanned. */
+ j += period;
+ memory = needle_len - period;
+ }
+ else
+ {
+ j += i - suffix + 1;
+ memory = 0;
+ }
+ }
+ }
+ else
+ {
+ /* The two halves of needle are distinct; no extra memory is
+ required, and any mismatch results in a maximal shift. */
+ size_t shift;
+ period = MAX (suffix, needle_len - suffix) + 1;
+ j = 0;
+ while (AVAILABLE (haystack, haystack_len, j, needle_len))
+ {
+ const unsigned char *pneedle;
+ const unsigned char *phaystack;
+
+ /* Check the last byte first; if it does not match, then
+ shift to the next possible match location. */
+ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])];
+ if (0 < shift)
+ {
+ j += shift;
+ continue;
+ }
+ /* Scan for matches in right half. The last byte has
+ already been matched, by virtue of the shift table. */
+ i = suffix;
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (i < needle_len - 1 && (CANON_ELEMENT (*pneedle++)
+ == CANON_ELEMENT (*phaystack++)))
+ ++i;
+ if (needle_len - 1 <= i)
+ {
+ /* Scan for matches in left half. */
+ i = suffix - 1;
+ pneedle = &needle[i];
+ phaystack = &haystack[i + j];
+ while (i != SIZE_MAX && (CANON_ELEMENT (*pneedle--)
+ == CANON_ELEMENT (*phaystack--)))
+ --i;
+ if (i == SIZE_MAX)
+ return (RETURN_TYPE) (haystack + j);
+ j += period;
+ }
+ else
+ j += i - suffix + 1;
+ }
+ }
+ return NULL;
+}
+
+#undef AVAILABLE
+#undef CANON_ELEMENT
+#undef CMP_FUNC
+#undef RET0_IF_0
+#undef RETURN_TYPE
+#undef CHECK_EOL
diff --git a/REORG.TODO/string/stratcliff.c b/REORG.TODO/string/stratcliff.c
new file mode 100644
index 0000000000..e28b0c5058
--- /dev/null
+++ b/REORG.TODO/string/stratcliff.c
@@ -0,0 +1,561 @@
+/* Test for string function add boundaries of usable memory.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _GNU_SOURCE 1
+
+/* Make sure we don't test the optimized inline functions if we want to
+ test the real implementation. */
+#undef __USE_STRING_INLINES
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+
+#ifndef CHAR
+# define L(c) c
+# define CHAR char
+# define MEMSET memset
+# define STRLEN strlen
+# define STRNLEN strnlen
+# define STRCHR strchr
+# define STRRCHR strrchr
+# define STRCPY strcpy
+# define STRNCPY strncpy
+# define MEMCMP memcmp
+# define STPCPY stpcpy
+# define STPNCPY stpncpy
+# define MEMCPY memcpy
+# define MEMPCPY mempcpy
+# define MEMCHR memchr
+# define STRCMP strcmp
+# define STRNCMP strncmp
+#endif
+
+
+#define STRINGIFY(s) STRINGIFY2 (s)
+#define STRINGIFY2(s) #s
+
+
+int
+do_test (void)
+{
+ int size = sysconf (_SC_PAGESIZE);
+ int nchars = size / sizeof (CHAR);
+ CHAR *adr;
+ CHAR *dest;
+ int result = 0;
+
+ adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (adr == MAP_FAILED || dest == MAP_FAILED)
+ {
+ if (errno == ENOSYS)
+ puts ("No test, mmap not available.");
+ else
+ {
+ printf ("mmap failed: %m");
+ result = 1;
+ }
+ }
+ else
+ {
+ int inner, middle, outer;
+
+ mprotect (adr, size, PROT_NONE);
+ mprotect (adr + 2 * nchars, size, PROT_NONE);
+ adr += nchars;
+
+ mprotect (dest, size, PROT_NONE);
+ mprotect (dest + 2 * nchars, size, PROT_NONE);
+ dest += nchars;
+
+ MEMSET (adr, L('T'), nchars);
+
+ /* strlen/wcslen test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
+ {
+ adr[inner] = L('\0');
+
+ if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (STRLEN), outer, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ }
+ }
+
+ /* strnlen/wcsnlen test */
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
+ {
+ adr[inner] = L('\0');
+
+ if (STRNLEN (&adr[outer], inner - outer + 1)
+ != (size_t) (inner - outer))
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (STRNLEN), outer, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ }
+ }
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner <= nchars; ++inner)
+ {
+ if (STRNLEN (&adr[outer], inner - outer)
+ != (size_t) (inner - outer))
+ {
+ printf ("%s flunked bounded for outer = %d, inner = %d\n",
+ STRINGIFY (STRNLEN), outer, inner);
+ result = 1;
+ }
+ }
+ }
+
+ /* strchr/wcschr test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ for (inner = middle; inner < nchars; ++inner)
+ {
+ adr[middle] = L('V');
+ adr[inner] = L('\0');
+
+ CHAR *cp = STRCHR (&adr[outer], L('V'));
+
+ if ((inner == middle && cp != NULL)
+ || (inner != middle
+ && (cp - &adr[outer]) != middle - outer))
+ {
+ printf ("%s flunked for outer = %d, middle = %d, "
+ "inner = %d\n",
+ STRINGIFY (STRCHR), outer, middle, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ adr[middle] = L('T');
+ }
+ }
+ }
+
+ /* Special test. */
+ adr[nchars - 1] = L('\0');
+ if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
+ {
+ printf ("%s flunked test of empty string at end of page\n",
+ STRINGIFY (STRCHR));
+ result = 1;
+ }
+
+ /* strrchr/wcsrchr test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ for (inner = middle; inner < nchars; ++inner)
+ {
+ adr[middle] = L('V');
+ adr[inner] = L('\0');
+
+ CHAR *cp = STRRCHR (&adr[outer], L('V'));
+
+ if ((inner == middle && cp != NULL)
+ || (inner != middle
+ && (cp - &adr[outer]) != middle - outer))
+ {
+ printf ("%s flunked for outer = %d, middle = %d, "
+ "inner = %d\n",
+ STRINGIFY (STRRCHR), outer, middle, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ adr[middle] = L('T');
+ }
+ }
+ }
+
+ /* memchr test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ adr[middle] = L('V');
+
+ CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
+
+ if (cp - &adr[outer] != middle - outer)
+ {
+ printf ("%s flunked for outer = %d, middle = %d\n",
+ STRINGIFY (MEMCHR), outer, middle);
+ result = 1;
+ }
+
+ adr[middle] = L('T');
+ }
+ }
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
+
+ if (cp != NULL)
+ {
+ printf ("%s flunked for outer = %d\n",
+ STRINGIFY (MEMCHR), outer);
+ result = 1;
+ }
+ }
+
+ /* These functions only exist for single-byte characters. */
+#ifndef WCSTEST
+ /* rawmemchr test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ adr[middle] = L('V');
+
+ CHAR *cp = rawmemchr (&adr[outer], L('V'));
+
+ if (cp - &adr[outer] != middle - outer)
+ {
+ printf ("%s flunked for outer = %d, middle = %d\n",
+ STRINGIFY (rawmemchr), outer, middle);
+ result = 1;
+ }
+
+ adr[middle] = L('T');
+ }
+ }
+
+ /* memrchr test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ adr[middle] = L('V');
+
+ CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
+
+ if (cp - &adr[outer] != middle - outer)
+ {
+ printf ("%s flunked for outer = %d, middle = %d\n",
+ STRINGIFY (memrchr), outer, middle);
+ result = 1;
+ }
+
+ adr[middle] = L('T');
+ }
+ }
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
+
+ if (cp != NULL)
+ {
+ printf ("%s flunked for outer = %d\n",
+ STRINGIFY (memrchr), outer);
+ result = 1;
+ }
+ }
+#endif
+
+ /* strcpy/wcscpy test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
+ {
+ adr[inner] = L('\0');
+
+ if (STRCPY (dest, &adr[outer]) != dest
+ || STRLEN (dest) != (size_t) (inner - outer))
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (STRCPY), outer, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ }
+ }
+
+ /* strcmp/wcscmp tests */
+ for (outer = 1; outer < 32; ++outer)
+ for (middle = 0; middle < 16; ++middle)
+ {
+ MEMSET (adr + middle, L('T'), 256);
+ adr[256] = L('\0');
+ MEMSET (dest + nchars - outer, L('T'), outer - 1);
+ dest[nchars - 1] = L('\0');
+
+ if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
+ {
+ printf ("%s 1 flunked for outer = %d, middle = %d\n",
+ STRINGIFY (STRCMP), outer, middle);
+ result = 1;
+ }
+
+ if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
+ {
+ printf ("%s 2 flunked for outer = %d, middle = %d\n",
+ STRINGIFY (STRCMP), outer, middle);
+ result = 1;
+ }
+ }
+
+ /* strncmp/wcsncmp tests */
+ for (outer = 1; outer < 32; ++outer)
+ for (middle = 0; middle < 16; ++middle)
+ {
+ MEMSET (adr + middle, L('T'), 256);
+ adr[256] = L('\0');
+ MEMSET (dest + nchars - outer, L('T'), outer - 1);
+ dest[nchars - 1] = L('U');
+
+ for (inner = 0; inner < outer; ++inner)
+ {
+ if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
+ {
+ printf ("%s 1 flunked for outer = %d, middle = %d, "
+ "inner = %d\n",
+ STRINGIFY (STRNCMP), outer, middle, inner);
+ result = 1;
+ }
+
+ if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
+ {
+ printf ("%s 2 flunked for outer = %d, middle = %d, "
+ "inner = %d\n",
+ STRINGIFY (STRNCMP), outer, middle, inner);
+ result = 1;
+ }
+ }
+
+ if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
+ {
+ printf ("%s 1 flunked for outer = %d, middle = %d, full\n",
+ STRINGIFY (STRNCMP), outer, middle);
+ result = 1;
+ }
+
+ if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
+ {
+ printf ("%s 2 flunked for outer = %d, middle = %d, full\n",
+ STRINGIFY (STRNCMP), outer, middle);
+ result = 1;
+ }
+ }
+
+ /* strncpy/wcsncpy tests */
+ adr[nchars - 1] = L('T');
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ size_t len;
+
+ for (len = 0; len < nchars - outer; ++len)
+ {
+ if (STRNCPY (dest, &adr[outer], len) != dest
+ || MEMCMP (dest, &adr[outer], len) != 0)
+ {
+ printf ("outer %s flunked for outer = %d, len = %Zd\n",
+ STRINGIFY (STRNCPY), outer, len);
+ result = 1;
+ }
+ }
+ }
+ adr[nchars - 1] = L('\0');
+
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
+ {
+ size_t len;
+
+ adr[inner] = L('\0');
+
+ for (len = 0; len < nchars - outer + 64; ++len)
+ {
+ if (STRNCPY (dest, &adr[outer], len) != dest
+ || MEMCMP (dest, &adr[outer],
+ MIN (inner - outer, len)) != 0
+ || (inner - outer < len
+ && STRLEN (dest) != (inner - outer)))
+ {
+ printf ("%s flunked for outer = %d, inner = %d, "
+ "len = %Zd\n",
+ STRINGIFY (STRNCPY), outer, inner, len);
+ result = 1;
+ }
+ if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
+ || MEMCMP (dest + 1, &adr[outer],
+ MIN (inner - outer, len)) != 0
+ || (inner - outer < len
+ && STRLEN (dest + 1) != (inner - outer)))
+ {
+ printf ("%s+1 flunked for outer = %d, inner = %d, "
+ "len = %Zd\n",
+ STRINGIFY (STRNCPY), outer, inner, len);
+ result = 1;
+ }
+ }
+
+ adr[inner] = L('T');
+ }
+ }
+
+ /* stpcpy/wcpcpy test */
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
+ {
+ adr[inner] = L('\0');
+
+ if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (STPCPY), outer, inner);
+ result = 1;
+ }
+
+ adr[inner] = L('T');
+ }
+ }
+
+ /* stpncpy/wcpncpy test */
+ adr[nchars - 1] = L('T');
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ {
+ size_t len;
+
+ for (len = 0; len < nchars - outer; ++len)
+ {
+ if (STPNCPY (dest, &adr[outer], len) != dest + len
+ || MEMCMP (dest, &adr[outer], len) != 0)
+ {
+ printf ("outer %s flunked for outer = %d, len = %Zd\n",
+ STRINGIFY (STPNCPY), outer, len);
+ result = 1;
+ }
+ }
+ }
+ adr[nchars - 1] = L('\0');
+
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ {
+ for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
+ {
+ adr[middle] = L('\0');
+
+ for (inner = 0; inner < nchars - outer; ++ inner)
+ {
+ if ((STPNCPY (dest, &adr[outer], inner) - dest)
+ != MIN (inner, middle - outer))
+ {
+ printf ("%s flunked for outer = %d, middle = %d, "
+ "inner = %d\n",
+ STRINGIFY (STPNCPY), outer, middle, inner);
+ result = 1;
+ }
+ }
+
+ adr[middle] = L('T');
+ }
+ }
+
+ /* memcpy/wmemcpy test */
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ for (inner = 0; inner < nchars - outer; ++inner)
+ if (MEMCPY (dest, &adr[outer], inner) != dest)
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (MEMCPY), outer, inner);
+ result = 1;
+ }
+
+ /* mempcpy/wmempcpy test */
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ for (inner = 0; inner < nchars - outer; ++inner)
+ if (MEMPCPY (dest, &adr[outer], inner) != dest + inner)
+ {
+ printf ("%s flunked for outer = %d, inner = %d\n",
+ STRINGIFY (MEMPCPY), outer, inner);
+ result = 1;
+ }
+
+ /* This function only exists for single-byte characters. */
+#ifndef WCSTEST
+ /* memccpy test */
+ memset (adr, '\0', nchars);
+ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
+ for (inner = 0; inner < nchars - outer; ++inner)
+ if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
+ {
+ printf ("memccpy flunked full copy for outer = %d, inner = %d\n",
+ outer, inner);
+ result = 1;
+ }
+ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
+ for (middle = 0; middle < nchars - outer; ++middle)
+ {
+ memset (dest, L('\2'), middle + 1);
+ for (inner = 0; inner < middle; ++inner)
+ {
+ adr[outer + inner] = L('\1');
+
+ if (memccpy (dest, &adr[outer], '\1', middle + 128)
+ != dest + inner + 1)
+ {
+ printf ("\
+memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n",
+ outer, middle, inner);
+ result = 1;
+ }
+ else if (dest[inner + 1] != L('\2'))
+ {
+ printf ("\
+memccpy copied too much for outer = %d, middle = %d, inner = %d\n",
+ outer, middle, inner);
+ result = 1;
+ }
+ adr[outer + inner] = L('\0');
+ }
+ }
+#endif
+ }
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/strcasecmp.c b/REORG.TODO/string/strcasecmp.c
new file mode 100644
index 0000000000..2d6ae0fa9d
--- /dev/null
+++ b/REORG.TODO/string/strcasecmp.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 , __locale_t loc
+#else
+# define LOCALE_PARAM
+#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 (const char *s1, const char *s2 LOCALE_PARAM)
+{
+#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/REORG.TODO/string/strcasecmp_l.c b/REORG.TODO/string/strcasecmp_l.c
new file mode 100644
index 0000000000..78271ad2ef
--- /dev/null
+++ b/REORG.TODO/string/strcasecmp_l.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1997-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define USE_IN_EXTENDED_LOCALE_MODEL 1
+#include "strcasecmp.c"
+
+libc_hidden_def (__strcasecmp_l)
+weak_alias (__strcasecmp_l, strcasecmp_l)
diff --git a/REORG.TODO/string/strcasestr.c b/REORG.TODO/string/strcasestr.c
new file mode 100644
index 0000000000..2acf003155
--- /dev/null
+++ b/REORG.TODO/string/strcasestr.c
@@ -0,0 +1,104 @@
+/* Return the offset of one string within another.
+ Copyright (C) 1994-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * 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 */
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <strings.h>
+
+#define TOLOWER(Ch) tolower (Ch)
+
+/* Two-Way algorithm. */
+#define RETURN_TYPE char *
+#define AVAILABLE(h, h_l, j, n_l) \
+ (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \
+ && ((h_l) = (j) + (n_l)))
+#define CHECK_EOL (1)
+#define RET0_IF_0(a) if (!a) goto ret0
+#define CANON_ELEMENT(c) TOLOWER (c)
+#define CMP_FUNC(p1, p2, l) \
+ __strncasecmp ((const char *) (p1), (const char *) (p2), l)
+#include "str-two-way.h"
+
+#undef strcasestr
+#undef __strcasestr
+
+#ifndef STRCASESTR
+#define STRCASESTR __strcasestr
+#endif
+
+
+/* Find the first occurrence of NEEDLE in HAYSTACK, using
+ case-insensitive comparison. This function gives unspecified
+ results in multibyte locales. */
+char *
+STRCASESTR (const char *haystack_start, const char *needle_start)
+{
+ const char *haystack = haystack_start;
+ const char *needle = needle_start;
+ size_t needle_len; /* Length of NEEDLE. */
+ size_t haystack_len; /* Known minimum length of HAYSTACK. */
+ bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */
+
+ /* Determine length of NEEDLE, and in the process, make sure
+ HAYSTACK is at least as long (no point processing all of a long
+ NEEDLE if HAYSTACK is too short). */
+ while (*haystack && *needle)
+ {
+ ok &= (TOLOWER ((unsigned char) *haystack)
+ == TOLOWER ((unsigned char) *needle));
+ haystack++;
+ needle++;
+ }
+ if (*needle)
+ return NULL;
+ if (ok)
+ return (char *) haystack_start;
+ needle_len = needle - needle_start;
+ haystack = haystack_start + 1;
+ haystack_len = needle_len - 1;
+
+ /* Perform the search. Abstract memory is considered to be an array
+ of 'unsigned char' values, not an array of 'char' values. See
+ ISO C 99 section 6.2.6.1. */
+ if (needle_len < LONG_NEEDLE_THRESHOLD)
+ return two_way_short_needle ((const unsigned char *) haystack,
+ haystack_len,
+ (const unsigned char *) needle_start,
+ needle_len);
+ return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
+ (const unsigned char *) needle_start,
+ needle_len);
+}
+
+#undef LONG_NEEDLE_THRESHOLD
+
+#ifndef NO_ALIAS
+weak_alias (__strcasestr, strcasestr)
+#endif
diff --git a/REORG.TODO/string/strcat.c b/REORG.TODO/string/strcat.c
new file mode 100644
index 0000000000..8373fabc1d
--- /dev/null
+++ b/REORG.TODO/string/strcat.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef strcat
+
+#ifndef STRCAT
+# define STRCAT strcat
+#endif
+
+/* Append SRC on the end of DEST. */
+char *
+STRCAT (char *dest, const char *src)
+{
+ strcpy (dest + strlen (dest), src);
+ return dest;
+}
+libc_hidden_builtin_def (strcat)
diff --git a/REORG.TODO/string/strchr.c b/REORG.TODO/string/strchr.c
new file mode 100644
index 0000000000..50e4172853
--- /dev/null
+++ b/REORG.TODO/string/strchr.c
@@ -0,0 +1,185 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+
+#undef strchr
+
+#ifndef STRCHR
+# define STRCHR strchr
+#endif
+
+/* Find the first occurrence of C in S. */
+char *
+STRCHR (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 char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the first few characters by reading one character at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0;
+ ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+ else if (*char_ptr == '\0')
+ return NULL;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to 8-byte longwords. */
+
+ longword_ptr = (unsigned long int *) char_ptr;
+
+ /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
+ the "holes." Note that there is a hole just to the left of
+ each byte, with an extra at the end:
+
+ bits: 01111110 11111110 11111110 11111111
+ bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+ The 1-bits make sure that carries propagate to the next 0-bit.
+ The 0-bits provide holes for carries to fall into. */
+ magic_bits = -1;
+ magic_bits = magic_bits / 0xff * 0xfe << 1 >> 1 | 1;
+
+ /* 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/REORG.TODO/string/strchrnul.c b/REORG.TODO/string/strchrnul.c
new file mode 100644
index 0000000000..d62dc9c595
--- /dev/null
+++ b/REORG.TODO/string/strchrnul.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <memcopy.h>
+#include <stdlib.h>
+
+#undef __strchrnul
+#undef strchrnul
+
+#ifndef STRCHRNUL
+# define STRCHRNUL __strchrnul
+#endif
+
+/* Find the first occurrence of C in S or the final NUL byte. */
+char *
+STRCHRNUL (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 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. */
+ magic_bits = -1;
+ magic_bits = magic_bits / 0xff * 0xfe << 1 >> 1 | 1;
+
+ /* 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/REORG.TODO/string/strcmp.c b/REORG.TODO/string/strcmp.c
new file mode 100644
index 0000000000..a818285ea2
--- /dev/null
+++ b/REORG.TODO/string/strcmp.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef strcmp
+
+#ifndef STRCMP
+# define STRCMP strcmp
+#endif
+
+/* 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 (const char *p1, const char *p2)
+{
+ const unsigned char *s1 = (const unsigned char *) p1;
+ const unsigned char *s2 = (const unsigned char *) p2;
+ unsigned 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/REORG.TODO/string/strcoll.c b/REORG.TODO/string/strcoll.c
new file mode 100644
index 0000000000..8996bf90f4
--- /dev/null
+++ b/REORG.TODO/string/strcoll.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#ifndef STRING_TYPE
+# define STRING_TYPE char
+# define STRCOLL strcoll
+# define STRCOLL_L __strcoll_l
+# define USE_HIDDEN_DEF
+#endif
+
+#include "../locale/localeinfo.h"
+
+
+int
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2)
+{
+ return STRCOLL_L (s1, s2, _NL_CURRENT_LOCALE);
+}
+
+#ifdef USE_HIDDEN_DEF
+libc_hidden_def (STRCOLL)
+#endif
diff --git a/REORG.TODO/string/strcoll_l.c b/REORG.TODO/string/strcoll_l.c
new file mode 100644
index 0000000000..8fd55b000a
--- /dev/null
+++ b/REORG.TODO/string/strcoll_l.c
@@ -0,0 +1,363 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#include <assert.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+
+#ifndef STRING_TYPE
+# define STRING_TYPE char
+# define USTRING_TYPE unsigned char
+# define STRCOLL __strcoll_l
+# define STRCMP strcmp
+# define WEIGHT_H "../locale/weight.h"
+# define SUFFIX MB
+# define L(arg) arg
+#endif
+
+#define CONCAT(a,b) CONCAT1(a,b)
+#define CONCAT1(a,b) a##b
+
+#include "../locale/localeinfo.h"
+#include WEIGHT_H
+
+/* Track status while looking for sequences in a string. */
+typedef struct
+{
+ int len; /* Length of the current sequence. */
+ size_t val; /* Position of the sequence relative to the
+ previous non-ignored sequence. */
+ size_t idxmax; /* Maximum index in sequences. */
+ size_t idxcnt; /* Current count of indices. */
+ size_t backw; /* Current Backward sequence index. */
+ size_t backw_stop; /* Index where the backward sequences stop. */
+ const USTRING_TYPE *us; /* The string. */
+ unsigned char rule; /* Saved rule for the first sequence. */
+ int32_t idx; /* Index to weight of the current sequence. */
+ int32_t save_idx; /* Save looked up index of a forward
+ sequence after the last backward
+ sequence. */
+ const USTRING_TYPE *back_us; /* Beginning of the backward sequence. */
+} coll_seq;
+
+/* Get next sequence. Traverse the string as required. */
+static __always_inline void
+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
+ const USTRING_TYPE *weights, const int32_t *table,
+ const USTRING_TYPE *extra, const int32_t *indirect,
+ int pass)
+{
+ size_t val = seq->val = 0;
+ int len = seq->len;
+ size_t backw_stop = seq->backw_stop;
+ size_t backw = seq->backw;
+ size_t idxcnt = seq->idxcnt;
+ size_t idxmax = seq->idxmax;
+ int32_t idx = seq->idx;
+ const USTRING_TYPE *us = seq->us;
+
+ while (len == 0)
+ {
+ ++val;
+ if (backw_stop != ~0ul)
+ {
+ /* There is something pushed. */
+ if (backw == backw_stop)
+ {
+ /* The last pushed character was handled. Continue
+ with forward characters. */
+ if (idxcnt < idxmax)
+ {
+ idx = seq->save_idx;
+ backw_stop = ~0ul;
+ }
+ else
+ {
+ /* Nothing anymore. The backward sequence ended with
+ the last sequence in the string. Note that len is
+ still zero. */
+ idx = 0;
+ break;
+ }
+ }
+ else
+ {
+ /* XXX Traverse BACKW sequences from the beginning of
+ BACKW_STOP to get the next sequence. Is ther a quicker way
+ to do this? */
+ size_t i = backw_stop;
+ us = seq->back_us;
+ while (i < backw)
+ {
+ int32_t tmp = findidx (table, indirect, extra, &us, -1);
+ idx = tmp & 0xffffff;
+ i++;
+ }
+ --backw;
+ us = seq->us;
+ }
+ }
+ else
+ {
+ backw_stop = idxmax;
+ int32_t prev_idx = idx;
+
+ while (*us != L('\0'))
+ {
+ int32_t tmp = findidx (table, indirect, extra, &us, -1);
+ unsigned char rule = tmp >> 24;
+ prev_idx = idx;
+ idx = tmp & 0xffffff;
+ idxcnt = idxmax++;
+
+ /* Save the rule for the first sequence. */
+ if (__glibc_unlikely (idxcnt == 0))
+ seq->rule = rule;
+
+ if ((rulesets[rule * nrules + pass]
+ & sort_backward) == 0)
+ /* No more backward characters to push. */
+ break;
+ ++idxcnt;
+ }
+
+ if (backw_stop >= idxcnt)
+ {
+ /* No sequence at all or just one. */
+ if (idxcnt == idxmax || backw_stop > idxcnt)
+ /* Note that len is still zero. */
+ break;
+
+ backw_stop = ~0ul;
+ }
+ else
+ {
+ /* We pushed backward sequences. If the stream ended with the
+ backward sequence, then we process the last sequence we
+ found. Otherwise we process the sequence before the last
+ one since the last one was a forward sequence. */
+ seq->back_us = seq->us;
+ seq->us = us;
+ backw = idxcnt;
+ if (idxmax > idxcnt)
+ {
+ backw--;
+ seq->save_idx = idx;
+ idx = prev_idx;
+ }
+ if (backw > backw_stop)
+ backw--;
+ }
+ }
+
+ /* With GCC 5.3 when compiling with -Os the compiler complains
+ that idx, taken from seq->idx (seq1 or seq2 from STRCOLL) may
+ be used uninitialized. In general this can't possibly be true
+ since seq1.idx and seq2.idx are initialized to zero in the
+ outer function. Only one case where seq->idx is restored from
+ seq->save_idx might result in an uninitialized idx value, but
+ it is guarded by a sequence of checks against backw_stop which
+ ensures that seq->save_idx was saved to first and contains a
+ valid value. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+ len = weights[idx++];
+ DIAG_POP_NEEDS_COMMENT;
+ /* Skip over indices of previous levels. */
+ for (int i = 0; i < pass; i++)
+ {
+ idx += len;
+ len = weights[idx];
+ idx++;
+ }
+ }
+
+ /* Update the structure. */
+ seq->val = val;
+ seq->len = len;
+ seq->backw_stop = backw_stop;
+ seq->backw = backw;
+ seq->idxcnt = idxcnt;
+ seq->idxmax = idxmax;
+ seq->us = us;
+ seq->idx = idx;
+}
+
+/* Compare two sequences. */
+static __always_inline int
+do_compare (coll_seq *seq1, coll_seq *seq2, int position,
+ const USTRING_TYPE *weights)
+{
+ int seq1len = seq1->len;
+ int seq2len = seq2->len;
+ size_t val1 = seq1->val;
+ size_t val2 = seq2->val;
+ int idx1 = seq1->idx;
+ int idx2 = seq2->idx;
+ int result = 0;
+
+ /* Test for position if necessary. */
+ if (position && val1 != val2)
+ {
+ result = val1 > val2 ? 1 : -1;
+ goto out;
+ }
+
+ /* Compare the two sequences. */
+ do
+ {
+ if (weights[idx1] != weights[idx2])
+ {
+ /* The sequences differ. */
+ result = weights[idx1] - weights[idx2];
+ goto out;
+ }
+
+ /* Increment the offsets. */
+ ++idx1;
+ ++idx2;
+
+ --seq1len;
+ --seq2len;
+ }
+ while (seq1len > 0 && seq2len > 0);
+
+ if (position && seq1len != seq2len)
+ result = seq1len - seq2len;
+
+out:
+ seq1->len = seq1len;
+ seq2->len = seq2len;
+ seq1->idx = idx1;
+ seq2->idx = idx2;
+ return result;
+}
+
+int
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
+{
+ struct __locale_data *current = l->__locales[LC_COLLATE];
+ uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+ /* We don't assign the following values right away since it might be
+ unnecessary in case there are no rules. */
+ const unsigned char *rulesets;
+ const int32_t *table;
+ const USTRING_TYPE *weights;
+ const USTRING_TYPE *extra;
+ const int32_t *indirect;
+
+ if (nrules == 0)
+ return STRCMP (s1, s2);
+
+ /* Catch empty strings. */
+ if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0'))
+ return (*s1 != '\0') - (*s2 != '\0');
+
+ rulesets = (const unsigned char *)
+ current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
+ table = (const int32_t *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
+ weights = (const USTRING_TYPE *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
+ extra = (const USTRING_TYPE *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
+ indirect = (const int32_t *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
+
+ assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
+ assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
+ assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
+ assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
+
+ int result = 0, rule = 0;
+
+ coll_seq seq1, seq2;
+ seq1.len = 0;
+ seq1.idxmax = 0;
+ seq1.rule = 0;
+ seq2.len = 0;
+ seq2.idxmax = 0;
+
+ for (int pass = 0; pass < nrules; ++pass)
+ {
+ seq1.idxcnt = 0;
+ seq1.idx = 0;
+ seq2.idx = 0;
+ seq1.backw_stop = ~0ul;
+ seq1.backw = ~0ul;
+ seq2.idxcnt = 0;
+ seq2.backw_stop = ~0ul;
+ seq2.backw = ~0ul;
+
+ /* We need the elements of the strings as unsigned values since they
+ are used as indices. */
+ seq1.us = (const USTRING_TYPE *) s1;
+ seq2.us = (const USTRING_TYPE *) s2;
+
+ /* We assume that if a rule has defined `position' in one section
+ this is true for all of them. Please note that the localedef programs
+ makes sure that `position' is not used at the first level. */
+
+ int position = rulesets[rule * nrules + pass] & sort_position;
+
+ while (1)
+ {
+ get_next_seq (&seq1, nrules, rulesets, weights, table,
+ extra, indirect, pass);
+ get_next_seq (&seq2, nrules, rulesets, weights, table,
+ extra, indirect, pass);
+ /* See whether any or both strings are empty. */
+ if (seq1.len == 0 || seq2.len == 0)
+ {
+ if (seq1.len == seq2.len)
+ {
+ /* Both strings ended and are equal at this level. Do a
+ byte-level comparison to ensure that we don't waste time
+ going through multiple passes for totally equal strings
+ before proceeding to subsequent passes. */
+ if (pass == 0 && STRCMP (s1, s2) == 0)
+ return result;
+ else
+ break;
+ }
+
+ /* This means one string is shorter than the other. Find out
+ which one and return an appropriate value. */
+ return seq1.len == 0 ? -1 : 1;
+ }
+
+ result = do_compare (&seq1, &seq2, position, weights);
+ if (result != 0)
+ return result;
+ }
+
+ rule = seq1.rule;
+ }
+
+ return result;
+}
+libc_hidden_def (STRCOLL)
+
+#ifndef WIDE_CHAR_VERSION
+weak_alias (__strcoll_l, strcoll_l)
+#endif
diff --git a/REORG.TODO/string/strcpy.c b/REORG.TODO/string/strcpy.c
new file mode 100644
index 0000000000..120da44ee7
--- /dev/null
+++ b/REORG.TODO/string/strcpy.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <string.h>
+
+#undef strcpy
+
+#ifndef STRCPY
+# define STRCPY strcpy
+#endif
+
+/* Copy SRC to DEST. */
+char *
+STRCPY (char *dest, const char *src)
+{
+ return memcpy (dest, src, strlen (src) + 1);
+}
+libc_hidden_builtin_def (strcpy)
diff --git a/REORG.TODO/string/strcspn.c b/REORG.TODO/string/strcspn.c
new file mode 100644
index 0000000000..1035552a8e
--- /dev/null
+++ b/REORG.TODO/string/strcspn.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdint.h>
+#include <libc-pointer-arith.h>
+
+#undef strcspn
+
+#ifndef STRCSPN
+# define STRCSPN strcspn
+#endif
+
+/* Return the length of the maximum initial segment of S
+ which contains no characters from REJECT. */
+size_t
+STRCSPN (const char *str, const char *reject)
+{
+ if (__glibc_unlikely (reject[0] == '\0') ||
+ __glibc_unlikely (reject[1] == '\0'))
+ return __strchrnul (str, reject [0]) - str;
+
+ /* Use multiple small memsets to enable inlining on most targets. */
+ unsigned char table[256];
+ unsigned char *p = memset (table, 0, 64);
+ memset (p + 64, 0, 64);
+ memset (p + 128, 0, 64);
+ memset (p + 192, 0, 64);
+
+ unsigned char *s = (unsigned char*) reject;
+ unsigned char tmp;
+ do
+ p[tmp = *s++] = 1;
+ while (tmp);
+
+ s = (unsigned char*) str;
+ if (p[s[0]]) return 0;
+ if (p[s[1]]) return 1;
+ if (p[s[2]]) return 2;
+ if (p[s[3]]) return 3;
+
+ s = (unsigned char *) PTR_ALIGN_DOWN (s, 4);
+
+ unsigned int c0, c1, c2, c3;
+ do
+ {
+ s += 4;
+ c0 = p[s[0]];
+ c1 = p[s[1]];
+ c2 = p[s[2]];
+ c3 = p[s[3]];
+ }
+ while ((c0 | c1 | c2 | c3) == 0);
+
+ size_t count = s - (unsigned char *) str;
+ return (c0 | c1) != 0 ? count - c0 + 1 : count - c2 + 3;
+}
+libc_hidden_builtin_def (strcspn)
diff --git a/REORG.TODO/string/strdup.c b/REORG.TODO/string/strdup.c
new file mode 100644
index 0000000000..40993fce1a
--- /dev/null
+++ b/REORG.TODO/string/strdup.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined _LIBC || defined STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else
+char *malloc ();
+char *memcpy ();
+#endif
+
+#undef __strdup
+#undef strdup
+
+#ifndef weak_alias
+# define __strdup strdup
+#endif
+
+/* Duplicate S, returning an identical malloc'd string. */
+char *
+__strdup (const char *s)
+{
+ size_t len = strlen (s) + 1;
+ void *new = malloc (len);
+
+ if (new == NULL)
+ return NULL;
+
+ return (char *) memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strdup)
+#endif
+#ifdef weak_alias
+weak_alias (__strdup, strdup)
+#endif
diff --git a/REORG.TODO/string/strerror.c b/REORG.TODO/string/strerror.c
new file mode 100644
index 0000000000..0d235c6b6b
--- /dev/null
+++ b/REORG.TODO/string/strerror.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* Return a string describing the errno code in ERRNUM.
+ The storage is good only until the next call to strerror.
+ Writing to the storage causes undefined behavior. */
+libc_freeres_ptr (static char *buf);
+
+char *
+strerror (int errnum)
+{
+ char *ret = __strerror_r (errnum, NULL, 0);
+ int saved_errno;
+
+ if (__glibc_likely (ret != NULL))
+ return ret;
+ saved_errno = errno;
+ if (buf == NULL)
+ buf = malloc (1024);
+ __set_errno (saved_errno);
+ if (buf == NULL)
+ return _("Unknown error");
+ return __strerror_r (errnum, buf, 1024);
+}
diff --git a/REORG.TODO/string/strerror_l.c b/REORG.TODO/string/strerror_l.c
new file mode 100644
index 0000000000..03a3257dfd
--- /dev/null
+++ b/REORG.TODO/string/strerror_l.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2007-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+static __thread char *last_value;
+
+
+static const char *
+translate (const char *str, locale_t loc)
+{
+ locale_t oldloc = __uselocale (loc);
+ const char *res = _(str);
+ __uselocale (oldloc);
+ return res;
+}
+
+
+/* Return a string describing the errno code in ERRNUM. */
+char *
+strerror_l (int errnum, locale_t loc)
+{
+
+
+ if (__builtin_expect (errnum < 0 || errnum >= _sys_nerr_internal
+ || _sys_errlist_internal[errnum] == NULL, 0))
+ {
+ free (last_value);
+ if (__asprintf (&last_value, "%s%d",
+ translate ("Unknown error ", loc), errnum) == -1)
+ last_value = NULL;
+
+ return last_value;
+ }
+
+ return (char *) translate (_sys_errlist_internal[errnum], loc);
+}
+
+
+#ifdef _LIBC
+# ifdef _LIBC_REENTRANT
+/* This is called when a thread is exiting to free the last_value string. */
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
+strerror_thread_freeres (void)
+{
+ free (last_value);
+}
+text_set_element (__libc_thread_subfreeres, strerror_thread_freeres);
+text_set_element (__libc_subfreeres, strerror_thread_freeres);
+# endif
+#endif
diff --git a/REORG.TODO/string/strfry.c b/REORG.TODO/string/strfry.c
new file mode 100644
index 0000000000..9d1bd88d4d
--- /dev/null
+++ b/REORG.TODO/string/strfry.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+char *
+strfry (char *string)
+{
+ static int init;
+ static struct random_data rdata;
+
+ if (!init)
+ {
+ static char state[32];
+ rdata.state = NULL;
+ __initstate_r (time ((time_t *) NULL) ^ getpid (),
+ state, sizeof (state), &rdata);
+ init = 1;
+ }
+
+ size_t len = strlen (string);
+ if (len > 0)
+ for (size_t i = 0; i < len - 1; ++i)
+ {
+ int32_t j;
+ __random_r (&rdata, &j);
+ j = j % (len - i) + i;
+
+ char c = string[i];
+ string[i] = string[j];
+ string[j] = c;
+ }
+
+ return string;
+}
diff --git a/REORG.TODO/string/string-inlines.c b/REORG.TODO/string/string-inlines.c
new file mode 100644
index 0000000000..fa4a1594b2
--- /dev/null
+++ b/REORG.TODO/string/string-inlines.c
@@ -0,0 +1,570 @@
+/* Copyright (C) 1999-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* <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>
+
+#include "shlib-compat.h"
+
+#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_25)
+/* The inline functions are not used from GLIBC 2.25 and forward, however
+ they are required to provide the symbols through string-inlines.c
+ (if inlining is not possible for compatibility reasons). */
+
+char *
+__old_strtok_r_1c (char *__s, char __sep, char **__nextp)
+{
+ char *__result;
+ if (__s == NULL)
+ __s = *__nextp;
+ while (*__s == __sep)
+ ++__s;
+ __result = NULL;
+ if (*__s != '\0')
+ {
+ __result = __s++;
+ while (*__s != '\0')
+ if (*__s++ == __sep)
+ {
+ __s[-1] = '\0';
+ break;
+ }
+ }
+ *__nextp = __s;
+ return __result;
+}
+compat_symbol (libc, __old_strtok_r_1c, __strtok_r_1c, GLIBC_2_1_1);
+
+char *
+__old_strsep_1c (char **__s, char __reject)
+{
+ char *__retval = *__s;
+ if (__retval != NULL && (*__s = strchr (__retval, __reject)) != NULL)
+ *(*__s)++ = '\0';
+ return __retval;
+}
+compat_symbol (libc, __old_strsep_1c, __strsep_1c, GLIBC_2_1_1);
+
+char *
+__old_strsep_2c (char **__s, char __reject1, char __reject2)
+{
+ char *__retval = *__s;
+ if (__retval != NULL)
+ {
+ char *__cp = __retval;
+ while (1)
+ {
+ if (*__cp == '\0')
+ {
+ __cp = NULL;
+ break;
+ }
+ if (*__cp == __reject1 || *__cp == __reject2)
+ {
+ *__cp++ = '\0';
+ break;
+ }
+ ++__cp;
+ }
+ *__s = __cp;
+ }
+ return __retval;
+}
+compat_symbol (libc, __old_strsep_2c, __strsep_2c, GLIBC_2_1_1);
+
+char *
+__old_strsep_3c (char **__s, char __reject1, char __reject2, char __reject3)
+{
+ char *__retval = *__s;
+ if (__retval != NULL)
+ {
+ char *__cp = __retval;
+ while (1)
+ {
+ if (*__cp == '\0')
+ {
+ __cp = NULL;
+ break;
+ }
+ if (*__cp == __reject1 || *__cp == __reject2 || *__cp == __reject3)
+ {
+ *__cp++ = '\0';
+ break;
+ }
+ ++__cp;
+ }
+ *__s = __cp;
+ }
+ return __retval;
+}
+compat_symbol (libc, __old_strsep_3c, __strsep_3c, GLIBC_2_1_1);
+#endif
+
+#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_24)
+/* The inline functions are not used from GLIBC 2.24 and forward, however
+ they are required to provide the symbols through string-inlines.c
+ (if inlining is not possible for compatibility reasons). */
+size_t
+__old_strcspn_c1 (const char *__s, int __reject)
+{
+ size_t __result = 0;
+ while (__s[__result] != '\0' && __s[__result] != __reject)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strcspn_c1, __strcspn_c1, GLIBC_2_1_1);
+
+size_t
+__old_strcspn_c2 (const char *__s, int __reject1, int __reject2)
+{
+ size_t __result = 0;
+ while (__s[__result] != '\0' && __s[__result] != __reject1
+ && __s[__result] != __reject2)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strcspn_c2, __strcspn_c2, GLIBC_2_1_1);
+
+size_t
+__old_strcspn_c3 (const char *__s, int __reject1, int __reject2,
+ int __reject3)
+{
+ size_t __result = 0;
+ while (__s[__result] != '\0' && __s[__result] != __reject1
+ && __s[__result] != __reject2 && __s[__result] != __reject3)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strcspn_c3, __strcspn_c3, GLIBC_2_1_1);
+
+size_t
+__old_strspn_c1 (const char *__s, int __accept)
+{
+ size_t __result = 0;
+ /* Please note that __accept never can be '\0'. */
+ while (__s[__result] == __accept)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strspn_c1, __strspn_c1, GLIBC_2_1_1);
+
+size_t
+__old_strspn_c2 (const char *__s, int __accept1, int __accept2)
+{
+ size_t __result = 0;
+ /* Please note that __accept1 and __accept2 never can be '\0'. */
+ while (__s[__result] == __accept1 || __s[__result] == __accept2)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strspn_c2, __strspn_c2, GLIBC_2_1_1);
+
+size_t
+__old_strspn_c3 (const char *__s, int __accept1, int __accept2,
+ int __accept3)
+{
+ size_t __result = 0;
+ /* Please note that __accept1 to __accept3 never can be '\0'. */
+ while (__s[__result] == __accept1 || __s[__result] == __accept2
+ || __s[__result] == __accept3)
+ ++__result;
+ return __result;
+}
+compat_symbol (libc, __old_strspn_c3, __strspn_c3, GLIBC_2_1_1);
+
+char *
+__old_strpbrk_c2 (const char *__s, int __accept1, int __accept2)
+{
+ /* Please note that __accept1 and __accept2 never can be '\0'. */
+ while (*__s != '\0' && *__s != __accept1 && *__s != __accept2)
+ ++__s;
+ return *__s == '\0' ? NULL : (char *) (size_t) __s;
+}
+compat_symbol (libc, __old_strpbrk_c2, __strpbrk_c2, GLIBC_2_1_1);
+
+char *
+__old_strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
+{
+ /* Please note that __accept1 to __accept3 never can be '\0'. */
+ while (*__s != '\0' && *__s != __accept1 && *__s != __accept2
+ && *__s != __accept3)
+ ++__s;
+ return *__s == '\0' ? NULL : (char *) (size_t) __s;
+}
+compat_symbol (libc, __old_strpbrk_c3, __strpbrk_c3, GLIBC_2_1_1);
+
+/* These are a few types we need for the optimizations if we cannot
+ use unaligned memory accesses. */
+# define __STRING2_COPY_TYPE(N) \
+ typedef struct { unsigned char __arr[N]; } \
+ __attribute__ ((__packed__)) __STRING2_COPY_ARR##N
+__STRING2_COPY_TYPE (2);
+__STRING2_COPY_TYPE (3);
+__STRING2_COPY_TYPE (4);
+__STRING2_COPY_TYPE (5);
+__STRING2_COPY_TYPE (6);
+__STRING2_COPY_TYPE (7);
+__STRING2_COPY_TYPE (8);
+# undef __STRING2_COPY_TYPE
+
+
+# if _STRING_INLINE_unaligned
+void *
+__old_mempcpy_small (void *__dest1,
+ char __src0_1, char __src2_1, char __src4_1, char __src6_1,
+ __uint16_t __src0_2, __uint16_t __src4_2,
+ __uint32_t __src0_4, __uint32_t __src4_4,
+ size_t __srclen)
+{
+ union {
+ __uint32_t __ui;
+ __uint16_t __usi;
+ unsigned char __uc;
+ unsigned char __c;
+ } *__u = __dest1;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__c = __src0_1;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 2:
+ __u->__usi = __src0_2;
+ __u = __extension__ ((void *) __u + 2);
+ break;
+ case 3:
+ __u->__usi = __src0_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__c = __src2_1;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 4:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ break;
+ case 5:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__c = __src4_1;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 6:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ __u = __extension__ ((void *) __u + 2);
+ break;
+ case 7:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__c = __src6_1;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 8:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__ui = __src4_4;
+ __u = __extension__ ((void *) __u + 4);
+ break;
+ }
+ return (void *) __u;
+}
+
+# else
+
+void *
+__old_mempcpy_small (void *__dest, char __src1,
+ __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+ __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+ __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+ __STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+ union {
+ char __c;
+ __STRING2_COPY_ARR2 __sca2;
+ __STRING2_COPY_ARR3 __sca3;
+ __STRING2_COPY_ARR4 __sca4;
+ __STRING2_COPY_ARR5 __sca5;
+ __STRING2_COPY_ARR6 __sca6;
+ __STRING2_COPY_ARR7 __sca7;
+ __STRING2_COPY_ARR8 __sca8;
+ } *__u = __dest;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__c = __src1;
+ break;
+ case 2:
+ __extension__ __u->__sca2 = __src2;
+ break;
+ case 3:
+ __extension__ __u->__sca3 = __src3;
+ break;
+ case 4:
+ __extension__ __u->__sca4 = __src4;
+ break;
+ case 5:
+ __extension__ __u->__sca5 = __src5;
+ break;
+ case 6:
+ __extension__ __u->__sca6 = __src6;
+ break;
+ case 7:
+ __extension__ __u->__sca7 = __src7;
+ break;
+ case 8:
+ __extension__ __u->__sca8 = __src8;
+ break;
+ }
+ return __extension__ ((void *) __u + __srclen);
+}
+# endif
+compat_symbol (libc, __old_mempcpy_small, __mempcpy_small, GLIBC_2_1_1);
+
+# if _STRING_INLINE_unaligned
+char *
+__old_strcpy_small (char *__dest,
+ __uint16_t __src0_2, __uint16_t __src4_2,
+ __uint32_t __src0_4, __uint32_t __src4_4,
+ size_t __srclen)
+{
+ union {
+ __uint32_t __ui;
+ __uint16_t __usi;
+ unsigned char __uc;
+ } *__u = (void *) __dest;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__uc = '\0';
+ break;
+ case 2:
+ __u->__usi = __src0_2;
+ break;
+ case 3:
+ __u->__usi = __src0_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__uc = '\0';
+ break;
+ case 4:
+ __u->__ui = __src0_4;
+ break;
+ case 5:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__uc = '\0';
+ break;
+ case 6:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ break;
+ case 7:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__uc = '\0';
+ break;
+ case 8:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__ui = __src4_4;
+ break;
+ }
+ return __dest;
+}
+
+# else
+
+char *
+__old_strcpy_small (char *__dest,
+ __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+ __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+ __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+ __STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+ union {
+ char __c;
+ __STRING2_COPY_ARR2 __sca2;
+ __STRING2_COPY_ARR3 __sca3;
+ __STRING2_COPY_ARR4 __sca4;
+ __STRING2_COPY_ARR5 __sca5;
+ __STRING2_COPY_ARR6 __sca6;
+ __STRING2_COPY_ARR7 __sca7;
+ __STRING2_COPY_ARR8 __sca8;
+ } *__u = (void *) __dest;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__c = '\0';
+ break;
+ case 2:
+ __extension__ __u->__sca2 = __src2;
+ break;
+ case 3:
+ __extension__ __u->__sca3 = __src3;
+ break;
+ case 4:
+ __extension__ __u->__sca4 = __src4;
+ break;
+ case 5:
+ __extension__ __u->__sca5 = __src5;
+ break;
+ case 6:
+ __extension__ __u->__sca6 = __src6;
+ break;
+ case 7:
+ __extension__ __u->__sca7 = __src7;
+ break;
+ case 8:
+ __extension__ __u->__sca8 = __src8;
+ break;
+ }
+ return __dest;
+}
+# endif
+compat_symbol (libc, __old_strcpy_small, __strcpy_small, GLIBC_2_1_1);
+
+# if _STRING_INLINE_unaligned
+char *
+__old_stpcpy_small (char *__dest,
+ __uint16_t __src0_2, __uint16_t __src4_2,
+ __uint32_t __src0_4, __uint32_t __src4_4,
+ size_t __srclen)
+{
+ union {
+ unsigned int __ui;
+ unsigned short int __usi;
+ unsigned char __uc;
+ char __c;
+ } *__u = (void *) __dest;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__uc = '\0';
+ break;
+ case 2:
+ __u->__usi = __src0_2;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 3:
+ __u->__usi = __src0_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__uc = '\0';
+ break;
+ case 4:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 3);
+ break;
+ case 5:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__uc = '\0';
+ break;
+ case 6:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ __u = __extension__ ((void *) __u + 1);
+ break;
+ case 7:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__usi = __src4_2;
+ __u = __extension__ ((void *) __u + 2);
+ __u->__uc = '\0';
+ break;
+ case 8:
+ __u->__ui = __src0_4;
+ __u = __extension__ ((void *) __u + 4);
+ __u->__ui = __src4_4;
+ __u = __extension__ ((void *) __u + 3);
+ break;
+ }
+ return &__u->__c;
+}
+
+# else
+
+char *
+__old_stpcpy_small (char *__dest,
+ __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+ __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+ __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+ __STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+ union {
+ char __c;
+ __STRING2_COPY_ARR2 __sca2;
+ __STRING2_COPY_ARR3 __sca3;
+ __STRING2_COPY_ARR4 __sca4;
+ __STRING2_COPY_ARR5 __sca5;
+ __STRING2_COPY_ARR6 __sca6;
+ __STRING2_COPY_ARR7 __sca7;
+ __STRING2_COPY_ARR8 __sca8;
+ } *__u = (void *) __dest;
+ switch ((unsigned int) __srclen)
+ {
+ case 1:
+ __u->__c = '\0';
+ break;
+ case 2:
+ __extension__ __u->__sca2 = __src2;
+ break;
+ case 3:
+ __extension__ __u->__sca3 = __src3;
+ break;
+ case 4:
+ __extension__ __u->__sca4 = __src4;
+ break;
+ case 5:
+ __extension__ __u->__sca5 = __src5;
+ break;
+ case 6:
+ __extension__ __u->__sca6 = __src6;
+ break;
+ case 7:
+ __extension__ __u->__sca7 = __src7;
+ break;
+ case 8:
+ __extension__ __u->__sca8 = __src8;
+ break;
+ }
+ return __dest + __srclen - 1;
+}
+# endif
+compat_symbol (libc, __old_stpcpy_small, __stpcpy_small, GLIBC_2_1_1);
+
+#endif
diff --git a/REORG.TODO/string/string.h b/REORG.TODO/string/string.h
new file mode 100644
index 0000000000..8eed67d77d
--- /dev/null
+++ b/REORG.TODO/string/string.h
@@ -0,0 +1,544 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * ISO C99 Standard: 7.21 String handling <string.h>
+ */
+
+#ifndef _STRING_H
+#define _STRING_H 1
+
+#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
+#include <bits/libc-header-start.h>
+
+__BEGIN_DECLS
+
+/* Get size_t and NULL from <stddef.h>. */
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+/* Tell the caller that we provide correct C++ prototypes. */
+#if defined __cplusplus && __GNUC_PREREQ (4, 4)
+# define __CORRECT_ISO_CPP_STRING_H_PROTO
+#endif
+
+
+/* Copy N bytes of SRC to DEST. */
+extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
+ size_t __n) __THROW __nonnull ((1, 2));
+/* Copy N bytes of SRC to DEST, guaranteeing
+ correct behavior for overlapping strings. */
+extern void *memmove (void *__dest, const void *__src, size_t __n)
+ __THROW __nonnull ((1, 2));
+
+/* 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. */
+#if defined __USE_MISC || defined __USE_XOPEN
+extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
+ int __c, size_t __n)
+ __THROW __nonnull ((1, 2));
+#endif /* Misc || X/Open. */
+
+
+/* Set N bytes of S to C. */
+extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
+
+/* Compare N bytes of S1 and S2. */
+extern int memcmp (const void *__s1, const void *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+/* Search N bytes of S for C. */
+#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++"
+{
+extern void *memchr (void *__s, int __c, size_t __n)
+ __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
+extern const void *memchr (const void *__s, int __c, size_t __n)
+ __THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
+
+# ifdef __OPTIMIZE__
+__extern_always_inline void *
+memchr (void *__s, int __c, size_t __n) __THROW
+{
+ return __builtin_memchr (__s, __c, __n);
+}
+
+__extern_always_inline const void *
+memchr (const void *__s, int __c, size_t __n) __THROW
+{
+ return __builtin_memchr (__s, __c, __n);
+}
+# endif
+}
+#else
+extern void *memchr (const void *__s, int __c, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1));
+#endif
+
+#ifdef __USE_GNU
+/* Search in S for C. This is similar to `memchr' but there is no
+ length limit. */
+# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++" void *rawmemchr (void *__s, int __c)
+ __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
+extern "C++" const void *rawmemchr (const void *__s, int __c)
+ __THROW __asm ("rawmemchr") __attribute_pure__ __nonnull ((1));
+# else
+extern void *rawmemchr (const void *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+# endif
+
+/* Search N bytes of S for the final occurrence of C. */
+# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++" void *memrchr (void *__s, int __c, size_t __n)
+ __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
+extern "C++" const void *memrchr (const void *__s, int __c, size_t __n)
+ __THROW __asm ("memrchr") __attribute_pure__ __nonnull ((1));
+# else
+extern void *memrchr (const void *__s, int __c, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1));
+# endif
+#endif
+
+
+/* Copy SRC to DEST. */
+extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
+ __THROW __nonnull ((1, 2));
+/* Copy no more than N characters of SRC to DEST. */
+extern char *strncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((1, 2));
+
+/* Append SRC onto DEST. */
+extern char *strcat (char *__restrict __dest, const char *__restrict __src)
+ __THROW __nonnull ((1, 2));
+/* Append no more than N characters from SRC onto DEST. */
+extern char *strncat (char *__restrict __dest, const char *__restrict __src,
+ size_t __n) __THROW __nonnull ((1, 2));
+
+/* Compare S1 and S2. */
+extern int strcmp (const char *__s1, const char *__s2)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+/* Compare N characters of S1 and S2. */
+extern int strncmp (const char *__s1, const char *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+/* Compare the collated forms of S1 and S2. */
+extern int strcoll (const char *__s1, const char *__s2)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+/* Put a transformation of SRC into no more than N bytes of DEST. */
+extern size_t strxfrm (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((2));
+
+#ifdef __USE_XOPEN2K8
+# include <xlocale.h>
+
+/* Compare the collated forms of S1 and S2, using sorting rules from L. */
+extern int strcoll_l (const char *__s1, const char *__s2, __locale_t __l)
+ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
+/* Put a transformation of SRC into no more than N bytes of DEST,
+ using sorting rules from L. */
+extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
+ __locale_t __l) __THROW __nonnull ((2, 4));
+#endif
+
+#if (defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 \
+ || __GLIBC_USE (LIB_EXT2))
+/* Duplicate S, returning an identical malloc'd string. */
+extern char *strdup (const char *__s)
+ __THROW __attribute_malloc__ __nonnull ((1));
+#endif
+
+/* Return a malloc'd copy of at most N bytes of STRING. The
+ resultant string is terminated even if no null terminator
+ appears before STRING[N]. */
+#if defined __USE_XOPEN2K8 || __GLIBC_USE (LIB_EXT2)
+extern char *strndup (const char *__string, size_t __n)
+ __THROW __attribute_malloc__ __nonnull ((1));
+#endif
+
+#if defined __USE_GNU && defined __GNUC__
+/* Duplicate S, returning an identical alloca'd string. */
+# define strdupa(s) \
+ (__extension__ \
+ ({ \
+ const char *__old = (s); \
+ size_t __len = strlen (__old) + 1; \
+ char *__new = (char *) __builtin_alloca (__len); \
+ (char *) memcpy (__new, __old, __len); \
+ }))
+
+/* Return an alloca'd copy of at most N bytes of string. */
+# define strndupa(s, n) \
+ (__extension__ \
+ ({ \
+ const char *__old = (s); \
+ size_t __len = strnlen (__old, (n)); \
+ char *__new = (char *) __builtin_alloca (__len + 1); \
+ __new[__len] = '\0'; \
+ (char *) memcpy (__new, __old, __len); \
+ }))
+#endif
+
+/* Find the first occurrence of C in S. */
+#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++"
+{
+extern char *strchr (char *__s, int __c)
+ __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
+extern const char *strchr (const char *__s, int __c)
+ __THROW __asm ("strchr") __attribute_pure__ __nonnull ((1));
+
+# ifdef __OPTIMIZE__
+__extern_always_inline char *
+strchr (char *__s, int __c) __THROW
+{
+ return __builtin_strchr (__s, __c);
+}
+
+__extern_always_inline const char *
+strchr (const char *__s, int __c) __THROW
+{
+ return __builtin_strchr (__s, __c);
+}
+# endif
+}
+#else
+extern char *strchr (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+#endif
+/* Find the last occurrence of C in S. */
+#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++"
+{
+extern char *strrchr (char *__s, int __c)
+ __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
+extern const char *strrchr (const char *__s, int __c)
+ __THROW __asm ("strrchr") __attribute_pure__ __nonnull ((1));
+
+# ifdef __OPTIMIZE__
+__extern_always_inline char *
+strrchr (char *__s, int __c) __THROW
+{
+ return __builtin_strrchr (__s, __c);
+}
+
+__extern_always_inline const char *
+strrchr (const char *__s, int __c) __THROW
+{
+ return __builtin_strrchr (__s, __c);
+}
+# endif
+}
+#else
+extern char *strrchr (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+#endif
+
+#ifdef __USE_GNU
+/* This function is similar to `strchr'. But it returns a pointer to
+ the closing NUL byte in case C is not found in S. */
+# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++" char *strchrnul (char *__s, int __c)
+ __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
+extern "C++" const char *strchrnul (const char *__s, int __c)
+ __THROW __asm ("strchrnul") __attribute_pure__ __nonnull ((1));
+# else
+extern char *strchrnul (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+# endif
+#endif
+
+/* Return the length of the initial segment of S which
+ consists entirely of characters not in REJECT. */
+extern size_t strcspn (const char *__s, const char *__reject)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+/* Return the length of the initial segment of S which
+ consists entirely of characters in ACCEPT. */
+extern size_t strspn (const char *__s, const char *__accept)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+/* Find the first occurrence in S of any character in ACCEPT. */
+#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++"
+{
+extern char *strpbrk (char *__s, const char *__accept)
+ __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));
+extern const char *strpbrk (const char *__s, const char *__accept)
+ __THROW __asm ("strpbrk") __attribute_pure__ __nonnull ((1, 2));
+
+# ifdef __OPTIMIZE__
+__extern_always_inline char *
+strpbrk (char *__s, const char *__accept) __THROW
+{
+ return __builtin_strpbrk (__s, __accept);
+}
+
+__extern_always_inline const char *
+strpbrk (const char *__s, const char *__accept) __THROW
+{
+ return __builtin_strpbrk (__s, __accept);
+}
+# endif
+}
+#else
+extern char *strpbrk (const char *__s, const char *__accept)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+#endif
+/* Find the first occurrence of NEEDLE in HAYSTACK. */
+#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++"
+{
+extern char *strstr (char *__haystack, const char *__needle)
+ __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
+extern const char *strstr (const char *__haystack, const char *__needle)
+ __THROW __asm ("strstr") __attribute_pure__ __nonnull ((1, 2));
+
+# ifdef __OPTIMIZE__
+__extern_always_inline char *
+strstr (char *__haystack, const char *__needle) __THROW
+{
+ return __builtin_strstr (__haystack, __needle);
+}
+
+__extern_always_inline const char *
+strstr (const char *__haystack, const char *__needle) __THROW
+{
+ return __builtin_strstr (__haystack, __needle);
+}
+# endif
+}
+#else
+extern char *strstr (const char *__haystack, const char *__needle)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+#endif
+
+
+/* Divide S into tokens separated by characters in DELIM. */
+extern char *strtok (char *__restrict __s, const char *__restrict __delim)
+ __THROW __nonnull ((2));
+
+/* Divide S into tokens separated by characters in DELIM. Information
+ passed between calls are stored in SAVE_PTR. */
+extern char *__strtok_r (char *__restrict __s,
+ const char *__restrict __delim,
+ char **__restrict __save_ptr)
+ __THROW __nonnull ((2, 3));
+#ifdef __USE_POSIX
+extern char *strtok_r (char *__restrict __s, const char *__restrict __delim,
+ char **__restrict __save_ptr)
+ __THROW __nonnull ((2, 3));
+#endif
+
+#ifdef __USE_GNU
+/* Similar to `strstr' but this function ignores the case of both strings. */
+# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++" char *strcasestr (char *__haystack, const char *__needle)
+ __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
+extern "C++" const char *strcasestr (const char *__haystack,
+ const char *__needle)
+ __THROW __asm ("strcasestr") __attribute_pure__ __nonnull ((1, 2));
+# else
+extern char *strcasestr (const char *__haystack, const char *__needle)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+# endif
+#endif
+
+#ifdef __USE_GNU
+/* Find the first occurrence of NEEDLE in HAYSTACK.
+ NEEDLE is NEEDLELEN bytes long;
+ HAYSTACK is HAYSTACKLEN bytes long. */
+extern void *memmem (const void *__haystack, size_t __haystacklen,
+ const void *__needle, size_t __needlelen)
+ __THROW __attribute_pure__ __nonnull ((1, 3));
+
+/* Copy N bytes of SRC to DEST, return pointer to bytes after the
+ last written byte. */
+extern void *__mempcpy (void *__restrict __dest,
+ const void *__restrict __src, size_t __n)
+ __THROW __nonnull ((1, 2));
+extern void *mempcpy (void *__restrict __dest,
+ const void *__restrict __src, size_t __n)
+ __THROW __nonnull ((1, 2));
+#endif
+
+
+/* Return the length of S. */
+extern size_t strlen (const char *__s)
+ __THROW __attribute_pure__ __nonnull ((1));
+
+#ifdef __USE_XOPEN2K8
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ If no '\0' terminator is found in that many characters, return MAXLEN. */
+extern size_t strnlen (const char *__string, size_t __maxlen)
+ __THROW __attribute_pure__ __nonnull ((1));
+#endif
+
+
+/* Return a string describing the meaning of the `errno' code in ERRNUM. */
+extern char *strerror (int __errnum) __THROW;
+#ifdef __USE_XOPEN2K
+/* Reentrant version of `strerror'.
+ There are 2 flavors of `strerror_r', GNU which returns the string
+ and may or may not use the supplied temporary buffer and POSIX one
+ which fills the string into the buffer.
+ To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L
+ without -D_GNU_SOURCE is needed, otherwise the GNU version is
+ preferred. */
+# if defined __USE_XOPEN2K && !defined __USE_GNU
+/* Fill BUF with a string describing the meaning of the `errno' code in
+ ERRNUM. */
+# ifdef __REDIRECT_NTH
+extern int __REDIRECT_NTH (strerror_r,
+ (int __errnum, char *__buf, size_t __buflen),
+ __xpg_strerror_r) __nonnull ((2));
+# else
+extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen)
+ __THROW __nonnull ((2));
+# define strerror_r __xpg_strerror_r
+# endif
+# else
+/* If a temporary buffer is required, at most BUFLEN bytes of BUF will be
+ used. */
+extern char *strerror_r (int __errnum, char *__buf, size_t __buflen)
+ __THROW __nonnull ((2)) __wur;
+# endif
+#endif
+
+#ifdef __USE_XOPEN2K8
+/* Translate error number to string according to the locale L. */
+extern char *strerror_l (int __errnum, __locale_t __l) __THROW;
+#endif
+
+#ifdef __USE_MISC
+# include <strings.h>
+
+/* Set N bytes of S to 0. The compiler will not delete a call to this
+ function, even if S is dead after the call. */
+extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+
+/* Return the next DELIM-delimited token from *STRINGP,
+ terminating it with a '\0', and update *STRINGP to point past it. */
+extern char *strsep (char **__restrict __stringp,
+ const char *__restrict __delim)
+ __THROW __nonnull ((1, 2));
+#endif
+
+#ifdef __USE_XOPEN2K8
+/* Return a string describing the meaning of the signal number in SIG. */
+extern char *strsignal (int __sig) __THROW;
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
+extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src)
+ __THROW __nonnull ((1, 2));
+extern char *stpcpy (char *__restrict __dest, const char *__restrict __src)
+ __THROW __nonnull ((1, 2));
+
+/* Copy no more than N characters of SRC to DEST, returning the address of
+ the last character written into DEST. */
+extern char *__stpncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((1, 2));
+extern char *stpncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((1, 2));
+#endif
+
+#ifdef __USE_GNU
+/* Compare S1 and S2 as strings holding name & indices/version numbers. */
+extern int strverscmp (const char *__s1, const char *__s2)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+/* Sautee STRING briskly. */
+extern char *strfry (char *__string) __THROW __nonnull ((1));
+
+/* Frobnicate N bytes of S. */
+extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1));
+
+# ifndef basename
+/* Return the file name within directory of FILENAME. We don't
+ declare the function if the `basename' macro is available (defined
+ in <libgen.h>) which makes the XPG version of this function
+ available. */
+# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
+extern "C++" char *basename (char *__filename)
+ __THROW __asm ("basename") __nonnull ((1));
+extern "C++" const char *basename (const char *__filename)
+ __THROW __asm ("basename") __nonnull ((1));
+# else
+extern char *basename (const char *__filename) __THROW __nonnull ((1));
+# endif
+# endif
+#endif
+
+
+#if __GNUC_PREREQ (3,4)
+# if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ \
+ && !defined __NO_INLINE__ && !defined __cplusplus
+/* When using GNU CC we provide some optimized versions of selected
+ functions from this header. There are two kinds of optimizations:
+
+ - machine-dependent optimizations, most probably using inline
+ assembler code; these might be quite expensive since the code
+ size can increase significantly.
+ These optimizations are not used unless the symbol
+ __USE_STRING_INLINES
+ is defined before including this header.
+
+ - machine-independent optimizations which do not increase the
+ code size significantly and which optimize mainly situations
+ where one or more arguments are compile-time constants.
+ These optimizations are used always when the compiler is
+ taught to optimize.
+
+ One can inhibit all optimizations by defining __NO_STRING_INLINES. */
+
+/* Get the machine-dependent optimizations (if any). */
+# include <bits/string.h>
+
+/* These are generic optimizations which do not add too much inline code. */
+# include <bits/string2.h>
+# endif
+
+# if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
+/* Functions with security checks. */
+# include <bits/string3.h>
+# endif
+#endif
+
+#if defined __USE_GNU && defined __OPTIMIZE__ \
+ && defined __extern_always_inline && __GNUC_PREREQ (3,2)
+# if !defined _FORCE_INLINES && !defined _HAVE_STRING_ARCH_mempcpy
+
+#define mempcpy(dest, src, n) __mempcpy_inline (dest, src, n)
+#define __mempcpy(dest, src, n) __mempcpy_inline (dest, src, n)
+
+__extern_always_inline void *
+__mempcpy_inline (void *__restrict __dest,
+ const void *__restrict __src, size_t __n)
+{
+ return (char *) memcpy (__dest, __src, __n) + __n;
+}
+
+# endif
+#endif
+
+__END_DECLS
+
+#endif /* string.h */
diff --git a/REORG.TODO/string/strings.h b/REORG.TODO/string/strings.h
new file mode 100644
index 0000000000..43207af09c
--- /dev/null
+++ b/REORG.TODO/string/strings.h
@@ -0,0 +1,147 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRINGS_H
+#define _STRINGS_H 1
+
+#include <features.h>
+#define __need_size_t
+#include <stddef.h>
+
+/* Tell the caller that we provide correct C++ prototypes. */
+#if defined __cplusplus && __GNUC_PREREQ (4, 4)
+# define __CORRECT_ISO_CPP_STRINGS_H_PROTO
+#endif
+
+__BEGIN_DECLS
+
+#if defined __USE_MISC || !defined __USE_XOPEN2K8
+/* Compare N bytes of S1 and S2 (same as memcmp). */
+extern int bcmp (const void *__s1, const void *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */
+extern void bcopy (const void *__src, void *__dest, size_t __n)
+ __THROW __nonnull ((1, 2));
+
+/* Set N bytes of S to 0. */
+extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+
+/* Find the first occurrence of C in S (same as strchr). */
+# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
+extern "C++"
+{
+extern char *index (char *__s, int __c)
+ __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
+extern const char *index (const char *__s, int __c)
+ __THROW __asm ("index") __attribute_pure__ __nonnull ((1));
+
+# if defined __OPTIMIZE__
+__extern_always_inline char *
+index (char *__s, int __c) __THROW
+{
+ return __builtin_index (__s, __c);
+}
+
+__extern_always_inline const char *
+index (const char *__s, int __c) __THROW
+{
+ return __builtin_index (__s, __c);
+}
+# endif
+}
+# else
+extern char *index (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+# endif
+
+/* Find the last occurrence of C in S (same as strrchr). */
+# ifdef __CORRECT_ISO_CPP_STRINGS_H_PROTO
+extern "C++"
+{
+extern char *rindex (char *__s, int __c)
+ __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
+extern const char *rindex (const char *__s, int __c)
+ __THROW __asm ("rindex") __attribute_pure__ __nonnull ((1));
+
+# if defined __OPTIMIZE__
+__extern_always_inline char *
+rindex (char *__s, int __c) __THROW
+{
+ return __builtin_rindex (__s, __c);
+}
+
+__extern_always_inline const char *
+rindex (const char *__s, int __c) __THROW
+{
+ return __builtin_rindex (__s, __c);
+}
+# endif
+}
+# else
+extern char *rindex (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1));
+# endif
+#endif
+
+#if defined __USE_MISC || !defined __USE_XOPEN2K8 || defined __USE_XOPEN2K8XSI
+/* Return the position of the first bit set in I, or 0 if none are set.
+ The least-significant bit is position 1, the most-significant 32. */
+extern int ffs (int __i) __THROW __attribute_const__;
+#endif
+
+/* The following two functions are non-standard but necessary for non-32 bit
+ platforms. */
+# ifdef __USE_GNU
+extern int ffsl (long int __l) __THROW __attribute_const__;
+__extension__ extern int ffsll (long long int __ll)
+ __THROW __attribute_const__;
+# endif
+
+/* Compare S1 and S2, ignoring case. */
+extern int strcasecmp (const char *__s1, const char *__s2)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+/* Compare no more than N chars of S1 and S2, ignoring case. */
+extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
+#ifdef __USE_XOPEN2K8
+# include <xlocale.h>
+
+/* Compare S1 and S2, ignoring case, using collation rules from LOC. */
+extern int strcasecmp_l (const char *__s1, const char *__s2, __locale_t __loc)
+ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
+
+/* Compare no more than N chars of S1 and S2, ignoring case, using
+ collation rules from LOC. */
+extern int strncasecmp_l (const char *__s1, const char *__s2,
+ size_t __n, __locale_t __loc)
+ __THROW __attribute_pure__ __nonnull ((1, 2, 4));
+#endif
+
+__END_DECLS
+
+#if __GNUC_PREREQ (3,4) && __USE_FORTIFY_LEVEL > 0 \
+ && defined __fortify_function
+/* Functions with security checks. */
+# if defined __USE_MISC || !defined __USE_XOPEN2K8
+# include <bits/strings_fortified.h>
+# endif
+#endif
+
+#endif /* strings.h */
diff --git a/REORG.TODO/string/strlen.c b/REORG.TODO/string/strlen.c
new file mode 100644
index 0000000000..b368ccf58f
--- /dev/null
+++ b/REORG.TODO/string/strlen.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+
+#undef strlen
+
+#ifndef STRLEN
+# define STRLEN strlen
+#endif
+
+/* 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 (const char *str)
+{
+ const char *char_ptr;
+ const unsigned long int *longword_ptr;
+ unsigned long int longword, 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. */
+ 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. */
+ 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 (;;)
+ {
+ longword = *longword_ptr++;
+
+ if (((longword - lomagic) & ~longword & himagic) != 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/REORG.TODO/string/strncase.c b/REORG.TODO/string/strncase.c
new file mode 100644
index 0000000000..6cb996cf91
--- /dev/null
+++ b/REORG.TODO/string/strncase.c
@@ -0,0 +1,69 @@
+/* Compare at most N characters of two strings without taking care for
+ the case.
+ Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 , __locale_t loc
+#else
+# define LOCALE_PARAM
+#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 (const char *s1, const char *s2, size_t n LOCALE_PARAM)
+{
+#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/REORG.TODO/string/strncase_l.c b/REORG.TODO/string/strncase_l.c
new file mode 100644
index 0000000000..395fc9fd08
--- /dev/null
+++ b/REORG.TODO/string/strncase_l.c
@@ -0,0 +1,24 @@
+/* Compare at most N characters of two strings without taking care for
+ the case using given locale.
+ Copyright (C) 1997-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define USE_IN_EXTENDED_LOCALE_MODEL 1
+#include "strncase.c"
+
+libc_hidden_def (__strncasecmp_l)
+weak_alias (__strncasecmp_l, strncasecmp_l)
diff --git a/REORG.TODO/string/strncat.c b/REORG.TODO/string/strncat.c
new file mode 100644
index 0000000000..71a13eec0b
--- /dev/null
+++ b/REORG.TODO/string/strncat.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#ifndef STRNCAT
+# undef strncat
+# define STRNCAT strncat
+#endif
+
+char *
+STRNCAT (char *s1, const char *s2, size_t n)
+{
+ char *s = s1;
+
+ /* Find the end of S1. */
+ s1 += strlen (s1);
+
+ size_t ss = __strnlen (s2, n);
+
+ s1[ss] = '\0';
+ memcpy (s1, s2, ss);
+
+ return s;
+}
diff --git a/REORG.TODO/string/strncmp.c b/REORG.TODO/string/strncmp.c
new file mode 100644
index 0000000000..c41e120091
--- /dev/null
+++ b/REORG.TODO/string/strncmp.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <memcopy.h>
+
+#undef strncmp
+
+#ifndef STRNCMP
+#define STRNCMP strncmp
+#endif
+
+/* 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 (const char *s1, const char *s2, size_t n)
+{
+ unsigned char c1 = '\0';
+ unsigned 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/REORG.TODO/string/strncpy.c b/REORG.TODO/string/strncpy.c
new file mode 100644
index 0000000000..1b45c52e73
--- /dev/null
+++ b/REORG.TODO/string/strncpy.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef strncpy
+
+#ifndef STRNCPY
+ #define STRNCPY strncpy
+#endif
+
+char *
+STRNCPY (char *s1, const char *s2, size_t n)
+{
+ size_t size = __strnlen (s2, n);
+ if (size != n)
+ memset (s1 + size, '\0', n - size);
+ return memcpy (s1, s2, size);
+}
+libc_hidden_builtin_def (strncpy)
diff --git a/REORG.TODO/string/strndup.c b/REORG.TODO/string/strndup.c
new file mode 100644
index 0000000000..fa0e7dcda1
--- /dev/null
+++ b/REORG.TODO/string/strndup.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 1996-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if defined _LIBC || defined STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else
+char *malloc ();
+#endif
+
+#undef __strndup
+#undef strndup
+
+#ifndef weak_alias
+# define __strndup strndup
+#endif
+
+char *
+__strndup (const char *s, size_t n)
+{
+ size_t len = __strnlen (s, n);
+ char *new = (char *) malloc (len + 1);
+
+ if (new == NULL)
+ return NULL;
+
+ new[len] = '\0';
+ return (char *) memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strndup)
+#endif
+#ifdef weak_alias
+weak_alias (__strndup, strndup)
+#endif
diff --git a/REORG.TODO/string/strnlen.c b/REORG.TODO/string/strnlen.c
new file mode 100644
index 0000000000..ff9fb6197a
--- /dev/null
+++ b/REORG.TODO/string/strnlen.c
@@ -0,0 +1,166 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ Copyright (C) 1991-2017 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, see <http://www.gnu.org/licenses/>. */
+
+#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. */
+
+#ifdef STRNLEN
+# define __strnlen STRNLEN
+#endif
+
+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, himagic, lomagic;
+
+ if (maxlen == 0)
+ return 0;
+
+ if (__glibc_unlikely (end_ptr < str))
+ 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. */
+ 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. */
+ 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;
+}
+#ifndef STRNLEN
+libc_hidden_def (__strnlen)
+weak_alias (__strnlen, strnlen)
+#endif
+libc_hidden_def (strnlen)
diff --git a/REORG.TODO/string/strpbrk.c b/REORG.TODO/string/strpbrk.c
new file mode 100644
index 0000000000..02d0bd2f63
--- /dev/null
+++ b/REORG.TODO/string/strpbrk.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef strpbrk
+
+#ifndef STRPBRK
+#define STRPBRK strpbrk
+#endif
+
+/* Find the first occurrence in S of any character in ACCEPT. */
+char *
+STRPBRK (const char *s, const char *accept)
+{
+ s += strcspn (s, accept);
+ return *s ? (char *)s : NULL;
+}
+libc_hidden_builtin_def (strpbrk)
diff --git a/REORG.TODO/string/strrchr.c b/REORG.TODO/string/strrchr.c
new file mode 100644
index 0000000000..92638a8fbd
--- /dev/null
+++ b/REORG.TODO/string/strrchr.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef strrchr
+
+#ifndef STRRCHR
+# define STRRCHR strrchr
+#endif
+
+/* Find the last occurrence of C in S. */
+char *
+STRRCHR (const char *s, int c)
+{
+ 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/REORG.TODO/string/strsep.c b/REORG.TODO/string/strsep.c
new file mode 100644
index 0000000000..7091234a6c
--- /dev/null
+++ b/REORG.TODO/string/strsep.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+#undef __strsep
+#undef strsep
+
+char *
+__strsep (char **stringp, const char *delim)
+{
+ char *begin, *end;
+
+ begin = *stringp;
+ if (begin == NULL)
+ return NULL;
+
+ /* Find the end of the token. */
+ end = begin + strcspn (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/REORG.TODO/string/strsignal.c b/REORG.TODO/string/strsignal.c
new file mode 100644
index 0000000000..6cb4399934
--- /dev/null
+++ b/REORG.TODO/string/strsignal.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+#include <libc-lock.h>
+
+static __libc_key_t key;
+
+/* If nonzero the key allocation failed and we should better use a
+ static buffer than fail. */
+#define BUFFERSIZ 100
+static char local_buf[BUFFERSIZ];
+static char *static_buf;
+
+/* Destructor for the thread-specific data. */
+static void init (void);
+static void free_key_mem (void *mem);
+static char *getbuffer (void);
+
+
+/* Return a string describing the meaning of the signal number SIGNUM. */
+char *
+strsignal (int signum)
+{
+ __libc_once_define (static, once);
+ const char *desc;
+
+ /* If we have not yet initialized the buffer do it now. */
+ __libc_once (once, init);
+
+ if (
+#ifdef SIGRTMIN
+ (signum >= SIGRTMIN && signum <= SIGRTMAX) ||
+#endif
+ signum < 0 || signum >= NSIG
+ || (desc = _sys_siglist[signum]) == NULL)
+ {
+ char *buffer = getbuffer ();
+ int len;
+#ifdef SIGRTMIN
+ if (signum >= SIGRTMIN && signum <= SIGRTMAX)
+ len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"),
+ signum - SIGRTMIN);
+ else
+#endif
+ len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"),
+ signum);
+ if (len >= BUFFERSIZ)
+ buffer = NULL;
+ else
+ buffer[len] = '\0';
+
+ return buffer;
+ }
+
+ return (char *) _(desc);
+}
+
+
+/* Initialize buffer. */
+static void
+init (void)
+{
+ if (__libc_key_create (&key, free_key_mem))
+ /* Creating the key failed. This means something really went
+ wrong. In any case use a static buffer which is better than
+ nothing. */
+ static_buf = local_buf;
+}
+
+
+/* Free the thread specific data, this is done if a thread terminates. */
+static void
+free_key_mem (void *mem)
+{
+ free (mem);
+ __libc_setspecific (key, NULL);
+}
+
+
+/* Return the buffer to be used. */
+static char *
+getbuffer (void)
+{
+ char *result;
+
+ if (static_buf != NULL)
+ result = static_buf;
+ else
+ {
+ /* We don't use the static buffer and so we have a key. Use it
+ to get the thread-specific buffer. */
+ result = __libc_getspecific (key);
+ if (result == NULL)
+ {
+ /* No buffer allocated so far. */
+ result = malloc (BUFFERSIZ);
+ if (result == NULL)
+ /* No more memory available. We use the static buffer. */
+ result = local_buf;
+ else
+ __libc_setspecific (key, result);
+ }
+ }
+
+ return result;
+}
diff --git a/REORG.TODO/string/strspn.c b/REORG.TODO/string/strspn.c
new file mode 100644
index 0000000000..c63197cdf0
--- /dev/null
+++ b/REORG.TODO/string/strspn.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdint.h>
+#include <libc-pointer-arith.h>
+
+#undef strspn
+#ifndef STRSPN
+# define STRSPN strspn
+#endif
+
+/* Return the length of the maximum initial segment
+ of S which contains only characters in ACCEPT. */
+size_t
+STRSPN (const char *str, const char *accept)
+{
+ if (accept[0] == '\0')
+ return 0;
+ if (__glibc_unlikely (accept[1] == '\0'))
+ {
+ const char *a = str;
+ for (; *str == *accept; str++);
+ return str - a;
+ }
+
+ /* Use multiple small memsets to enable inlining on most targets. */
+ unsigned char table[256];
+ unsigned char *p = memset (table, 0, 64);
+ memset (p + 64, 0, 64);
+ memset (p + 128, 0, 64);
+ memset (p + 192, 0, 64);
+
+ unsigned char *s = (unsigned char*) accept;
+ /* Different from strcspn it does not add the NULL on the table
+ so can avoid check if str[i] is NULL, since table['\0'] will
+ be 0 and thus stopping the loop check. */
+ do
+ p[*s++] = 1;
+ while (*s);
+
+ s = (unsigned char*) str;
+ if (!p[s[0]]) return 0;
+ if (!p[s[1]]) return 1;
+ if (!p[s[2]]) return 2;
+ if (!p[s[3]]) return 3;
+
+ s = (unsigned char *) PTR_ALIGN_DOWN (s, 4);
+
+ unsigned int c0, c1, c2, c3;
+ do {
+ s += 4;
+ c0 = p[s[0]];
+ c1 = p[s[1]];
+ c2 = p[s[2]];
+ c3 = p[s[3]];
+ } while ((c0 & c1 & c2 & c3) != 0);
+
+ size_t count = s - (unsigned char *) str;
+ return (c0 & c1) == 0 ? count + c0 : count + c2 + 2;
+}
+libc_hidden_builtin_def (strspn)
diff --git a/REORG.TODO/string/strstr.c b/REORG.TODO/string/strstr.c
new file mode 100644
index 0000000000..88f1d5de36
--- /dev/null
+++ b/REORG.TODO/string/strstr.c
@@ -0,0 +1,92 @@
+/* Return the offset of one string within another.
+ Copyright (C) 1994-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This particular implementation was written by Eric Blake, 2008. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Specification of strstr. */
+#include <string.h>
+
+#include <stdbool.h>
+
+#ifndef _LIBC
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#define RETURN_TYPE char *
+#define AVAILABLE(h, h_l, j, n_l) \
+ (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \
+ && ((h_l) = (j) + (n_l)))
+#define CHECK_EOL (1)
+#define RET0_IF_0(a) if (!a) goto ret0
+#include "str-two-way.h"
+
+#undef strstr
+
+#ifndef STRSTR
+#define STRSTR strstr
+#endif
+
+/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK
+ if NEEDLE is empty, otherwise NULL if NEEDLE is not found in
+ HAYSTACK. */
+char *
+STRSTR (const char *haystack_start, const char *needle_start)
+{
+ const char *haystack = haystack_start;
+ const char *needle = needle_start;
+ size_t needle_len; /* Length of NEEDLE. */
+ size_t haystack_len; /* Known minimum length of HAYSTACK. */
+ bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */
+
+ /* Determine length of NEEDLE, and in the process, make sure
+ HAYSTACK is at least as long (no point processing all of a long
+ NEEDLE if HAYSTACK is too short). */
+ while (*haystack && *needle)
+ ok &= *haystack++ == *needle++;
+ if (*needle)
+ return NULL;
+ if (ok)
+ return (char *) haystack_start;
+
+ /* Reduce the size of haystack using strchr, since it has a smaller
+ linear coefficient than the Two-Way algorithm. */
+ needle_len = needle - needle_start;
+ haystack = strchr (haystack_start + 1, *needle_start);
+ if (!haystack || __builtin_expect (needle_len == 1, 0))
+ return (char *) haystack;
+ needle -= needle_len;
+ haystack_len = (haystack > haystack_start + needle_len ? 1
+ : needle_len + haystack_start - haystack);
+
+ /* Perform the search. Abstract memory is considered to be an array
+ of 'unsigned char' values, not an array of 'char' values. See
+ ISO C 99 section 6.2.6.1. */
+ if (needle_len < LONG_NEEDLE_THRESHOLD)
+ return two_way_short_needle ((const unsigned char *) haystack,
+ haystack_len,
+ (const unsigned char *) needle, needle_len);
+ return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
+ (const unsigned char *) needle, needle_len);
+}
+libc_hidden_builtin_def (strstr)
+
+#undef LONG_NEEDLE_THRESHOLD
diff --git a/REORG.TODO/string/strtok.c b/REORG.TODO/string/strtok.c
new file mode 100644
index 0000000000..6b9de89747
--- /dev/null
+++ b/REORG.TODO/string/strtok.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+
+/* 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 (char *s, const char *delim)
+{
+ static char *olds;
+ return __strtok_r (s, delim, &olds);
+}
diff --git a/REORG.TODO/string/strtok_r.c b/REORG.TODO/string/strtok_r.c
new file mode 100644
index 0000000000..ace3520a25
--- /dev/null
+++ b/REORG.TODO/string/strtok_r.c
@@ -0,0 +1,79 @@
+/* Reentrant string tokenizer. Generic version.
+ Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#ifndef _LIBC
+/* Get specification. */
+# include "strtok_r.h"
+# define __strtok_r strtok_r
+#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 *end;
+
+ if (s == NULL)
+ s = *save_ptr;
+
+ if (*s == '\0')
+ {
+ *save_ptr = s;
+ return NULL;
+ }
+
+ /* Scan leading delimiters. */
+ s += strspn (s, delim);
+ if (*s == '\0')
+ {
+ *save_ptr = s;
+ return NULL;
+ }
+
+ /* Find the end of the token. */
+ end = s + strcspn (s, delim);
+ if (*end == '\0')
+ {
+ *save_ptr = end;
+ return s;
+ }
+
+ /* Terminate the token and make *SAVE_PTR point past it. */
+ *end = '\0';
+ *save_ptr = end + 1;
+ return s;
+}
+#ifdef weak_alias
+libc_hidden_def (__strtok_r)
+weak_alias (__strtok_r, strtok_r)
+#endif
diff --git a/REORG.TODO/string/strverscmp.c b/REORG.TODO/string/strverscmp.c
new file mode 100644
index 0000000000..383f6445c8
--- /dev/null
+++ b/REORG.TODO/string/strverscmp.c
@@ -0,0 +1,107 @@
+/* Compare strings while treating digits characters numerically.
+ Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+ fractionnal parts, S_Z: idem but with leading Zeroes only */
+#define S_N 0x0
+#define S_I 0x3
+#define S_F 0x6
+#define S_Z 0x9
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP 2
+#define LEN 3
+
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+ returning less than, equal to or greater than zero if S1 is less than,
+ equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+
+ /* Symbol(s) 0 [1-9] others
+ Transition (10) 0 (01) d (00) x */
+ static const uint8_t next_state[] =
+ {
+ /* state x d 0 */
+ /* S_N */ S_N, S_I, S_Z,
+ /* S_I */ S_N, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z
+ };
+
+ static const int8_t result_type[] =
+ {
+ /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
+
+ /* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP
+ };
+
+ if (p1 == p2)
+ return 0;
+
+ unsigned char c1 = *p1++;
+ unsigned char c2 = *p2++;
+ /* Hint: '0' is a digit too. */
+ int state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
+
+ int diff;
+ while ((diff = c1 - c2) == 0)
+ {
+ if (c1 == '\0')
+ return diff;
+
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state += (c1 == '0') + (isdigit (c1) != 0);
+ }
+
+ state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
+
+ switch (state)
+ {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while (isdigit (*p1++))
+ if (!isdigit (*p2++))
+ return 1;
+
+ return isdigit (*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
+libc_hidden_def (__strverscmp)
+weak_alias (__strverscmp, strverscmp)
diff --git a/REORG.TODO/string/strxfrm.c b/REORG.TODO/string/strxfrm.c
new file mode 100644
index 0000000000..5210466555
--- /dev/null
+++ b/REORG.TODO/string/strxfrm.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <locale/localeinfo.h>
+
+#ifndef STRING_TYPE
+# define STRING_TYPE char
+# define STRXFRM strxfrm
+# define STRXFRM_L __strxfrm_l
+#endif
+
+size_t
+STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n)
+{
+ return STRXFRM_L (dest, src, n, _NL_CURRENT_LOCALE);
+}
diff --git a/REORG.TODO/string/strxfrm_l.c b/REORG.TODO/string/strxfrm_l.c
new file mode 100644
index 0000000000..dd98a4caaf
--- /dev/null
+++ b/REORG.TODO/string/strxfrm_l.c
@@ -0,0 +1,747 @@
+/* Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#ifndef STRING_TYPE
+# define STRING_TYPE char
+# define USTRING_TYPE unsigned char
+# define STRXFRM __strxfrm_l
+# define STRLEN strlen
+# define STPNCPY __stpncpy
+# define WEIGHT_H "../locale/weight.h"
+# define SUFFIX MB
+# define L(arg) arg
+#endif
+
+#define CONCAT(a,b) CONCAT1(a,b)
+#define CONCAT1(a,b) a##b
+
+/* Maximum string size that is calculated with cached indices. Right now this
+ is an arbitrary value open to optimizations. SMALL_STR_SIZE * 4 has to be
+ lower than __MAX_ALLOCA_CUTOFF. Keep localedata/xfrm-test.c in sync. */
+#define SMALL_STR_SIZE 4095
+
+#include "../locale/localeinfo.h"
+#include WEIGHT_H
+
+/* Group locale data for shorter parameter lists. */
+typedef struct
+{
+ uint_fast32_t nrules;
+ unsigned char *rulesets;
+ USTRING_TYPE *weights;
+ int32_t *table;
+ USTRING_TYPE *extra;
+ int32_t *indirect;
+} locale_data_t;
+
+#ifndef WIDE_CHAR_VERSION
+
+/* We need UTF-8 encoding of numbers. */
+static int
+utf8_encode (char *buf, int val)
+{
+ int retval;
+
+ if (val < 0x80)
+ {
+ *buf++ = (char) val;
+ retval = 1;
+ }
+ else
+ {
+ int step;
+
+ for (step = 2; step < 6; ++step)
+ if ((val & (~(uint32_t)0 << (5 * step + 1))) == 0)
+ break;
+ retval = step;
+
+ *buf = (unsigned char) (~0xff >> step);
+ --step;
+ do
+ {
+ buf[step] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ }
+ while (--step > 0);
+ *buf |= val;
+ }
+
+ return retval;
+}
+#endif
+
+/* Find next weight and rule index. Inlined since called for every char. */
+static __always_inline size_t
+find_idx (const USTRING_TYPE **us, int32_t *weight_idx,
+ unsigned char *rule_idx, const locale_data_t *l_data, const int pass)
+{
+ int32_t tmp = findidx (l_data->table, l_data->indirect, l_data->extra, us,
+ -1);
+ *rule_idx = tmp >> 24;
+ int32_t idx = tmp & 0xffffff;
+ size_t len = l_data->weights[idx++];
+
+ /* Skip over indices of previous levels. */
+ for (int i = 0; i < pass; i++)
+ {
+ idx += len;
+ len = l_data->weights[idx++];
+ }
+
+ *weight_idx = idx;
+ return len;
+}
+
+static int
+find_position (const USTRING_TYPE *us, const locale_data_t *l_data,
+ const int pass)
+{
+ int32_t weight_idx;
+ unsigned char rule_idx;
+ const USTRING_TYPE *usrc = us;
+
+ find_idx (&usrc, &weight_idx, &rule_idx, l_data, pass);
+ return l_data->rulesets[rule_idx * l_data->nrules + pass] & sort_position;
+}
+
+/* Do the transformation. */
+static size_t
+do_xfrm (const USTRING_TYPE *usrc, STRING_TYPE *dest, size_t n,
+ const locale_data_t *l_data)
+{
+ int32_t weight_idx;
+ unsigned char rule_idx;
+ uint_fast32_t pass;
+ size_t needed = 0;
+ size_t last_needed;
+
+ /* Now the passes over the weights. */
+ for (pass = 0; pass < l_data->nrules; ++pass)
+ {
+ size_t backw_len = 0;
+ last_needed = needed;
+ const USTRING_TYPE *cur = usrc;
+ const USTRING_TYPE *backw_start = NULL;
+
+ /* We assume that if a rule has defined `position' in one section
+ this is true for all of them. */
+ int position = find_position (cur, l_data, pass);
+
+ if (position == 0)
+ {
+ while (*cur != L('\0'))
+ {
+ const USTRING_TYPE *pos = cur;
+ size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data,
+ pass);
+ int rule = l_data->rulesets[rule_idx * l_data->nrules + pass];
+
+ if ((rule & sort_forward) != 0)
+ {
+ /* Handle the pushed backward sequence. */
+ if (backw_start != NULL)
+ {
+ for (size_t i = backw_len; i > 0; )
+ {
+ int32_t weight_idx;
+ unsigned char rule_idx;
+ size_t len = find_idx (&backw_start, &weight_idx,
+ &rule_idx, l_data, pass);
+ if (needed + i < n)
+ for (size_t j = len; j > 0; j--)
+ dest[needed + i - j] =
+ l_data->weights[weight_idx++];
+
+ i -= len;
+ }
+
+ needed += backw_len;
+ backw_start = NULL;
+ backw_len = 0;
+ }
+
+ /* Now handle the forward element. */
+ if (needed + len < n)
+ while (len-- > 0)
+ dest[needed++] = l_data->weights[weight_idx++];
+ else
+ /* No more characters fit into the buffer. */
+ needed += len;
+ }
+ else
+ {
+ /* Remember start of the backward sequence & track length. */
+ if (backw_start == NULL)
+ backw_start = pos;
+ backw_len += len;
+ }
+ }
+
+
+ /* Handle the pushed backward sequence. */
+ if (backw_start != NULL)
+ {
+ for (size_t i = backw_len; i > 0; )
+ {
+ size_t len = find_idx (&backw_start, &weight_idx, &rule_idx,
+ l_data, pass);
+ if (needed + i < n)
+ for (size_t j = len; j > 0; j--)
+ dest[needed + i - j] =
+ l_data->weights[weight_idx++];
+
+ i -= len;
+ }
+
+ needed += backw_len;
+ }
+ }
+ else
+ {
+ int val = 1;
+#ifndef WIDE_CHAR_VERSION
+ char buf[7];
+ size_t buflen;
+#endif
+ size_t i;
+
+ while (*cur != L('\0'))
+ {
+ const USTRING_TYPE *pos = cur;
+ size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data,
+ pass);
+ int rule = l_data->rulesets[rule_idx * l_data->nrules + pass];
+
+ if ((rule & sort_forward) != 0)
+ {
+ /* Handle the pushed backward sequence. */
+ if (backw_start != NULL)
+ {
+ for (size_t p = backw_len; p > 0; p--)
+ {
+ size_t len;
+ int32_t weight_idx;
+ unsigned char rule_idx;
+ const USTRING_TYPE *backw_cur = backw_start;
+
+ /* To prevent a warning init the used vars. */
+ len = find_idx (&backw_cur, &weight_idx,
+ &rule_idx, l_data, pass);
+
+ for (i = 1; i < p; i++)
+ len = find_idx (&backw_cur, &weight_idx,
+ &rule_idx, l_data, pass);
+
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1 + len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += buflen + len;
+#endif
+ val = 1;
+ }
+ else
+ ++val;
+ }
+
+ backw_start = NULL;
+ backw_len = 0;
+ }
+
+ /* Now handle the forward element. */
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1 + len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += buflen + len;
+#endif
+ val = 1;
+ }
+ else
+ ++val;
+ }
+ else
+ {
+ /* Remember start of the backward sequence & track length. */
+ if (backw_start == NULL)
+ backw_start = pos;
+ backw_len++;
+ }
+ }
+
+ /* Handle the pushed backward sequence. */
+ if (backw_start != NULL)
+ {
+ for (size_t p = backw_len; p > 0; p--)
+ {
+ size_t len;
+ int32_t weight_idx;
+ unsigned char rule_idx;
+ const USTRING_TYPE *backw_cur = backw_start;
+
+ /* To prevent a warning init the used vars. */
+ len = find_idx (&backw_cur, &weight_idx,
+ &rule_idx, l_data, pass);
+
+ for (i = 1; i < p; i++)
+ len = find_idx (&backw_cur, &weight_idx,
+ &rule_idx, l_data, pass);
+
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1 + len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ l_data->weights[weight_idx + i];
+ }
+ needed += buflen + len;
+#endif
+ val = 1;
+ }
+ else
+ ++val;
+ }
+ }
+ }
+
+ /* Finally store the byte to separate the passes or terminate
+ the string. */
+ if (needed < n)
+ dest[needed] = pass + 1 < l_data->nrules ? L('\1') : L('\0');
+ ++needed;
+ }
+
+ /* This is a little optimization: many collation specifications have
+ a `position' rule at the end and if no non-ignored character
+ is found the last \1 byte is immediately followed by a \0 byte
+ signalling this. We can avoid the \1 byte(s). */
+ if (needed > 2 && needed == last_needed + 1)
+ {
+ /* Remove the \1 byte. */
+ if (--needed <= n)
+ dest[needed - 1] = L('\0');
+ }
+
+ /* Return the number of bytes/words we need, but don't count the NUL
+ byte/word at the end. */
+ return needed - 1;
+}
+
+/* Do the transformation using weight-index and rule cache. */
+static size_t
+do_xfrm_cached (STRING_TYPE *dest, size_t n, const locale_data_t *l_data,
+ size_t idxmax, int32_t *idxarr, const unsigned char *rulearr)
+{
+ uint_fast32_t nrules = l_data->nrules;
+ unsigned char *rulesets = l_data->rulesets;
+ USTRING_TYPE *weights = l_data->weights;
+ uint_fast32_t pass;
+ size_t needed = 0;
+ size_t last_needed;
+ size_t idxcnt;
+
+ /* Now the passes over the weights. */
+ for (pass = 0; pass < nrules; ++pass)
+ {
+ size_t backw_stop = ~0ul;
+ int rule = rulesets[rulearr[0] * nrules + pass];
+ /* We assume that if a rule has defined `position' in one section
+ this is true for all of them. */
+ int position = rule & sort_position;
+
+ last_needed = needed;
+ if (position == 0)
+ {
+ for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
+ {
+ if ((rule & sort_forward) != 0)
+ {
+ size_t len;
+
+ if (backw_stop != ~0ul)
+ {
+ /* Handle the pushed elements now. */
+ size_t backw;
+
+ for (backw = idxcnt; backw > backw_stop; )
+ {
+ --backw;
+ len = weights[idxarr[backw]++];
+
+ if (needed + len < n)
+ while (len-- > 0)
+ dest[needed++] = weights[idxarr[backw]++];
+ else
+ {
+ /* No more characters fit into the buffer. */
+ needed += len;
+ idxarr[backw] += len;
+ }
+ }
+
+ backw_stop = ~0ul;
+ }
+
+ /* Now handle the forward element. */
+ len = weights[idxarr[idxcnt]++];
+ if (needed + len < n)
+ while (len-- > 0)
+ dest[needed++] = weights[idxarr[idxcnt]++];
+ else
+ {
+ /* No more characters fit into the buffer. */
+ needed += len;
+ idxarr[idxcnt] += len;
+ }
+ }
+ else
+ {
+ /* Remember where the backwards series started. */
+ if (backw_stop == ~0ul)
+ backw_stop = idxcnt;
+ }
+
+ rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
+ }
+
+
+ if (backw_stop != ~0ul)
+ {
+ /* Handle the pushed elements now. */
+ size_t backw;
+
+ backw = idxcnt;
+ while (backw > backw_stop)
+ {
+ size_t len = weights[idxarr[--backw]++];
+
+ if (needed + len < n)
+ while (len-- > 0)
+ dest[needed++] = weights[idxarr[backw]++];
+ else
+ {
+ /* No more characters fit into the buffer. */
+ needed += len;
+ idxarr[backw] += len;
+ }
+ }
+ }
+ }
+ else
+ {
+ int val = 1;
+#ifndef WIDE_CHAR_VERSION
+ char buf[7];
+ size_t buflen;
+#endif
+ size_t i;
+
+ for (idxcnt = 0; idxcnt < idxmax; ++idxcnt)
+ {
+ if ((rule & sort_forward) != 0)
+ {
+ size_t len;
+
+ if (backw_stop != ~0ul)
+ {
+ /* Handle the pushed elements now. */
+ size_t backw;
+
+ for (backw = idxcnt; backw > backw_stop; )
+ {
+ --backw;
+ len = weights[idxarr[backw]++];
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1 + len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ weights[idxarr[backw] + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ weights[idxarr[backw] + i];
+ }
+ needed += buflen + len;
+#endif
+ idxarr[backw] += len;
+ val = 1;
+ }
+ else
+ ++val;
+ }
+
+ backw_stop = ~0ul;
+ }
+
+ /* Now handle the forward element. */
+ len = weights[idxarr[idxcnt]++];
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1+ len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ weights[idxarr[idxcnt] + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ weights[idxarr[idxcnt] + i];
+ }
+ needed += buflen + len;
+#endif
+ idxarr[idxcnt] += len;
+ val = 1;
+ }
+ else
+ /* Note that we don't have to increment `idxarr[idxcnt]'
+ since the length is zero. */
+ ++val;
+ }
+ else
+ {
+ /* Remember where the backwards series started. */
+ if (backw_stop == ~0ul)
+ backw_stop = idxcnt;
+ }
+
+ rule = rulesets[rulearr[idxcnt + 1] * nrules + pass];
+ }
+
+ if (backw_stop != ~0ul)
+ {
+ /* Handle the pushed elements now. */
+ size_t backw;
+
+ backw = idxmax - 1;
+ while (backw > backw_stop)
+ {
+ size_t len = weights[idxarr[--backw]++];
+ if (len != 0)
+ {
+#ifdef WIDE_CHAR_VERSION
+ if (needed + 1 + len < n)
+ {
+ dest[needed] = val;
+ for (i = 0; i < len; ++i)
+ dest[needed + 1 + i] =
+ weights[idxarr[backw] + i];
+ }
+ needed += 1 + len;
+#else
+ buflen = utf8_encode (buf, val);
+ if (needed + buflen + len < n)
+ {
+ for (i = 0; i < buflen; ++i)
+ dest[needed + i] = buf[i];
+ for (i = 0; i < len; ++i)
+ dest[needed + buflen + i] =
+ weights[idxarr[backw] + i];
+ }
+ needed += buflen + len;
+#endif
+ idxarr[backw] += len;
+ val = 1;
+ }
+ else
+ ++val;
+ }
+ }
+ }
+
+ /* Finally store the byte to separate the passes or terminate
+ the string. */
+ if (needed < n)
+ dest[needed] = pass + 1 < nrules ? L('\1') : L('\0');
+ ++needed;
+ }
+
+ /* This is a little optimization: many collation specifications have
+ a `position' rule at the end and if no non-ignored character
+ is found the last \1 byte is immediately followed by a \0 byte
+ signalling this. We can avoid the \1 byte(s). */
+ if (needed > 2 && needed == last_needed + 1)
+ {
+ /* Remove the \1 byte. */
+ if (--needed <= n)
+ dest[needed - 1] = L('\0');
+ }
+
+ /* Return the number of bytes/words we need, but don't count the NUL
+ byte/word at the end. */
+ return needed - 1;
+}
+
+size_t
+STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
+{
+ locale_data_t l_data;
+ struct __locale_data *current = l->__locales[LC_COLLATE];
+ l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
+
+ /* Handle byte comparison case. */
+ if (l_data.nrules == 0)
+ {
+ size_t srclen = STRLEN (src);
+
+ if (n != 0)
+ STPNCPY (dest, src, MIN (srclen + 1, n));
+
+ return srclen;
+ }
+
+ /* Handle an empty string, code hereafter relies on strlen (src) > 0. */
+ if (*src == L('\0'))
+ {
+ if (n != 0)
+ *dest = L('\0');
+ return 0;
+ }
+
+ /* Get the locale data. */
+ l_data.rulesets = (unsigned char *)
+ current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
+ l_data.table = (int32_t *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
+ l_data.weights = (USTRING_TYPE *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
+ l_data.extra = (USTRING_TYPE *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
+ l_data.indirect = (int32_t *)
+ current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
+
+ assert (((uintptr_t) l_data.table) % __alignof__ (l_data.table[0]) == 0);
+ assert (((uintptr_t) l_data.weights) % __alignof__ (l_data.weights[0]) == 0);
+ assert (((uintptr_t) l_data.extra) % __alignof__ (l_data.extra[0]) == 0);
+ assert (((uintptr_t) l_data.indirect) % __alignof__ (l_data.indirect[0]) == 0);
+
+ /* We need the elements of the string as unsigned values since they
+ are used as indeces. */
+ const USTRING_TYPE *usrc = (const USTRING_TYPE *) src;
+
+ /* Allocate cache for small strings on the stack and fill it with weight and
+ rule indices. If the cache size is not sufficient, continue with the
+ uncached xfrm version. */
+ size_t idxmax = 0;
+ const USTRING_TYPE *cur = usrc;
+ int32_t *idxarr = alloca (SMALL_STR_SIZE * sizeof (int32_t));
+ unsigned char *rulearr = alloca (SMALL_STR_SIZE + 1);
+
+ do
+ {
+ int32_t tmp = findidx (l_data.table, l_data.indirect, l_data.extra, &cur,
+ -1);
+ rulearr[idxmax] = tmp >> 24;
+ idxarr[idxmax] = tmp & 0xffffff;
+
+ ++idxmax;
+ }
+ while (*cur != L('\0') && idxmax < SMALL_STR_SIZE);
+
+ /* This element is only read, the value never used but to determine
+ another value which then is ignored. */
+ rulearr[idxmax] = '\0';
+
+ /* Do the transformation. */
+ if (*cur == L('\0'))
+ return do_xfrm_cached (dest, n, &l_data, idxmax, idxarr, rulearr);
+ else
+ return do_xfrm (usrc, dest, n, &l_data);
+}
+libc_hidden_def (STRXFRM)
+
+#ifndef WIDE_CHAR_VERSION
+weak_alias (__strxfrm_l, strxfrm_l)
+#endif
diff --git a/REORG.TODO/string/swab.c b/REORG.TODO/string/swab.c
new file mode 100644
index 0000000000..bcdf6595b6
--- /dev/null
+++ b/REORG.TODO/string/swab.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1992-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+void
+swab (const void *bfrom, void *bto, ssize_t n)
+{
+ const char *from = (const char *) bfrom;
+ char *to = (char *) bto;
+
+ n &= ~((ssize_t) 1);
+ while (n > 1)
+ {
+ const char b0 = from[--n], b1 = from[--n];
+ to[n] = b0;
+ to[n + 1] = b1;
+ }
+}
diff --git a/REORG.TODO/string/test-bcopy.c b/REORG.TODO/string/test-bcopy.c
new file mode 100644
index 0000000000..11acf07b79
--- /dev/null
+++ b/REORG.TODO/string/test-bcopy.c
@@ -0,0 +1,20 @@
+/* Test and measure bcopy functions.
+ Copyright (C) 2012-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_BCOPY
+#include "test-memmove.c"
diff --git a/REORG.TODO/string/test-bzero.c b/REORG.TODO/string/test-bzero.c
new file mode 100644
index 0000000000..a24c448804
--- /dev/null
+++ b/REORG.TODO/string/test-bzero.c
@@ -0,0 +1,19 @@
+/* Test and measure bzero functions.
+ Copyright (C) 2012-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+#define TEST_BZERO
+#include "test-memset.c"
diff --git a/REORG.TODO/string/test-endian-types.c b/REORG.TODO/string/test-endian-types.c
new file mode 100644
index 0000000000..86a89324f7
--- /dev/null
+++ b/REORG.TODO/string/test-endian-types.c
@@ -0,0 +1,49 @@
+/* Test endian.h endian-conversion macros always return the correct type.
+ Copyright (C) 2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <endian.h>
+#include <stdint.h>
+
+int i;
+uint16_t u16;
+uint32_t u32;
+uint64_t u64;
+
+int
+do_test (void)
+{
+ /* This is a compilation test. */
+ extern __typeof (htobe16 (i)) u16;
+ extern __typeof (htole16 (i)) u16;
+ extern __typeof (be16toh (i)) u16;
+ extern __typeof (le16toh (i)) u16;
+ extern __typeof (htobe32 (i)) u32;
+ extern __typeof (htole32 (i)) u32;
+ extern __typeof (be32toh (i)) u32;
+ extern __typeof (le32toh (i)) u32;
+ extern __typeof (htobe64 (i)) u64;
+ extern __typeof (htole64 (i)) u64;
+ extern __typeof (be64toh (i)) u64;
+ extern __typeof (le64toh (i)) u64;
+ (void) u16;
+ (void) u32;
+ (void) u64;
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-explicit_bzero.c b/REORG.TODO/string/test-explicit_bzero.c
new file mode 100644
index 0000000000..7e41163eb1
--- /dev/null
+++ b/REORG.TODO/string/test-explicit_bzero.c
@@ -0,0 +1,20 @@
+/* Test and measure explicit_bzero.
+ Copyright (C) 2016-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+#define TEST_EXPLICIT_BZERO
+#define TEST_BZERO
+#include "test-memset.c"
diff --git a/REORG.TODO/string/test-ffs.c b/REORG.TODO/string/test-ffs.c
new file mode 100644
index 0000000000..11b6ea838b
--- /dev/null
+++ b/REORG.TODO/string/test-ffs.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
+ On-Line Applications Research Corporation.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ int failures = 0;
+ int i;
+
+ auto void try (const char *name, long long int param, int value,
+ int expected);
+
+ void try (const char *name, long long int param, int value, int expected)
+ {
+ if (value != expected)
+ {
+ printf ("%s(%#llx) expected %d got %d\n",
+ name, param, expected, value);
+ ++failures;
+ }
+ else
+ printf ("%s(%#llx) as expected %d\n", name, param, value);
+ }
+
+#define TEST(fct, type) \
+ try (#fct, 0, fct ((type) 0), 0); \
+ for (i=0 ; i < 8 * sizeof (type); i++) \
+ try (#fct, 1ll << i, fct (((type) 1) << i), i + 1); \
+ for (i=0 ; i < 8 * sizeof (type) ; i++) \
+ try (#fct, (~((type) 0) >> i) << i, fct ((~((type) 0) >> i) << i), i + 1);\
+ try (#fct, 0x80008000, fct ((type) 0x80008000), 16)
+
+ TEST (ffs, int);
+ TEST (ffsl, long int);
+ TEST (ffsll, long long int);
+
+ if (failures)
+ printf ("Test FAILED! %d failure%s.\n", failures, &"s"[failures == 1]);
+ else
+ puts ("Test succeeded.");
+
+ return failures;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memccpy.c b/REORG.TODO/string/test-memccpy.c
new file mode 100644
index 0000000000..7bd67a61e7
--- /dev/null
+++ b/REORG.TODO/string/test-memccpy.c
@@ -0,0 +1,269 @@
+/* Test and measure memccpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define TEST_NAME "memccpy"
+#include "test-string.h"
+
+void *simple_memccpy (void *, const void *, int, size_t);
+void *stupid_memccpy (void *, const void *, int, size_t);
+
+IMPL (stupid_memccpy, 0)
+IMPL (simple_memccpy, 0)
+IMPL (memccpy, 1)
+
+void *
+simple_memccpy (void *dst, const void *src, int c, size_t n)
+{
+ const char *s = src;
+ char *d = dst;
+
+ while (n-- > 0)
+ if ((*d++ = *s++) == (char) c)
+ return d;
+
+ return NULL;
+}
+
+void *
+stupid_memccpy (void *dst, const void *src, int c, size_t n)
+{
+ void *p = memchr (src, c, n);
+
+ if (p != NULL)
+ return mempcpy (dst, src, p - src + 1);
+
+ memcpy (dst, src, n);
+ return NULL;
+}
+
+typedef void *(*proto_t) (void *, const void *, int c, size_t);
+
+static void
+do_one_test (impl_t *impl, void *dst, const void *src, int c, size_t len,
+ size_t n)
+{
+ void *expect = len > n ? NULL : (char *) dst + len;
+ if (CALL (impl, dst, src, c, n) != expect)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ CALL (impl, dst, src, c, n), expect);
+ ret = 1;
+ return;
+ }
+
+ if (memcmp (dst, src, len > n ? n : len) != 0)
+ {
+ error (0, 0, "Wrong result in function %s", impl->name);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, int c, size_t len, size_t n,
+ int max_char)
+{
+ size_t i;
+ char *s1, *s2;
+
+ align1 &= 7;
+ if (align1 + len >= page_size)
+ return;
+
+ align2 &= 7;
+ if (align2 + len >= page_size)
+ return;
+
+ s1 = (char *) (buf1 + align1);
+ s2 = (char *) (buf2 + align2);
+
+ for (i = 0; i < len - 1; ++i)
+ {
+ s1[i] = 32 + 23 * i % (max_char - 32);
+ if (s1[i] == (char) c)
+ --s1[i];
+ }
+ s1[len - 1] = c;
+ for (i = len; i + align1 < page_size && i < len + 64; ++i)
+ s1[i] = 32 + 32 * i % (max_char - 32);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s2, s1, c, len, n);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len, size, mode;
+ unsigned char *p1 = buf1 + page_size - 512;
+ unsigned char *p2 = buf2 + page_size - 512;
+ unsigned char *res, c;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ mode = random ();
+ c = random ();
+ if (mode & 1)
+ {
+ size = random () & 255;
+ align1 = 512 - size - (random () & 15);
+ if (mode & 2)
+ align2 = align1 - (random () & 24);
+ else
+ align2 = align1 - (random () & 31);
+ if (mode & 4)
+ {
+ j = align1;
+ align1 = align2;
+ align2 = j;
+ }
+ if (mode & 8)
+ len = size - (random () & 31);
+ else
+ len = 512;
+ if (len >= 512)
+ len = random () & 511;
+ }
+ else
+ {
+ align1 = random () & 31;
+ if (mode & 2)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ len = random () & 511;
+ j = align1;
+ if (align2 > j)
+ j = align2;
+ if (mode & 4)
+ {
+ size = random () & 511;
+ if (size + j > 512)
+ size = 512 - j - (random() & 31);
+ }
+ else
+ size = 512 - j;
+ if ((mode & 8) && len + j >= 512)
+ len = 512 - j - (random () & 7);
+ }
+ j = len + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align1)
+ p1[i] = c;
+ else
+ {
+ p1[i] = random () & 255;
+ if (i >= align1 && i < len + align1 && p1[i] == c)
+ p1[i] = (random () & 127) + 3 + c;
+ }
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ unsigned char *expect;
+ memset (p2 - 64, '\1', 512 + 64);
+ res = CALL (impl, p2 + align2, p1 + align1, (char) c, size);
+ if (len >= size)
+ expect = NULL;
+ else
+ expect = p2 + align2 + len + 1;
+
+ if (res != expect)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %d) %p != %p",
+ n, impl->name, align1, align2, len, size, c, res, expect);
+ ret = 1;
+ }
+ for (j = 0; j < align2 + 64; ++j)
+ {
+ if (p2[j - 64] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ j = align2 + len + 1;
+ if (size + align2 < j)
+ j = size + align2;
+ for (; j < 512; ++j)
+ {
+ if (p2[j] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ j = len + 1;
+ if (size < j)
+ j = size;
+ if (memcmp (p1 + align1, p2 + align2, j))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%28s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, i, 12, 16, 16, 127);
+ do_test (i, i, 23, 16, 16, 255);
+ do_test (i, 2 * i, 28, 16, 16, 127);
+ do_test (2 * i, i, 31, 16, 16, 255);
+ do_test (8 - i, 2 * i, 1, 1 << i, 2 << i, 127);
+ do_test (2 * i, 8 - i, 17, 2 << i, 1 << i, 127);
+ do_test (8 - i, 2 * i, 0, 1 << i, 2 << i, 255);
+ do_test (2 * i, 8 - i, i, 2 << i, 1 << i, 255);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, i, 4 << i, 8 << i, 127);
+ do_test (0, 0, i, 16 << i, 8 << i, 127);
+ do_test (8 - i, 2 * i, i, 4 << i, 8 << i, 127);
+ do_test (8 - i, 2 * i, i, 16 << i, 8 << i, 127);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memchr.c b/REORG.TODO/string/test-memchr.c
new file mode 100644
index 0000000000..73a93f0fc9
--- /dev/null
+++ b/REORG.TODO/string/test-memchr.c
@@ -0,0 +1,227 @@
+/* Test memchr functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "memchr"
+#else
+# define TEST_NAME "wmemchr"
+#endif /* WIDE */
+
+#include "test-string.h"
+#include <stdint.h>
+
+#ifndef WIDE
+# define MEMCHR memchr
+# define CHAR char
+# define UCHAR unsigned char
+# define SIMPLE_MEMCHR simple_memchr
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#else
+# include <wchar.h>
+# define MEMCHR wmemchr
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define SIMPLE_MEMCHR simple_wmemchr
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#endif /* WIDE */
+
+typedef CHAR *(*proto_t) (const CHAR *, int, size_t);
+CHAR *SIMPLE_MEMCHR (const CHAR *, int, size_t);
+
+IMPL (SIMPLE_MEMCHR, 0)
+IMPL (MEMCHR, 1)
+
+CHAR *
+SIMPLE_MEMCHR (const CHAR *s, int c, size_t n)
+{
+ while (n--)
+ if (*s++ == (CHAR) c)
+ return (CHAR *) s - 1;
+ return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, int c, size_t n, CHAR *exp_res)
+{
+ CHAR *res = CALL (impl, s, c, n);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, size_t n, int seek_char)
+{
+ size_t i;
+ CHAR *result;
+
+ if ((align + len) * sizeof (CHAR) >= page_size)
+ return;
+
+ CHAR *buf = (CHAR *) (buf1);
+
+ for (i = 0; i < len; ++i)
+ {
+ buf[align + i] = 1 + 23 * i % SMALL_CHAR;
+ if (buf[align + i] == seek_char)
+ buf[align + i] = seek_char + 1;
+ }
+ buf[align + len] = 0;
+
+ if (pos < len)
+ {
+ buf[align + pos] = seek_char;
+ buf[align + len] = -seek_char;
+ result = (CHAR *) (buf + align + pos);
+ }
+ else
+ {
+ result = NULL;
+ buf[align + len] = seek_char;
+ }
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (CHAR *) (buf + align), seek_char, n, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len;
+ int seek_char;
+ CHAR *result;
+ UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ pos = random () & 511;
+ if (pos + align >= 512)
+ pos = 511 - align - (random () & 7);
+ len = random () & 511;
+ if (pos >= len)
+ len = pos + (random () & 7);
+ if (len + align >= 512)
+ len = 512 - align - (random () & 7);
+ seek_char = random () & BIG_CHAR;
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == pos + align)
+ p[i] = seek_char;
+ else
+ {
+ p[i] = random () & BIG_CHAR;
+ if (i < pos + align && p[i] == seek_char)
+ p[i] = seek_char + 13;
+ }
+ }
+
+ if (pos < len)
+ {
+ size_t r = random ();
+ if ((r & 31) == 0)
+ len = ~(uintptr_t) (p + align) - ((r >> 5) & 31);
+ result = (CHAR *) (p + pos + align);
+ }
+ else
+ result = NULL;
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align), seek_char, len) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+ n, impl->name, align, seek_char, len, pos,
+ CALL (impl, (CHAR *) (p + align), seek_char, len),
+ result, p);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i, j;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ /* Test n == 0. */
+ do_test (i, i, 0, 0, 23);
+ do_test (i, i, 0, 0, 0);
+
+ do_test (0, 16 << i, 2048, 2048, 23);
+ do_test (i, 64, 256, 256, 23);
+ do_test (0, 16 << i, 2048, 2048, 0);
+ do_test (i, 64, 256, 256, 0);
+
+ /* Check for large input sizes and for these cases we need to
+ make sure the byte is within the size range (that's why
+ 7 << i must be smaller than 2048). */
+ do_test (0, 7 << i, 2048, SIZE_MAX, 23);
+ do_test (0, 2048 - i, 2048, SIZE_MAX, 23);
+ do_test (i, 64, 256, SIZE_MAX, 23);
+ do_test (0, 7 << i, 2048, SIZE_MAX, 0);
+ do_test (0, 2048 - i, 2048, SIZE_MAX, 0);
+ do_test (i, 64, 256, SIZE_MAX, 0);
+ }
+
+ for (i = 1; i < 64; ++i)
+ {
+ for (j = 1; j < 64; j++)
+ {
+ do_test (0, 64 - j, 64, SIZE_MAX, 23);
+ do_test (i, 64 - j, 64, SIZE_MAX, 23);
+ }
+ }
+
+ for (i = 1; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, i + 1, 23);
+ do_test (0, i, i + 1, i + 1, 0);
+ }
+
+ /* BZ#21182 - wrong overflow calculation for i686 implementation
+ with address near end of the page. */
+ for (i = 2; i < 16; ++i)
+ /* page_size is in fact getpagesize() * 2. */
+ do_test (page_size / 2 - i, i, i, 1, 0x9B);
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memcmp.c b/REORG.TODO/string/test-memcmp.c
new file mode 100644
index 0000000000..a7969edaea
--- /dev/null
+++ b/REORG.TODO/string/test-memcmp.c
@@ -0,0 +1,525 @@
+/* Test and measure memcmp functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wmemcmp support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wmemcmp"
+#else
+# define TEST_NAME "memcmp"
+#endif
+#include "test-string.h"
+#ifdef WIDE
+# include <inttypes.h>
+# include <wchar.h>
+
+# define MEMCMP wmemcmp
+# define MEMCPY wmemcpy
+# define SIMPLE_MEMCMP simple_wmemcmp
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define CHARBYTES 4
+# define CHAR__MIN WCHAR_MIN
+# define CHAR__MAX WCHAR_MAX
+int
+simple_wmemcmp (const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ int ret = 0;
+ /* Warning!
+ wmemcmp has to use SIGNED comparison for elements.
+ memcmp has to use UNSIGNED comparison for elemnts.
+ */
+ while (n-- && (ret = *s1 < *s2 ? -1 : *s1 == *s2 ? 0 : 1) == 0) {s1++; s2++;}
+ return ret;
+}
+#else
+# include <limits.h>
+
+# define MEMCMP memcmp
+# define MEMCPY memcpy
+# define SIMPLE_MEMCMP simple_memcmp
+# define CHAR char
+# define MAX_CHAR 255
+# define UCHAR unsigned char
+# define CHARBYTES 1
+# define CHAR__MIN CHAR_MIN
+# define CHAR__MAX CHAR_MAX
+
+int
+simple_memcmp (const char *s1, const char *s2, size_t n)
+{
+ int ret = 0;
+
+ while (n-- && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0);
+ return ret;
+}
+#endif
+
+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
+
+IMPL (SIMPLE_MEMCMP, 0)
+IMPL (MEMCMP, 1)
+
+static int
+check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len,
+ int exp_result)
+{
+ int result = CALL (impl, s1, s2, len);
+ if ((exp_result == 0 && result != 0)
+ || (exp_result < 0 && result >= 0)
+ || (exp_result > 0 && result <= 0))
+ {
+ error (0, 0, "Wrong result in function %s %d %d", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len,
+ int exp_result)
+{
+ if (check_result (impl, s1, s2, len, exp_result) < 0)
+ return;
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, int exp_result)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+ if (len == 0)
+ return;
+
+ align1 &= 63;
+ if (align1 + (len + 1) * CHARBYTES >= page_size)
+ return;
+
+ align2 &= 63;
+ if (align2 + (len + 1) * CHARBYTES >= page_size)
+ return;
+
+ s1 = (CHAR *) (buf1 + align1);
+ s2 = (CHAR *) (buf2 + align2);
+
+ for (i = 0; i < len; i++)
+ s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % CHAR__MAX;
+
+ s1[len] = align1;
+ s2[len] = align2;
+ s2[len - 1] -= exp_result;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, len, exp_result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, pos, len;
+ int result;
+ long r;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ pos = random () & 511;
+ j = align1;
+ if (align2 > j)
+ j = align2;
+ if (pos + j >= 512)
+ pos = 511 - j - (random () & 7);
+ len = random () & 511;
+ if (len + j >= 512)
+ len = 511 - j - (random () & 7);
+ j = len + align1 + 64;
+ if (j > 512) j = 512;
+ for (i = 0; i < j; ++i)
+ p1[i] = random () & 255;
+ for (i = 0; i < j; ++i)
+ p2[i] = random () & 255;
+
+ result = 0;
+ if (pos >= len)
+ MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, len);
+ else
+ {
+ MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, pos);
+ if (p2[align2 + pos] == p1[align1 + pos])
+ {
+ p2[align2 + pos] = random () & 255;
+ if (p2[align2 + pos] == p1[align1 + pos])
+ p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
+ }
+
+ if (p1[align1 + pos] < p2[align2 + pos])
+ result = -1;
+ else
+ result = 1;
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ r = CALL (impl, (CHAR *) p1 + align1, (const CHAR *) p2 + align2,
+ len);
+ if ((r == 0 && result)
+ || (r < 0 && result >= 0)
+ || (r > 0 && result <= 0))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
+ n, impl->name, align1 * CHARBYTES & 63, align2 * CHARBYTES & 63, len, pos, r, result, p1, p2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+static void
+check1 (void)
+{
+ CHAR s1[116], s2[116];
+ int n, exp_result;
+
+ s1[0] = -108;
+ s2[0] = -108;
+ s1[1] = 99;
+ s2[1] = 99;
+ s1[2] = -113;
+ s2[2] = -113;
+ s1[3] = 1;
+ s2[3] = 1;
+ s1[4] = 116;
+ s2[4] = 116;
+ s1[5] = 99;
+ s2[5] = 99;
+ s1[6] = -113;
+ s2[6] = -113;
+ s1[7] = 1;
+ s2[7] = 1;
+ s1[8] = 84;
+ s2[8] = 84;
+ s1[9] = 99;
+ s2[9] = 99;
+ s1[10] = -113;
+ s2[10] = -113;
+ s1[11] = 1;
+ s2[11] = 1;
+ s1[12] = 52;
+ s2[12] = 52;
+ s1[13] = 99;
+ s2[13] = 99;
+ s1[14] = -113;
+ s2[14] = -113;
+ s1[15] = 1;
+ s2[15] = 1;
+ s1[16] = -76;
+ s2[16] = -76;
+ s1[17] = -14;
+ s2[17] = -14;
+ s1[18] = -109;
+ s2[18] = -109;
+ s1[19] = 1;
+ s2[19] = 1;
+ s1[20] = -108;
+ s2[20] = -108;
+ s1[21] = -14;
+ s2[21] = -14;
+ s1[22] = -109;
+ s2[22] = -109;
+ s1[23] = 1;
+ s2[23] = 1;
+ s1[24] = 84;
+ s2[24] = 84;
+ s1[25] = -15;
+ s2[25] = -15;
+ s1[26] = -109;
+ s2[26] = -109;
+ s1[27] = 1;
+ s2[27] = 1;
+ s1[28] = 52;
+ s2[28] = 52;
+ s1[29] = -15;
+ s2[29] = -15;
+ s1[30] = -109;
+ s2[30] = -109;
+ s1[31] = 1;
+ s2[31] = 1;
+ s1[32] = 20;
+ s2[32] = 20;
+ s1[33] = -15;
+ s2[33] = -15;
+ s1[34] = -109;
+ s2[34] = -109;
+ s1[35] = 1;
+ s2[35] = 1;
+ s1[36] = 20;
+ s2[36] = 20;
+ s1[37] = -14;
+ s2[37] = -14;
+ s1[38] = -109;
+ s2[38] = -109;
+ s1[39] = 1;
+ s2[39] = 1;
+ s1[40] = 52;
+ s2[40] = 52;
+ s1[41] = -14;
+ s2[41] = -14;
+ s1[42] = -109;
+ s2[42] = -109;
+ s1[43] = 1;
+ s2[43] = 1;
+ s1[44] = 84;
+ s2[44] = 84;
+ s1[45] = -14;
+ s2[45] = -14;
+ s1[46] = -109;
+ s2[46] = -109;
+ s1[47] = 1;
+ s2[47] = 1;
+ s1[48] = 116;
+ s2[48] = 116;
+ s1[49] = -14;
+ s2[49] = -14;
+ s1[50] = -109;
+ s2[50] = -109;
+ s1[51] = 1;
+ s2[51] = 1;
+ s1[52] = 116;
+ s2[52] = 116;
+ s1[53] = -15;
+ s2[53] = -15;
+ s1[54] = -109;
+ s2[54] = -109;
+ s1[55] = 1;
+ s2[55] = 1;
+ s1[56] = -44;
+ s2[56] = -44;
+ s1[57] = -14;
+ s2[57] = -14;
+ s1[58] = -109;
+ s2[58] = -109;
+ s1[59] = 1;
+ s2[59] = 1;
+ s1[60] = -108;
+ s2[60] = -108;
+ s1[61] = -15;
+ s2[61] = -15;
+ s1[62] = -109;
+ s2[62] = -109;
+ s1[63] = 1;
+ s2[63] = 1;
+ s1[64] = -76;
+ s2[64] = -76;
+ s1[65] = -15;
+ s2[65] = -15;
+ s1[66] = -109;
+ s2[66] = -109;
+ s1[67] = 1;
+ s2[67] = 1;
+ s1[68] = -44;
+ s2[68] = -44;
+ s1[69] = -15;
+ s2[69] = -15;
+ s1[70] = -109;
+ s2[70] = -109;
+ s1[71] = 1;
+ s2[71] = 1;
+ s1[72] = -12;
+ s2[72] = -12;
+ s1[73] = -15;
+ s2[73] = -15;
+ s1[74] = -109;
+ s2[74] = -109;
+ s1[75] = 1;
+ s2[75] = 1;
+ s1[76] = -12;
+ s2[76] = -12;
+ s1[77] = -14;
+ s2[77] = -14;
+ s1[78] = -109;
+ s2[78] = -109;
+ s1[79] = 1;
+ s2[79] = 1;
+ s1[80] = 20;
+ s2[80] = -68;
+ s1[81] = -12;
+ s2[81] = 64;
+ s1[82] = -109;
+ s2[82] = -106;
+ s1[83] = 1;
+ s2[83] = 1;
+ s1[84] = -12;
+ s2[84] = -12;
+ s1[85] = -13;
+ s2[85] = -13;
+ s1[86] = -109;
+ s2[86] = -109;
+ s1[87] = 1;
+ s2[87] = 1;
+ s1[88] = -44;
+ s2[88] = -44;
+ s1[89] = -13;
+ s2[89] = -13;
+ s1[90] = -109;
+ s2[90] = -109;
+ s1[91] = 1;
+ s2[91] = 1;
+ s1[92] = -76;
+ s2[92] = -76;
+ s1[93] = -13;
+ s2[93] = -13;
+ s1[94] = -109;
+ s2[94] = -109;
+ s1[95] = 1;
+ s2[95] = 1;
+ s1[96] = -108;
+ s2[96] = -108;
+ s1[97] = -13;
+ s2[97] = -13;
+ s1[98] = -109;
+ s2[98] = -109;
+ s1[99] = 1;
+ s2[99] = 1;
+ s1[100] = 116;
+ s2[100] = 116;
+ s1[101] = CHAR__MIN;
+ s2[101] = CHAR__MAX;
+ s1[102] = -109;
+ s2[102] = -109;
+ s1[103] = 1;
+ s2[103] = 1;
+ s1[104] = 84;
+ s2[104] = 84;
+ s1[105] = -13;
+ s2[105] = -13;
+ s1[106] = -109;
+ s2[106] = -109;
+ s1[107] = 1;
+ s2[107] = 1;
+ s1[108] = 52;
+ s2[108] = 52;
+ s1[109] = -13;
+ s2[109] = -13;
+ s1[110] = -109;
+ s2[110] = -109;
+ s1[111] = 1;
+ s2[111] = 1;
+ s1[112] = CHAR__MAX;
+ s2[112] = CHAR__MIN;
+ s1[113] = -13;
+ s2[113] = -13;
+ s1[114] = -109;
+ s2[114] = -109;
+ s1[115] = 1;
+ s2[115] = 1;
+
+ n = 116;
+ for (size_t i = 0; i < n; i++)
+ {
+ exp_result = SIMPLE_MEMCMP (s1 + i, s2 + i, n - i);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1 + i, s2 + i, n - i, exp_result);
+ }
+}
+
+/* This test checks that memcmp doesn't overrun buffers. */
+static void
+check2 (void)
+{
+ size_t max_length = page_size / sizeof (CHAR);
+
+ /* Initialize buf2 to the same values as buf1. The bug requires the
+ last compared byte to be different. */
+ memcpy (buf2, buf1, page_size);
+ ((char *) buf2)[page_size - 1] ^= 0x11;
+
+ for (size_t length = 1; length < max_length; length++)
+ {
+ CHAR *s1 = (CHAR *) buf1 + max_length - length;
+ CHAR *s2 = (CHAR *) buf2 + max_length - length;
+
+ const int exp_result = SIMPLE_MEMCMP (s1, s2, length);
+
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, length, exp_result);
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ check1 ();
+ check2 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 16; ++i)
+ {
+ do_test (i * CHARBYTES, i * CHARBYTES, i, 0);
+ do_test (i * CHARBYTES, i * CHARBYTES, i, 1);
+ do_test (i * CHARBYTES, i * CHARBYTES, i, -1);
+ }
+
+ for (i = 0; i < 16; ++i)
+ {
+ do_test (0, 0, i, 0);
+ do_test (0, 0, i, 1);
+ do_test (0, 0, i, -1);
+ }
+
+ for (i = 1; i < 10; ++i)
+ {
+ do_test (0, 0, 2 << i, 0);
+ do_test (0, 0, 2 << i, 1);
+ do_test (0, 0, 2 << i, -1);
+ do_test (0, 0, 16 << i, 0);
+ do_test ((8 - i) * CHARBYTES, (2 * i) * CHARBYTES, 16 << i, 0);
+ do_test (0, 0, 16 << i, 1);
+ do_test (0, 0, 16 << i, -1);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 0);
+ do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 1);
+ do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, -1);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memcpy.c b/REORG.TODO/string/test-memcpy.c
new file mode 100644
index 0000000000..49f0a76047
--- /dev/null
+++ b/REORG.TODO/string/test-memcpy.c
@@ -0,0 +1,259 @@
+/* Test and measure memcpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef MEMCPY_RESULT
+# define MEMCPY_RESULT(dst, len) dst
+# define MIN_PAGE_SIZE 131072
+# define TEST_MAIN
+# define TEST_NAME "memcpy"
+# include "test-string.h"
+
+char *simple_memcpy (char *, const char *, size_t);
+char *builtin_memcpy (char *, const char *, size_t);
+
+IMPL (simple_memcpy, 0)
+IMPL (builtin_memcpy, 0)
+IMPL (memcpy, 1)
+
+char *
+simple_memcpy (char *dst, const char *src, size_t n)
+{
+ char *ret = dst;
+ while (n--)
+ *dst++ = *src++;
+ return ret;
+}
+
+char *
+builtin_memcpy (char *dst, const char *src, size_t n)
+{
+ return __builtin_memcpy (dst, src, n);
+}
+#endif
+
+typedef char *(*proto_t) (char *, const char *, size_t);
+
+static void
+do_one_test (impl_t *impl, char *dst, const char *src,
+ size_t len)
+{
+ size_t i;
+
+ /* Must clear the destination buffer set by the previous run. */
+ for (i = 0; i < len; i++)
+ dst[i] = 0;
+
+ if (CALL (impl, dst, src, len) != MEMCPY_RESULT (dst, len))
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ CALL (impl, dst, src, len), MEMCPY_RESULT (dst, len));
+ ret = 1;
+ return;
+ }
+
+ if (memcmp (dst, src, len) != 0)
+ {
+ error (0, 0, "Wrong result in function %s dst %p \"%.*s\" src %p \"%.*s\" len %zu",
+ impl->name, dst, (int) len, dst, src, (int) len, src, len);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len)
+{
+ size_t i, j;
+ char *s1, *s2;
+
+ align1 &= 63;
+ if (align1 + len >= page_size)
+ return;
+
+ align2 &= 63;
+ if (align2 + len >= page_size)
+ return;
+
+ s1 = (char *) (buf1 + align1);
+ s2 = (char *) (buf2 + align2);
+
+ for (i = 0, j = 1; i < len; i++, j += 23)
+ s1[i] = j;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s2, s1, len);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len, size1, size2, size;
+ int c;
+ unsigned char *p1, *p2;
+ unsigned char *res;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ if (n == 0)
+ {
+ len = getpagesize ();
+ size = len + 512;
+ size1 = size;
+ size2 = size;
+ align1 = 512;
+ align2 = 512;
+ }
+ else
+ {
+ if ((random () & 255) == 0)
+ size = 65536;
+ else
+ size = 768;
+ if (size > page_size)
+ size = page_size;
+ size1 = size;
+ size2 = size;
+ i = random ();
+ if (i & 3)
+ size -= 256;
+ if (i & 1)
+ size1 -= 256;
+ if (i & 2)
+ size2 -= 256;
+ if (i & 4)
+ {
+ len = random () % size;
+ align1 = size1 - len - (random () & 31);
+ align2 = size2 - len - (random () & 31);
+ if (align1 > size1)
+ align1 = 0;
+ if (align2 > size2)
+ align2 = 0;
+ }
+ else
+ {
+ align1 = random () & 63;
+ align2 = random () & 63;
+ len = random () % size;
+ if (align1 + len > size1)
+ align1 = size1 - len;
+ if (align2 + len > size2)
+ align2 = size2 - len;
+ }
+ }
+ p1 = buf1 + page_size - size1;
+ p2 = buf2 + page_size - size2;
+ c = random () & 255;
+ j = align1 + len + 256;
+ if (j > size1)
+ j = size1;
+ for (i = 0; i < j; ++i)
+ p1[i] = random () & 255;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ j = align2 + len + 256;
+ if (j > size2)
+ j = size2;
+ memset (p2, c, j);
+ res = (unsigned char *) CALL (impl,
+ (char *) (p2 + align2),
+ (char *) (p1 + align1), len);
+ if (res != MEMCPY_RESULT (p2 + align2, len))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
+ n, impl->name, align1, align2, len, res,
+ MEMCPY_RESULT (p2 + align2, len));
+ ret = 1;
+ }
+ for (i = 0; i < align2; ++i)
+ {
+ if (p2[i] != c)
+ {
+ error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ for (i = align2 + len; i < j; ++i)
+ {
+ if (p2[i] != c)
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ if (memcmp (p1 + align1, p2 + align2, len))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 18; ++i)
+ {
+ do_test (0, 0, 1 << i);
+ do_test (i, 0, 1 << i);
+ do_test (0, i, 1 << i);
+ do_test (i, i, 1 << i);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, 0, i);
+ do_test (i, 0, i);
+ do_test (0, i, i);
+ do_test (i, i, i);
+ }
+
+ for (i = 3; i < 32; ++i)
+ {
+ if ((i & (i - 1)) == 0)
+ continue;
+ do_test (0, 0, 16 * i);
+ do_test (i, 0, 16 * i);
+ do_test (0, i, 16 * i);
+ do_test (i, i, 16 * i);
+ }
+
+ do_test (0, 0, getpagesize ());
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memmem.c b/REORG.TODO/string/test-memmem.c
new file mode 100644
index 0000000000..82fd93ccde
--- /dev/null
+++ b/REORG.TODO/string/test-memmem.c
@@ -0,0 +1,184 @@
+/* Test and measure memmem functions.
+ Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2008.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define TEST_NAME "memmem"
+#define BUF1PAGES 20
+#define ITERATIONS 500
+#include "test-string.h"
+
+typedef char *(*proto_t) (const void *, size_t, const void *, size_t);
+void *simple_memmem (const void *, size_t, const void *, size_t);
+
+IMPL (simple_memmem, 0)
+IMPL (memmem, 1)
+
+void *
+simple_memmem (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 (__glibc_unlikely (haystack_len < needle_len))
+ 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;
+}
+
+static int
+check_result (impl_t *impl, const void *haystack, size_t haystack_len,
+ const void *needle, size_t needle_len, const void *expected)
+{
+ void *res;
+
+ res = CALL (impl, haystack, haystack_len, needle, needle_len);
+ if (res != expected)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, expected);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const void *haystack, size_t haystack_len,
+ const void *needle, size_t needle_len, const void *expected)
+{
+ if (check_result (impl, haystack, haystack_len, needle, needle_len,
+ expected) < 0)
+ return;
+}
+
+static void
+do_test (const char *str, size_t len, size_t idx)
+{
+ char tmpbuf[len];
+
+ memcpy (tmpbuf, buf1 + idx, len);
+ memcpy (buf1 + idx, str, len);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, buf1, BUF1PAGES * page_size, str, len, buf1 + idx);
+
+ memcpy (buf1 + idx, tmpbuf, len);
+}
+
+static void
+do_random_tests (void)
+{
+ for (size_t n = 0; n < ITERATIONS; ++n)
+ {
+ char tmpbuf[32];
+
+ size_t shift = random () % 11;
+ size_t rel = random () % ((2 << (shift + 1)) * 64);
+ size_t idx = MIN ((2 << shift) * 64 + rel, BUF1PAGES * page_size - 2);
+ size_t len = random () % (sizeof (tmpbuf) - 1) + 1;
+ len = MIN (len, BUF1PAGES * page_size - idx - 1);
+ memcpy (tmpbuf, buf1 + idx, len);
+ for (size_t i = random () % len / 2 + 1; i > 0; --i)
+ {
+ size_t off = random () % len;
+ char ch = '0' + random () % 10;
+
+ buf1[idx + off] = ch;
+ }
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, buf1, BUF1PAGES * page_size, buf1 + idx, len,
+ buf1 + idx);
+
+ memcpy (buf1 + idx, tmpbuf, len);
+ }
+}
+
+static void
+check1 (void)
+{
+
+ const char search_buf_data[5] = { 0x56, 0x34, 0x12, 0x78, 0x78 };
+ const char pattern[2] = { 0x78, 0x56 };
+ void *search_buf = (void *) buf1 + page_size - sizeof search_buf_data;
+ void *exp_result;
+
+ memcpy (search_buf, search_buf_data, sizeof search_buf_data);
+ exp_result = simple_memmem (search_buf, sizeof search_buf_data,
+ pattern, sizeof pattern);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, search_buf, sizeof search_buf_data,
+ pattern, sizeof pattern, exp_result);
+}
+
+static const char *const strs[] =
+ {
+ "00000", "00112233", "0123456789", "0000111100001111",
+ "00000111110000022222", "012345678901234567890",
+ "abc0", "aaaa0", "abcabc0"
+ };
+
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ check1 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < BUF1PAGES * page_size; ++i)
+ buf1[i] = 60 + random () % 32;
+
+ for (i = 0; i < sizeof (strs) / sizeof (strs[0]); ++i)
+ for (size_t j = 0; j < 120; j += 7)
+ {
+ size_t len = strlen (strs[i]);
+
+ do_test (strs[i], len, j);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memmove.c b/REORG.TODO/string/test-memmove.c
new file mode 100644
index 0000000000..51f79f6eb4
--- /dev/null
+++ b/REORG.TODO/string/test-memmove.c
@@ -0,0 +1,290 @@
+/* Test and measure memmove functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef TEST_BCOPY
+# define TEST_NAME "bcopy"
+#else
+# define TEST_NAME "memmove"
+#endif
+#include "test-string.h"
+
+char *simple_memmove (char *, const char *, size_t);
+
+#ifdef TEST_BCOPY
+typedef void (*proto_t) (const char *, char *, size_t);
+void simple_bcopy (const char *, char *, size_t);
+
+IMPL (simple_bcopy, 0)
+IMPL (bcopy, 1)
+
+void
+simple_bcopy (const char *src, char *dst, size_t n)
+{
+ simple_memmove (dst, src, n);
+}
+#else
+typedef char *(*proto_t) (char *, const char *, size_t);
+
+IMPL (simple_memmove, 0)
+IMPL (memmove, 1)
+#endif
+
+char *
+inhibit_loop_to_libcall
+simple_memmove (char *dst, const char *src, size_t n)
+{
+ char *ret = dst;
+ if (src < dst)
+ {
+ dst += n;
+ src += n;
+ while (n--)
+ *--dst = *--src;
+ }
+ else
+ while (n--)
+ *dst++ = *src++;
+ return ret;
+}
+
+static void
+do_one_test (impl_t *impl, char *dst, char *src, const char *orig_src,
+ size_t len)
+{
+ /* This also clears the destination buffer set by the previous run. */
+ memcpy (src, orig_src, len);
+#ifdef TEST_BCOPY
+ CALL (impl, src, dst, len);
+#else
+ char *res;
+
+ res = CALL (impl, dst, src, len);
+ if (res != dst)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, dst);
+ ret = 1;
+ return;
+ }
+#endif
+
+ if (memcmp (dst, orig_src, len) != 0)
+ {
+ error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"",
+ impl->name, dst, src);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len)
+{
+ size_t i, j;
+ char *s1, *s2;
+
+ align1 &= 63;
+ if (align1 + len >= page_size)
+ return;
+
+ align2 &= 63;
+ if (align2 + len >= page_size)
+ return;
+
+ s1 = (char *) (buf1 + align1);
+ s2 = (char *) (buf2 + align2);
+
+ for (i = 0, j = 1; i < len; i++, j += 23)
+ s1[i] = j;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s2, (char *) (buf2 + align1), s1, len);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, n, align1, align2, len, size;
+ size_t srcstart, srcend, dststart, dstend;
+ int c;
+ unsigned char *p1, *p2;
+#ifndef TEST_BCOPY
+ unsigned char *res;
+#endif
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ if ((random () & 255) == 0)
+ size = 65536;
+ else
+ size = 512;
+ if (size > page_size)
+ size = page_size;
+ if ((random () & 3) == 0)
+ {
+ len = random () & (size - 1);
+ align1 = size - len - (random () & 31);
+ align2 = size - len - (random () & 31);
+ if (align1 > size)
+ align1 = 0;
+ if (align2 > size)
+ align2 = 0;
+ }
+ else
+ {
+ align1 = random () & (size / 2 - 1);
+ align2 = random () & (size / 2 - 1);
+ len = random () & (size - 1);
+ if (align1 + len > size)
+ align1 = size - len;
+ if (align2 + len > size)
+ align2 = size - len;
+ }
+
+ p1 = buf1 + page_size - size;
+ p2 = buf2 + page_size - size;
+ c = random () & 255;
+ srcend = align1 + len + 256;
+ if (srcend > size)
+ srcend = size;
+ if (align1 > 256)
+ srcstart = align1 - 256;
+ else
+ srcstart = 0;
+ for (i = srcstart; i < srcend; ++i)
+ p1[i] = random () & 255;
+ dstend = align2 + len + 256;
+ if (dstend > size)
+ dstend = size;
+ if (align2 > 256)
+ dststart = align2 - 256;
+ else
+ dststart = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ memset (p2 + dststart, c, dstend - dststart);
+ memcpy (p2 + srcstart, p1 + srcstart, srcend - srcstart);
+#ifdef TEST_BCOPY
+ CALL (impl, (char *) (p2 + align1), (char *) (p2 + align2), len);
+#else
+ res = (unsigned char *) CALL (impl,
+ (char *) (p2 + align2),
+ (char *) (p2 + align1), len);
+ if (res != p2 + align2)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
+ n, impl->name, align1, align2, len, res, p2 + align2);
+ ret = 1;
+ }
+#endif
+ if (memcmp (p1 + align1, p2 + align2, len))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ }
+ for (i = dststart; i < dstend; ++i)
+ {
+ if (i >= align2 && i < align2 + len)
+ {
+ i = align2 + len - 1;
+ continue;
+ }
+ if (i >= srcstart && i < srcend)
+ {
+ i = srcend - 1;
+ continue;
+ }
+ if (p2[i] != c)
+ {
+ error (0, 0, "Iteration %zd - garbage in memset area, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+
+ if (srcstart < align2
+ && memcmp (p2 + srcstart, p1 + srcstart,
+ (srcend > align2 ? align2 : srcend) - srcstart))
+ {
+ error (0, 0, "Iteration %zd - garbage before dst, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+
+ i = srcstart > align2 + len ? srcstart : align2 + len;
+ if (srcend > align2 + len
+ && memcmp (p2 + i, p1 + i, srcend - i))
+ {
+ error (0, 0, "Iteration %zd - garbage after dst, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 14; ++i)
+ {
+ do_test (0, 32, 1 << i);
+ do_test (32, 0, 1 << i);
+ do_test (0, i, 1 << i);
+ do_test (i, 0, 1 << i);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, 32, i);
+ do_test (32, 0, i);
+ do_test (0, i, i);
+ do_test (i, 0, i);
+ }
+
+ for (i = 3; i < 32; ++i)
+ {
+ if ((i & (i - 1)) == 0)
+ continue;
+ do_test (0, 32, 16 * i);
+ do_test (32, 0, 16 * i);
+ do_test (0, i, 16 * i);
+ do_test (i, 0, 16 * i);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-mempcpy.c b/REORG.TODO/string/test-mempcpy.c
new file mode 100644
index 0000000000..364a811c62
--- /dev/null
+++ b/REORG.TODO/string/test-mempcpy.c
@@ -0,0 +1,38 @@
+/* Test and measure mempcpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define MEMCPY_RESULT(dst, len) (dst) + (len)
+#define TEST_MAIN
+#define TEST_NAME "mempcpy"
+#include "test-string.h"
+
+char *simple_mempcpy (char *, const char *, size_t);
+
+IMPL (simple_mempcpy, 0)
+IMPL (mempcpy, 1)
+
+char *
+simple_mempcpy (char *dst, const char *src, size_t n)
+{
+ while (n--)
+ *dst++ = *src++;
+ return dst;
+}
+
+#include "test-memcpy.c"
diff --git a/REORG.TODO/string/test-memrchr.c b/REORG.TODO/string/test-memrchr.c
new file mode 100644
index 0000000000..15483f5cb5
--- /dev/null
+++ b/REORG.TODO/string/test-memrchr.c
@@ -0,0 +1,186 @@
+/* Test and measure memrchr functions.
+ Copyright (C) 2013-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define TEST_NAME "memrchr"
+#include "test-string.h"
+
+typedef char *(*proto_t) (const char *, int, size_t);
+char *simple_memrchr (const char *, int, size_t);
+
+IMPL (simple_memrchr, 0)
+IMPL (memrchr, 1)
+
+char *
+simple_memrchr (const char *s, int c, size_t n)
+{
+ s = s + n;
+ while (n--)
+ if (*--s == (char) c)
+ return (char *) s;
+ return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res)
+{
+ char *res = CALL (impl, s, c, n);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char)
+{
+ size_t i;
+ char *result;
+
+ align &= 7;
+ if (align + len >= page_size)
+ return;
+
+ for (i = 0; i < len; ++i)
+ {
+ buf1[align + i] = 1 + 23 * i % 127;
+ if (buf1[align + i] == seek_char)
+ buf1[align + i] = seek_char + 1;
+ }
+ buf1[align + len] = 0;
+
+ if (pos < len)
+ {
+ buf1[align + pos] = seek_char;
+ buf1[align + len] = -seek_char;
+ result = (char *) (buf1 + align + pos);
+ }
+ else
+ {
+ result = NULL;
+ buf1[align + len] = seek_char;
+ }
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (char *) (buf1 + align), seek_char, len, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len;
+ int seek_char;
+ char *result;
+ unsigned char *p = buf1 + page_size - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ pos = random () & 511;
+ if (pos + align >= 512)
+ pos = 511 - align - (random () & 7);
+ len = random () & 511;
+ if (pos >= len)
+ len = pos + (random () & 7);
+ if (len + align >= 512)
+ len = 512 - align - (random () & 7);
+ seek_char = random () & 255;
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == pos + align)
+ p[i] = seek_char;
+ else
+ {
+ p[i] = random () & 255;
+ if (p[i] == seek_char)
+ p[i] = seek_char + 13;
+ }
+ }
+
+ if (pos < len)
+ result = (char *) (p + pos + align);
+ else
+ result = NULL;
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (char *) (p + align), seek_char, len) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+ n, impl->name, align, seek_char, len, pos,
+ CALL (impl, (char *) (p + align), seek_char, len),
+ result, p);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ /* Test len == 0. */
+ do_test (i, i, 0, 0);
+ do_test (i, i, 0, 23);
+
+ do_test (0, 16 << i, 2048, 23);
+ do_test (i, 64, 256, 23);
+ do_test (0, 16 << i, 2048, 0);
+ do_test (i, 64, 256, 0);
+
+ do_test (0, i, 256, 23);
+ do_test (0, i, 256, 0);
+ do_test (i, i, 256, 23);
+ do_test (i, i, 256, 0);
+
+ }
+ for (i = 1; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, 23);
+ do_test (0, i, i + 1, 0);
+ do_test (i, i, i + 1, 23);
+ do_test (i, i, i + 1, 0);
+
+ do_test (0, 1, i + 1, 23);
+ do_test (0, 2, i + 1, 0);
+ do_test (i, 1, i + 1, 23);
+ do_test (i, 2, i + 1, 0);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-memset.c b/REORG.TODO/string/test-memset.c
new file mode 100644
index 0000000000..ca1bfe1e3b
--- /dev/null
+++ b/REORG.TODO/string/test-memset.c
@@ -0,0 +1,267 @@
+/* Test memset functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef TEST_BZERO
+# ifdef TEST_EXPLICIT_BZERO
+# define TEST_NAME "explicit_bzero"
+# else
+# define TEST_NAME "bzero"
+# endif
+#else
+# ifndef WIDE
+# define TEST_NAME "memset"
+# else
+# define TEST_NAME "wmemset"
+# endif /* WIDE */
+#endif /* !TEST_BZERO */
+#define MIN_PAGE_SIZE 131072
+#include "test-string.h"
+
+#ifndef WIDE
+# define MEMSET memset
+# define CHAR char
+# define UCHAR unsigned char
+# define SIMPLE_MEMSET simple_memset
+# define MEMCMP memcmp
+# define BIG_CHAR CHAR_MAX
+#else
+# include <wchar.h>
+# define MEMSET wmemset
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define SIMPLE_MEMSET simple_wmemset
+# define MEMCMP wmemcmp
+# define BIG_CHAR WCHAR_MAX
+#endif /* WIDE */
+
+CHAR *SIMPLE_MEMSET (CHAR *, int, size_t);
+
+#ifdef TEST_BZERO
+typedef void (*proto_t) (char *, size_t);
+void simple_bzero (char *, size_t);
+void builtin_bzero (char *, size_t);
+
+IMPL (simple_bzero, 0)
+IMPL (builtin_bzero, 0)
+#ifdef TEST_EXPLICIT_BZERO
+IMPL (explicit_bzero, 1)
+#else
+IMPL (bzero, 1)
+#endif
+
+void
+simple_bzero (char *s, size_t n)
+{
+ SIMPLE_MEMSET (s, 0, n);
+}
+
+void
+builtin_bzero (char *s, size_t n)
+{
+ __builtin_bzero (s, n);
+}
+#else
+typedef CHAR *(*proto_t) (CHAR *, int, size_t);
+
+IMPL (SIMPLE_MEMSET, 0)
+# ifndef WIDE
+char *builtin_memset (char *, int, size_t);
+IMPL (builtin_memset, 0)
+# endif /* !WIDE */
+IMPL (MEMSET, 1)
+
+# ifndef WIDE
+char *
+builtin_memset (char *s, int c, size_t n)
+{
+ return __builtin_memset (s, c, n);
+}
+# endif /* !WIDE */
+#endif /* !TEST_BZERO */
+
+CHAR *
+inhibit_loop_to_libcall
+SIMPLE_MEMSET (CHAR *s, int c, size_t n)
+{
+ CHAR *r = s, *end = s + n;
+ while (r < end)
+ *r++ = c;
+ return s;
+}
+
+static void
+do_one_test (impl_t *impl, CHAR *s, int c __attribute ((unused)), size_t n)
+{
+ CHAR tstbuf[n];
+#ifdef TEST_BZERO
+ simple_bzero (tstbuf, n);
+ CALL (impl, s, n);
+ if (memcmp (s, tstbuf, n) != 0)
+#else
+ CHAR *res = CALL (impl, s, c, n);
+ if (res != s
+ || SIMPLE_MEMSET (tstbuf, c, n) != tstbuf
+ || MEMCMP (s, tstbuf, n) != 0)
+#endif /* !TEST_BZERO */
+ {
+ error (0, 0, "Wrong result in function %s", impl->name);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, int c, size_t len)
+{
+ align &= 7;
+ if ((align + len) * sizeof (CHAR) > page_size)
+ return;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (CHAR *) (buf1) + align, c, len);
+}
+
+#ifndef TEST_BZERO
+static void
+do_random_tests (void)
+{
+ size_t i, j, k, n, align, len, size;
+ int c, o;
+ UCHAR *p, *res;
+ UCHAR *p2 = (UCHAR *) buf2;
+
+ for (i = 0; i < 65536 / sizeof (CHAR); ++i)
+ p2[i] = random () & BIG_CHAR;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ if ((random () & 31) == 0)
+ size = 65536 / sizeof (CHAR);
+ else
+ size = 512;
+ p = (UCHAR *) (buf1 + page_size) - size;
+ len = random () & (size - 1);
+ align = size - len - (random () & 31);
+ if (align > size)
+ align = size - len;
+ if ((random () & 7) == 0)
+ align &= ~63;
+ if ((random () & 7) == 0)
+ c = 0;
+ else
+ c = random () & BIG_CHAR;
+ o = random () & BIG_CHAR;
+ if (o == c)
+ o = (c + 1) & BIG_CHAR;
+ j = len + align + 128;
+ if (j > size)
+ j = size;
+ if (align >= 128)
+ k = align - 128;
+ else
+ k = 0;
+ for (i = k; i < align; ++i)
+ p[i] = o;
+ for (i = align + len; i < j; ++i)
+ p[i] = o;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ for (i = 0; i < len; ++i)
+ {
+ p[i + align] = p2[i];
+ if (p[i + align] == c)
+ p[i + align] = o;
+ }
+ res = (UCHAR *) CALL (impl, (CHAR *) p + align, c, len);
+ if (res != p + align)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p",
+ n, impl->name, align, c, len, res, p + align);
+ ret = 1;
+ }
+ for (i = k; i < align; ++i)
+ if (p[i] != o)
+ {
+ error (0, 0, "Iteration %zd - garbage before %s (%zd, %d, %zd)",
+ n, impl->name, align, c, len);
+ ret = 1;
+ break;
+ }
+ for (; i < align + len; ++i)
+ if (p[i] != c)
+ {
+ error (0, 0, "Iteration %zd - not cleared correctly %s (%zd, %d, %zd)",
+ n, impl->name, align, c, len);
+ ret = 1;
+ break;
+ }
+ for (; i < j; ++i)
+ if (p[i] != o)
+ {
+ error (0, 0, "Iteration %zd - garbage after %s (%zd, %d, %zd)",
+ n, impl->name, align, c, len);
+ ret = 1;
+ break;
+ }
+ }
+ }
+}
+#endif /* !TEST_BZERO */
+
+int
+test_main (void)
+{
+ size_t i;
+ int c = 0;
+
+ test_init ();
+
+ printf ("%24s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+#ifndef TEST_BZERO
+ for (c = -65; c <= 130; c += 65)
+#endif
+ {
+ for (i = 0; i < 18; ++i)
+ do_test (0, c, 1 << i);
+ for (i = 1; i < 32; ++i)
+ {
+ do_test (i, c, i);
+ if (i & (i - 1))
+ do_test (0, c, i);
+ }
+ do_test (1, c, 14);
+ do_test (3, c, 1024);
+ do_test (4, c, 64);
+ do_test (2, c, 25);
+ }
+
+#ifndef TEST_BZERO
+ do_random_tests ();
+#endif
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-rawmemchr.c b/REORG.TODO/string/test-rawmemchr.c
new file mode 100644
index 0000000000..2a53e71026
--- /dev/null
+++ b/REORG.TODO/string/test-rawmemchr.c
@@ -0,0 +1,165 @@
+/* Test and measure memchr functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+
+#define TEST_MAIN
+#define TEST_NAME "rawmemchr"
+#include "test-string.h"
+
+typedef char *(*proto_t) (const char *, int);
+char *simple_rawmemchr (const char *, int);
+
+IMPL (simple_rawmemchr, 0)
+IMPL (rawmemchr, 1)
+
+char *
+simple_rawmemchr (const char *s, int c)
+{
+ while (1)
+ if (*s++ == (char) c)
+ return (char *) s - 1;
+ return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, int c, char *exp_res)
+{
+ char *res = CALL (impl, s, c);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char)
+{
+ size_t i;
+ char *result;
+
+ align &= 7;
+ if (align + len >= page_size)
+ return;
+
+ for (i = 0; i < len; ++i)
+ {
+ buf1[align + i] = 1 + 23 * i % 127;
+ if (buf1[align + i] == seek_char)
+ buf1[align + i] = seek_char + 1;
+ }
+ buf1[align + len] = 0;
+
+ assert (pos < len);
+
+ buf1[align + pos] = seek_char;
+ buf1[align + len] = -seek_char;
+ result = (char *) (buf1 + align + pos);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (char *) (buf1 + align), seek_char, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len;
+ int seek_char;
+ char *result;
+ unsigned char *p = buf1 + page_size - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ pos = random () & 511;
+ if (pos + align >= 512)
+ pos = 511 - align - (random () & 7);
+ len = random () & 511;
+ if (len + align >= 512)
+ len = 512 - align - (random () & 7);
+ if (pos >= len)
+ continue;
+ seek_char = random () & 255;
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == pos + align)
+ p[i] = seek_char;
+ else
+ {
+ p[i] = random () & 255;
+ if (i < pos + align && p[i] == seek_char)
+ p[i] = seek_char + 13;
+ }
+ }
+
+ assert (pos < len);
+ size_t r = random ();
+ if ((r & 31) == 0)
+ len = ~(uintptr_t) (p + align) - ((r >> 5) & 31);
+ result = (char *) (p + pos + align);
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (char *) (p + align), seek_char) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+ n, impl->name, align, seek_char, len, pos,
+ CALL (impl, (char *) (p + align), seek_char),
+ result, p);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 7; ++i)
+ {
+ do_test (0, 16 << i, 2048, 23);
+ do_test (i, 64, 256, 23);
+ do_test (0, 16 << i, 2048, 0);
+ do_test (i, 64, 256, 0);
+ }
+ for (i = 1; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, 23);
+ do_test (0, i, i + 1, 0);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-stpcpy.c b/REORG.TODO/string/test-stpcpy.c
new file mode 100644
index 0000000000..5e31abf962
--- /dev/null
+++ b/REORG.TODO/string/test-stpcpy.c
@@ -0,0 +1,52 @@
+/* Test stpcpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define STRCPY_RESULT(dst, len) ((dst) + (len))
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "stpcpy"
+#else
+# define TEST_NAME "wcpcpy"
+#endif /* !WIDE */
+#include "test-string.h"
+#ifndef WIDE
+# define CHAR char
+# define SIMPLE_STPCPY simple_stpcpy
+# define STPCPY stpcpy
+#else
+# include <wchar.h>
+# define CHAR wchar_t
+# define SIMPLE_STPCPY simple_wcpcpy
+# define STPCPY wcpcpy
+#endif /* !WIDE */
+
+CHAR *SIMPLE_STPCPY (CHAR *, const CHAR *);
+
+IMPL (SIMPLE_STPCPY, 0)
+IMPL (STPCPY, 1)
+
+CHAR *
+SIMPLE_STPCPY (CHAR *dst, const CHAR *src)
+{
+ while ((*dst++ = *src++) != '\0');
+ return dst - 1;
+}
+
+#undef CHAR
+#include "test-strcpy.c"
diff --git a/REORG.TODO/string/test-stpncpy.c b/REORG.TODO/string/test-stpncpy.c
new file mode 100644
index 0000000000..5b26ae5e4f
--- /dev/null
+++ b/REORG.TODO/string/test-stpncpy.c
@@ -0,0 +1,79 @@
+/* Test and measure stpncpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len)))
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "stpncpy"
+#else
+# define TEST_NAME "wcpncpy"
+#endif /* WIDE */
+#include "test-string.h"
+#ifndef WIDE
+# define CHAR char
+# define SIMPLE_STPNCPY simple_stpncpy
+# define STUPID_STPNCPY stupid_stpncpy
+# define STPNCPY stpncpy
+# define STRNLEN strnlen
+#else
+# include <wchar.h>
+# define CHAR wchar_t
+# define SIMPLE_STPNCPY simple_wcpncpy
+# define STUPID_STPNCPY stupid_wcpncpy
+# define STPNCPY wcpncpy
+# define STRNLEN wcsnlen
+#endif /* WIDE */
+
+CHAR *SIMPLE_STPNCPY (CHAR *, const CHAR *, size_t);
+CHAR *STUPID_STPNCPY (CHAR *, const CHAR *, size_t);
+
+IMPL (STUPID_STPNCPY, 0)
+IMPL (SIMPLE_STPNCPY, 0)
+IMPL (STPNCPY, 1)
+
+CHAR *
+SIMPLE_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
+{
+ while (n--)
+ if ((*dst++ = *src++) == '\0')
+ {
+ size_t i;
+
+ for (i = 0; i < n; ++i)
+ dst[i] = '\0';
+ return dst - 1;
+ }
+ return dst;
+}
+
+CHAR *
+STUPID_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
+{
+ size_t nc = STRNLEN (src, n);
+ size_t i;
+
+ for (i = 0; i < nc; ++i)
+ dst[i] = src[i];
+ for (; i < n; ++i)
+ dst[i] = '\0';
+ return dst + nc;
+}
+
+#undef CHAR
+#include "test-strncpy.c"
diff --git a/REORG.TODO/string/test-strcasecmp.c b/REORG.TODO/string/test-strcasecmp.c
new file mode 100644
index 0000000000..9c333f0072
--- /dev/null
+++ b/REORG.TODO/string/test-strcasecmp.c
@@ -0,0 +1,270 @@
+/* Test and measure strcasecmp functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <ctype.h>
+#define TEST_MAIN
+#define TEST_NAME "strcasecmp"
+#include "test-string.h"
+
+typedef int (*proto_t) (const char *, const char *);
+static int simple_strcasecmp (const char *, const char *);
+static int stupid_strcasecmp (const char *, const char *);
+
+IMPL (stupid_strcasecmp, 0)
+IMPL (simple_strcasecmp, 0)
+IMPL (strcasecmp, 1)
+
+static int
+simple_strcasecmp (const char *s1, const char *s2)
+{
+ int ret;
+
+ while ((ret = ((unsigned char) tolower (*s1)
+ - (unsigned char) tolower (*s2))) == 0
+ && *s1++)
+ ++s2;
+ return ret;
+}
+
+static int
+stupid_strcasecmp (const char *s1, const char *s2)
+{
+ size_t ns1 = strlen (s1) + 1, ns2 = strlen (s2) + 1;
+ size_t n = ns1 < ns2 ? ns1 : ns2;
+ int ret = 0;
+
+ while (n--)
+ {
+ if ((ret = ((unsigned char) tolower (*s1)
+ - (unsigned char) tolower (*s2))) != 0)
+ break;
+ ++s1;
+ ++s2;
+ }
+ return ret;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s1, const char *s2, int exp_result)
+{
+ int result = CALL (impl, s1, s2);
+ if ((exp_result == 0 && result != 0)
+ || (exp_result < 0 && result >= 0)
+ || (exp_result > 0 && result <= 0))
+ {
+ error (0, 0, "Wrong result in function %s %d %d", impl->name,
+ result, exp_result);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, int max_char,
+ int exp_result)
+{
+ size_t i;
+ char *s1, *s2;
+
+ if (len == 0)
+ return;
+
+ align1 &= 7;
+ if (align1 + len + 1 >= page_size)
+ return;
+
+ align2 &= 7;
+ if (align2 + len + 1 >= page_size)
+ return;
+
+ s1 = (char *) (buf1 + align1);
+ s2 = (char *) (buf2 + align2);
+
+ for (i = 0; i < len; i++)
+ {
+ s1[i] = toupper (1 + 23 * i % max_char);
+ s2[i] = tolower (s1[i]);
+ }
+
+ s1[len] = s2[len] = 0;
+ s1[len + 1] = 23;
+ s2[len + 1] = 24 + exp_result;
+ if ((s2[len - 1] == 'z' && exp_result == -1)
+ || (s2[len - 1] == 'a' && exp_result == 1))
+ s1[len - 1] += exp_result;
+ else
+ s2[len - 1] -= exp_result;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, exp_result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, pos, len1, len2;
+ int result;
+ long r;
+ unsigned char *p1 = buf1 + page_size - 512;
+ unsigned char *p2 = buf2 + page_size - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ pos = random () & 511;
+ j = align1 > align2 ? align1 : align2;
+ if (pos + j >= 511)
+ pos = 510 - j - (random () & 7);
+ len1 = random () & 511;
+ if (pos >= len1 && (random () & 1))
+ len1 = pos + (random () & 7);
+ if (len1 + j >= 512)
+ len1 = 511 - j - (random () & 7);
+ if (pos >= len1)
+ len2 = len1;
+ else
+ len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
+ j = (pos > len2 ? pos : len2) + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; ++i)
+ {
+ p1[i] = tolower (random () & 255);
+ if (i < len1 + align1 && !p1[i])
+ {
+ p1[i] = tolower (random () & 255);
+ if (!p1[i])
+ p1[i] = tolower (1 + (random () & 127));
+ }
+ }
+ for (i = 0; i < j; ++i)
+ {
+ p2[i] = toupper (random () & 255);
+ if (i < len2 + align2 && !p2[i])
+ {
+ p2[i] = toupper (random () & 255);
+ if (!p2[i])
+ toupper (p2[i] = 1 + (random () & 127));
+ }
+ }
+
+ result = 0;
+ memcpy (p2 + align2, p1 + align1, pos);
+ if (pos < len1)
+ {
+ if (tolower (p2[align2 + pos]) == p1[align1 + pos])
+ {
+ p2[align2 + pos] = toupper (random () & 255);
+ if (tolower (p2[align2 + pos]) == p1[align1 + pos])
+ p2[align2 + pos] = toupper (p1[align1 + pos]
+ + 3 + (random () & 127));
+ }
+
+ if (p1[align1 + pos] < tolower (p2[align2 + pos]))
+ result = -1;
+ else
+ result = 1;
+ }
+ p1[len1 + align1] = 0;
+ p2[len2 + align2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2));
+ /* Test whether on 64-bit architectures where ABI requires
+ callee to promote has the promotion been done. */
+ asm ("" : "=g" (r) : "0" (r));
+ if ((r == 0 && result)
+ || (r < 0 && result >= 0)
+ || (r > 0 && result <= 0))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
+ n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+static void
+test_locale (const char *locale)
+{
+ size_t i;
+
+ if (setlocale (LC_CTYPE, locale) == NULL)
+ {
+ error (0, 0, "cannot set locale \"%s\"", locale);
+ ret = 1;
+ }
+
+ printf ("%-23s", locale);
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 16; ++i)
+ {
+ do_test (i, i, i, 127, 0);
+ do_test (i, i, i, 127, 1);
+ do_test (i, i, i, 127, -1);
+ }
+
+ for (i = 1; i < 10; ++i)
+ {
+ do_test (0, 0, 2 << i, 127, 0);
+ do_test (0, 0, 2 << i, 254, 0);
+ do_test (0, 0, 2 << i, 127, 1);
+ do_test (0, 0, 2 << i, 254, 1);
+ do_test (0, 0, 2 << i, 127, -1);
+ do_test (0, 0, 2 << i, 254, -1);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 2 * i, 8 << i, 127, 0);
+ do_test (2 * i, i, 8 << i, 254, 0);
+ do_test (i, 2 * i, 8 << i, 127, 1);
+ do_test (2 * i, i, 8 << i, 254, 1);
+ do_test (i, 2 * i, 8 << i, 127, -1);
+ do_test (2 * i, i, 8 << i, 254, -1);
+ }
+
+ do_random_tests ();
+}
+
+int
+test_main (void)
+{
+ test_init ();
+
+ test_locale ("C");
+ test_locale ("en_US.ISO-8859-1");
+ test_locale ("en_US.UTF-8");
+ test_locale ("tr_TR.ISO-8859-9");
+ test_locale ("tr_TR.UTF-8");
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strcasestr.c b/REORG.TODO/string/test-strcasestr.c
new file mode 100644
index 0000000000..abb3916732
--- /dev/null
+++ b/REORG.TODO/string/test-strcasestr.c
@@ -0,0 +1,194 @@
+/* Test and measure strcasestr functions.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2010.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define TEST_NAME "strcasestr"
+#include "test-string.h"
+
+
+#define STRCASESTR simple_strcasestr
+#define NO_ALIAS
+#define __strncasecmp strncasecmp
+#include "strcasestr.c"
+
+
+static char *
+stupid_strcasestr (const char *s1, const char *s2)
+{
+ ssize_t s1len = strlen (s1);
+ ssize_t s2len = strlen (s2);
+
+ if (s2len > s1len)
+ return NULL;
+
+ for (ssize_t i = 0; i <= s1len - s2len; ++i)
+ {
+ size_t j;
+ for (j = 0; j < s2len; ++j)
+ if (tolower (s1[i + j]) != tolower (s2[j]))
+ break;
+ if (j == s2len)
+ return (char *) s1 + i;
+ }
+
+ return NULL;
+}
+
+
+typedef char *(*proto_t) (const char *, const char *);
+
+IMPL (stupid_strcasestr, 0)
+IMPL (simple_strcasestr, 0)
+IMPL (strcasestr, 1)
+
+
+static int
+check_result (impl_t *impl, const char *s1, const char *s2,
+ char *exp_result)
+{
+ char *result = CALL (impl, s1, s2);
+ if (result != exp_result)
+ {
+ error (0, 0, "Wrong result in function %s %s %s", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result)
+{
+ if (check_result (impl, s1, s2, exp_result) < 0)
+ return;
+}
+
+
+static void
+do_test (size_t align1, size_t align2, size_t len1, size_t len2,
+ int fail)
+{
+ char *s1 = (char *) (buf1 + align1);
+ char *s2 = (char *) (buf2 + align2);
+
+ static const char d[] = "1234567890abcxyz";
+#define dl (sizeof (d) - 1)
+ char *ss2 = s2;
+ for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0)
+ {
+ size_t t = l > dl ? dl : l;
+ ss2 = mempcpy (ss2, d, t);
+ }
+ s2[len2] = '\0';
+
+ if (fail)
+ {
+ char *ss1 = s1;
+ for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0)
+ {
+ size_t t = l > dl ? dl : l;
+ memcpy (ss1, d, t);
+ ++ss1[len2 > 7 ? 7 : len2 - 1];
+ ss1 += t;
+ }
+ }
+ else
+ {
+ memset (s1, '0', len1);
+ for (size_t i = 0; i < len2; ++i)
+ s1[len1 - len2 + i] = toupper (s2[i]);
+ }
+ s1[len1] = '\0';
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2);
+}
+
+static void
+check1 (void)
+{
+ const char s1[] = "AOKB";
+ const char s2[] = "OK";
+ char *exp_result;
+
+ exp_result = stupid_strcasestr (s1, s2);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, exp_result);
+}
+
+static int
+test_main (void)
+{
+ test_init ();
+
+ check1 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (size_t klen = 2; klen < 32; ++klen)
+ for (size_t hlen = 2 * klen; hlen < 16 * klen; hlen += klen)
+ {
+ do_test (0, 0, hlen, klen, 0);
+ do_test (0, 0, hlen, klen, 1);
+ do_test (0, 3, hlen, klen, 0);
+ do_test (0, 3, hlen, klen, 1);
+ do_test (0, 9, hlen, klen, 0);
+ do_test (0, 9, hlen, klen, 1);
+ do_test (0, 15, hlen, klen, 0);
+ do_test (0, 15, hlen, klen, 1);
+
+ do_test (3, 0, hlen, klen, 0);
+ do_test (3, 0, hlen, klen, 1);
+ do_test (3, 3, hlen, klen, 0);
+ do_test (3, 3, hlen, klen, 1);
+ do_test (3, 9, hlen, klen, 0);
+ do_test (3, 9, hlen, klen, 1);
+ do_test (3, 15, hlen, klen, 0);
+ do_test (3, 15, hlen, klen, 1);
+
+ do_test (9, 0, hlen, klen, 0);
+ do_test (9, 0, hlen, klen, 1);
+ do_test (9, 3, hlen, klen, 0);
+ do_test (9, 3, hlen, klen, 1);
+ do_test (9, 9, hlen, klen, 0);
+ do_test (9, 9, hlen, klen, 1);
+ do_test (9, 15, hlen, klen, 0);
+ do_test (9, 15, hlen, klen, 1);
+
+ do_test (15, 0, hlen, klen, 0);
+ do_test (15, 0, hlen, klen, 1);
+ do_test (15, 3, hlen, klen, 0);
+ do_test (15, 3, hlen, klen, 1);
+ do_test (15, 9, hlen, klen, 0);
+ do_test (15, 9, hlen, klen, 1);
+ do_test (15, 15, hlen, klen, 0);
+ do_test (15, 15, hlen, klen, 1);
+ }
+
+ do_test (0, 0, page_size - 1, 16, 0);
+ do_test (0, 0, page_size - 1, 16, 1);
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strcat.c b/REORG.TODO/string/test-strcat.c
new file mode 100644
index 0000000000..01d180eb50
--- /dev/null
+++ b/REORG.TODO/string/test-strcat.c
@@ -0,0 +1,272 @@
+/* Test strcat functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strcat"
+#else
+# define TEST_NAME "wcscat"
+#endif /* WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRCAT strcat
+# define CHAR char
+# define UCHAR unsigned char
+# define sfmt "s"
+# define SIMPLE_STRCAT simple_strcat
+# define STRLEN strlen
+# define STRCMP strcmp
+# define MEMSET memset
+# define MEMCPY memcpy
+# define MEMCMP memcmp
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#else
+# include <wchar.h>
+# define STRCAT wcscat
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define sfmt "ls"
+# define SIMPLE_STRCAT simple_wcscat
+# define STRLEN wcslen
+# define STRCMP wcscmp
+# define MEMSET wmemset
+# define MEMCPY wmemcpy
+# define MEMCMP wmemcmp
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#endif /* WIDE */
+
+typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
+CHAR *SIMPLE_STRCAT (CHAR *, const CHAR *);
+
+IMPL (SIMPLE_STRCAT, 0)
+IMPL (STRCAT, 1)
+
+CHAR *
+SIMPLE_STRCAT (CHAR *dst, const CHAR *src)
+{
+ CHAR *ret = dst;
+ while (*dst++ != '\0');
+ --dst;
+ while ((*dst++ = *src++) != '\0');
+ return ret;
+}
+
+static void
+do_one_test (impl_t *impl, CHAR *dst, const CHAR *src)
+{
+ size_t k = STRLEN (dst);
+ if (CALL (impl, dst, src) != dst)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ CALL (impl, dst, src), dst);
+ ret = 1;
+ return;
+ }
+
+ if (STRCMP (dst + k, src) != 0)
+ {
+ error (0, 0, "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"",
+ impl->name, dst, src);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len1, size_t len2, int max_char)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+ align1 &= 7;
+ if ((align1 + len1) * sizeof (CHAR) >= page_size)
+ return;
+
+ align2 &= 7;
+ if ((align2 + len1 + len2) * sizeof (CHAR) >= page_size)
+ return;
+
+ s1 = (CHAR *) (buf1) + align1;
+ s2 = (CHAR *) (buf2) + align2;
+
+ for (i = 0; i < len1; ++i)
+ s1[i] = 32 + 23 * i % (max_char - 32);
+ s1[len1] = '\0';
+
+ for (i = 0; i < len2; i++)
+ s2[i] = 32 + 23 * i % (max_char - 32);
+
+ FOR_EACH_IMPL (impl, 0)
+ {
+ s2[len2] = '\0';
+ do_one_test (impl, s2, s1);
+ }
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len1, len2;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
+ UCHAR *p3 = (UCHAR *) buf1;
+ UCHAR *res;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ len1 = random () & 511;
+ if (len1 + align2 > 512)
+ len2 = random () & 7;
+ else
+ len2 = (512 - len1 - align2) * (random () & (1024 * 1024 - 1))
+ / (1024 * 1024);
+ j = align1;
+ if (align2 + len2 > j)
+ j = align2 + len2;
+ if (len1 + j >= 511)
+ len1 = 510 - j - (random () & 7);
+ if (len1 >= 512)
+ len1 = 0;
+ if (align1 + len1 < 512 - 8)
+ {
+ j = 510 - align1 - len1 - (random () & 31);
+ if (j > 0 && j < 512)
+ align1 += j;
+ }
+ j = len1 + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; i++)
+ {
+ if (i == len1 + align1)
+ p1[i] = 0;
+ else
+ {
+ p1[i] = random () & BIG_CHAR;
+ if (i >= align1 && i < len1 + align1 && !p1[i])
+ p1[i] = (random () & SMALL_CHAR) + 3;
+ }
+ }
+ for (i = 0; i < len2; i++)
+ {
+ p3[i] = random () & BIG_CHAR;
+ if (!p3[i])
+ p3[i] = (random () & SMALL_CHAR) + 3;
+ }
+ p3[len2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ MEMSET (p2 - 64, '\1', align2 + 64);
+ MEMSET (p2 + align2 + len2 + 1, '\1', 512 - align2 - len2 - 1);
+ MEMCPY (p2 + align2, p3, len2 + 1);
+ res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2),
+ (CHAR *) (p1 + align1));
+ if (res != p2 + align2)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd %zd) %p != %p",
+ n, impl->name, align1, align2, len1, len2, res,
+ p2 + align2);
+ ret = 1;
+ }
+ for (j = 0; j < align2 + 64; ++j)
+ {
+ if (p2[j - 64] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2);
+ ret = 1;
+ break;
+ }
+ }
+ if (MEMCMP (p2 + align2, p3, len2))
+ {
+ error (0, 0, "Iteration %zd - garbage in string before, %s (%zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2);
+ ret = 1;
+ }
+ for (j = align2 + len1 + len2 + 1; j < 512; ++j)
+ {
+ if (p2[j] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2);
+ ret = 1;
+ break;
+ }
+ }
+ if (MEMCMP (p1 + align1, p2 + align2 + len2, len1 + 1))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%28s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 16; ++i)
+ {
+ do_test (0, 0, i, i, SMALL_CHAR);
+ do_test (0, 0, i, i, BIG_CHAR);
+ do_test (0, i, i, i, SMALL_CHAR);
+ do_test (i, 0, i, i, BIG_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, 8 << i, 8 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 8 << i, SMALL_CHAR);
+ do_test (0, 0, 8 << i, 2 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 2 << i, SMALL_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 2 * i, 8 << i, 1, SMALL_CHAR);
+ do_test (2 * i, i, 8 << i, 1, BIG_CHAR);
+ do_test (i, i, 8 << i, 10, SMALL_CHAR);
+ do_test (i, i, 8 << i, 10, BIG_CHAR);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strchr.c b/REORG.TODO/string/test-strchr.c
new file mode 100644
index 0000000000..de9a274f7b
--- /dev/null
+++ b/REORG.TODO/string/test-strchr.c
@@ -0,0 +1,296 @@
+/* Test STRCHR functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wcschr support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# ifdef USE_FOR_STRCHRNUL
+# define TEST_NAME "strchrnul"
+# else
+# define TEST_NAME "strchr"
+# endif /* !USE_FOR_STRCHRNUL */
+#else
+# ifdef USE_FOR_STRCHRNUL
+# define TEST_NAME "wcschrnul"
+# else
+# define TEST_NAME "wcschr"
+# endif /* !USE_FOR_STRCHRNUL */
+#endif /* WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# ifdef USE_FOR_STRCHRNUL
+# define STRCHR strchrnul
+# define stupid_STRCHR stupid_STRCHRNUL
+# define simple_STRCHR simple_STRCHRNUL
+# else
+# define STRCHR strchr
+# endif /* !USE_FOR_STRCHRNUL */
+# define STRLEN strlen
+# define CHAR char
+# define BIG_CHAR CHAR_MAX
+# define MIDDLE_CHAR 127
+# define SMALL_CHAR 23
+# define UCHAR unsigned char
+# define L(s) s
+#else
+# include <wchar.h>
+# ifdef USE_FOR_STRCHRNUL
+# define STRCHR wcschrnul
+# define stupid_STRCHR stupid_WCSCHRNUL
+# define simple_STRCHR simple_WCSCHRNUL
+# else
+# define STRCHR wcschr
+# endif /* !USE_FOR_STRCHRNUL */
+# define STRLEN wcslen
+# define CHAR wchar_t
+# define BIG_CHAR WCHAR_MAX
+# define MIDDLE_CHAR 1121
+# define SMALL_CHAR 851
+# define UCHAR wchar_t
+# define L(s) L ## s
+#endif /* WIDE */
+
+#ifdef USE_FOR_STRCHRNUL
+# define NULLRET(endptr) endptr
+#else
+# define NULLRET(endptr) NULL
+#endif /* !USE_FOR_STRCHRNUL */
+
+
+typedef CHAR *(*proto_t) (const CHAR *, int);
+
+CHAR *
+simple_STRCHR (const CHAR *s, int c)
+{
+ for (; *s != (CHAR) c; ++s)
+ if (*s == '\0')
+ return NULLRET ((CHAR *) s);
+ return (CHAR *) s;
+}
+
+CHAR *
+stupid_STRCHR (const CHAR *s, int c)
+{
+ size_t n = STRLEN (s) + 1;
+
+ while (n--)
+ if (*s++ == (CHAR) c)
+ return (CHAR *) s - 1;
+ return NULLRET ((CHAR *) s - 1);
+}
+
+IMPL (stupid_STRCHR, 0)
+IMPL (simple_STRCHR, 0)
+IMPL (STRCHR, 1)
+
+static int
+check_result (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res)
+{
+ CHAR *res = CALL (impl, s, c);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %#x %p %p", impl->name,
+ c, res, exp_res);
+ ret = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res)
+{
+ if (check_result (impl, s, c, exp_res) < 0)
+ return;
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
+/* For wcschr: align here means align not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
+ len for wcschr here isn't in bytes but it's number of wchar_t symbols. */
+{
+ size_t i;
+ CHAR *result;
+ CHAR *buf = (CHAR *) buf1;
+ align &= 15;
+ if ((align + len) * sizeof (CHAR) >= page_size)
+ return;
+
+ for (i = 0; i < len; ++i)
+ {
+ buf[align + i] = 32 + 23 * i % max_char;
+ if (buf[align + i] == seek_char)
+ buf[align + i] = seek_char + 1;
+ else if (buf[align + i] == 0)
+ buf[align + i] = 1;
+ }
+ buf[align + len] = 0;
+
+ if (pos < len)
+ {
+ buf[align + pos] = seek_char;
+ result = buf + align + pos;
+ }
+ else if (seek_char == 0)
+ result = buf + align + len;
+ else
+ result = NULLRET (buf + align + len);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, buf + align, seek_char, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len;
+ int seek_char;
+ CHAR *result;
+ UCHAR *p = (UCHAR *) (buf1 + page_size - 512 * sizeof (CHAR));
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ /* For wcschr: align here means align not in bytes, but in wchar_ts,
+ in bytes it will equal to align * (sizeof (wchar_t)). */
+ align = random () & 15;
+ pos = random () & 511;
+ seek_char = random () & 255;
+ if (pos + align >= 511)
+ pos = 510 - align - (random () & 7);
+ /* len for wcschr here isn't in bytes but it's number of wchar_t
+ symbols. */
+ len = random () & 511;
+ if ((pos == len && seek_char)
+ || (pos > len && (random () & 1)))
+ len = pos + 1 + (random () & 7);
+ if (len + align >= 512)
+ len = 511 - align - (random () & 7);
+ if (pos == len && seek_char)
+ len = pos + 1;
+ j = (pos > len ? pos : len) + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == pos + align)
+ p[i] = seek_char;
+ else if (i == len + align)
+ p[i] = 0;
+ else
+ {
+ p[i] = random () & 255;
+ if (i < pos + align && p[i] == seek_char)
+ p[i] = seek_char + 13;
+ if (i < len + align && !p[i])
+ {
+ p[i] = seek_char - 13;
+ if (!p[i])
+ p[i] = 140;
+ }
+ }
+ }
+
+ if (pos <= len)
+ result = (CHAR *) (p + pos + align);
+ else if (seek_char == 0)
+ result = (CHAR *) (p + len + align);
+ else
+ result = NULLRET ((CHAR *) (p + len + align));
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align), seek_char) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function \
+ %s (align in bytes: %zd, seek_char: %d, len: %zd, pos: %zd) %p != %p, p %p",
+ n, impl->name, align * sizeof (CHAR), seek_char, len, pos,
+ CALL (impl, (CHAR *) (p + align), seek_char), result, p);
+ ret = 1;
+ }
+ }
+}
+
+static void
+check1 (void)
+{
+ CHAR s[] __attribute__((aligned(16))) = L ("\xff");
+ CHAR c = L ('\xfe');
+ CHAR *exp_result = stupid_STRCHR (s, c);
+
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s, c, exp_result);
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ check1 ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR);
+ do_test (i, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 64, 256, SMALL_CHAR, MIDDLE_CHAR);
+ do_test (i, 64, 256, SMALL_CHAR, BIG_CHAR);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, SMALL_CHAR, MIDDLE_CHAR);
+ do_test (0, i, i + 1, SMALL_CHAR, BIG_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 2048, 0, MIDDLE_CHAR);
+ do_test (i, 16 << i, 2048, 0, MIDDLE_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 64, 256, 0, MIDDLE_CHAR);
+ do_test (i, 64, 256, 0, BIG_CHAR);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, 0, MIDDLE_CHAR);
+ do_test (0, i, i + 1, 0, BIG_CHAR);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strchrnul.c b/REORG.TODO/string/test-strchrnul.c
new file mode 100644
index 0000000000..b8f79b1897
--- /dev/null
+++ b/REORG.TODO/string/test-strchrnul.c
@@ -0,0 +1,21 @@
+/* Test and measure strchrnul function.
+
+ Copyright (C) 2011-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define USE_FOR_STRCHRNUL 1
+#include "test-strchr.c"
diff --git a/REORG.TODO/string/test-strcmp.c b/REORG.TODO/string/test-strcmp.c
new file mode 100644
index 0000000000..f7af219149
--- /dev/null
+++ b/REORG.TODO/string/test-strcmp.c
@@ -0,0 +1,409 @@
+/* Test and measure strcmp and wcscmp functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wcscmp support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wcscmp"
+#else
+# define TEST_NAME "strcmp"
+#endif
+#include "test-string.h"
+
+#ifdef WIDE
+# include <wchar.h>
+
+# define L(str) L##str
+# define STRCMP wcscmp
+# define STRCPY wcscpy
+# define STRLEN wcslen
+# define MEMCPY wmemcpy
+# define SIMPLE_STRCMP simple_wcscmp
+# define STUPID_STRCMP stupid_wcscmp
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define CHARBYTES 4
+# define CHARBYTESLOG 2
+# define CHARALIGN __alignof__ (CHAR)
+# define MIDCHAR 0x7fffffff
+# define LARGECHAR 0xfffffffe
+# define CHAR__MAX WCHAR_MAX
+# define CHAR__MIN WCHAR_MIN
+
+/* Wcscmp uses signed semantics for comparison, not unsigned */
+/* Avoid using substraction since possible overflow */
+
+int
+simple_wcscmp (const wchar_t *s1, const wchar_t *s2)
+{
+ wchar_t c1, c2;
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c2 == L'\0')
+ return c1 - c2;
+ }
+ while (c1 == c2);
+
+ return c1 < c2 ? -1 : 1;
+}
+
+int
+stupid_wcscmp (const wchar_t *s1, const wchar_t *s2)
+{
+ size_t ns1 = wcslen (s1) + 1;
+ size_t ns2 = wcslen (s2) + 1;
+ size_t n = ns1 < ns2 ? ns1 : ns2;
+ int ret = 0;
+
+ wchar_t c1, c2;
+
+ while (n--) {
+ c1 = *s1++;
+ c2 = *s2++;
+ if ((ret = c1 < c2 ? -1 : c1 == c2 ? 0 : 1) != 0)
+ break;
+ }
+ return ret;
+}
+
+#else
+# include <limits.h>
+
+# define L(str) str
+# define STRCMP strcmp
+# define STRCPY strcpy
+# define STRLEN strlen
+# define MEMCPY memcpy
+# define SIMPLE_STRCMP simple_strcmp
+# define STUPID_STRCMP stupid_strcmp
+# define CHAR char
+# define UCHAR unsigned char
+# define CHARBYTES 1
+# define CHARBYTESLOG 0
+# define CHARALIGN 1
+# define MIDCHAR 0x7f
+# define LARGECHAR 0xfe
+# define CHAR__MAX CHAR_MAX
+# define CHAR__MIN CHAR_MIN
+
+/* Strcmp uses unsigned semantics for comparison. */
+int
+simple_strcmp (const char *s1, const char *s2)
+{
+ int ret;
+
+ while ((ret = *(unsigned char *) s1 - *(unsigned char*) s2++) == 0 && *s1++);
+ return ret;
+}
+
+int
+stupid_strcmp (const char *s1, const char *s2)
+{
+ size_t ns1 = strlen (s1) + 1;
+ size_t ns2 = strlen (s2) + 1;
+ size_t n = ns1 < ns2 ? ns1 : ns2;
+ int ret = 0;
+
+ while (n--)
+ if ((ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) != 0)
+ break;
+ return ret;
+}
+#endif
+
+typedef int (*proto_t) (const CHAR *, const CHAR *);
+
+IMPL (STUPID_STRCMP, 1)
+IMPL (SIMPLE_STRCMP, 1)
+IMPL (STRCMP, 1)
+
+static int
+check_result (impl_t *impl,
+ const CHAR *s1, const CHAR *s2,
+ int exp_result)
+{
+ int result = CALL (impl, s1, s2);
+ if ((exp_result == 0 && result != 0)
+ || (exp_result < 0 && result >= 0)
+ || (exp_result > 0 && result <= 0))
+ {
+ error (0, 0, "Wrong result in function %s %d %d", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl,
+ const CHAR *s1, const CHAR *s2,
+ int exp_result)
+{
+ if (check_result (impl, s1, s2, exp_result) < 0)
+ return;
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, int max_char,
+ int exp_result)
+{
+ size_t i;
+
+ CHAR *s1, *s2;
+
+ if (len == 0)
+ return;
+
+ align1 &= 63;
+ if (align1 + (len + 1) * CHARBYTES >= page_size)
+ return;
+
+ align2 &= 63;
+ if (align2 + (len + 1) * CHARBYTES >= page_size)
+ return;
+
+ /* Put them close to the end of page. */
+ i = align1 + CHARBYTES * (len + 2);
+ s1 = (CHAR *) (buf1 + ((page_size - i) / 16 * 16) + align1);
+ i = align2 + CHARBYTES * (len + 2);
+ s2 = (CHAR *) (buf2 + ((page_size - i) / 16 * 16) + align2);
+
+ for (i = 0; i < len; i++)
+ s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
+
+ s1[len] = s2[len] = 0;
+ s1[len + 1] = 23;
+ s2[len + 1] = 24 + exp_result;
+ s2[len - 1] -= exp_result;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, exp_result);
+}
+
+static void
+do_random_tests (void)
+{
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
+
+ for (size_t n = 0; n < ITERATIONS; n++)
+ {
+ /* for wcscmp case align1 and align2 mean here alignment
+ in wchar_t symbols, it equal 4*k alignment in bytes, we
+ don't check other alignments like for example
+ p1 = (wchar_t *)(buf1 + 1)
+ because it's wrong using of wchar_t type. */
+ size_t align1 = random () & 31;
+ size_t align2;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ size_t pos = random () & 511;
+ size_t j = align1 > align2 ? align1 : align2;
+ if (pos + j >= 511)
+ pos = 510 - j - (random () & 7);
+ size_t len1 = random () & 511;
+ if (pos >= len1 && (random () & 1))
+ len1 = pos + (random () & 7);
+ if (len1 + j >= 512)
+ len1 = 511 - j - (random () & 7);
+ size_t len2;
+ if (pos >= len1)
+ len2 = len1;
+ else
+ len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
+ j = (pos > len2 ? pos : len2) + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (size_t i = 0; i < j; ++i)
+ {
+ p1[i] = random () & 255;
+ if (i < len1 + align1 && !p1[i])
+ {
+ p1[i] = random () & 255;
+ if (!p1[i])
+ p1[i] = 1 + (random () & 127);
+ }
+ }
+ for (size_t i = 0; i < j; ++i)
+ {
+ p2[i] = random () & 255;
+ if (i < len2 + align2 && !p2[i])
+ {
+ p2[i] = random () & 255;
+ if (!p2[i])
+ p2[i] = 1 + (random () & 127);
+ }
+ }
+
+ int result = 0;
+ MEMCPY (p2 + align2, p1 + align1, pos);
+ if (pos < len1)
+ {
+ if (p2[align2 + pos] == p1[align1 + pos])
+ {
+ p2[align2 + pos] = random () & 255;
+ if (p2[align2 + pos] == p1[align1 + pos])
+ p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
+ }
+
+ if (p1[align1 + pos] < p2[align2 + pos])
+ result = -1;
+ else
+ result = 1;
+ }
+ p1[len1 + align1] = 0;
+ p2[len2 + align2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ int r = CALL (impl, (CHAR *) (p1 + align1), (CHAR *) (p2 + align2));
+ /* Test whether on 64-bit architectures where ABI requires
+ callee to promote has the promotion been done. */
+ asm ("" : "=g" (r) : "0" (r));
+ if ((r == 0 && result)
+ || (r < 0 && result >= 0)
+ || (r > 0 && result <= 0))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (align in bytes: %zd, align in bytes: %zd, len1: %zd, len2: %zd, pos: %zd) %d != %d, p1 %p p2 %p",
+ n, impl->name, (size_t) (p1 + align1) & 63, (size_t) (p1 + align2) & 63, len1, len2, pos, r, result, p1, p2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+static void
+check (void)
+{
+ CHAR *s1 = (CHAR *) (buf1 + 0xb2c);
+ CHAR *s2 = (CHAR *) (buf1 + 0xfd8);
+
+ STRCPY(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"));
+ STRCPY(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV"));
+
+ /* Check correct working for negatives values */
+
+ s1[0] = 1;
+ s2[0] = 1;
+ s1[1] = 1;
+ s2[1] = 1;
+ s1[2] = -1;
+ s2[2] = 3;
+ s1[3] = 0;
+ s2[3] = -1;
+
+ /* Check possible overflow bug, actual more for wcscmp */
+
+ s1[7] = CHAR__MIN;
+ s2[7] = CHAR__MAX;
+
+ size_t l1 = STRLEN (s1);
+ size_t l2 = STRLEN (s2);
+
+ for (size_t i1 = 0; i1 < l1; i1++)
+ for (size_t i2 = 0; i2 < l2; i2++)
+ {
+ int exp_result = SIMPLE_STRCMP (s1 + i1, s2 + i2);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1 + i1, s2 + i2, exp_result);
+ }
+
+ /* Test cases where there are multiple zero bytes after the first. */
+
+ for (size_t i = 0; i < 16 + 1; i++)
+ {
+ s1[i] = 0x00;
+ s2[i] = 0x00;
+ }
+
+ for (size_t i = 0; i < 16; i++)
+ {
+ int exp_result;
+
+ for (int val = 0x01; val < 0x100; val++)
+ {
+ for (size_t j = 0; j < i; j++)
+ {
+ s1[j] = val;
+ s2[j] = val;
+ }
+
+ s2[i] = val;
+
+ exp_result = SIMPLE_STRCMP (s1, s2);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, exp_result);
+ }
+ }
+}
+
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+ check();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 32; ++i)
+ {
+ do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, 0);
+ do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, 1);
+ do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, -1);
+ }
+
+ for (i = 1; i < 10 + CHARBYTESLOG; ++i)
+ {
+ do_test (0, 0, 2 << i, MIDCHAR, 0);
+ do_test (0, 0, 2 << i, LARGECHAR, 0);
+ do_test (0, 0, 2 << i, MIDCHAR, 1);
+ do_test (0, 0, 2 << i, LARGECHAR, 1);
+ do_test (0, 0, 2 << i, MIDCHAR, -1);
+ do_test (0, 0, 2 << i, LARGECHAR, -1);
+ do_test (0, CHARBYTES * i, 2 << i, MIDCHAR, 1);
+ do_test (CHARBYTES * i, CHARBYTES * (i + 1), 2 << i, LARGECHAR, 1);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, 0);
+ do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, 0);
+ do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, 1);
+ do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, 1);
+ do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, -1);
+ do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, -1);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strcpy.c b/REORG.TODO/string/test-strcpy.c
new file mode 100644
index 0000000000..d4de65a590
--- /dev/null
+++ b/REORG.TODO/string/test-strcpy.c
@@ -0,0 +1,245 @@
+/* Test and measure strcpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wcscpy support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef WIDE
+# include <wchar.h>
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define sfmt "ls"
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+# define STRCMP wcscmp
+# define MEMCMP wmemcmp
+# define MEMSET wmemset
+#else
+# define CHAR char
+# define UCHAR unsigned char
+# define sfmt "s"
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+# define STRCMP strcmp
+# define MEMCMP memcmp
+# define MEMSET memset
+#endif
+
+#ifndef STRCPY_RESULT
+# define STRCPY_RESULT(dst, len) dst
+# define TEST_MAIN
+# ifndef WIDE
+# define TEST_NAME "strcpy"
+# else
+# define TEST_NAME "wcscpy"
+# endif
+# include "test-string.h"
+# ifndef WIDE
+# define SIMPLE_STRCPY simple_strcpy
+# define STRCPY strcpy
+# else
+# define SIMPLE_STRCPY simple_wcscpy
+# define STRCPY wcscpy
+# endif
+
+CHAR *SIMPLE_STRCPY (CHAR *, const CHAR *);
+
+IMPL (SIMPLE_STRCPY, 0)
+IMPL (STRCPY, 1)
+
+CHAR *
+SIMPLE_STRCPY (CHAR *dst, const CHAR *src)
+{
+ CHAR *ret = dst;
+ while ((*dst++ = *src++) != '\0');
+ return ret;
+}
+#endif
+
+typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
+
+static void
+do_one_test (impl_t *impl, CHAR *dst, const CHAR *src,
+ size_t len __attribute__((unused)))
+{
+ if (CALL (impl, dst, src) != STRCPY_RESULT (dst, len))
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ CALL (impl, dst, src), STRCPY_RESULT (dst, len));
+ ret = 1;
+ return;
+ }
+
+ if (STRCMP (dst, src) != 0)
+ {
+ error (0, 0,
+ "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"",
+ impl->name, dst, src);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, int max_char)
+{
+ size_t i;
+ CHAR *s1, *s2;
+/* For wcscpy: align1 and align2 here mean alignment not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
+ len for wcschr here isn't in bytes but it's number of wchar_t symbols. */
+ align1 &= 7;
+ if ((align1 + len) * sizeof(CHAR) >= page_size)
+ return;
+
+ align2 &= 7;
+ if ((align2 + len) * sizeof(CHAR) >= page_size)
+ return;
+
+ s1 = (CHAR *) (buf1) + align1;
+ s2 = (CHAR *) (buf2) + align2;
+
+ for (i = 0; i < len; i++)
+ s1[i] = 32 + 23 * i % (max_char - 32);
+ s1[len] = 0;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s2, s1, len);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
+ UCHAR *res;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ /* For wcsrchr: align1 and align2 here mean align not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof
+ (wchar_t)). For strrchr we need to check all alignments from
+ 0 to 63 since some assembly implementations have separate
+ prolog for alignments more 48. */
+
+ align1 = random () & (63 / sizeof(CHAR));
+ if (random () & 1)
+ align2 = random () & (63 / sizeof(CHAR));
+ else
+ align2 = align1 + (random () & 24);
+ len = random () & 511;
+ j = align1;
+ if (align2 > j)
+ j = align2;
+ if (len + j >= 511)
+ len = 510 - j - (random () & 7);
+ j = len + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align1)
+ p1[i] = 0;
+ else
+ {
+ p1[i] = random () & BIG_CHAR;
+ if (i >= align1 && i < len + align1 && !p1[i])
+ p1[i] = (random () & SMALL_CHAR) + 3;
+ }
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ MEMSET (p2 - 64, '\1', 512 + 64);
+ res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2), (CHAR *) (p1 + align1));
+ if (res != STRCPY_RESULT (p2 + align2, len))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
+ n, impl->name, align1, align2, len, res,
+ STRCPY_RESULT (p2 + align2, len));
+ ret = 1;
+ }
+ for (j = 0; j < align2 + 64; ++j)
+ {
+ if (p2[j - 64] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ for (j = align2 + len + 1; j < 512; ++j)
+ {
+ if (p2[j] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ if (MEMCMP (p1 + align1, p2 + align2, len + 1))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 16; ++i)
+ {
+ do_test (0, 0, i, SMALL_CHAR);
+ do_test (0, 0, i, BIG_CHAR);
+ do_test (0, i, i, SMALL_CHAR);
+ do_test (i, 0, i, BIG_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, 8 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, SMALL_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 2 * i, 8 << i, SMALL_CHAR);
+ do_test (2 * i, i, 8 << i, BIG_CHAR);
+ do_test (i, i, 8 << i, SMALL_CHAR);
+ do_test (i, i, 8 << i, BIG_CHAR);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strcspn.c b/REORG.TODO/string/test-strcspn.c
new file mode 100644
index 0000000000..d83c1347d1
--- /dev/null
+++ b/REORG.TODO/string/test-strcspn.c
@@ -0,0 +1,81 @@
+/* Test strcspn functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define STRPBRK_RESULT(s, pos) (pos)
+#define RES_TYPE size_t
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strcspn"
+#else
+# define TEST_NAME "wcscspn"
+#endif /* WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRCSPN strcspn
+# define CHAR char
+# define SIMPLE_STRCSPN simple_strcspn
+# define STUPID_STRCSPN stupid_strcspn
+# define STRLEN strlen
+#else
+# include <wchar.h>
+# define STRCSPN wcscspn
+# define CHAR wchar_t
+# define SIMPLE_STRCSPN simple_wcscspn
+# define STUPID_STRCSPN stupid_wcscspn
+# define STRLEN wcslen
+#endif /* WIDE */
+
+typedef size_t (*proto_t) (const CHAR *, const CHAR *);
+size_t SIMPLE_STRCSPN (const CHAR *, const CHAR *);
+size_t STUPID_STRCSPN (const CHAR *, const CHAR *);
+
+IMPL (STUPID_STRCSPN, 0)
+IMPL (SIMPLE_STRCSPN, 0)
+IMPL (STRCSPN, 1)
+
+size_t
+SIMPLE_STRCSPN (const CHAR *s, const CHAR *rej)
+{
+ const CHAR *r, *str = s;
+ CHAR c;
+
+ while ((c = *s++) != '\0')
+ for (r = rej; *r != '\0'; ++r)
+ if (*r == c)
+ return s - str - 1;
+ return s - str - 1;
+}
+
+size_t
+STUPID_STRCSPN (const CHAR *s, const CHAR *rej)
+{
+ size_t ns = STRLEN (s), nrej = STRLEN (rej);
+ size_t i, j;
+
+ for (i = 0; i < ns; ++i)
+ for (j = 0; j < nrej; ++j)
+ if (s[i] == rej[j])
+ return i;
+ return i;
+}
+
+#undef CHAR
+#undef STRLEN
+#include "test-strpbrk.c"
diff --git a/REORG.TODO/string/test-string.h b/REORG.TODO/string/test-string.h
new file mode 100644
index 0000000000..6e13bf4aa3
--- /dev/null
+++ b/REORG.TODO/string/test-string.h
@@ -0,0 +1,219 @@
+/* Test and measure string and memory functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/cdefs.h>
+
+typedef struct
+{
+ const char *name;
+ void (*fn) (void);
+ long test;
+} impl_t;
+extern impl_t __start_impls[], __stop_impls[];
+
+#define IMPL(name, test) \
+ impl_t tst_ ## name \
+ __attribute__ ((section ("impls"), aligned (sizeof (void *)))) \
+ = { __STRING (name), (void (*) (void))name, test };
+
+#ifdef TEST_MAIN
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#undef __USE_STRING_INLINES
+
+/* We are compiled under _ISOMAC, so libc-symbols.h does not do this
+ for us. */
+#include "config.h"
+#ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
+# define inhibit_loop_to_libcall \
+ __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
+#else
+# define inhibit_loop_to_libcall
+#endif
+
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <error.h>
+#include <errno.h>
+#include <time.h>
+#include <ifunc-impl-list.h>
+#define GL(x) _##x
+#define GLRO(x) _##x
+
+
+# define TEST_FUNCTION test_main
+# define TIMEOUT (4 * 60)
+# define OPT_ITERATIONS 10000
+# define OPT_RANDOM 10001
+# define OPT_SEED 10002
+
+unsigned char *buf1, *buf2;
+int ret, do_srandom;
+unsigned int seed;
+size_t page_size;
+
+# ifndef ITERATIONS
+size_t iterations = 100000;
+# define ITERATIONS_OPTIONS \
+ { "iterations", required_argument, NULL, OPT_ITERATIONS },
+# define ITERATIONS_PROCESS \
+ case OPT_ITERATIONS: \
+ iterations = strtoul (optarg, NULL, 0); \
+ break;
+# define ITERATIONS iterations
+# else
+# define ITERATIONS_OPTIONS
+# define ITERATIONS_PROCESS
+# endif
+
+# define CMDLINE_OPTIONS ITERATIONS_OPTIONS \
+ { "random", no_argument, NULL, OPT_RANDOM }, \
+ { "seed", required_argument, NULL, OPT_SEED },
+
+static void __attribute__ ((used))
+cmdline_process_function (int c)
+{
+ switch (c)
+ {
+ ITERATIONS_PROCESS
+ case OPT_RANDOM:
+ {
+ int fdr = open ("/dev/urandom", O_RDONLY);
+ if (fdr < 0 || read (fdr, &seed, sizeof (seed)) != sizeof (seed))
+ seed = time (NULL);
+ if (fdr >= 0)
+ close (fdr);
+ do_srandom = 1;
+ break;
+ }
+
+ case OPT_SEED:
+ seed = strtoul (optarg, NULL, 0);
+ do_srandom = 1;
+ break;
+ }
+}
+# define CMDLINE_PROCESS cmdline_process_function
+
+#define CALL(impl, ...) \
+ (* (proto_t) (impl)->fn) (__VA_ARGS__)
+
+#ifdef TEST_NAME
+/* Increase size of FUNC_LIST if assert is triggered at run-time. */
+static struct libc_ifunc_impl func_list[32];
+static int func_count;
+static int impl_count = -1;
+static impl_t *impl_array;
+
+# define FOR_EACH_IMPL(impl, notall) \
+ impl_t *impl; \
+ int count; \
+ if (impl_count == -1) \
+ { \
+ impl_count = 0; \
+ if (func_count != 0) \
+ { \
+ int f; \
+ impl_t *skip = NULL, *a; \
+ for (impl = __start_impls; impl < __stop_impls; ++impl) \
+ if (strcmp (impl->name, TEST_NAME) == 0) \
+ skip = impl; \
+ else \
+ impl_count++; \
+ a = impl_array = malloc ((impl_count + func_count) * \
+ sizeof (impl_t)); \
+ for (impl = __start_impls; impl < __stop_impls; ++impl) \
+ if (impl != skip) \
+ *a++ = *impl; \
+ for (f = 0; f < func_count; f++) \
+ if (func_list[f].usable) \
+ { \
+ a->name = func_list[f].name; \
+ a->fn = func_list[f].fn; \
+ a->test = 1; \
+ a++; \
+ } \
+ impl_count = a - impl_array; \
+ } \
+ else \
+ { \
+ impl_count = __stop_impls - __start_impls; \
+ impl_array = __start_impls; \
+ } \
+ } \
+ impl = impl_array; \
+ for (count = 0; count < impl_count; ++count, ++impl) \
+ if (!notall || impl->test)
+#else
+# define FOR_EACH_IMPL(impl, notall) \
+ for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \
+ if (!notall || impl->test)
+#endif
+
+#ifndef BUF1PAGES
+# define BUF1PAGES 1
+#endif
+
+static void
+test_init (void)
+{
+#ifdef TEST_NAME
+ func_count = __libc_ifunc_impl_list (TEST_NAME, func_list,
+ (sizeof func_list
+ / sizeof func_list[0]));
+#endif
+
+ page_size = 2 * getpagesize ();
+#ifdef MIN_PAGE_SIZE
+ if (page_size < MIN_PAGE_SIZE)
+ page_size = MIN_PAGE_SIZE;
+#endif
+ buf1 = mmap (0, (BUF1PAGES + 1) * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (buf1 == MAP_FAILED)
+ error (EXIT_FAILURE, errno, "mmap failed");
+ if (mprotect (buf1 + BUF1PAGES * page_size, page_size, PROT_NONE))
+ error (EXIT_FAILURE, errno, "mprotect failed");
+ buf2 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (buf2 == MAP_FAILED)
+ error (EXIT_FAILURE, errno, "mmap failed");
+ if (mprotect (buf2 + page_size, page_size, PROT_NONE))
+ error (EXIT_FAILURE, errno, "mprotect failed");
+ if (do_srandom)
+ {
+ printf ("Setting seed to 0x%x\n", seed);
+ srandom (seed);
+ }
+
+ memset (buf1, 0xa5, BUF1PAGES * page_size);
+ memset (buf2, 0x5a, page_size);
+}
+
+#endif
diff --git a/REORG.TODO/string/test-strlen.c b/REORG.TODO/string/test-strlen.c
new file mode 100644
index 0000000000..99be380e6e
--- /dev/null
+++ b/REORG.TODO/string/test-strlen.c
@@ -0,0 +1,167 @@
+/* Test and measure STRLEN functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wcslen support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strlen"
+#else
+# define TEST_NAME "wcslen"
+#endif
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRLEN strlen
+# define CHAR char
+# define MAX_CHAR CHAR_MAX
+#else
+# include <wchar.h>
+# define STRLEN wcslen
+# define CHAR wchar_t
+# define MAX_CHAR WCHAR_MAX
+#endif
+
+typedef size_t (*proto_t) (const CHAR *);
+
+size_t
+simple_STRLEN (const CHAR *s)
+{
+ const CHAR *p;
+
+ for (p = s; *p; ++p);
+ return p - s;
+}
+
+#ifndef WIDE
+size_t
+builtin_strlen (const CHAR *p)
+{
+ return __builtin_strlen (p);
+}
+IMPL (builtin_strlen, 0)
+#endif
+
+IMPL (simple_STRLEN, 0)
+IMPL (STRLEN, 1)
+
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, size_t exp_len)
+{
+ size_t len = CALL (impl, s);
+ if (len != exp_len)
+ {
+ error (0, 0, "Wrong result in function %s %zd %zd", impl->name,
+ len, exp_len);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t len)
+{
+ size_t i;
+
+ align &= 63;
+ if (align + sizeof(CHAR) * len >= page_size)
+ return;
+
+ CHAR *buf = (CHAR *) (buf1);
+
+ for (i = 0; i < len; ++i)
+ buf[align + i] = 1 + 11111 * i % MAX_CHAR;
+ buf[align + len] = 0;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (CHAR *) (buf + align), len);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, len;
+ CHAR *p = (CHAR *) (buf1 + page_size - 512 * sizeof(CHAR));
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ len = random () & 511;
+ if (len + align > 510)
+ len = 511 - align - (random () & 7);
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align)
+ p[i] = 0;
+ else
+ {
+ p[i] = random () & 255;
+ if (i >= align && i < len + align && !p[i])
+ p[i] = (random () & 127) + 1;
+ }
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align)) != len)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd) %zd != %zd, p %p",
+ n, impl->name, align, CALL (impl, (CHAR *) (p + align)),
+ len, p);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ /* Checking with only 4 * N alignments for wcslen, other alignments are wrong for wchar_t type arrays*/
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (sizeof(CHAR) * i, i);
+ do_test (0, i);
+ }
+
+ for (i = 2; i <= 12; ++i)
+ {
+ do_test (0, 1 << i);
+ do_test (sizeof(CHAR) * 7, 1 << i);
+ do_test (sizeof(CHAR) * i, 1 << i);
+ do_test (sizeof(CHAR) * i, (size_t)((1 << i) / 1.5));
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strncasecmp.c b/REORG.TODO/string/test-strncasecmp.c
new file mode 100644
index 0000000000..bf501cf798
--- /dev/null
+++ b/REORG.TODO/string/test-strncasecmp.c
@@ -0,0 +1,353 @@
+/* Test and measure strncasecmp functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <ctype.h>
+#define TEST_MAIN
+#define TEST_NAME "strncasecmp"
+#include "test-string.h"
+
+typedef int (*proto_t) (const char *, const char *, size_t);
+static int simple_strncasecmp (const char *, const char *, size_t);
+static int stupid_strncasecmp (const char *, const char *, size_t);
+
+IMPL (stupid_strncasecmp, 0)
+IMPL (simple_strncasecmp, 0)
+IMPL (strncasecmp, 1)
+
+static int
+simple_strncasecmp (const char *s1, const char *s2, size_t n)
+{
+ int ret;
+
+ if (n == 0)
+ return 0;
+
+ while ((ret = ((unsigned char) tolower (*s1)
+ - (unsigned char) tolower (*s2))) == 0
+ && *s1++)
+ {
+ if (--n == 0)
+ return 0;
+ ++s2;
+ }
+ return ret;
+}
+
+static int
+stupid_strncasecmp (const char *s1, const char *s2, size_t max)
+{
+ size_t ns1 = strlen (s1) + 1;
+ size_t ns2 = strlen (s2) + 1;
+ size_t n = ns1 < ns2 ? ns1 : ns2;
+ if (n > max)
+ n = max;
+ int ret = 0;
+
+ while (n--)
+ {
+ if ((ret = ((unsigned char) tolower (*s1)
+ - (unsigned char) tolower (*s2))) != 0)
+ break;
+ ++s1;
+ ++s2;
+ }
+ return ret;
+}
+
+static int
+check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
+ int exp_result)
+{
+ int result = CALL (impl, s1, s2, n);
+ if ((exp_result == 0 && result != 0)
+ || (exp_result < 0 && result >= 0)
+ || (exp_result > 0 && result <= 0))
+ {
+ error (0, 0, "Wrong result in function %s %d %d", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
+ int exp_result)
+{
+ if (check_result (impl, s1, s2, n, exp_result) < 0)
+ return;
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
+ int exp_result)
+{
+ size_t i;
+ char *s1, *s2;
+
+ if (len == 0)
+ return;
+
+ align1 &= 7;
+ if (align1 + len + 1 >= page_size)
+ return;
+
+ align2 &= 7;
+ if (align2 + len + 1 >= page_size)
+ return;
+
+ s1 = (char *) (buf1 + align1);
+ s2 = (char *) (buf2 + align2);
+
+ for (i = 0; i < len; i++)
+ {
+ s1[i] = toupper (1 + 23 * i % max_char);
+ s2[i] = tolower (s1[i]);
+ }
+
+ s1[len] = s2[len] = 0;
+ s1[len + 1] = 23;
+ s2[len + 1] = 24 + exp_result;
+ if ((s2[len - 1] == 'z' && exp_result == -1)
+ || (s2[len - 1] == 'a' && exp_result == 1))
+ s1[len - 1] += exp_result;
+ else
+ s2[len - 1] -= exp_result;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, n, exp_result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, pos, len1, len2;
+ int result;
+ long r;
+ unsigned char *p1 = buf1 + page_size - 512;
+ unsigned char *p2 = buf2 + page_size - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ pos = random () & 511;
+ j = align1 > align2 ? align1 : align2;
+ if (pos + j >= 511)
+ pos = 510 - j - (random () & 7);
+ len1 = random () & 511;
+ if (pos >= len1 && (random () & 1))
+ len1 = pos + (random () & 7);
+ if (len1 + j >= 512)
+ len1 = 511 - j - (random () & 7);
+ if (pos >= len1)
+ len2 = len1;
+ else
+ len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
+ j = (pos > len2 ? pos : len2) + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; ++i)
+ {
+ p1[i] = tolower (random () & 255);
+ if (i < len1 + align1 && !p1[i])
+ {
+ p1[i] = tolower (random () & 255);
+ if (!p1[i])
+ p1[i] = tolower (1 + (random () & 127));
+ }
+ }
+ for (i = 0; i < j; ++i)
+ {
+ p2[i] = toupper (random () & 255);
+ if (i < len2 + align2 && !p2[i])
+ {
+ p2[i] = toupper (random () & 255);
+ if (!p2[i])
+ toupper (p2[i] = 1 + (random () & 127));
+ }
+ }
+
+ result = 0;
+ memcpy (p2 + align2, p1 + align1, pos);
+ if (pos < len1)
+ {
+ if (tolower (p2[align2 + pos]) == p1[align1 + pos])
+ {
+ p2[align2 + pos] = toupper (random () & 255);
+ if (tolower (p2[align2 + pos]) == p1[align1 + pos])
+ p2[align2 + pos] = toupper (p1[align1 + pos]
+ + 3 + (random () & 127));
+ }
+
+ if (p1[align1 + pos] < tolower (p2[align2 + pos]))
+ result = -1;
+ else
+ result = 1;
+ }
+ p1[len1 + align1] = 0;
+ p2[len2 + align2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2),
+ pos + 1 + (random () & 255));
+ /* Test whether on 64-bit architectures where ABI requires
+ callee to promote has the promotion been done. */
+ asm ("" : "=g" (r) : "0" (r));
+ if ((r == 0 && result)
+ || (r < 0 && result >= 0)
+ || (r > 0 && result <= 0))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
+ n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+/* Regression test for BZ #12205 */
+static void
+bz12205 (void)
+{
+ static char cp [4096+16] __attribute__ ((aligned(4096)));
+ static char gotrel[4096] __attribute__ ((aligned(4096)));
+ char *s1 = cp + 0xffa;
+ char *s2 = gotrel + 0xcbe;
+ int exp_result;
+ size_t n = 6;
+
+ strcpy (s1, "gottpoff");
+ strcpy (s2, "GOTPLT");
+
+ exp_result = simple_strncasecmp (s1, s2, n);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, n, exp_result);
+}
+
+/* Regression test for BZ #14195 */
+static void
+bz14195 (void)
+{
+ const char *empty_string = "";
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, empty_string, "", 5, 0);
+}
+
+static void
+test_locale (const char *locale)
+{
+ size_t i;
+
+ if (setlocale (LC_CTYPE, locale) == NULL)
+ {
+ error (0, 0, "cannot set locale \"%s\"", locale);
+ ret = 1;
+ }
+
+ bz12205 ();
+ bz14195 ();
+
+ printf ("%23s", locale);
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 16; ++i)
+ {
+ do_test (i, i, i - 1, i, 127, 0);
+
+ do_test (i, i, i, i, 127, 0);
+ do_test (i, i, i, i, 127, 1);
+ do_test (i, i, i, i, 127, -1);
+
+ do_test (i, i, i + 1, i, 127, 0);
+ do_test (i, i, i + 1, i, 127, 1);
+ do_test (i, i, i + 1, i, 127, -1);
+ }
+
+ for (i = 1; i < 10; ++i)
+ {
+ do_test (0, 0, (2 << i) - 1, 2 << i, 127, 0);
+ do_test (0, 0, 2 << i, 2 << i, 254, 0);
+ do_test (0, 0, (2 << i) + 1, 2 << i, 127, 0);
+
+ do_test (0, 0, (2 << i) + 1, 2 << i, 254, 0);
+
+ do_test (0, 0, 2 << i, 2 << i, 127, 1);
+ do_test (0, 0, (2 << i) + 10, 2 << i, 127, 1);
+
+ do_test (0, 0, 2 << i, 2 << i, 254, 1);
+ do_test (0, 0, (2 << i) + 10, 2 << i, 254, 1);
+
+ do_test (0, 0, 2 << i, 2 << i, 127, -1);
+ do_test (0, 0, (2 << i) + 10, 2 << i, 127, -1);
+
+ do_test (0, 0, 2 << i, 2 << i, 254, -1);
+ do_test (0, 0, (2 << i) + 10, 2 << i, 254, -1);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 2 * i, (8 << i) - 1, 8 << i, 127, 0);
+ do_test (i, 2 * i, 8 << i, 8 << i, 127, 0);
+ do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 0);
+
+ do_test (2 * i, i, (8 << i) - 1, 8 << i, 254, 0);
+ do_test (2 * i, i, 8 << i, 8 << i, 254, 0);
+ do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 0);
+
+ do_test (i, 2 * i, 8 << i, 8 << i, 127, 1);
+ do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 1);
+
+ do_test (2 * i, i, 8 << i, 8 << i, 254, 1);
+ do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 1);
+
+ do_test (i, 2 * i, 8 << i, 8 << i, 127, -1);
+ do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, -1);
+
+ do_test (2 * i, i, 8 << i, 8 << i, 254, -1);
+ do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, -1);
+ }
+
+ do_random_tests ();
+}
+
+int
+test_main (void)
+{
+ test_init ();
+
+ test_locale ("C");
+ test_locale ("en_US.ISO-8859-1");
+ test_locale ("en_US.UTF-8");
+ test_locale ("tr_TR.ISO-8859-9");
+ test_locale ("tr_TR.UTF-8");
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strncat.c b/REORG.TODO/string/test-strncat.c
new file mode 100644
index 0000000000..66d58e534d
--- /dev/null
+++ b/REORG.TODO/string/test-strncat.c
@@ -0,0 +1,322 @@
+/* Test strncat functions.
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strncat"
+#else
+# define TEST_NAME "wcsncat"
+#endif /* WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRNCAT strncat
+# define CHAR char
+# define UCHAR unsigned char
+# define SIMPLE_STRNCAT simple_strncat
+# define STUPID_STRNCAT stupid_strncat
+# define STRLEN strlen
+# define MEMSET memset
+# define MEMCPY memcpy
+# define MEMCMP memcmp
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#else
+# include <wchar.h>
+# define STRNCAT wcsncat
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define SIMPLE_STRNCAT simple_wcsncat
+# define STUPID_STRNCAT stupid_wcsncat
+# define STRLEN wcslen
+# define MEMSET wmemset
+# define MEMCPY wmemcpy
+# define MEMCMP wmemcmp
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#endif /* WIDE */
+
+typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
+CHAR *STUPID_STRNCAT (CHAR *, const CHAR *, size_t);
+CHAR *SIMPLE_STRNCAT (CHAR *, const CHAR *, size_t);
+
+IMPL (STUPID_STRNCAT, 0)
+IMPL (STRNCAT, 2)
+
+CHAR *
+STUPID_STRNCAT (CHAR *dst, const CHAR *src, size_t n)
+{
+ CHAR *ret = dst;
+ while (*dst++ != '\0');
+ --dst;
+ while (n--)
+ if ((*dst++ = *src++) == '\0')
+ return ret;
+ *dst = '\0';
+ return ret;
+}
+
+static void
+do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, size_t n)
+{
+ size_t k = STRLEN (dst);
+ if (CALL (impl, dst, src, n) != dst)
+ {
+ error (0, 0, "Wrong result in function %s %p != %p", impl->name,
+ CALL (impl, dst, src, n), dst);
+ ret = 1;
+ return;
+ }
+
+ size_t len = STRLEN (src);
+ if (MEMCMP (dst + k, src, len + 1 > n ? n : len + 1) != 0)
+ {
+ error (0, 0, "Incorrect concatenation in function %s",
+ impl->name);
+ ret = 1;
+ return;
+ }
+ if (n < len && dst[k + n] != '\0')
+ {
+ error (0, 0, "There is no zero in the end of output string in %s",
+ impl->name);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len1, size_t len2,
+ size_t n, int max_char)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+ align1 &= 7;
+ if ((align1 + len1) * sizeof (CHAR) >= page_size)
+ return;
+ if ((align1 + n) * sizeof (CHAR) > page_size)
+ return;
+ align2 &= 7;
+ if ((align2 + len1 + len2) * sizeof (CHAR) >= page_size)
+ return;
+ if ((align2 + len1 + n) * sizeof (CHAR) > page_size)
+ return;
+ s1 = (CHAR *) (buf1) + align1;
+ s2 = (CHAR *) (buf2) + align2;
+
+ for (i = 0; i < len1; ++i)
+ s1[i] = 32 + 23 * i % (max_char - 32);
+ s1[len1] = '\0';
+
+ for (i = 0; i < len2; i++)
+ s2[i] = 32 + 23 * i % (max_char - 32);
+
+ FOR_EACH_IMPL (impl, 0)
+ {
+ s2[len2] = '\0';
+ do_one_test (impl, s2, s1, n);
+ }
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len1, len2, N;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
+ UCHAR *p3 = (UCHAR *) buf1;
+ UCHAR *res;
+ fprintf (stdout, "Number of iterations in random test = %zd\n",
+ ITERATIONS);
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ N = random () & 255;
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ len1 = random () & 511;
+ if (len1 + align2 > 512)
+ len2 = random () & 7;
+ else
+ len2 = (512 - len1 - align2) * (random () & (1024 * 1024 - 1))
+ / (1024 * 1024);
+ j = align1;
+ if (align2 + len2 > j)
+ j = align2 + len2;
+ if (len1 + j >= 511)
+ len1 = 510 - j - (random () & 7);
+ if (len1 >= 512)
+ len1 = 0;
+ if (align1 + len1 < 512 - 8)
+ {
+ j = 510 - align1 - len1 - (random () & 31);
+ if (j > 0 && j < 512)
+ align1 += j;
+ }
+ j = len1 + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; i++)
+ {
+ if (i == len1 + align1)
+ p1[i] = 0;
+ else
+ {
+ p1[i] = random () & BIG_CHAR;
+ if (i >= align1 && i < len1 + align1 && !p1[i])
+ p1[i] = (random () & SMALL_CHAR) + 3;
+ }
+ }
+ for (i = 0; i < len2; i++)
+ {
+ p3[i] = random () & BIG_CHAR;
+ if (!p3[i])
+ p3[i] = (random () & SMALL_CHAR) + 3;
+ }
+ p3[len2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ MEMSET (p2 - 64, '\1', align2 + 64);
+ MEMSET (p2 + align2 + len2 + 1, '\1', 512 - align2 - len2 - 1);
+ MEMCPY (p2 + align2, p3, len2 + 1);
+ res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2),
+ (CHAR *) (p1 + align1), N);
+ if (res != p2 + align2)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s "
+ "(%zd, %zd, %zd, %zd, %zd) %p != %p",
+ n, impl->name, align1, align2, len1, len2, N,
+ res, p2 + align2);
+ ret = 1;
+ }
+ for (j = 0; j < align2 + 64; ++j)
+ {
+ if (p2[j - 64] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage before dst, %s "
+ "%zd, %zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2, N);
+ ret = 1;
+ break;
+ }
+ }
+ if (MEMCMP (p2 + align2, p3, len2))
+ {
+ error (0, 0, "Iteration %zd - garbage in string before, %s "
+ "(%zd, %zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2, N);
+ ret = 1;
+ }
+
+ if ((len1 + 1) > N)
+ j = align2 + N + 1 + len2;
+ else
+ j = align2 + len1 + 1 + len2;
+ for (; j < 512; ++j)
+ {
+ if (p2[j] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s "
+ "(%zd, %zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2, N);
+ ret = 1;
+ break;
+ }
+ }
+ if (len1 + 1 > N)
+ {
+ if (p2[align2 + N + len2] != '\0')
+ {
+ error (0, 0, "Iteration %zd - there is no zero at the "
+ "end of output string, %s (%zd, %zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2, N);
+ ret = 1;
+ }
+ }
+ if (MEMCMP (p1 + align1, p2 + align2 + len2,
+ (len1 + 1) > N ? N : len1 + 1))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s "
+ "(%zd, %zd, %zd, %zd, %zd)",
+ n, impl->name, align1, align2, len1, len2, N);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i, n;
+
+ test_init ();
+
+ printf ("%28s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (n = 2; n <= 2048; n*=4)
+ {
+ do_test (0, 2, 2, 2, n, SMALL_CHAR);
+ do_test (0, 0, 4, 4, n, SMALL_CHAR);
+ do_test (4, 0, 4, 4, n, BIG_CHAR);
+ do_test (0, 0, 8, 8, n, SMALL_CHAR);
+ do_test (0, 8, 8, 8, n, SMALL_CHAR);
+
+ do_test (0, 2, 2, 2, SIZE_MAX, SMALL_CHAR);
+ do_test (0, 0, 4, 4, SIZE_MAX, SMALL_CHAR);
+ do_test (4, 0, 4, 4, SIZE_MAX, BIG_CHAR);
+ do_test (0, 0, 8, 8, SIZE_MAX, SMALL_CHAR);
+ do_test (0, 8, 8, 8, SIZE_MAX, SMALL_CHAR);
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, 8 << i, 8 << i, n, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 8 << i, n, SMALL_CHAR);
+ do_test (0, 0, 8 << i, 2 << i, n, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 2 << i, n, SMALL_CHAR);
+
+ do_test (0, 0, 8 << i, 8 << i, SIZE_MAX, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 8 << i, SIZE_MAX, SMALL_CHAR);
+ do_test (0, 0, 8 << i, 2 << i, SIZE_MAX, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 8 << i, 2 << i, SIZE_MAX, SMALL_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 2 * i, 8 << i, 1, n, SMALL_CHAR);
+ do_test (2 * i, i, 8 << i, 1, n, BIG_CHAR);
+ do_test (i, i, 8 << i, 10, n, SMALL_CHAR);
+
+ do_test (i, 2 * i, 8 << i, 1, SIZE_MAX, SMALL_CHAR);
+ do_test (2 * i, i, 8 << i, 1, SIZE_MAX, BIG_CHAR);
+ do_test (i, i, 8 << i, 10, SIZE_MAX, SMALL_CHAR);
+ }
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strncmp.c b/REORG.TODO/string/test-strncmp.c
new file mode 100644
index 0000000000..fe3c4e3320
--- /dev/null
+++ b/REORG.TODO/string/test-strncmp.c
@@ -0,0 +1,479 @@
+/* Test strncmp and wcsncmp functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wcsncmp"
+#else
+# define TEST_NAME "strncmp"
+#endif
+#include "test-string.h"
+
+#ifdef WIDE
+# include <wchar.h>
+
+# define L(str) L##str
+# define STRNCMP wcsncmp
+# define STRCPY wcscpy
+# define STRDUP wcsdup
+# define MEMCPY wmemcpy
+# define SIMPLE_STRNCMP simple_wcsncmp
+# define STUPID_STRNCMP stupid_wcsncmp
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define CHARBYTES 4
+# define CHAR__MAX WCHAR_MAX
+# define CHAR__MIN WCHAR_MIN
+
+/* Wcsncmp uses signed semantics for comparison, not unsigned.
+ Avoid using substraction since possible overflow */
+int
+simple_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
+{
+ wchar_t c1, c2;
+
+ while (n--)
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c1 == L('\0') || c1 != c2)
+ return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
+ }
+ return 0;
+}
+
+int
+stupid_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
+{
+ wchar_t c1, c2;
+ size_t ns1 = wcsnlen (s1, n) + 1, ns2 = wcsnlen (s2, n) + 1;
+
+ n = ns1 < n ? ns1 : n;
+ n = ns2 < n ? ns2 : n;
+
+ while (n--)
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c1 != c2)
+ return c1 > c2 ? 1 : -1;
+ }
+ return 0;
+}
+
+#else
+# define L(str) str
+# define STRNCMP strncmp
+# define STRCPY strcpy
+# define STRDUP strdup
+# define MEMCPY memcpy
+# define SIMPLE_STRNCMP simple_strncmp
+# define STUPID_STRNCMP stupid_strncmp
+# define CHAR char
+# define UCHAR unsigned char
+# define CHARBYTES 1
+# define CHAR__MAX CHAR_MAX
+# define CHAR__MIN CHAR_MIN
+
+/* Strncmp uses unsigned semantics for comparison. */
+int
+simple_strncmp (const char *s1, const char *s2, size_t n)
+{
+ int ret = 0;
+
+ while (n-- && (ret = *(unsigned char *) s1 - * (unsigned char *) s2++) == 0
+ && *s1++);
+ return ret;
+}
+
+int
+stupid_strncmp (const char *s1, const char *s2, size_t n)
+{
+ size_t ns1 = strnlen (s1, n) + 1, ns2 = strnlen (s2, n) + 1;
+ int ret = 0;
+
+ n = ns1 < n ? ns1 : n;
+ n = ns2 < n ? ns2 : n;
+ while (n-- && (ret = *(unsigned char *) s1++ - * (unsigned char *) s2++) == 0);
+ return ret;
+}
+
+#endif
+
+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
+
+IMPL (STUPID_STRNCMP, 0)
+IMPL (SIMPLE_STRNCMP, 0)
+IMPL (STRNCMP, 1)
+
+
+static int
+check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
+ int exp_result)
+{
+ int result = CALL (impl, s1, s2, n);
+ if ((exp_result == 0 && result != 0)
+ || (exp_result < 0 && result >= 0)
+ || (exp_result > 0 && result <= 0))
+ {
+ error (0, 0, "Wrong result in function %s %d %d", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
+ int exp_result)
+{
+ if (check_result (impl, s1, s2, n, exp_result) < 0)
+ return;
+}
+
+static void
+do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
+ int exp_result)
+{
+ size_t i, align_n;
+ CHAR *s1, *s2;
+
+ align1 &= ~(CHARBYTES - 1);
+ align2 &= ~(CHARBYTES - 1);
+
+ if (n == 0)
+ {
+ s1 = (CHAR *) (buf1 + page_size);
+ s2 = (CHAR *) (buf2 + page_size);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, n, 0);
+
+ return;
+ }
+
+ align1 &= 15;
+ align2 &= 15;
+ align_n = (page_size - n * CHARBYTES) & 15;
+
+ s1 = (CHAR *) (buf1 + page_size - n * CHARBYTES);
+ s2 = (CHAR *) (buf2 + page_size - n * CHARBYTES);
+
+ if (align1 < align_n)
+ s1 = (CHAR *) ((char *) s1 - (align_n - align1));
+
+ if (align2 < align_n)
+ s2 = (CHAR *) ((char *) s2 - (align_n - align2));
+
+ for (i = 0; i < n; i++)
+ s1[i] = s2[i] = 1 + 23 * i % max_char;
+
+ if (len < n)
+ {
+ s1[len] = 0;
+ s2[len] = 0;
+ if (exp_result < 0)
+ s2[len] = 32;
+ else if (exp_result > 0)
+ s1[len] = 64;
+ }
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, n, exp_result);
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
+ int exp_result)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+ align1 &= ~(CHARBYTES - 1);
+ align2 &= ~(CHARBYTES - 1);
+
+ if (n == 0)
+ return;
+
+ align1 &= 63;
+ if (align1 + (n + 1) * CHARBYTES >= page_size)
+ return;
+
+ align2 &= 63;
+ if (align2 + (n + 1) * CHARBYTES >= page_size)
+ return;
+
+ s1 = (CHAR *) (buf1 + align1);
+ s2 = (CHAR *) (buf2 + align2);
+
+ for (i = 0; i < n; i++)
+ s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
+
+ s1[n] = 24 + exp_result;
+ s2[n] = 23;
+ s1[len] = 0;
+ s2[len] = 0;
+ if (exp_result < 0)
+ s2[len] = 32;
+ else if (exp_result > 0)
+ s1[len] = 64;
+ if (len >= n)
+ s2[n - 1] -= exp_result;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, n, exp_result);
+}
+
+static void
+do_page_test (size_t offset1, size_t offset2, CHAR *s2)
+{
+ CHAR *s1;
+ int exp_result;
+
+ if (offset1 * CHARBYTES >= page_size || offset2 * CHARBYTES >= page_size)
+ return;
+
+ s1 = (CHAR *) buf1;
+ s1 += offset1;
+ s2 += offset2;
+
+ exp_result= *s1;
+
+ FOR_EACH_IMPL (impl, 0)
+ {
+ check_result (impl, s1, s2, page_size, -exp_result);
+ check_result (impl, s2, s1, page_size, exp_result);
+ }
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, pos, len1, len2, size;
+ int result;
+ long r;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align1 = random () & 31;
+ if (random () & 1)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ pos = random () & 511;
+ size = random () & 511;
+ j = align1 > align2 ? align1 : align2;
+ if (pos + j >= 511)
+ pos = 510 - j - (random () & 7);
+ len1 = random () & 511;
+ if (pos >= len1 && (random () & 1))
+ len1 = pos + (random () & 7);
+ if (len1 + j >= 512)
+ len1 = 511 - j - (random () & 7);
+ if (pos >= len1)
+ len2 = len1;
+ else
+ len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
+ j = (pos > len2 ? pos : len2) + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; ++i)
+ {
+ p1[i] = random () & 255;
+ if (i < len1 + align1 && !p1[i])
+ {
+ p1[i] = random () & 255;
+ if (!p1[i])
+ p1[i] = 1 + (random () & 127);
+ }
+ }
+ for (i = 0; i < j; ++i)
+ {
+ p2[i] = random () & 255;
+ if (i < len2 + align2 && !p2[i])
+ {
+ p2[i] = random () & 255;
+ if (!p2[i])
+ p2[i] = 1 + (random () & 127);
+ }
+ }
+
+ result = 0;
+ MEMCPY (p2 + align2, p1 + align1, pos);
+ if (pos < len1)
+ {
+ if (p2[align2 + pos] == p1[align1 + pos])
+ {
+ p2[align2 + pos] = random () & 255;
+ if (p2[align2 + pos] == p1[align1 + pos])
+ p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
+ }
+
+ if (pos < size)
+ {
+ if (p1[align1 + pos] < p2[align2 + pos])
+ result = -1;
+ else
+ result = 1;
+ }
+ }
+ p1[len1 + align1] = 0;
+ p2[len2 + align2] = 0;
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ r = CALL (impl, (CHAR *) (p1 + align1), (CHAR *) (p2 + align2), size);
+ /* Test whether on 64-bit architectures where ABI requires
+ callee to promote has the promotion been done. */
+ asm ("" : "=g" (r) : "0" (r));
+ if ((r == 0 && result)
+ || (r < 0 && result >= 0)
+ || (r > 0 && result <= 0))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
+ n, impl->name, align1, align2, len1, len2, pos, size, r, result, p1, p2);
+ ret = 1;
+ }
+ }
+ }
+}
+
+static void
+check1 (void)
+{
+ CHAR *s1 = (CHAR *) (buf1 + 0xb2c);
+ CHAR *s2 = (CHAR *) (buf1 + 0xfd8);
+ size_t i, offset;
+ int exp_result;
+
+ STRCPY(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"));
+ STRCPY(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV"));
+
+ /* Check possible overflow bug for wcsncmp */
+ s1[4] = CHAR__MAX;
+ s2[4] = CHAR__MIN;
+
+ for (offset = 0; offset < 6; offset++)
+ {
+ for (i = 0; i < 80; i++)
+ {
+ exp_result = SIMPLE_STRNCMP (s1 + offset, s2 + offset, i);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1 + offset, s2 + offset, i, exp_result);
+ }
+ }
+}
+
+static void
+check2 (void)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+ s1 = (CHAR *) buf1;
+ for (i = 0; i < (page_size / CHARBYTES) - 1; i++)
+ s1[i] = 23;
+ s1[i] = 0;
+
+ s2 = STRDUP (s1);
+
+ for (i = 0; i < 64; ++i)
+ do_page_test ((3988 / CHARBYTES) + i, (2636 / CHARBYTES), s2);
+
+ free (s2);
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ check1 ();
+ check2 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i =0; i < 16; ++i)
+ {
+ do_test (0, 0, 8, i, 127, 0);
+ do_test (0, 0, 8, i, 127, -1);
+ do_test (0, 0, 8, i, 127, 1);
+ do_test (i, i, 8, i, 127, 0);
+ do_test (i, i, 8, i, 127, 1);
+ do_test (i, i, 8, i, 127, -1);
+ do_test (i, 2 * i, 8, i, 127, 0);
+ do_test (2 * i, i, 8, i, 127, 1);
+ do_test (i, 3 * i, 8, i, 127, -1);
+ do_test (0, 0, 8, i, 255, 0);
+ do_test (0, 0, 8, i, 255, -1);
+ do_test (0, 0, 8, i, 255, 1);
+ do_test (i, i, 8, i, 255, 0);
+ do_test (i, i, 8, i, 255, 1);
+ do_test (i, i, 8, i, 255, -1);
+ do_test (i, 2 * i, 8, i, 255, 0);
+ do_test (2 * i, i, 8, i, 255, 1);
+ do_test (i, 3 * i, 8, i, 255, -1);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, 8 << i, 16 << i, 127, 0);
+ do_test (0, 0, 8 << i, 16 << i, 127, 1);
+ do_test (0, 0, 8 << i, 16 << i, 127, -1);
+ do_test (0, 0, 8 << i, 16 << i, 255, 0);
+ do_test (0, 0, 8 << i, 16 << i, 255, 1);
+ do_test (0, 0, 8 << i, 16 << i, 255, -1);
+ do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 0);
+ do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 1);
+ do_test (2 * i, i, 8 << i, 16 << i, 255, 0);
+ do_test (2 * i, i, 8 << i, 16 << i, 255, 1);
+ }
+
+ do_test_limit (0, 0, 0, 0, 127, 0);
+ do_test_limit (4, 0, 21, 20, 127, 0);
+ do_test_limit (0, 4, 21, 20, 127, 0);
+ do_test_limit (8, 0, 25, 24, 127, 0);
+ do_test_limit (0, 8, 25, 24, 127, 0);
+
+ for (i = 0; i < 8; ++i)
+ {
+ do_test_limit (0, 0, 17 - i, 16 - i, 127, 0);
+ do_test_limit (0, 0, 17 - i, 16 - i, 255, 0);
+ do_test_limit (0, 0, 15 - i, 16 - i, 127, 0);
+ do_test_limit (0, 0, 15 - i, 16 - i, 127, 1);
+ do_test_limit (0, 0, 15 - i, 16 - i, 127, -1);
+ do_test_limit (0, 0, 15 - i, 16 - i, 255, 0);
+ do_test_limit (0, 0, 15 - i, 16 - i, 255, 1);
+ do_test_limit (0, 0, 15 - i, 16 - i, 255, -1);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strncpy.c b/REORG.TODO/string/test-strncpy.c
new file mode 100644
index 0000000000..43f9c236f1
--- /dev/null
+++ b/REORG.TODO/string/test-strncpy.c
@@ -0,0 +1,323 @@
+/* Test strncpy functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef WIDE
+# include <wchar.h>
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+# define MEMCMP wmemcmp
+# define MEMSET wmemset
+# define STRNLEN wcsnlen
+#else
+# define CHAR char
+# define UCHAR unsigned char
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+# define MEMCMP memcmp
+# define MEMSET memset
+# define STRNLEN strnlen
+#endif /* !WIDE */
+
+
+#ifndef STRNCPY_RESULT
+# define STRNCPY_RESULT(dst, len, n) dst
+# define TEST_MAIN
+# ifndef WIDE
+# define TEST_NAME "strncpy"
+# else
+# define TEST_NAME "wcsncpy"
+# endif /* WIDE */
+# include "test-string.h"
+# ifndef WIDE
+# define SIMPLE_STRNCPY simple_strncpy
+# define STUPID_STRNCPY stupid_strncpy
+# define STRNCPY strncpy
+# else
+# define SIMPLE_STRNCPY simple_wcsncpy
+# define STUPID_STRNCPY stupid_wcsncpy
+# define STRNCPY wcsncpy
+# endif /* WIDE */
+
+CHAR *SIMPLE_STRNCPY (CHAR *, const CHAR *, size_t);
+CHAR *STUPID_STRNCPY (CHAR *, const CHAR *, size_t);
+
+IMPL (STUPID_STRNCPY, 0)
+IMPL (SIMPLE_STRNCPY, 0)
+IMPL (STRNCPY, 1)
+
+CHAR *
+SIMPLE_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
+{
+ CHAR *ret = dst;
+ while (n--)
+ if ((*dst++ = *src++) == '\0')
+ {
+ while (n--)
+ *dst++ = '\0';
+ return ret;
+ }
+ return ret;
+}
+
+CHAR *
+STUPID_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
+{
+ size_t nc = STRNLEN (src, n);
+ size_t i;
+
+ for (i = 0; i < nc; ++i)
+ dst[i] = src[i];
+ for (; i < n; ++i)
+ dst[i] = '\0';
+ return dst;
+}
+#endif /* !STRNCPY_RESULT */
+
+typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
+
+static void
+do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, size_t len, size_t n)
+{
+ if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n))
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ CALL (impl, dst, src, n), dst);
+ ret = 1;
+ return;
+ }
+
+ if (memcmp (dst, src, (len > n ? n : len) * sizeof (CHAR)) != 0)
+ {
+ error (0, 0, "Wrong result in function %s", impl->name);
+ ret = 1;
+ return;
+ }
+
+ if (n > len)
+ {
+ size_t i;
+
+ for (i = len; i < n; ++i)
+ if (dst [i] != '\0')
+ {
+ error (0, 0, "Wrong result in function %s", impl->name);
+ ret = 1;
+ return;
+ }
+ }
+}
+
+static void
+do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
+{
+ size_t i;
+ CHAR *s1, *s2;
+
+/* For wcsncpy: align1 and align2 here mean alignment not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)). */
+ align1 &= 7;
+ if ((align1 + len) * sizeof (CHAR) >= page_size)
+ return;
+
+ align2 &= 7;
+ if ((align2 + len) * sizeof (CHAR) >= page_size)
+ return;
+
+ s1 = (CHAR *) (buf1) + align1;
+ s2 = (CHAR *) (buf2) + align2;
+
+ for (i = 0; i < len; ++i)
+ s1[i] = 32 + 23 * i % (max_char - 32);
+ s1[len] = 0;
+ for (i = len + 1; (i + align1) * sizeof (CHAR) < page_size && i < len + 64;
+ ++i)
+ s1[i] = 32 + 32 * i % (max_char - 32);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s2, s1, len, n);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align1, align2, len, size, mode;
+ UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
+ UCHAR *res;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ /* For wcsncpy: align1 and align2 here mean align not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof
+ (wchar_t)). */
+
+ mode = random ();
+ if (mode & 1)
+ {
+ size = random () & 255;
+ align1 = 512 - size - (random () & 15);
+ if (mode & 2)
+ align2 = align1 - (random () & 24);
+ else
+ align2 = align1 - (random () & 31);
+ if (mode & 4)
+ {
+ j = align1;
+ align1 = align2;
+ align2 = j;
+ }
+ if (mode & 8)
+ len = size - (random () & 31);
+ else
+ len = 512;
+ if (len >= 512)
+ len = random () & 511;
+ }
+ else
+ {
+ align1 = random () & 31;
+ if (mode & 2)
+ align2 = random () & 31;
+ else
+ align2 = align1 + (random () & 24);
+ len = random () & 511;
+ j = align1;
+ if (align2 > j)
+ j = align2;
+ if (mode & 4)
+ {
+ size = random () & 511;
+ if (size + j > 512)
+ size = 512 - j - (random () & 31);
+ }
+ else
+ size = 512 - j;
+ if ((mode & 8) && len + j >= 512)
+ len = 512 - j - (random () & 7);
+ }
+ j = len + align1 + 64;
+ if (j > 512)
+ j = 512;
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align1)
+ p1[i] = 0;
+ else
+ {
+ p1[i] = random () & BIG_CHAR;
+ if (i >= align1 && i < len + align1 && !p1[i])
+ p1[i] = (random () & SMALL_CHAR) + 3;
+ }
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ MEMSET (p2 - 64, '\1', 512 + 64);
+ res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2),
+ (CHAR *) (p1 + align1), size);
+ if (res != STRNCPY_RESULT (p2 + align2, len, size))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
+ n, impl->name, align1, align2, len, res,
+ STRNCPY_RESULT (p2 + align2, len, size));
+ ret = 1;
+ }
+ for (j = 0; j < align2 + 64; ++j)
+ {
+ if (p2[j - 64] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ j = align2 + len + 1;
+ if (size + align2 > j)
+ j = size + align2;
+ for (; j < 512; ++j)
+ {
+ if (p2[j] != '\1')
+ {
+ error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ }
+ for (j = align2 + len + 1; j < align2 + size; ++j)
+ if (p2[j])
+ {
+ error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ break;
+ }
+ j = len + 1;
+ if (size < j)
+ j = size;
+ if (MEMCMP (p1 + align1, p2 + align2, j))
+ {
+ error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+ n, impl->name, align1, align2, len);
+ ret = 1;
+ }
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%28s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, i, 16, 16, SMALL_CHAR);
+ do_test (i, i, 16, 16, BIG_CHAR);
+ do_test (i, 2 * i, 16, 16, SMALL_CHAR);
+ do_test (2 * i, i, 16, 16, BIG_CHAR);
+ do_test (8 - i, 2 * i, 1 << i, 2 << i, SMALL_CHAR);
+ do_test (2 * i, 8 - i, 2 << i, 1 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 1 << i, 2 << i, BIG_CHAR);
+ do_test (2 * i, 8 - i, 2 << i, 1 << i, BIG_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 0, 4 << i, 8 << i, SMALL_CHAR);
+ do_test (0, 0, 16 << i, 8 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 4 << i, 8 << i, SMALL_CHAR);
+ do_test (8 - i, 2 * i, 16 << i, 8 << i, SMALL_CHAR);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strnlen.c b/REORG.TODO/string/test-strnlen.c
new file mode 100644
index 0000000000..e56cdb6708
--- /dev/null
+++ b/REORG.TODO/string/test-strnlen.c
@@ -0,0 +1,248 @@
+/* Test strlen functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strnlen"
+#else
+# define TEST_NAME "wcsnlen"
+#endif /* !WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRNLEN strnlen
+# define CHAR char
+# define BIG_CHAR CHAR_MAX
+# define MIDDLE_CHAR 127
+# define SIMPLE_STRNLEN simple_strnlen
+#else
+# include <wchar.h>
+# define STRNLEN wcsnlen
+# define CHAR wchar_t
+# define BIG_CHAR WCHAR_MAX
+# define MIDDLE_CHAR 1121
+# define SIMPLE_STRNLEN simple_wcsnlen
+#endif /* !WIDE */
+
+typedef size_t (*proto_t) (const CHAR *, size_t);
+size_t SIMPLE_STRNLEN (const CHAR *, size_t);
+
+IMPL (SIMPLE_STRNLEN, 0)
+IMPL (STRNLEN, 1)
+
+size_t
+SIMPLE_STRNLEN (const CHAR *s, size_t maxlen)
+{
+ size_t i;
+
+ for (i = 0; i < maxlen && s[i]; ++i);
+ return i;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, size_t maxlen, size_t exp_len)
+{
+ size_t len = CALL (impl, s, maxlen);
+ if (len != exp_len)
+ {
+ error (0, 0, "Wrong result in function %s %zd %zd", impl->name,
+ len, exp_len);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t len, size_t maxlen, int max_char)
+{
+ size_t i;
+
+ align &= 63;
+ if ((align + len) * sizeof (CHAR) >= page_size)
+ return;
+
+ CHAR *buf = (CHAR *) (buf1);
+
+ for (i = 0; i < len; ++i)
+ buf[align + i] = 1 + 11111 * i % max_char;
+ buf[align + len] = 0;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (CHAR *) (buf + align), maxlen, MIN (len, maxlen));
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, len;
+ CHAR *p = (CHAR *) (buf1 + page_size - 512 * sizeof (CHAR));
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ len = random () & 511;
+ if (len + align > 510)
+ len = 511 - align - (random () & 7);
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align)
+ p[i] = 0;
+ else
+ {
+ p[i] = random () & 255;
+ if (i >= align && i < len + align && !p[i])
+ p[i] = (random () & 127) + 1;
+ }
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ {
+ if (len > 0
+ && CALL (impl, (CHAR *) (p + align), len - 1) != len - 1)
+ {
+ error (0, 0, "Iteration %zd (limited) - wrong result in function %s (%zd) %zd != %zd, p %p",
+ n, impl->name, align,
+ CALL (impl, (CHAR *) (p + align), len - 1), len - 1, p);
+ ret = 1;
+ }
+ if (CALL (impl, (CHAR *) (p + align), len) != len)
+ {
+ error (0, 0, "Iteration %zd (exact) - wrong result in function %s (%zd) %zd != %zd, p %p",
+ n, impl->name, align,
+ CALL (impl, (CHAR *) (p + align), len), len, p);
+ ret = 1;
+ }
+ if (CALL (impl, (CHAR *) (p + align), len + 1) != len)
+ {
+ error (0, 0, "Iteration %zd (long) - wrong result in function %s (%zd) %zd != %zd, p %p",
+ n, impl->name, align,
+ CALL (impl, (CHAR *) (p + align), len + 1), len, p);
+ ret = 1;
+ }
+ }
+ }
+}
+
+/* Tests meant to unveil fail on implementation that does not access bytes
+ around the page boundary accordingly. */
+static void
+do_page_tests (void)
+{
+ size_t i, exp_len, start_offset, offset;
+ /* Calculate the null character offset. */
+ size_t last_offset = (page_size / sizeof (CHAR)) - 1;
+
+ CHAR *s = (CHAR *) buf2;
+ memset (s, 65, (last_offset - 1));
+ s[last_offset] = 0;
+
+ /* Place short strings ending at page boundary. */
+ offset = last_offset;
+ for (i = 0; i < 128; i++)
+ {
+ /* Decrease offset to stress several sizes and alignments. */
+ offset--;
+ exp_len = last_offset - offset;
+ FOR_EACH_IMPL (impl, 0)
+ {
+ /* Varies maxlen value to cover the cases where it is:
+ - larger than length;
+ - slightly greater than length;
+ - equal to length;
+ - slightly less than length. */
+ do_one_test (impl, (CHAR *) (s + offset), page_size, exp_len);
+ do_one_test (impl, (CHAR *) (s + offset), exp_len + 1, exp_len);
+ do_one_test (impl, (CHAR *) (s + offset), exp_len, exp_len);
+ if (exp_len > 0)
+ do_one_test (impl, (CHAR *) (s + offset), exp_len - 1, exp_len - 1);
+ }
+ }
+
+ /* Place long strings ending at page boundary. */
+ start_offset = (last_offset + 1) / 2;
+ for (i = 0; i < 64; ++i)
+ {
+ /* Increase offset to stress several alignments. */
+ offset = start_offset + i;
+ if (offset >= (last_offset + 1))
+ break;
+ exp_len = last_offset - offset;
+ FOR_EACH_IMPL (impl, 0)
+ {
+ /* Checks only for maxlen much larger than length because smaller
+ values are already covered in do_random_tests function. */
+ do_one_test (impl, (CHAR *) (s + offset), page_size, exp_len);
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, i, i - 1, MIDDLE_CHAR);
+ do_test (0, i, i, MIDDLE_CHAR);
+ do_test (0, i, i + 1, MIDDLE_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, i, i - 1, MIDDLE_CHAR);
+ do_test (i, i, i, MIDDLE_CHAR);
+ do_test (i, i, i + 1, MIDDLE_CHAR);
+ }
+
+ for (i = 2; i <= 10; ++i)
+ {
+ do_test (0, 1 << i, 5000, MIDDLE_CHAR);
+ do_test (1, 1 << i, 5000, MIDDLE_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ do_test (0, i, 5000, BIG_CHAR);
+
+ for (i = 1; i < 8; ++i)
+ do_test (i, i, 5000, BIG_CHAR);
+
+ for (i = 2; i <= 10; ++i)
+ {
+ do_test (0, 1 << i, 5000, BIG_CHAR);
+ do_test (1, 1 << i, 5000, BIG_CHAR);
+ }
+
+ do_random_tests ();
+ do_page_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strpbrk.c b/REORG.TODO/string/test-strpbrk.c
new file mode 100644
index 0000000000..4d680ab354
--- /dev/null
+++ b/REORG.TODO/string/test-strpbrk.c
@@ -0,0 +1,267 @@
+/* Test and measure strpbrk functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef WIDE
+# define CHAR char
+# define UCHAR unsigned char
+# define STRLEN strlen
+# define STRCHR strchr
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#else
+# include <wchar.h>
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define STRLEN wcslen
+# define STRCHR wcschr
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#endif /* WIDE */
+
+#ifndef STRPBRK_RESULT
+# define STRPBRK_RESULT(s, pos) ((s)[(pos)] ? (s) + (pos) : NULL)
+# define RES_TYPE CHAR *
+# define TEST_MAIN
+# ifndef WIDE
+# define TEST_NAME "strpbrk"
+# else
+# define TEST_NAME "wcspbrk"
+# endif /* WIDE */
+# include "test-string.h"
+
+# ifndef WIDE
+# define STRPBRK strpbrk
+# define SIMPLE_STRPBRK simple_strpbrk
+# define STUPID_STRPBRK stupid_strpbrk
+# else
+# include <wchar.h>
+# define STRPBRK wcspbrk
+# define SIMPLE_STRPBRK simple_wcspbrk
+# define STUPID_STRPBRK stupid_wcspbrk
+# endif /* WIDE */
+
+typedef CHAR *(*proto_t) (const CHAR *, const CHAR *);
+CHAR *SIMPLE_STRPBRK (const CHAR *, const CHAR *);
+CHAR *STUPID_STRPBRK (const CHAR *, const CHAR *);
+
+IMPL (STUPID_STRPBRK, 0)
+IMPL (SIMPLE_STRPBRK, 0)
+IMPL (STRPBRK, 1)
+
+CHAR *
+SIMPLE_STRPBRK (const CHAR *s, const CHAR *rej)
+{
+ const CHAR *r;
+ CHAR c;
+
+ while ((c = *s++) != '\0')
+ for (r = rej; *r != '\0'; ++r)
+ if (*r == c)
+ return (CHAR *) s - 1;
+ return NULL;
+}
+
+CHAR *
+STUPID_STRPBRK (const CHAR *s, const CHAR *rej)
+{
+ size_t ns = STRLEN (s), nrej = STRLEN (rej);
+ size_t i, j;
+
+ for (i = 0; i < ns; ++i)
+ for (j = 0; j < nrej; ++j)
+ if (s[i] == rej[j])
+ return (CHAR *) s + i;
+ return NULL;
+}
+#endif /* !STRPBRK_RESULT */
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, const CHAR *rej, RES_TYPE exp_res)
+{
+ RES_TYPE res = CALL (impl, s, rej);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ (void *) res, (void *) exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len)
+{
+ size_t i;
+ int c;
+ RES_TYPE result;
+ CHAR *rej, *s;
+
+ align &= 7;
+ if ((align + pos + 10) * sizeof (CHAR) >= page_size || len > 240)
+ return;
+
+ rej = (CHAR *) (buf2) + (random () & 255);
+ s = (CHAR *) (buf1) + align;
+
+ for (i = 0; i < len; ++i)
+ {
+ rej[i] = random () & BIG_CHAR;
+ if (!rej[i])
+ rej[i] = random () & BIG_CHAR;
+ if (!rej[i])
+ rej[i] = 1 + (random () & SMALL_CHAR);
+ }
+ rej[len] = '\0';
+ for (c = 1; c <= BIG_CHAR; ++c)
+ if (STRCHR (rej, c) == NULL)
+ break;
+
+ for (i = 0; i < pos; ++i)
+ {
+ s[i] = random () & BIG_CHAR;
+ if (STRCHR (rej, s[i]))
+ {
+ s[i] = random () & BIG_CHAR;
+ if (STRCHR (rej, s[i]))
+ s[i] = c;
+ }
+ }
+ s[pos] = rej[random () % (len + 1)];
+ if (s[pos])
+ {
+ for (i = pos + 1; i < pos + 10; ++i)
+ s[i] = random () & BIG_CHAR;
+ s[i] = '\0';
+ }
+ result = STRPBRK_RESULT (s, pos);
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s, rej, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len, rlen;
+ RES_TYPE result;
+ int c;
+ UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *rej;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ pos = random () & 511;
+ if (pos + align >= 511)
+ pos = 510 - align - (random () & 7);
+ len = random () & 511;
+ if (pos >= len && (random () & 1))
+ len = pos + 1 + (random () & 7);
+ if (len + align >= 512)
+ len = 511 - align - (random () & 7);
+ if (random () & 1)
+ rlen = random () & 63;
+ else
+ rlen = random () & 15;
+ rej = (UCHAR *) (buf2 + page_size) - rlen - 1 - (random () & 7);
+ for (i = 0; i < rlen; ++i)
+ {
+ rej[i] = random () & BIG_CHAR;
+ if (!rej[i])
+ rej[i] = random () & BIG_CHAR;
+ if (!rej[i])
+ rej[i] = 1 + (random () & SMALL_CHAR);
+ }
+ rej[i] = '\0';
+ for (c = 1; c <= BIG_CHAR; ++c)
+ if (STRCHR ((CHAR *) rej, c) == NULL)
+ break;
+ j = (pos > len ? pos : len) + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align)
+ p[i] = '\0';
+ else if (i == pos + align)
+ p[i] = rej[random () % (rlen + 1)];
+ else if (i < align || i > pos + align)
+ p[i] = random () & BIG_CHAR;
+ else
+ {
+ p[i] = random () & BIG_CHAR;
+ if (STRCHR ((CHAR *) rej, p[i]))
+ {
+ p[i] = random () & BIG_CHAR;
+ if (STRCHR ((CHAR *) rej, p[i]))
+ p[i] = c;
+ }
+ }
+ }
+
+ result = STRPBRK_RESULT ((CHAR *) (p + align), pos < len ? pos : len);
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align), (CHAR *) rej) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd, %zd) %p != %p",
+ n, impl->name, align, rej, rlen, pos, len,
+ (void *) CALL (impl, (CHAR *) (p + align), (CHAR *) rej),
+ (void *) result);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%32s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, 512, i);
+ do_test (i, 512, i);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 4);
+ do_test (i, 16 << i, 4);
+ }
+
+ for (i = 1; i < 8; ++i)
+ do_test (i, 64, 10);
+
+ for (i = 0; i < 64; ++i)
+ do_test (0, i, 6);
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strrchr.c b/REORG.TODO/string/test-strrchr.c
new file mode 100644
index 0000000000..10c070aef1
--- /dev/null
+++ b/REORG.TODO/string/test-strrchr.c
@@ -0,0 +1,247 @@
+/* Test and measure STRCHR functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+ Added wcsrrchr support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>,
+ 2011.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifdef WIDE
+# define TEST_NAME "wcsrchr"
+#else
+# define TEST_NAME "strrchr"
+#endif
+#include "test-string.h"
+
+#ifdef WIDE
+# include <wchar.h>
+# define SIMPLE_STRRCHR simple_wcsrchr
+# define STRRCHR wcsrchr
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#else
+# define SIMPLE_STRRCHR simple_strrchr
+# define STRRCHR strrchr
+# define CHAR char
+# define UCHAR unsigned char
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#endif
+
+typedef CHAR *(*proto_t) (const CHAR *, int);
+CHAR *SIMPLE_STRRCHR (const CHAR *, int);
+
+IMPL (SIMPLE_STRRCHR, 0)
+IMPL (STRRCHR, 1)
+
+CHAR *
+SIMPLE_STRRCHR (const CHAR *s, int c)
+{
+ const CHAR *ret = NULL;
+
+ for (; *s != '\0'; ++s)
+ if (*s == (CHAR) c)
+ ret = s;
+
+ return (CHAR *) (c == '\0' ? s : ret);
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res)
+{
+ CHAR *res = CALL (impl, s, c);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ res, exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
+/* For wcsrchr: align here means align not in bytes,
+ but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
+ len for wcschr here isn't in bytes but it's number of wchar_t symbols. */
+{
+ size_t i;
+ CHAR *result;
+ CHAR *buf = (CHAR *) buf1;
+
+ align &= 7;
+ if ( (align + len) * sizeof(CHAR) >= page_size)
+ return;
+
+ for (i = 0; i < len; ++i)
+ {
+ buf[align + i] = (random () * random ()) & max_char;
+ if (!buf[align + i])
+ buf[align + i] = (random () * random ()) & max_char;
+ if (!buf[align + i])
+ buf[align + i] = 1;
+ if ((i > pos || pos >= len) && buf[align + i] == seek_char)
+ buf[align + i] = seek_char + 10 + (random () & 15);
+ }
+ buf[align + len] = 0;
+
+ if (pos < len)
+ {
+ buf[align + pos] = seek_char;
+ result = (CHAR *) (buf + align + pos);
+ }
+ else if (seek_char == 0)
+ result = (CHAR *) (buf + align + len);
+ else
+ result = NULL;
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, (CHAR *) (buf + align), seek_char, result);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, len;
+ int seek_char;
+ CHAR *result;
+ UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & (63 / sizeof(CHAR));
+ /* For wcsrchr: align here means align not in bytes, but in wchar_ts,
+ in bytes it will equal to align * (sizeof (wchar_t)).
+ For strrchr we need to check all alignments from 0 to 63 since
+ some assembly implementations have separate prolog for alignments
+ more 48. */
+ pos = random () & 511;
+ if (pos + align >= 511)
+ pos = 510 - align - (random () & 7);
+ len = random () & 511;
+ /* len for wcschr here isn't in bytes but it's number of wchar_t
+ symbols. */
+ if (pos >= len)
+ len = pos + (random () & 7);
+ if (len + align >= 512)
+ len = 511 - align - (random () & 7);
+ seek_char = random () & 255;
+ if (seek_char && pos == len)
+ {
+ if (pos)
+ --pos;
+ else
+ ++len;
+ }
+ j = len + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == pos + align)
+ p[i] = seek_char;
+ else if (i == len + align)
+ p[i] = 0;
+ else
+ {
+ p[i] = random () & 255;
+ if (((i > pos + align && i < len + align) || pos > len)
+ && p[i] == seek_char)
+ p[i] = seek_char + 13;
+ if (i < len + align && !p[i])
+ {
+ p[i] = seek_char - 13;
+ if (!p[i])
+ p[i] = 140;
+ }
+ }
+ }
+
+ if (pos <= len)
+ result = (CHAR *) (p + pos + align);
+ else if (seek_char == 0)
+ result = (CHAR *) (p + len + align);
+ else
+ result = NULL;
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align), seek_char) != result)
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+ n, impl->name, align, seek_char, len, pos,
+ CALL (impl, (CHAR *) (p + align), seek_char), result, p);
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%20s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 2048, 23, SMALL_CHAR);
+ do_test (i, 16 << i, 2048, 23, SMALL_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 64, 256, 23, SMALL_CHAR);
+ do_test (i, 64, 256, 23, BIG_CHAR);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, 23, SMALL_CHAR);
+ do_test (0, i, i + 1, 23, BIG_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 2048, 0, SMALL_CHAR);
+ do_test (i, 16 << i, 2048, 0, SMALL_CHAR);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (i, 64, 256, 0, SMALL_CHAR);
+ do_test (i, 64, 256, 0, BIG_CHAR);
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, i, i + 1, 0, SMALL_CHAR);
+ do_test (0, i, i + 1, 0, BIG_CHAR);
+ }
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strspn.c b/REORG.TODO/string/test-strspn.c
new file mode 100644
index 0000000000..d26331fb6d
--- /dev/null
+++ b/REORG.TODO/string/test-strspn.c
@@ -0,0 +1,245 @@
+/* Test and measure strspn functions.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#ifndef WIDE
+# define TEST_NAME "strspn"
+#else
+# define TEST_NAME "wcsspn"
+#endif /* WIDE */
+#include "test-string.h"
+
+#ifndef WIDE
+# define STRSPN strspn
+# define CHAR char
+# define UCHAR unsigned char
+# define SIMPLE_STRSPN simple_strspn
+# define STUPID_STRSPN stupid_strspn
+# define STRLEN strlen
+# define STRCHR strchr
+# define BIG_CHAR CHAR_MAX
+# define SMALL_CHAR 127
+#else
+# include <wchar.h>
+# define STRSPN wcsspn
+# define CHAR wchar_t
+# define UCHAR wchar_t
+# define SIMPLE_STRSPN simple_wcsspn
+# define STUPID_STRSPN stupid_wcsspn
+# define STRLEN wcslen
+# define STRCHR wcschr
+# define BIG_CHAR WCHAR_MAX
+# define SMALL_CHAR 1273
+#endif /* WIDE */
+
+typedef size_t (*proto_t) (const CHAR *, const CHAR *);
+size_t SIMPLE_STRSPN (const CHAR *, const CHAR *);
+size_t STUPID_STRSPN (const CHAR *, const CHAR *);
+
+IMPL (STUPID_STRSPN, 0)
+IMPL (SIMPLE_STRSPN, 0)
+IMPL (STRSPN, 1)
+
+size_t
+SIMPLE_STRSPN (const CHAR *s, const CHAR *acc)
+{
+ const CHAR *r, *str = s;
+ CHAR c;
+
+ while ((c = *s++) != '\0')
+ {
+ for (r = acc; *r != '\0'; ++r)
+ if (*r == c)
+ break;
+ if (*r == '\0')
+ return s - str - 1;
+ }
+ return s - str - 1;
+}
+
+size_t
+STUPID_STRSPN (const CHAR *s, const CHAR *acc)
+{
+ size_t ns = STRLEN (s), nacc = STRLEN (acc);
+ size_t i, j;
+
+ for (i = 0; i < ns; ++i)
+ {
+ for (j = 0; j < nacc; ++j)
+ if (s[i] == acc[j])
+ break;
+ if (j == nacc)
+ return i;
+ }
+ return i;
+}
+
+static void
+do_one_test (impl_t *impl, const CHAR *s, const CHAR *acc, size_t exp_res)
+{
+ size_t res = CALL (impl, s, acc);
+ if (res != exp_res)
+ {
+ error (0, 0, "Wrong result in function %s %p %p", impl->name,
+ (void *) res, (void *) exp_res);
+ ret = 1;
+ return;
+ }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len)
+{
+ size_t i;
+ CHAR *acc, *s;
+
+ align &= 7;
+ if ((align + pos + 10) * sizeof (CHAR) >= page_size || len > 240 || ! len)
+ return;
+
+ acc = (CHAR *) (buf2) + (random () & 255);
+ s = (CHAR *) (buf1) + align;
+
+ for (i = 0; i < len; ++i)
+ {
+ acc[i] = random () & BIG_CHAR;
+ if (!acc[i])
+ acc[i] = random () & BIG_CHAR;
+ if (!acc[i])
+ acc[i] = 1 + (random () & SMALL_CHAR);
+ }
+ acc[len] = '\0';
+
+ for (i = 0; i < pos; ++i)
+ s[i] = acc[random () % len];
+ s[pos] = random () & BIG_CHAR;
+ if (STRCHR (acc, s[pos]))
+ s[pos] = '\0';
+ else
+ {
+ for (i = pos + 1; i < pos + 10; ++i)
+ s[i] = random () & BIG_CHAR;
+ s[i] = '\0';
+ }
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s, acc, pos);
+}
+
+static void
+do_random_tests (void)
+{
+ size_t i, j, n, align, pos, alen, len;
+ UCHAR *p = (UCHAR *) (buf1 + page_size) - 512;
+ UCHAR *acc;
+
+ for (n = 0; n < ITERATIONS; n++)
+ {
+ align = random () & 15;
+ if (random () & 1)
+ alen = random () & 63;
+ else
+ alen = random () & 15;
+ if (!alen)
+ pos = 0;
+ else
+ pos = random () & 511;
+ if (pos + align >= 511)
+ pos = 510 - align - (random () & 7);
+ len = random () & 511;
+ if (len + align >= 512)
+ len = 511 - align - (random () & 7);
+ acc = (UCHAR *) (buf2 + page_size) - alen - 1 - (random () & 7);
+ for (i = 0; i < alen; ++i)
+ {
+ acc[i] = random () & BIG_CHAR;
+ if (!acc[i])
+ acc[i] = random () & BIG_CHAR;
+ if (!acc[i])
+ acc[i] = 1 + (random () & SMALL_CHAR);
+ }
+ acc[i] = '\0';
+ j = (pos > len ? pos : len) + align + 64;
+ if (j > 512)
+ j = 512;
+
+ for (i = 0; i < j; i++)
+ {
+ if (i == len + align)
+ p[i] = '\0';
+ else if (i == pos + align)
+ {
+ p[i] = random () & BIG_CHAR;
+ if (STRCHR ((CHAR *) acc, p[i]))
+ p[i] = '\0';
+ }
+ else if (i < align || i > pos + align)
+ p[i] = random () & BIG_CHAR;
+ else
+ p[i] = acc [random () % alen];
+ }
+
+ FOR_EACH_IMPL (impl, 1)
+ if (CALL (impl, (CHAR *) (p + align),
+ (CHAR *) acc) != (pos < len ? pos : len))
+ {
+ error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd, %zd) %zd != %zd",
+ n, impl->name, align, acc, alen, pos, len,
+ CALL (impl, (CHAR *) (p + align), (CHAR *) acc),
+ (pos < len ? pos : len));
+ ret = 1;
+ }
+ }
+}
+
+int
+test_main (void)
+{
+ size_t i;
+
+ test_init ();
+
+ printf ("%32s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (i = 0; i < 32; ++i)
+ {
+ do_test (0, 512, i);
+ do_test (i, 512, i);
+ }
+
+ for (i = 1; i < 8; ++i)
+ {
+ do_test (0, 16 << i, 4);
+ do_test (i, 16 << i, 4);
+ }
+
+ for (i = 1; i < 8; ++i)
+ do_test (i, 64, 10);
+
+ for (i = 0; i < 64; ++i)
+ do_test (0, i, 6);
+
+ do_random_tests ();
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/test-strstr.c b/REORG.TODO/string/test-strstr.c
new file mode 100644
index 0000000000..33f221149a
--- /dev/null
+++ b/REORG.TODO/string/test-strstr.c
@@ -0,0 +1,212 @@
+/* Test and measure strstr functions.
+ Copyright (C) 2010-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2010.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define TEST_NAME "strstr"
+#include "test-string.h"
+
+
+#define STRSTR simple_strstr
+#define libc_hidden_builtin_def(arg) /* nothing */
+#include "strstr.c"
+
+
+static char *
+stupid_strstr (const char *s1, const char *s2)
+{
+ ssize_t s1len = strlen (s1);
+ ssize_t s2len = strlen (s2);
+
+ if (s2len > s1len)
+ return NULL;
+
+ for (ssize_t i = 0; i <= s1len - s2len; ++i)
+ {
+ size_t j;
+ for (j = 0; j < s2len; ++j)
+ if (s1[i + j] != s2[j])
+ break;
+ if (j == s2len)
+ return (char *) s1 + i;
+ }
+
+ return NULL;
+}
+
+
+typedef char *(*proto_t) (const char *, const char *);
+
+IMPL (stupid_strstr, 0)
+IMPL (simple_strstr, 0)
+IMPL (strstr, 1)
+
+
+static int
+check_result (impl_t *impl, const char *s1, const char *s2,
+ char *exp_result)
+{
+ char *result = CALL (impl, s1, s2);
+ if (result != exp_result)
+ {
+ error (0, 0, "Wrong result in function %s %s %s", impl->name,
+ result, exp_result);
+ ret = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result)
+{
+ if (check_result (impl, s1, s2, exp_result) < 0)
+ return;
+}
+
+
+static void
+do_test (size_t align1, size_t align2, size_t len1, size_t len2,
+ int fail)
+{
+ char *s1 = (char *) (buf1 + align1);
+ char *s2 = (char *) (buf2 + align2);
+
+ static const char d[] = "1234567890abcdef";
+#define dl (sizeof (d) - 1)
+ char *ss2 = s2;
+ for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0)
+ {
+ size_t t = l > dl ? dl : l;
+ ss2 = mempcpy (ss2, d, t);
+ }
+ s2[len2] = '\0';
+
+ if (fail)
+ {
+ char *ss1 = s1;
+ for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0)
+ {
+ size_t t = l > dl ? dl : l;
+ memcpy (ss1, d, t);
+ ++ss1[len2 > 7 ? 7 : len2 - 1];
+ ss1 += t;
+ }
+ }
+ else
+ {
+ memset (s1, '0', len1);
+ memcpy (s1 + len1 - len2, s2, len2);
+ }
+ s1[len1] = '\0';
+
+ FOR_EACH_IMPL (impl, 0)
+ do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2);
+
+}
+
+static void
+check1 (void)
+{
+ const char s1[] =
+ "F_BD_CE_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_88_20_EF_BF_BD_EF_BF_BD_EF_BF_BD_C3_A7_20_EF_BF_BD";
+ const char s2[] = "_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD_EF_BF_BD";
+ char *exp_result;
+
+ exp_result = stupid_strstr (s1, s2);
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, exp_result);
+}
+
+static void
+check2 (void)
+{
+ const char s1[] = ", enable_static, \0, enable_shared, ";
+ char *exp_result;
+ char *s2 = (void *) buf1 + page_size - 18;
+
+ strcpy (s2, s1);
+ exp_result = stupid_strstr (s1, s1 + 18);
+ FOR_EACH_IMPL (impl, 0)
+ {
+ check_result (impl, s1, s1 + 18, exp_result);
+ check_result (impl, s2, s1 + 18, exp_result);
+ }
+}
+
+static int
+test_main (void)
+{
+ test_init ();
+
+ check1 ();
+ check2 ();
+
+ printf ("%23s", "");
+ FOR_EACH_IMPL (impl, 0)
+ printf ("\t%s", impl->name);
+ putchar ('\n');
+
+ for (size_t klen = 2; klen < 32; ++klen)
+ for (size_t hlen = 2 * klen; hlen < 16 * klen; hlen += klen)
+ {
+ do_test (0, 0, hlen, klen, 0);
+ do_test (0, 0, hlen, klen, 1);
+ do_test (0, 3, hlen, klen, 0);
+ do_test (0, 3, hlen, klen, 1);
+ do_test (0, 9, hlen, klen, 0);
+ do_test (0, 9, hlen, klen, 1);
+ do_test (0, 15, hlen, klen, 0);
+ do_test (0, 15, hlen, klen, 1);
+
+ do_test (3, 0, hlen, klen, 0);
+ do_test (3, 0, hlen, klen, 1);
+ do_test (3, 3, hlen, klen, 0);
+ do_test (3, 3, hlen, klen, 1);
+ do_test (3, 9, hlen, klen, 0);
+ do_test (3, 9, hlen, klen, 1);
+ do_test (3, 15, hlen, klen, 0);
+ do_test (3, 15, hlen, klen, 1);
+
+ do_test (9, 0, hlen, klen, 0);
+ do_test (9, 0, hlen, klen, 1);
+ do_test (9, 3, hlen, klen, 0);
+ do_test (9, 3, hlen, klen, 1);
+ do_test (9, 9, hlen, klen, 0);
+ do_test (9, 9, hlen, klen, 1);
+ do_test (9, 15, hlen, klen, 0);
+ do_test (9, 15, hlen, klen, 1);
+
+ do_test (15, 0, hlen, klen, 0);
+ do_test (15, 0, hlen, klen, 1);
+ do_test (15, 3, hlen, klen, 0);
+ do_test (15, 3, hlen, klen, 1);
+ do_test (15, 9, hlen, klen, 0);
+ do_test (15, 9, hlen, klen, 1);
+ do_test (15, 15, hlen, klen, 0);
+ do_test (15, 15, hlen, klen, 1);
+ }
+
+ do_test (0, 0, page_size - 1, 16, 0);
+ do_test (0, 0, page_size - 1, 16, 1);
+
+ return ret;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/testcopy.c b/REORG.TODO/string/testcopy.c
new file mode 100644
index 0000000000..8c9dd4c500
--- /dev/null
+++ b/REORG.TODO/string/testcopy.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 1990-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+int
+main (void)
+{
+ char *mem, *memp;
+ char *rand_mem;
+ char *lo_around, *hi_around;
+ int size, max_size;
+ int src_off, dst_off;
+ int i;
+ int space_around = 10;
+
+ max_size = 256;
+
+ mem = malloc (max_size + 2 * max_size + 2 * space_around);
+ rand_mem = malloc (max_size);
+ lo_around = malloc (space_around);
+ hi_around = malloc (space_around);
+ memp = mem + space_around;
+
+ /* Fill RAND_MEM with random bytes, each non-zero. */
+ for (i = 0; i < max_size; i++)
+ {
+ int x;
+ do
+ x = random ();
+ while (x == 0);
+ rand_mem[i] = x;
+ }
+
+ for (size = 0; size < max_size; size++)
+ {
+ printf("phase %d\n", size);
+ for (src_off = 0; src_off <= 16; src_off++)
+ {
+ for (dst_off = 0; dst_off <= 16; dst_off++)
+ {
+ /* Put zero around the intended destination, to check
+ that it's not clobbered. */
+ for (i = 1; i < space_around; i++)
+ {
+ memp[dst_off - i] = 0;
+ memp[dst_off + size - 1 + i] = 0;
+ }
+
+ /* Fill the source area with known contents. */
+ for (i = 0; i < size; i++)
+ memp[src_off + i] = rand_mem[i];
+
+ /* Remember the contents around the destination area.
+ (It might not be what we wrote some lines above, since
+ the src area and the dst area overlap.) */
+ for (i = 1; i < space_around; i++)
+ {
+ lo_around[i] = memp[dst_off - i];
+ hi_around[i] = memp[dst_off + size - 1 + i];
+ }
+
+ memmove (memp + dst_off, memp + src_off, size);
+
+ /* Check that the destination area has the same
+ contents we wrote to the source area. */
+ for (i = 0; i < size; i++)
+ {
+ if (memp[dst_off + i] != rand_mem[i])
+ abort ();
+ }
+
+ /* Check that the area around the destination is not
+ clobbered. */
+ for (i = 1; i < space_around; i++)
+ {
+ if (memp[dst_off - i] != lo_around[i])
+ abort ();
+ if (memp[dst_off + size - 1 + i] != hi_around[i])
+ abort ();
+ }
+ }
+ }
+ }
+
+ puts ("Test succeeded.");
+
+ return 0;
+}
diff --git a/REORG.TODO/string/tester.c b/REORG.TODO/string/tester.c
new file mode 100644
index 0000000000..4b928b4f5e
--- /dev/null
+++ b/REORG.TODO/string/tester.c
@@ -0,0 +1,1685 @@
+/* Tester for string functions.
+ Copyright (C) 1995-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/* Make sure we don't test the optimized inline functions if we want to
+ test the real implementation. */
+#if !defined DO_STRING_INLINES
+#undef __USE_STRING_INLINES
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <libc-diag.h>
+
+
+#define STREQ(a, b) (strcmp((a), (b)) == 0)
+
+const char *it = "<UNSET>"; /* Routine name for message routines. */
+size_t errors = 0;
+
+/* Complain if condition is not true. */
+static void
+check (int thing, int number)
+{
+ if (!thing)
+ {
+ printf ("%s flunked test %d\n", it, number);
+ ++errors;
+ }
+}
+
+/* Complain if first two args don't strcmp as equal. */
+static void
+equal (const char *a, const char *b, int number)
+{
+ check (a != NULL && b != NULL && STREQ (a, b), number);
+}
+
+char one[50];
+char two[50];
+char *cp;
+
+static void
+test_strcmp (void)
+{
+ it = "strcmp";
+ check (strcmp ("", "") == 0, 1); /* Trivial case. */
+ check (strcmp ("a", "a") == 0, 2); /* Identity. */
+ check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
+ check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
+ check (strcmp ("abcd", "abc") > 0, 5);
+ check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
+ check (strcmp ("abce", "abcd") > 0, 7);
+ check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
+ check (strcmp ("a\203", "a\003") > 0, 9);
+
+ {
+ char buf1[0x40], buf2[0x40];
+ int i, j;
+ for (i=0; i < 0x10; i++)
+ for (j = 0; j < 0x10; j++)
+ {
+ int k;
+ for (k = 0; k < 0x3f; k++)
+ {
+ buf1[k] = '0' ^ (k & 4);
+ buf2[k] = '4' ^ (k & 4);
+ }
+ buf1[i] = buf1[0x3f] = 0;
+ buf2[j] = buf2[0x3f] = 0;
+ for (k = 0; k < 0xf; k++)
+ {
+ int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
+ check (strcmp (buf1+i,buf2+j) == 0, cnum);
+ buf1[i+k] = 'A' + i + k;
+ buf1[i+k+1] = 0;
+ check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
+ check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
+ buf2[j+k] = 'B' + i + k;
+ buf2[j+k+1] = 0;
+ check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
+ check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
+ buf2[j+k] = 'A' + i + k;
+ buf1[i] = 'A' + i + 0x80;
+ check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
+ check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
+ buf1[i] = 'A' + i;
+ }
+ }
+ }
+}
+
+#define SIMPLE_COPY(fn, n, str, ntest) \
+ do { \
+ int __n; \
+ char *cp; \
+ for (__n = 0; __n < (int) sizeof (one); ++__n) \
+ one[__n] = 'Z'; \
+ fn (one, str); \
+ for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
+ check (*cp == '0' + (n % 10), ntest); \
+ check (*cp == '\0', ntest); \
+ } while (0)
+
+static void
+test_strcpy (void)
+{
+ int i;
+ it = "strcpy";
+ check (strcpy (one, "abcd") == one, 1); /* Returned value. */
+ equal (one, "abcd", 2); /* Basic test. */
+
+ (void) strcpy (one, "x");
+ equal (one, "x", 3); /* Writeover. */
+ equal (one+2, "cd", 4); /* Wrote too much? */
+
+ (void) strcpy (two, "hi there");
+ (void) strcpy (one, two);
+ equal (one, "hi there", 5); /* Basic test encore. */
+ equal (two, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy (one, "");
+ equal (one, "", 7); /* Boundary condition. */
+
+ for (i = 0; i < 16; i++)
+ {
+ (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
+ equal (one + i, "hi there", 8 + (i * 2));
+ (void) strcpy (two, one + i); /* Unaligned source. */
+ equal (two, "hi there", 9 + (i * 2));
+ }
+
+ SIMPLE_COPY(strcpy, 0, "", 41);
+ SIMPLE_COPY(strcpy, 1, "1", 42);
+ SIMPLE_COPY(strcpy, 2, "22", 43);
+ SIMPLE_COPY(strcpy, 3, "333", 44);
+ SIMPLE_COPY(strcpy, 4, "4444", 45);
+ SIMPLE_COPY(strcpy, 5, "55555", 46);
+ SIMPLE_COPY(strcpy, 6, "666666", 47);
+ SIMPLE_COPY(strcpy, 7, "7777777", 48);
+ SIMPLE_COPY(strcpy, 8, "88888888", 49);
+ SIMPLE_COPY(strcpy, 9, "999999999", 50);
+ SIMPLE_COPY(strcpy, 10, "0000000000", 51);
+ SIMPLE_COPY(strcpy, 11, "11111111111", 52);
+ SIMPLE_COPY(strcpy, 12, "222222222222", 53);
+ SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
+ SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
+ SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
+ SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
+
+ /* Simple test using implicitly coerced `void *' arguments. */
+ const void *src = "frobozz";
+ void *dst = one;
+ check (strcpy (dst, src) == dst, 1);
+ equal (dst, "frobozz", 2);
+}
+
+static void
+test_stpcpy (void)
+{
+ it = "stpcpy";
+ check ((stpcpy (one, "a") - one) == 1, 1);
+ equal (one, "a", 2);
+
+ check ((stpcpy (one, "ab") - one) == 2, 3);
+ equal (one, "ab", 4);
+
+ check ((stpcpy (one, "abc") - one) == 3, 5);
+ equal (one, "abc", 6);
+
+ check ((stpcpy (one, "abcd") - one) == 4, 7);
+ equal (one, "abcd", 8);
+
+ check ((stpcpy (one, "abcde") - one) == 5, 9);
+ equal (one, "abcde", 10);
+
+ check ((stpcpy (one, "abcdef") - one) == 6, 11);
+ equal (one, "abcdef", 12);
+
+ check ((stpcpy (one, "abcdefg") - one) == 7, 13);
+ equal (one, "abcdefg", 14);
+
+ check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
+ equal (one, "abcdefgh", 16);
+
+ check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
+ equal (one, "abcdefghi", 18);
+
+ check ((stpcpy (one, "x") - one) == 1, 19);
+ equal (one, "x", 20); /* Writeover. */
+ equal (one+2, "cdefghi", 21); /* Wrote too much? */
+
+ check ((stpcpy (one, "xx") - one) == 2, 22);
+ equal (one, "xx", 23); /* Writeover. */
+ equal (one+3, "defghi", 24); /* Wrote too much? */
+
+ check ((stpcpy (one, "xxx") - one) == 3, 25);
+ equal (one, "xxx", 26); /* Writeover. */
+ equal (one+4, "efghi", 27); /* Wrote too much? */
+
+ check ((stpcpy (one, "xxxx") - one) == 4, 28);
+ equal (one, "xxxx", 29); /* Writeover. */
+ equal (one+5, "fghi", 30); /* Wrote too much? */
+
+ check ((stpcpy (one, "xxxxx") - one) == 5, 31);
+ equal (one, "xxxxx", 32); /* Writeover. */
+ equal (one+6, "ghi", 33); /* Wrote too much? */
+
+ check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
+ equal (one, "xxxxxx", 35); /* Writeover. */
+ equal (one+7, "hi", 36); /* Wrote too much? */
+
+ check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
+ equal (one, "xxxxxxx", 38); /* Writeover. */
+ equal (one+8, "i", 39); /* Wrote too much? */
+
+ check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
+ equal (one, "abc", 41);
+ equal (one + 4, "xxx", 42);
+
+ SIMPLE_COPY(stpcpy, 0, "", 43);
+ SIMPLE_COPY(stpcpy, 1, "1", 44);
+ SIMPLE_COPY(stpcpy, 2, "22", 45);
+ SIMPLE_COPY(stpcpy, 3, "333", 46);
+ SIMPLE_COPY(stpcpy, 4, "4444", 47);
+ SIMPLE_COPY(stpcpy, 5, "55555", 48);
+ SIMPLE_COPY(stpcpy, 6, "666666", 49);
+ SIMPLE_COPY(stpcpy, 7, "7777777", 50);
+ SIMPLE_COPY(stpcpy, 8, "88888888", 51);
+ SIMPLE_COPY(stpcpy, 9, "999999999", 52);
+ SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
+ SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
+ SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
+ SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
+ SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
+ SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
+ SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
+}
+
+static void
+test_stpncpy (void)
+{
+ it = "stpncpy";
+ memset (one, 'x', sizeof (one));
+ check (stpncpy (one, "abc", 2) == one + 2, 1);
+ check (stpncpy (one, "abc", 3) == one + 3, 2);
+ check (stpncpy (one, "abc", 4) == one + 3, 3);
+ check (one[3] == '\0' && one[4] == 'x', 4);
+ check (stpncpy (one, "abcd", 5) == one + 4, 5);
+ check (one[4] == '\0' && one[5] == 'x', 6);
+ check (stpncpy (one, "abcd", 6) == one + 4, 7);
+ check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
+}
+
+static void
+test_strcat (void)
+{
+ it = "strcat";
+ (void) strcpy (one, "ijk");
+ check (strcat (one, "lmn") == one, 1); /* Returned value. */
+ equal (one, "ijklmn", 2); /* Basic test. */
+
+ (void) strcpy (one, "x");
+ (void) strcat (one, "yz");
+ equal (one, "xyz", 3); /* Writeover. */
+ equal (one+4, "mn", 4); /* Wrote too much? */
+
+ (void) strcpy (one, "gh");
+ (void) strcpy (two, "ef");
+ (void) strcat (one, two);
+ equal (one, "ghef", 5); /* Basic test encore. */
+ equal (two, "ef", 6); /* Stomped on source? */
+
+ (void) strcpy (one, "");
+ (void) strcat (one, "");
+ equal (one, "", 7); /* Boundary conditions. */
+ (void) strcpy (one, "ab");
+ (void) strcat (one, "");
+ equal (one, "ab", 8);
+ (void) strcpy (one, "");
+ (void) strcat (one, "cd");
+ equal (one, "cd", 9);
+
+ int ntest = 10;
+ char buf1[80] __attribute__ ((aligned (16)));
+ char buf2[32] __attribute__ ((aligned (16)));
+ for (size_t n1 = 0; n1 < 16; ++n1)
+ for (size_t n2 = 0; n2 < 16; ++n2)
+ for (size_t n3 = 0; n3 < 32; ++n3)
+ {
+ size_t olderrors = errors;
+
+ memset (buf1, 'b', sizeof (buf1));
+
+ memset (buf1 + n2, 'a', n3);
+ buf1[n2 + n3] = '\0';
+ strcpy (buf2 + n1, "123");
+
+ check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
+ if (errors == olderrors)
+ for (size_t i = 0; i < sizeof (buf1); ++i)
+ {
+ if (i < n2)
+ check (buf1[i] == 'b', ntest);
+ else if (i < n2 + n3)
+ check (buf1[i] == 'a', ntest);
+ else if (i < n2 + n3 + 3)
+ check (buf1[i] == "123"[i - (n2 + n3)], ntest);
+ else if (i == n2 + n3 + 3)
+ check (buf1[i] == '\0', ntest);
+ else
+ check (buf1[i] == 'b', ntest);
+
+ if (errors != olderrors)
+ {
+ printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
+ n1, n2, n3, buf1[0]);
+ for (size_t j = 1; j < sizeof (buf1); ++j)
+ printf (",%02hhx", buf1[j]);
+ putchar_unlocked ('\n');
+ break;
+ }
+ }
+ }
+}
+
+static void
+test_strncat (void)
+{
+ /* First test it as strcat, with big counts, then test the count
+ mechanism. */
+ it = "strncat";
+ (void) strcpy (one, "ijk");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "ijklmn", 2); /* Basic test. */
+
+ (void) strcpy (one, "x");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, "yz", 99);
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "xyz", 3); /* Writeover. */
+ equal (one+4, "mn", 4); /* Wrote too much? */
+
+ (void) strcpy (one, "gh");
+ (void) strcpy (two, "ef");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, two, 99);
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "ghef", 5); /* Basic test encore. */
+ equal (two, "ef", 6); /* Stomped on source? */
+
+ (void) strcpy (one, "");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, "", 99);
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "", 7); /* Boundary conditions. */
+ (void) strcpy (one, "ab");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, "", 99);
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "ab", 8);
+ (void) strcpy (one, "");
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, "cd", 99);
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "cd", 9);
+
+ (void) strcpy (one, "ab");
+ (void) strncat (one, "cdef", 2);
+ equal (one, "abcd", 10); /* Count-limited. */
+
+ (void) strncat (one, "gh", 0);
+ equal (one, "abcd", 11); /* Zero count. */
+
+ (void) strncat (one, "gh", 2);
+ equal (one, "abcdgh", 12); /* Count and length equal. */
+
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being larger than
+ the size of the buffer; this is deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
+ DIAG_POP_NEEDS_COMMENT;
+ equal (one, "abcdghij", 13);
+
+ int ntest = 14;
+ char buf1[80] __attribute__ ((aligned (16)));
+ char buf2[32] __attribute__ ((aligned (16)));
+ for (size_t n1 = 0; n1 < 16; ++n1)
+ for (size_t n2 = 0; n2 < 16; ++n2)
+ for (size_t n3 = 0; n3 < 32; ++n3)
+ for (size_t n4 = 0; n4 < 16; ++n4)
+ {
+ size_t olderrors = errors;
+
+ memset (buf1, 'b', sizeof (buf1));
+
+ memset (buf1 + n2, 'a', n3);
+ buf1[n2 + n3] = '\0';
+ strcpy (buf2 + n1, "123");
+
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ /* GCC 7 warns about the size passed to strncat being
+ larger than the size of the buffer; this is
+ deliberately tested here.. */
+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
+#endif
+ check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
+ == buf1 + n2, ntest);
+ DIAG_POP_NEEDS_COMMENT;
+ if (errors == olderrors)
+ for (size_t i = 0; i < sizeof (buf1); ++i)
+ {
+ if (i < n2)
+ check (buf1[i] == 'b', ntest);
+ else if (i < n2 + n3)
+ check (buf1[i] == 'a', ntest);
+ else if (i < n2 + n3 + 3)
+ check (buf1[i] == "123"[i - (n2 + n3)], ntest);
+ else if (i == n2 + n3 + 3)
+ check (buf1[i] == '\0', ntest);
+ else
+ check (buf1[i] == 'b', ntest);
+
+ if (errors != olderrors)
+ {
+ printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
+ n1, n2, n3, n4, buf1[0]);
+ for (size_t j = 1; j < sizeof (buf1); ++j)
+ printf (",%02hhx", buf1[j]);
+ putchar_unlocked ('\n');
+ break;
+ }
+ }
+ }
+}
+
+static void
+test_strncmp (void)
+{
+ /* First test as strcmp with big counts, then test count code. */
+ it = "strncmp";
+ check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
+ check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
+ check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
+ check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
+ check (strncmp ("abcd", "abc", 99) > 0, 5);
+ check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
+ check (strncmp ("abce", "abcd", 99) > 0, 7);
+ check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
+ check (strncmp ("a\203", "a\003", 2) > 0, 9);
+ check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
+ check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
+ check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
+ check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
+ check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
+ check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
+}
+
+static void
+test_strncpy (void)
+{
+ /* Testing is a bit different because of odd semantics. */
+ it = "strncpy";
+ check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
+ equal (one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy (one, "abcdefgh");
+ (void) strncpy (one, "xyz", 2);
+ equal (one, "xycdefgh", 3); /* Copy cut by count. */
+
+ (void) strcpy (one, "abcdefgh");
+ (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
+ equal (one, "xyzdefgh", 4);
+
+ (void) strcpy (one, "abcdefgh");
+ (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
+ equal (one, "xyz", 5);
+ equal (one+4, "efgh", 6); /* Wrote too much? */
+
+ (void) strcpy (one, "abcdefgh");
+ (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
+ equal (one, "xyz", 7);
+ equal (one+4, "", 8);
+ equal (one+5, "fgh", 9);
+
+ (void) strcpy (one, "abc");
+ (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
+ equal (one, "abc", 10);
+
+ (void) strncpy (one, "", 2); /* Zero-length source. */
+ equal (one, "", 11);
+ equal (one+1, "", 12);
+ equal (one+2, "c", 13);
+
+ (void) strcpy (one, "hi there");
+ (void) strncpy (two, one, 9);
+ equal (two, "hi there", 14); /* Just paranoia. */
+ equal (one, "hi there", 15); /* Stomped on source? */
+}
+
+static void
+test_strlen (void)
+{
+ it = "strlen";
+ check (strlen ("") == 0, 1); /* Empty. */
+ check (strlen ("a") == 1, 2); /* Single char. */
+ check (strlen ("abcd") == 4, 3); /* Multiple chars. */
+ {
+ char buf[4096];
+ int i;
+ char *p;
+ for (i=0; i < 0x100; i++)
+ {
+ p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p+3, "BAD/WRONG");
+ check (strlen (p) == 2, 4+i);
+ }
+ }
+}
+
+static void
+test_strnlen (void)
+{
+ it = "strnlen";
+ check (strnlen ("", 10) == 0, 1); /* Empty. */
+ check (strnlen ("a", 10) == 1, 2); /* Single char. */
+ check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
+ check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
+ check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
+ check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
+ check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
+ check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
+ check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
+
+ char buf[4096];
+ for (int i = 0; i < 0x100; ++i)
+ {
+ char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p + 3, "BAD/WRONG");
+ check (strnlen (p, 100) == 2, 10 + i);
+ }
+}
+
+static void
+test_strchr (void)
+{
+ it = "strchr";
+ check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy (one, "abcd");
+ check (strchr (one, 'c') == one+2, 2); /* Basic test. */
+ check (strchr (one, 'd') == one+3, 3); /* End of string. */
+ check (strchr (one, 'a') == one, 4); /* Beginning. */
+ check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (strchr (one, 'b') == one+1, 6); /* Finding first. */
+ (void) strcpy (one, "");
+ check (strchr (one, 'b') == NULL, 7); /* Empty string. */
+ check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
+ {
+ char buf[4096];
+ int i;
+ char *p;
+ for (i=0; i < 0x100; i++)
+ {
+ p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p+3, "BAD/WRONG");
+ check (strchr (p, '/') == NULL, 9+i);
+ }
+ }
+}
+
+static void
+test_strchrnul (void)
+{
+ const char *os;
+ it = "strchrnul";
+ cp = strchrnul ((os = "abcd"), 'z');
+ check (*cp == '\0', 1); /* Not found. */
+ check (cp == os + 4, 2);
+ (void) strcpy (one, "abcd");
+ check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
+ check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
+ check (strchrnul (one, 'a') == one, 5); /* Beginning. */
+ check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
+ (void) strcpy (one, "");
+ check (strchrnul (one, 'b') == one, 8); /* Empty string. */
+ check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
+ {
+ char buf[4096];
+ int i;
+ char *p;
+ for (i=0; i < 0x100; i++)
+ {
+ p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p+3, "BAD/WRONG");
+ cp = strchrnul (p, '/');
+ check (*cp == '\0', 9+2*i);
+ check (cp == p+2, 10+2*i);
+ }
+ }
+}
+
+static void
+test_rawmemchr (void)
+{
+ it = "rawmemchr";
+ (void) strcpy (one, "abcd");
+ check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
+ check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
+ check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
+ check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
+ (void) strcpy (one, "");
+ check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
+ {
+ char buf[4096];
+ int i;
+ char *p;
+ for (i=0; i < 0x100; i++)
+ {
+ p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p+3, "BAD/WRONG");
+ check (rawmemchr (p, 'R') == p+8, 6+i);
+ }
+ }
+}
+
+static void
+test_index (void)
+{
+ it = "index";
+ check (index ("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy (one, "abcd");
+ check (index (one, 'c') == one+2, 2); /* Basic test. */
+ check (index (one, 'd') == one+3, 3); /* End of string. */
+ check (index (one, 'a') == one, 4); /* Beginning. */
+ check (index (one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (index (one, 'b') == one+1, 6); /* Finding first. */
+ (void) strcpy (one, "");
+ check (index (one, 'b') == NULL, 7); /* Empty string. */
+ check (index (one, '\0') == one, 8); /* NUL in empty string. */
+}
+
+static void
+test_strrchr (void)
+{
+ it = "strrchr";
+ check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy (one, "abcd");
+ check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
+ check (strrchr (one, 'd') == one+3, 3); /* End of string. */
+ check (strrchr (one, 'a') == one, 4); /* Beginning. */
+ check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
+ (void) strcpy (one, "");
+ check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
+ check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
+ {
+ char buf[4096];
+ int i;
+ char *p;
+ for (i=0; i < 0x100; i++)
+ {
+ p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
+ strcpy (p, "OK");
+ strcpy (p+3, "BAD/WRONG");
+ check (strrchr (p, '/') == NULL, 9+i);
+ }
+ }
+}
+
+static void
+test_memrchr (void)
+{
+ size_t l;
+ it = "memrchr";
+ check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
+ (void) strcpy (one, "abcd");
+ l = strlen (one) + 1;
+ check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
+ check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
+ check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
+ check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ l = strlen (one) + 1;
+ check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
+ (void) strcpy (one, "");
+ l = strlen (one) + 1;
+ check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
+ check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
+
+ /* now test all possible alignment and length combinations to catch
+ bugs due to unrolled loops (assuming unrolling is limited to no
+ more than 128 byte chunks: */
+ {
+ char buf[128 + sizeof(long)];
+ long align, len, i, pos, n = 9;
+
+ for (align = 0; align < (long) sizeof(long); ++align) {
+ for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
+ for (i = 0; i < len; ++i)
+ buf[align + i] = 'x'; /* don't depend on memset... */
+
+ for (pos = len - 1; pos >= 0; --pos) {
+#if 0
+ printf("align %d, len %d, pos %d\n", align, len, pos);
+#endif
+ check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
+ check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
+ n++);
+ buf[align + pos] = '-';
+ }
+ }
+ }
+ }
+}
+
+static void
+test_rindex (void)
+{
+ it = "rindex";
+ check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
+ (void) strcpy (one, "abcd");
+ check (rindex (one, 'c') == one+2, 2); /* Basic test. */
+ check (rindex (one, 'd') == one+3, 3); /* End of string. */
+ check (rindex (one, 'a') == one, 4); /* Beginning. */
+ check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
+ (void) strcpy (one, "ababa");
+ check (rindex (one, 'b') == one+3, 6); /* Finding last. */
+ (void) strcpy (one, "");
+ check (rindex (one, 'b') == NULL, 7); /* Empty string. */
+ check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
+}
+
+static void
+test_strpbrk (void)
+{
+ it = "strpbrk";
+ check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
+ check(strpbrk(one, "d") == one+3, 3); /* End of string. */
+ check(strpbrk(one, "a") == one, 4); /* Beginning. */
+ check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
+ check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
+ (void) strcpy(one, "abcabdea");
+ check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
+ check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
+ check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
+ (void) strcpy(one, "");
+ check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
+ (void) strcpy(one, "");
+ check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
+ (void) strcpy(one, "");
+ check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
+ check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
+ (void) strcpy(one, "abcabdea");
+ check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
+ check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
+ check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
+ check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
+}
+
+static void
+test_strstr (void)
+{
+ it = "strstr";
+ check(strstr("abcd", "z") == NULL, 1); /* Not found. */
+ check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
+ (void) strcpy(one, "abcd");
+ check(strstr(one, "c") == one+2, 3); /* Basic test. */
+ check(strstr(one, "bc") == one+1, 4); /* Multichar. */
+ check(strstr(one, "d") == one+3, 5); /* End of string. */
+ check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
+ check(strstr(one, "abc") == one, 7); /* Beginning. */
+ check(strstr(one, "abcd") == one, 8); /* Exact match. */
+ check(strstr(one, "abcde") == NULL, 9); /* Too long. */
+ check(strstr(one, "de") == NULL, 10); /* Past end. */
+ check(strstr(one, "") == one, 11); /* Finding empty. */
+ (void) strcpy(one, "ababa");
+ check(strstr(one, "ba") == one+1, 12); /* Finding first. */
+ (void) strcpy(one, "");
+ check(strstr(one, "b") == NULL, 13); /* Empty string. */
+ check(strstr(one, "") == one, 14); /* Empty in empty string. */
+ (void) strcpy(one, "bcbca");
+ check(strstr(one, "bca") == one+2, 15); /* False start. */
+ (void) strcpy(one, "bbbcabbca");
+ check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
+}
+
+static void
+test_strspn (void)
+{
+ it = "strspn";
+ check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
+ check(strspn("abcba", "ab") == 2, 2); /* Partial. */
+ check(strspn("abc", "qx") == 0, 3); /* None. */
+ check(strspn("", "ab") == 0, 4); /* Null string. */
+ check(strspn("abc", "") == 0, 5); /* Null search list. */
+}
+
+static void
+test_strcspn (void)
+{
+ it = "strcspn";
+ check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
+ check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
+ check(strcspn("abc", "abc") == 0, 3); /* None. */
+ check(strcspn("", "ab") == 0, 4); /* Null string. */
+ check(strcspn("abc", "") == 3, 5); /* Null search list. */
+}
+
+static void
+test_strtok (void)
+{
+ it = "strtok";
+ (void) strcpy(one, "first, second, third");
+ equal(strtok(one, ", "), "first", 1); /* Basic test. */
+ equal(one, "first", 2);
+ equal(strtok((char *)NULL, ", "), "second", 3);
+ equal(strtok((char *)NULL, ", "), "third", 4);
+ check(strtok((char *)NULL, ", ") == NULL, 5);
+ (void) strcpy(one, ", first, ");
+ equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
+ check(strtok((char *)NULL, ", ") == NULL, 7);
+ (void) strcpy(one, "1a, 1b; 2a, 2b");
+ equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
+ equal(strtok((char *)NULL, "; "), "1b", 9);
+ equal(strtok((char *)NULL, ", "), "2a", 10);
+ (void) strcpy(two, "x-y");
+ equal(strtok(two, "-"), "x", 11); /* New string before done. */
+ equal(strtok((char *)NULL, "-"), "y", 12);
+ check(strtok((char *)NULL, "-") == NULL, 13);
+ (void) strcpy(one, "a,b, c,, ,d");
+ equal(strtok(one, ", "), "a", 14); /* Different separators. */
+ equal(strtok((char *)NULL, ", "), "b", 15);
+ equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
+ equal(strtok((char *)NULL, " ,"), "d", 17);
+ check(strtok((char *)NULL, ", ") == NULL, 18);
+ check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
+ (void) strcpy(one, ", ");
+ check(strtok(one, ", ") == NULL, 20); /* No tokens. */
+ (void) strcpy(one, "");
+ check(strtok(one, ", ") == NULL, 21); /* Empty string. */
+ (void) strcpy(one, "abc");
+ equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
+ check(strtok((char *)NULL, ", ") == NULL, 23);
+ (void) strcpy(one, "abc");
+ equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
+ check(strtok((char *)NULL, "") == NULL, 25);
+ (void) strcpy(one, "abcdefgh");
+ (void) strcpy(one, "a,b,c");
+ equal(strtok(one, ","), "a", 26); /* Basics again... */
+ equal(strtok((char *)NULL, ","), "b", 27);
+ equal(strtok((char *)NULL, ","), "c", 28);
+ check(strtok((char *)NULL, ",") == NULL, 29);
+ equal(one+6, "gh", 30); /* Stomped past end? */
+ equal(one, "a", 31); /* Stomped old tokens? */
+ equal(one+2, "b", 32);
+ equal(one+4, "c", 33);
+}
+
+static void
+test_strtok_r (void)
+{
+ it = "strtok_r";
+ (void) strcpy(one, "first, second, third");
+ cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
+ equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
+ equal(one, "first", 2);
+ equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
+ equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
+ (void) strcpy(one, ", first, ");
+ cp = NULL;
+ equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
+ (void) strcpy(one, "1a, 1b; 2a, 2b");
+ cp = NULL;
+ equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
+ equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
+ equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
+ (void) strcpy(two, "x-y");
+ cp = NULL;
+ equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
+ equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
+ check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
+ (void) strcpy(one, "a,b, c,, ,d");
+ cp = NULL;
+ equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
+ equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
+ equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
+ equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
+ (void) strcpy(one, ", ");
+ cp = NULL;
+ check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
+ (void) strcpy(one, "");
+ cp = NULL;
+ check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
+ (void) strcpy(one, "abc");
+ cp = NULL;
+ equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
+ check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
+ (void) strcpy(one, "abc");
+ cp = NULL;
+ equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
+ check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
+ (void) strcpy(one, "abcdefgh");
+ (void) strcpy(one, "a,b,c");
+ cp = NULL;
+ equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
+ equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
+ equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
+ check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
+ equal(one+6, "gh", 31); /* Stomped past end? */
+ equal(one, "a", 32); /* Stomped old tokens? */
+ equal(one+2, "b", 33);
+ equal(one+4, "c", 34);
+ strcpy (one, ":::");
+ cp = NULL;
+ check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
+ check (strtok_r (NULL, ":", &cp) == NULL, 36);
+}
+
+static void
+test_strsep (void)
+{
+ char *ptr;
+ it = "strsep";
+ cp = strcpy(one, "first, second, third");
+ equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
+ equal(one, "first", 2);
+ equal(strsep(&cp, ", "), "", 3);
+ equal(strsep(&cp, ", "), "second", 4);
+ equal(strsep(&cp, ", "), "", 5);
+ equal(strsep(&cp, ", "), "third", 6);
+ check(strsep(&cp, ", ") == NULL, 7);
+ cp = strcpy(one, ", first, ");
+ equal(strsep(&cp, ", "), "", 8);
+ equal(strsep(&cp, ", "), "", 9);
+ equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
+ equal(strsep(&cp, ", "), "", 11);
+ equal(strsep(&cp, ", "), "", 12);
+ check(strsep(&cp, ", ") == NULL, 13);
+ cp = strcpy(one, "1a, 1b; 2a, 2b");
+ equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
+ equal(strsep(&cp, ", "), "", 15);
+ equal(strsep(&cp, "; "), "1b", 16);
+ equal(strsep(&cp, ", "), "", 17);
+ equal(strsep(&cp, ", "), "2a", 18);
+ cp = strcpy(two, "x-y");
+ equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
+ equal(strsep(&cp, "-"), "y", 20);
+ check(strsep(&cp, "-") == NULL, 21);
+ cp = strcpy(one, "a,b, c,, ,d ");
+ equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
+ equal(strsep(&cp, ", "), "b", 23);
+ equal(strsep(&cp, " ,"), "", 24);
+ equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
+ equal(strsep(&cp, " ,"), "", 26);
+ equal(strsep(&cp, " ,"), "", 27);
+ equal(strsep(&cp, " ,"), "", 28);
+ equal(strsep(&cp, " ,"), "d", 29);
+ equal(strsep(&cp, " ,"), "", 30);
+ check(strsep(&cp, ", ") == NULL, 31);
+ check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
+ cp = strcpy(one, ", ");
+ equal(strsep(&cp, ", "), "", 33);
+ equal(strsep(&cp, ", "), "", 34);
+ equal(strsep(&cp, ", "), "", 35);
+ check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
+ cp = strcpy(one, "");
+ equal(strsep(&cp, ", "), "", 37);
+ check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
+ cp = strcpy(one, "abc");
+ equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
+ check(strsep(&cp, ", ") == NULL, 40);
+ cp = strcpy(one, "abc");
+ equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
+ check(strsep(&cp, "") == NULL, 42);
+ (void) strcpy(one, "abcdefgh");
+ cp = strcpy(one, "a,b,c");
+ equal(strsep(&cp, ","), "a", 43); /* Basics again... */
+ equal(strsep(&cp, ","), "b", 44);
+ equal(strsep(&cp, ","), "c", 45);
+ check(strsep(&cp, ",") == NULL, 46);
+ equal(one+6, "gh", 47); /* Stomped past end? */
+ equal(one, "a", 48); /* Stomped old tokens? */
+ equal(one+2, "b", 49);
+ equal(one+4, "c", 50);
+
+ {
+ char text[] = "This,is,a,test";
+ char *list = strdupa (text);
+ equal (strsep (&list, ","), "This", 51);
+ equal (strsep (&list, ","), "is", 52);
+ equal (strsep (&list, ","), "a", 53);
+ equal (strsep (&list, ","), "test", 54);
+ check (strsep (&list, ",") == NULL, 55);
+ }
+
+ cp = strcpy(one, "a,b, c,, ,d,");
+ equal(strsep(&cp, ","), "a", 56); /* Different separators. */
+ equal(strsep(&cp, ","), "b", 57);
+ equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
+ equal(strsep(&cp, ","), "", 59);
+ equal(strsep(&cp, ","), " ", 60);
+ equal(strsep(&cp, ","), "d", 61);
+ equal(strsep(&cp, ","), "", 62);
+ check(strsep(&cp, ",") == NULL, 63);
+ check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
+
+ cp = strcpy(one, "a,b, c,, ,d,");
+ equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
+ equal(strsep(&cp, "x,y"), "b", 66);
+ equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
+ equal(strsep(&cp, "xy,"), "", 68);
+ equal(strsep(&cp, "x,y"), " ", 69);
+ equal(strsep(&cp, ",xy"), "d", 70);
+ equal(strsep(&cp, "xy,"), "", 71);
+ check(strsep(&cp, "x,y") == NULL, 72);
+ check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
+
+ cp = strcpy(one, "ABC");
+ one[4] = ':';
+ equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
+ ptr = strsep(&cp, ":");
+ equal(ptr, "", 75);
+ check(ptr == one + 3, 76);
+ check(cp == NULL, 77);
+
+ cp = strcpy(one, "ABC");
+ one[4] = ':';
+ equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
+ ptr = strsep(&cp, ":.");
+ equal(ptr, "", 79);
+ check(ptr == one + 3, 80);
+
+ cp = strcpy(one, "ABC"); /* No token in string. */
+ equal(strsep(&cp, ","), "ABC", 81);
+ check(cp == NULL, 82);
+
+ *one = '\0'; /* Empty string. */
+ cp = one;
+ ptr = strsep(&cp, ",");
+ equal(ptr, "", 83);
+ check(ptr == one, 84);
+ check(cp == NULL, 85);
+
+ *one = '\0'; /* Empty string and no token. */
+ cp = one;
+ ptr = strsep(&cp, "");
+ equal(ptr, "", 86);
+ check(ptr == one , 87);
+ check(cp == NULL, 88);
+}
+
+static void
+test_memcmp (void)
+{
+ int cnt = 1;
+ char one[21];
+ char two[21];
+
+ it = "memcmp";
+ check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
+ check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
+ check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
+ check(memcmp("abcf", "abcd", 4) > 0, cnt++);
+ check(memcmp("alph", "cold", 4) < 0, cnt++);
+ check(memcmp("a\203", "a\003", 2) > 0, cnt++);
+ check(memcmp("a\003", "a\203", 2) < 0, cnt++);
+ check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
+ check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
+ check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
+ check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
+ check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
+ /* Comparisons with shifting 4-byte boundaries. */
+ for (int i = 0; i < 4; ++i)
+ {
+ char *a = one + i;
+ char *b = two + i;
+ strncpy(a, "--------11112222", 16);
+ strncpy(b, "--------33334444", 16);
+ check(memcmp(b, a, 16) > 0, cnt++);
+ check(memcmp(a, b, 16) < 0, cnt++);
+ }
+}
+
+static void
+test_memchr (void)
+{
+ it = "memchr";
+ check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
+ (void) strcpy(one, "abcd");
+ check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
+ check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
+ check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
+ check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
+ check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
+ (void) strcpy(one, "ababa");
+ check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
+ check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
+ check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
+ (void) strcpy(one, "a\203b");
+ check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
+
+ /* now test all possible alignment and length combinations to catch
+ bugs due to unrolled loops (assuming unrolling is limited to no
+ more than 128 byte chunks: */
+ {
+ char buf[128 + sizeof(long)];
+ long align, len, i, pos;
+
+ for (align = 0; align < (long) sizeof(long); ++align) {
+ for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
+ for (i = 0; i < len; ++i) {
+ buf[align + i] = 'x'; /* don't depend on memset... */
+ }
+ for (pos = 0; pos < len; ++pos) {
+#if 0
+ printf("align %d, len %d, pos %d\n", align, len, pos);
+#endif
+ check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
+ check(memchr(buf + align, 'x', pos) == NULL, 11);
+ buf[align + pos] = '-';
+ }
+ }
+ }
+ }
+}
+
+static void
+test_memcpy (void)
+{
+ int i;
+ it = "memcpy";
+ check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memcpy(one+1, "xyz", 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) memcpy(one, "xyz", 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) memcpy(two, one, 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ for (i = 0; i < 16; i++)
+ {
+ const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ strcpy (one, x);
+ check (memcpy (one + i, "hi there", 9) == one + i,
+ 7 + (i * 6)); /* Unaligned destination. */
+ check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
+ equal (one + i, "hi there", 9 + (i * 6));
+ check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
+ check (memcpy (two, one + i, 9) == two,
+ 11 + (i * 6)); /* Unaligned source. */
+ equal (two, "hi there", 12 + (i * 6));
+ }
+}
+
+static void
+test_mempcpy (void)
+{
+ int i;
+ it = "mempcpy";
+ check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) mempcpy(one+1, "xyz", 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) mempcpy(one, "xyz", 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) mempcpy(two, one, 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ for (i = 0; i < 16; i++)
+ {
+ const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ strcpy (one, x);
+ check (mempcpy (one + i, "hi there", 9) == one + i + 9,
+ 7 + (i * 6)); /* Unaligned destination. */
+ check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
+ equal (one + i, "hi there", 9 + (i * 6));
+ check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
+ check (mempcpy (two, one + i, 9) == two + 9,
+ 11 + (i * 6)); /* Unaligned source. */
+ equal (two, "hi there", 12 + (i * 6));
+ }
+}
+
+static void
+test_memmove (void)
+{
+ it = "memmove";
+ check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memmove(one+1, "xyz", 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) memmove(one, "xyz", 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) memmove(two, one, 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memmove(one+1, one, 9);
+ equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memmove(one+1, one+2, 7);
+ equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memmove(one, one, 9);
+ equal(one, "abcdefgh", 9); /* 100% overlap. */
+}
+
+static void
+test_memccpy (void)
+{
+ /* First test like memcpy, then the search part The SVID, the only
+ place where memccpy is mentioned, says overlap might fail, so we
+ don't try it. Besides, it's hard to see the rationale for a
+ non-left-to-right memccpy. */
+ it = "memccpy";
+ check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
+ equal(one, "abc", 2); /* Did the copy go right? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) memccpy(one+1, "xyz", 'q', 2);
+ equal(one, "axydefgh", 3); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) memccpy(one, "xyz", 'q', 0);
+ equal(one, "abc", 4); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) memccpy(two, one, 'q', 9);
+ equal(two, "hi there", 5); /* Just paranoia. */
+ equal(one, "hi there", 6); /* Stomped on source? */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) strcpy(two, "horsefeathers");
+ check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
+ equal(one, "abcdefgh", 8); /* Source intact? */
+ equal(two, "abcdefeathers", 9); /* Copy correct? */
+
+ (void) strcpy(one, "abcd");
+ (void) strcpy(two, "bumblebee");
+ check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
+ equal(two, "aumblebee", 11);
+ check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
+ equal(two, "abcdlebee", 13);
+ (void) strcpy(one, "xyz");
+ check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
+ equal(two, "xbcdlebee", 15);
+}
+
+static void
+test_memset (void)
+{
+ int i;
+
+ it = "memset";
+ (void) strcpy(one, "abcdefgh");
+ check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
+ equal(one, "axxxefgh", 2); /* Basic test. */
+
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about a zero-length memset because the arguments to memset
+ may be in the wrong order. But we really want to test this. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args")
+#endif
+ (void) memset(one+2, 'y', 0);
+ equal(one, "axxxefgh", 3); /* Zero-length set. */
+ DIAG_POP_NEEDS_COMMENT;
+
+ (void) memset(one+5, 0, 1);
+ equal(one, "axxxe", 4); /* Zero fill. */
+ equal(one+6, "gh", 5); /* And the leftover. */
+
+ (void) memset(one+2, 010045, 1);
+ equal(one, "ax\045xe", 6); /* Unsigned char convert. */
+
+ /* Non-8bit fill character. */
+ memset (one, 0x101, sizeof (one));
+ for (i = 0; i < (int) sizeof (one); ++i)
+ check (one[i] == '\01', 7);
+
+ /* Test for more complex versions of memset, for all alignments and
+ lengths up to 256. This test takes a little while, perhaps it should
+ be made weaker? */
+ {
+ char data[512];
+ int j;
+ int k;
+ int c;
+
+ for (i = 0; i < 512; i++)
+ data[i] = 'x';
+ for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
+ memset(,'y',) */
+ for (j = 0; j < 256; j++)
+ for (i = 0; i < 256; i++)
+ {
+ memset (data + i, c, j);
+ for (k = 0; k < i; k++)
+ if (data[k] != 'x')
+ goto fail;
+ for (k = i; k < i+j; k++)
+ {
+ if (data[k] != c)
+ goto fail;
+ data[k] = 'x';
+ }
+ for (k = i+j; k < 512; k++)
+ if (data[k] != 'x')
+ goto fail;
+ continue;
+
+ fail:
+ check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
+ }
+ }
+}
+
+static void
+test_bcopy (void)
+{
+ /* Much like memcpy. Berklix manual is silent about overlap, so
+ don't test it. */
+ it = "bcopy";
+ (void) bcopy("abc", one, 4);
+ equal(one, "abc", 1); /* Simple copy. */
+
+ (void) strcpy(one, "abcdefgh");
+ (void) bcopy("xyz", one+1, 2);
+ equal(one, "axydefgh", 2); /* Basic test. */
+
+ (void) strcpy(one, "abc");
+ (void) bcopy("xyz", one, 0);
+ equal(one, "abc", 3); /* Zero-length copy. */
+
+ (void) strcpy(one, "hi there");
+ (void) strcpy(two, "foo");
+ (void) bcopy(one, two, 9);
+ equal(two, "hi there", 4); /* Just paranoia. */
+ equal(one, "hi there", 5); /* Stomped on source? */
+}
+
+static void
+test_bzero (void)
+{
+ it = "bzero";
+ (void) strcpy(one, "abcdef");
+ bzero(one+2, 2);
+ equal(one, "ab", 1); /* Basic test. */
+ equal(one+3, "", 2);
+ equal(one+4, "ef", 3);
+
+ (void) strcpy(one, "abcdef");
+ bzero(one+2, 0);
+ equal(one, "abcdef", 4); /* Zero-length copy. */
+}
+
+static void
+test_strndup (void)
+{
+ char *p, *q;
+ it = "strndup";
+ p = strndup("abcdef", 12);
+ check(p != NULL, 1);
+ if (p != NULL)
+ {
+ equal(p, "abcdef", 2);
+ q = strndup(p + 1, 2);
+ check(q != NULL, 3);
+ if (q != NULL)
+ equal(q, "bc", 4);
+ free (q);
+ }
+ free (p);
+ p = strndup("abc def", 3);
+ check(p != NULL, 5);
+ if (p != NULL)
+ equal(p, "abc", 6);
+ free (p);
+}
+
+static void
+test_bcmp (void)
+{
+ it = "bcmp";
+ check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
+ check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
+ check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
+ check(bcmp("abce", "abcd", 4) != 0, 4);
+ check(bcmp("alph", "beta", 4) != 0, 5);
+ check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
+ check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
+}
+
+static void
+test_strerror (void)
+{
+ it = "strerror";
+ check(strerror(EDOM) != 0, 1);
+ check(strerror(ERANGE) != 0, 2);
+ check(strerror(ENOENT) != 0, 3);
+}
+
+static void
+test_strcasecmp (void)
+{
+ it = "strcasecmp";
+ /* Note that the locale is "C". */
+ check(strcasecmp("a", "a") == 0, 1);
+ check(strcasecmp("a", "A") == 0, 2);
+ check(strcasecmp("A", "a") == 0, 3);
+ check(strcasecmp("a", "b") < 0, 4);
+ check(strcasecmp("c", "b") > 0, 5);
+ check(strcasecmp("abc", "AbC") == 0, 6);
+ check(strcasecmp("0123456789", "0123456789") == 0, 7);
+ check(strcasecmp("", "0123456789") < 0, 8);
+ check(strcasecmp("AbC", "") > 0, 9);
+ check(strcasecmp("AbC", "A") > 0, 10);
+ check(strcasecmp("AbC", "Ab") > 0, 11);
+ check(strcasecmp("AbC", "ab") > 0, 12);
+}
+
+static void
+test_strncasecmp (void)
+{
+ it = "strncasecmp";
+ /* Note that the locale is "C". */
+ check(strncasecmp("a", "a", 5) == 0, 1);
+ check(strncasecmp("a", "A", 5) == 0, 2);
+ check(strncasecmp("A", "a", 5) == 0, 3);
+ check(strncasecmp("a", "b", 5) < 0, 4);
+ check(strncasecmp("c", "b", 5) > 0, 5);
+ check(strncasecmp("abc", "AbC", 5) == 0, 6);
+ check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
+ check(strncasecmp("", "0123456789", 10) < 0, 8);
+ check(strncasecmp("AbC", "", 5) > 0, 9);
+ check(strncasecmp("AbC", "A", 5) > 0, 10);
+ check(strncasecmp("AbC", "Ab", 5) > 0, 11);
+ check(strncasecmp("AbC", "ab", 5) > 0, 12);
+ check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
+ check(strncasecmp("AbC", "abc", 1) == 0, 14);
+ check(strncasecmp("AbC", "abc", 2) == 0, 15);
+ check(strncasecmp("AbC", "abc", 3) == 0, 16);
+ check(strncasecmp("AbC", "abcd", 3) == 0, 17);
+ check(strncasecmp("AbC", "abcd", 4) < 0, 18);
+ check(strncasecmp("ADC", "abcd", 1) == 0, 19);
+ check(strncasecmp("ADC", "abcd", 2) > 0, 20);
+}
+
+int
+main (void)
+{
+ int status;
+
+ /* Test strcmp first because we use it to test other things. */
+ test_strcmp ();
+
+ /* Test strcpy next because we need it to set up other tests. */
+ test_strcpy ();
+
+ /* A closely related function is stpcpy. */
+ test_stpcpy ();
+
+ /* stpncpy. */
+ test_stpncpy ();
+
+ /* strcat. */
+ test_strcat ();
+
+ /* strncat. */
+ test_strncat ();
+
+ /* strncmp. */
+ test_strncmp ();
+
+ /* strncpy. */
+ test_strncpy ();
+
+ /* strlen. */
+ test_strlen ();
+
+ /* strnlen. */
+ test_strnlen ();
+
+ /* strchr. */
+ test_strchr ();
+
+ /* strchrnul. */
+ test_strchrnul ();
+
+ /* rawmemchr. */
+ test_rawmemchr ();
+
+ /* index - just like strchr. */
+ test_index ();
+
+ /* strrchr. */
+ test_strrchr ();
+
+ /* memrchr. */
+ test_memrchr ();
+
+ /* rindex - just like strrchr. */
+ test_rindex ();
+
+ /* strpbrk - somewhat like strchr. */
+ test_strpbrk ();
+
+ /* strstr - somewhat like strchr. */
+ test_strstr ();
+
+ /* strspn. */
+ test_strspn ();
+
+ /* strcspn. */
+ test_strcspn ();
+
+ /* strtok - the hard one. */
+ test_strtok ();
+
+ /* strtok_r. */
+ test_strtok_r ();
+
+ /* strsep. */
+ test_strsep ();
+
+ /* memcmp. */
+ test_memcmp ();
+
+ /* memchr. */
+ test_memchr ();
+
+ /* memcpy - need not work for overlap. */
+ test_memcpy ();
+
+ /* memmove - must work on overlap. */
+ test_memmove ();
+
+ /* mempcpy */
+ test_mempcpy ();
+
+ /* memccpy. */
+ test_memccpy ();
+
+ /* memset. */
+ test_memset ();
+
+ /* bcopy. */
+ test_bcopy ();
+
+ /* bzero. */
+ test_bzero ();
+
+ /* bcmp - somewhat like memcmp. */
+ test_bcmp ();
+
+ /* strndup. */
+ test_strndup ();
+
+ /* strerror - VERY system-dependent. */
+ test_strerror ();
+
+ /* strcasecmp. Without locale dependencies. */
+ test_strcasecmp ();
+
+ /* strncasecmp. Without locale dependencies. */
+ test_strncasecmp ();
+
+ if (errors == 0)
+ {
+ status = EXIT_SUCCESS;
+ puts("No errors.");
+ }
+ else
+ {
+ status = EXIT_FAILURE;
+ printf("%Zd errors.\n", errors);
+ }
+
+ return status;
+}
diff --git a/REORG.TODO/string/tst-bswap.c b/REORG.TODO/string/tst-bswap.c
new file mode 100644
index 0000000000..def6e2f28a
--- /dev/null
+++ b/REORG.TODO/string/tst-bswap.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <byteswap.h>
+#include <stdio.h>
+
+extern unsigned long long int wash (unsigned long long int a);
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ /* Test the functions with constant arguments. */
+ if (bswap_16 (0x1234) != 0x3412)
+ {
+ puts ("bswap_16 (constant) flunked");
+ result = 1;
+ }
+ if (bswap_32 (0x12345678) != 0x78563412)
+ {
+ puts ("bswap_32 (constant) flunked");
+ result = 1;
+ }
+ if (bswap_64 (0x1234567890abcdefULL) != 0xefcdab9078563412ULL)
+ {
+ puts ("bswap_64 (constant) flunked");
+ result = 1;
+ }
+
+ /* Test the functions with non-constant arguments. */
+ if (bswap_16 (wash (0x1234)) != 0x3412)
+ {
+ puts ("bswap_16 (non-constant) flunked");
+ result = 1;
+ }
+ if (bswap_32 (wash (0x12345678)) != 0x78563412)
+ {
+ puts ("bswap_32 (non-constant) flunked");
+ result = 1;
+ }
+ if (bswap_64 (wash (0x1234567890abcdefULL)) != 0xefcdab9078563412ULL)
+ {
+ puts ("bswap_64 (non-constant) flunked");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+unsigned long long int
+wash (unsigned long long int a)
+{
+ /* Do nothing. This function simply exists to avoid that the compiler
+ regards the argument to the bswap_*() functions as constant. */
+ return a + 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-cmp.c b/REORG.TODO/string/tst-cmp.c
new file mode 100644
index 0000000000..d7720194e9
--- /dev/null
+++ b/REORG.TODO/string/tst-cmp.c
@@ -0,0 +1,212 @@
+/* Alignment/padding coverage test for string comparison.
+ Copyright (C) 2016-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This performs test comparisons with various (mis)alignments and
+ characters in the padding. It is partly a regression test for bug
+ 20327. */
+
+#include <limits.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+signum (int val)
+{
+ if (val < 0)
+ return -1;
+ if (val > 0)
+ return 1;
+ else
+ return 0;
+}
+
+static size_t
+max_size_t (size_t left, size_t right)
+{
+ if (left > right)
+ return left;
+ else
+ return right;
+}
+
+/* Wrappers for strncmp and strncasecmp which determine the maximum
+ string length in some, either based on the input string length, or
+ using fixed constants. */
+
+static int
+strncmp_no_terminator (const char *left, const char *right)
+{
+ size_t left_len = strlen (left);
+ size_t right_len = strlen (right);
+ return strncmp (left, right, max_size_t (left_len, right_len));
+}
+
+static int
+strncasecmp_no_terminator (const char *left, const char *right)
+{
+ size_t left_len = strlen (left);
+ size_t right_len = strlen (right);
+ return strncasecmp (left, right, max_size_t (left_len, right_len));
+}
+
+static int
+strncmp_terminator (const char *left, const char *right)
+{
+ size_t left_len = strlen (left);
+ size_t right_len = strlen (right);
+ return strncmp (left, right, max_size_t (left_len, right_len));
+}
+
+static int
+strncasecmp_terminator (const char *left, const char *right)
+{
+ size_t left_len = strlen (left);
+ size_t right_len = strlen (right);
+ return strncasecmp (left, right, max_size_t (left_len, right_len));
+}
+
+static int
+strncmp_64 (const char *left, const char *right)
+{
+ return strncmp (left, right, 64);
+}
+
+static int
+strncasecmp_64 (const char *left, const char *right)
+{
+ return strncasecmp (left, right, 64);
+}
+
+static int
+strncmp_max (const char *left, const char *right)
+{
+ return strncmp (left, right, SIZE_MAX);
+}
+
+static int
+strncasecmp_max (const char *left, const char *right)
+{
+ return strncasecmp (left, right, SIZE_MAX);
+}
+
+int
+do_test (void)
+{
+ enum {
+ max_align = 64,
+ max_string_length = 33
+ };
+ size_t blob_size = max_align + max_string_length + 1;
+ char *left = memalign (max_align, blob_size);
+ char *right = memalign (max_align, blob_size);
+ if (left == NULL || right == NULL)
+ {
+ printf ("error: out of memory\n");
+ return 1;
+ }
+
+ const struct
+ {
+ const char *name;
+ int (*implementation) (const char *, const char *);
+ } functions[] =
+ {
+ { "strcmp", strcmp },
+ { "strcasecmp", strcasecmp },
+ { "strncmp (without NUL)", strncmp_no_terminator},
+ { "strncasecmp (without NUL)", strncasecmp_no_terminator},
+ { "strncmp (with NUL)", strncmp_terminator},
+ { "strncasecmp (with NUL)", strncasecmp_terminator},
+ { "strncmp (length 64)", strncmp_64},
+ { "strncasecmp (length 64)", strncasecmp_64},
+ { "strncmp (length SIZE_MAX)", strncmp_max},
+ { "strncasecmp (length SIZE_MAX)", strncasecmp_max},
+ { NULL, NULL }
+ };
+ const char *const strings[] =
+ {
+ "",
+ "0",
+ "01",
+ "01234567",
+ "0123456789abcde",
+ "0123456789abcdef",
+ "0123456789abcdefg",
+ "1",
+ "10",
+ "123456789abcdef",
+ "123456789abcdefg",
+ "23456789abcdef",
+ "23456789abcdefg",
+ "abcdefghijklmnopqrstuvwxyzABCDEF",
+ NULL
+ };
+ const unsigned char pads[] =
+ { 0, 1, 32, 64, 128, '0', '1', 'e', 'f', 'g', 127, 192, 255 };
+
+ bool errors = false;
+ for (int left_idx = 0; strings[left_idx] != NULL; ++left_idx)
+ for (int left_align = 0; left_align < max_align; ++left_align)
+ for (unsigned pad_left = 0; pad_left < sizeof (pads); ++pad_left)
+ {
+ memset (left, pads[pad_left], blob_size);
+ strcpy (left + left_align, strings[left_idx]);
+
+ for (int right_idx = 0; strings[right_idx] != NULL; ++right_idx)
+ for (unsigned pad_right = 0; pad_right < sizeof (pads);
+ ++pad_right)
+ for (int right_align = 0; right_align < max_align;
+ ++right_align)
+ {
+ memset (right, pads[pad_right], blob_size);
+ strcpy (right + right_align, strings[right_idx]);
+
+ for (int func = 0; functions[func].name != NULL; ++func)
+ {
+ int expected = left_idx - right_idx;
+ int actual = functions[func].implementation
+ (left + left_align, right + right_align);
+ if (signum (actual) != signum (expected))
+ {
+ printf ("error: mismatch for %s: %d\n"
+ " left: \"%s\"\n"
+ " right: \"%s\"\n"
+ " pad_left = %u, pad_right = %u,\n"
+ " left_align = %d, right_align = %d\n",
+ functions[func].name, actual,
+ strings[left_idx], strings[right_idx],
+ pad_left, pad_right,
+ left_align, right_align);
+ errors = true;
+ }
+ }
+ }
+ }
+ free (right);
+ free (left);
+ return errors;
+}
+
+/* The nested loops need a long time to complete on slower
+ machines. */
+#define TIMEOUT 300
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-endian.c b/REORG.TODO/string/tst-endian.c
new file mode 100644
index 0000000000..b156ede199
--- /dev/null
+++ b/REORG.TODO/string/tst-endian.c
@@ -0,0 +1,134 @@
+#include <byteswap.h>
+#include <endian.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <libc-diag.h>
+
+#if __GNUC_PREREQ (6, 0)
+/* GCC 6.0 warns on big endian systems about:
+ htobeXX (beXXtoh (i)) != i
+ warning: self-comparison always evaluates to false [-Wtautological-compare]
+ because htobeXX(x) and beXXtoh(x) is defined to (x)
+ in string/endian.h on big endian systems.
+ The same applies to htoleXX/leXXtoh on little endian systems. */
+# define DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE() \
+ DIAG_IGNORE_NEEDS_COMMENT (6, "-Wtautological-compare")
+#else
+# define DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE()
+#endif
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ for (uint64_t i = 0; i < (~UINT64_C (0)) >> 2; i = (i << 1) + 3)
+ {
+ if (i < UINT64_C (65536))
+ {
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
+ if (htobe16 (be16toh (i)) != i)
+ {
+ printf ("htobe16 (be16toh (%" PRIx64 ")) == %" PRIx16 "\n",
+ i, (uint16_t) htobe16 (be16toh (i)));
+ result = 1;
+ }
+ if (htole16 (le16toh (i)) != i)
+ {
+ printf ("htole16 (le16toh (%" PRIx64 ")) == %" PRIx16 "\n",
+ i, (uint16_t) htole16 (le16toh (i)));
+ result = 1;
+ }
+ DIAG_POP_NEEDS_COMMENT;
+
+ uint16_t n[2];
+ n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_16 (i);
+ n[__BYTE_ORDER == __BIG_ENDIAN] = i;
+ if (htole16 (i) != n[0])
+ {
+ printf ("htole16 (%" PRIx64 ") == %" PRIx16 " != %" PRIx16 "\n",
+ i, (uint16_t) htole16 (i), n[0]);
+ result = 1;
+ }
+ if (htobe16 (i) != n[1])
+ {
+ printf ("htobe16 (%" PRIx64 ") == %" PRIx16 " != %" PRIx16 "\n",
+ i, (uint16_t) htobe16 (i), n[1]);
+ result = 1;
+ }
+ }
+
+ if (i < UINT64_C (4294967296))
+ {
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
+ if (htobe32 (be32toh (i)) != i)
+ {
+ printf ("htobe32 (be32toh (%" PRIx64 ")) == %" PRIx32 "\n",
+ i, (uint32_t) htobe32 (be32toh (i)));
+ result = 1;
+ }
+ if (htole32 (le32toh (i)) != i)
+ {
+ printf ("htole32 (le32toh (%" PRIx64 ")) == %" PRIx32 "\n",
+ i, (uint32_t) htole32 (le32toh (i)));
+ result = 1;
+ }
+ DIAG_POP_NEEDS_COMMENT;
+
+ uint32_t n[2];
+ n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_32 (i);
+ n[__BYTE_ORDER == __BIG_ENDIAN] = i;
+ if (htole32 (i) != n[0])
+ {
+ printf ("htole32 (%" PRIx64 ") == %" PRIx32 " != %" PRIx32 "\n",
+ i, (uint32_t) htole32 (i), n[0]);
+ result = 1;
+ }
+ if (htobe32 (i) != n[1])
+ {
+ printf ("htobe32 (%" PRIx64 ") == %" PRIx32 " != %" PRIx32 "\n",
+ i, (uint32_t) htobe32 (i), n[1]);
+ result = 1;
+ }
+ }
+
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
+ if (htobe64 (be64toh (i)) != i)
+ {
+ printf ("htobe64 (be64toh (%" PRIx64 ")) == %" PRIx64 "\n",
+ i, htobe64 (be64toh (i)));
+ result = 1;
+ }
+ if (htole64 (le64toh (i)) != i)
+ {
+ printf ("htole64 (le64toh (%" PRIx64 ")) == %" PRIx64 "\n",
+ i, htole64 (le64toh (i)));
+ result = 1;
+ }
+ DIAG_POP_NEEDS_COMMENT;
+
+ uint64_t n[2];
+ n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_64 (i);
+ n[__BYTE_ORDER == __BIG_ENDIAN] = i;
+ if (htole64 (i) != n[0])
+ {
+ printf ("htole64 (%" PRIx64 ") == %" PRIx64 " != %" PRIx64 "\n",
+ i, htole64 (i), n[0]);
+ result = 1;
+ }
+ if (htobe64 (i) != n[1])
+ {
+ printf ("htobe64 (%" PRIx64 ") == %" PRIx64 " != %" PRIx64 "\n",
+ i, htobe64 (i), n[1]);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-inlcall.c b/REORG.TODO/string/tst-inlcall.c
new file mode 100644
index 0000000000..f39f2c33a0
--- /dev/null
+++ b/REORG.TODO/string/tst-inlcall.c
@@ -0,0 +1,84 @@
+/* Tester for calling inline string functions.
+ Copyright (C) 1998-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/* Make sure we test the optimized inline functions. */
+#define __USE_STRING_INLINES 1
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+
+
+int
+do_test (void)
+{
+ int status;
+ int errors = 0;
+ char buf1[1000];
+ char *cp;
+ char ch;
+
+ cp = strcpy (buf1, "hello world");
+ if (strcmp ("hello world", cp++) != 0)
+ {
+ puts ("strcmp test 1 failed");
+ ++errors;
+ }
+
+ cp = buf1;
+ if (strcmp (cp++, "hello world") != 0)
+ {
+ puts ("strcmp test 2 failed");
+ ++errors;
+ }
+
+ ch = 'h';
+ if (strchr ("hello world", ch++) == NULL)
+ {
+ puts ("strchr test 1 failed");
+ ++errors;
+ }
+
+ const char * const hw = "hello world";
+ if (strpbrk (hw, "o") - hw != 4)
+ {
+ puts ("strpbrk test 1 failed");
+ ++errors;
+ }
+
+ if (errors == 0)
+ {
+ status = EXIT_SUCCESS;
+ puts ("No errors.");
+ }
+ else
+ {
+ status = EXIT_FAILURE;
+ printf ("%d errors.\n", errors);
+ }
+ return status;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strcoll-overflow.c b/REORG.TODO/string/tst-strcoll-overflow.c
new file mode 100644
index 0000000000..826af4f8a8
--- /dev/null
+++ b/REORG.TODO/string/tst-strcoll-overflow.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2013-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <support/check.h>
+#include <support/test-driver.h>
+
+/* Verify that strcoll does not crash for large strings for which it
+ cannot cache weight lookup results. The size is large enough to
+ cause integer overflows on 32-bit as well as buffer overflows on
+ 64-bit. */
+#define SIZE 0x40000000ul
+
+int
+do_test (void)
+{
+ TEST_VERIFY_EXIT (setlocale (LC_COLLATE, "en_GB.UTF-8") != NULL);
+
+ char *p = malloc (SIZE);
+ if (p == NULL)
+ {
+ puts ("info: could not allocate memory, cannot run test");
+ return EXIT_UNSUPPORTED;
+ }
+
+ memset (p, 'x', SIZE - 1);
+ p[SIZE - 1] = 0;
+ printf ("info: strcoll result: %d\n", strcoll (p, p));
+ return 0;
+}
+
+/* This test can rung for a long time, but it should complete within
+ this time on reasonably current hardware. */
+#define TIMEOUT 300
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strfry.c b/REORG.TODO/string/tst-strfry.c
new file mode 100644
index 0000000000..e4e9018c5b
--- /dev/null
+++ b/REORG.TODO/string/tst-strfry.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ char str[] = "this is a test";
+
+ strfry (str);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strlen.c b/REORG.TODO/string/tst-strlen.c
new file mode 100644
index 0000000000..15fbc8bd7b
--- /dev/null
+++ b/REORG.TODO/string/tst-strlen.c
@@ -0,0 +1,57 @@
+/* Make sure we don't test the optimized inline functions if we want to
+ test the real implementation. */
+#undef __USE_STRING_INLINES
+
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ static const size_t lens[] = { 0, 1, 0, 2, 0, 1, 0, 3,
+ 0, 1, 0, 2, 0, 1, 0, 4 };
+ char basebuf[24 + 32];
+ size_t base;
+
+ for (base = 0; base < 32; ++base)
+ {
+ char *buf = basebuf + base;
+ size_t words;
+
+ for (words = 0; words < 4; ++words)
+ {
+ size_t last;
+ memset (buf, 'a', words * 4);
+
+ for (last = 0; last < 16; ++last)
+ {
+ buf[words * 4 + 0] = (last & 1) != 0 ? 'b' : '\0';
+ buf[words * 4 + 1] = (last & 2) != 0 ? 'c' : '\0';
+ buf[words * 4 + 2] = (last & 4) != 0 ? 'd' : '\0';
+ buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0';
+ buf[words * 4 + 4] = '\0';
+
+ if (strlen (buf) != words * 4 + lens[last])
+ {
+ printf ("\
+strlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\n",
+ base, words, last,
+ strlen (buf), words * 4 + lens[last]);
+ return 1;
+ }
+
+ if (strnlen (buf, -1) != words * 4 + lens[last])
+ {
+ printf ("\
+strnlen failed for base=%Zu, words=%Zu, and last=%Zu (is %zd, expected %zd)\n",
+ base, words, last,
+ strnlen (buf, -1), words * 4 + lens[last]);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strtok.c b/REORG.TODO/string/tst-strtok.c
new file mode 100644
index 0000000000..628e106a46
--- /dev/null
+++ b/REORG.TODO/string/tst-strtok.c
@@ -0,0 +1,25 @@
+/* Testcase for strtok reported by Andrew Church <achurch@achurch.org>. */
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ char buf[1] = { 0 };
+ int result = 0;
+
+ if (strtok (buf, " ") != NULL)
+ {
+ puts ("first strtok call did not return NULL");
+ result = 1;
+ }
+ else if (strtok (NULL, " ") != NULL)
+ {
+ puts ("second strtok call did not return NULL");
+ result = 1;
+ }
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strtok_r.c b/REORG.TODO/string/tst-strtok_r.c
new file mode 100644
index 0000000000..fc3ed60b63
--- /dev/null
+++ b/REORG.TODO/string/tst-strtok_r.c
@@ -0,0 +1,38 @@
+/* Test strtok_r regression for BZ #14229.
+ Copyright (C) 2012-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_MAIN
+#define BUF1PAGES 1
+#include "test-string.h"
+
+int
+test_main (void)
+{
+ char line[] = "udf 75868 1 - Live 0xffffffffa0bfb000\n";
+ char **saveptrp;
+ char *tok;
+
+ test_init ();
+
+ /* Check strtok_r won't write beyond the size of (*saveptrp). */
+ saveptrp = (char **) (buf1 + page_size - sizeof (*saveptrp));
+ tok = strtok_r (line, " \t", saveptrp);
+ return strcmp (tok, "udf") != 0;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strxfrm.c b/REORG.TODO/string/tst-strxfrm.c
new file mode 100644
index 0000000000..ffe191c60d
--- /dev/null
+++ b/REORG.TODO/string/tst-strxfrm.c
@@ -0,0 +1,73 @@
+/* Based on a test case by Paul Eggert. */
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+char const string[] = "";
+
+
+static int
+test (const char *locale)
+{
+ size_t bufsize;
+ size_t r;
+ size_t l;
+ char *buf;
+ locale_t loc;
+ int result = 0;
+
+ if (setlocale (LC_COLLATE, locale) == NULL)
+ {
+ printf ("cannot set locale \"%s\"\n", locale);
+ return 1;
+ }
+ bufsize = strxfrm (NULL, string, 0) + 1;
+ buf = malloc (bufsize);
+ if (buf == NULL)
+ {
+ printf ("cannot allocate %zd bytes\n", bufsize);
+ return 1;
+ }
+ r = strxfrm (buf, string, bufsize);
+ l = strlen (buf);
+ if (r != l)
+ {
+ printf ("locale \"%s\": strxfrm returned %zu, strlen returned %zu\n",
+ locale, r, l);
+ result = 1;
+ }
+
+ loc = newlocale (1 << LC_ALL, locale, NULL);
+
+ r = strxfrm_l (buf, string, bufsize, loc);
+ l = strlen (buf);
+ if (r != l)
+ {
+ printf ("locale \"%s\": strxfrm_l returned %zu, strlen returned %zu\n",
+ locale, r, l);
+ result = 1;
+ }
+
+ freelocale (loc);
+
+ free (buf);
+
+ return result;
+}
+
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ result |= test ("C");
+ result |= test ("en_US.ISO-8859-1");
+ result |= test ("de_DE.UTF-8");
+
+ return result;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-strxfrm2.c b/REORG.TODO/string/tst-strxfrm2.c
new file mode 100644
index 0000000000..12117e80d6
--- /dev/null
+++ b/REORG.TODO/string/tst-strxfrm2.c
@@ -0,0 +1,84 @@
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (void)
+{
+ static const char test_locale[] = "de_DE.UTF-8";
+
+ int res = 0;
+
+ char buf[20];
+ size_t l1 = strxfrm (NULL, "ab", 0);
+ size_t l2 = strxfrm (buf, "ab", 1);
+ size_t l3 = strxfrm (buf, "ab", sizeof (buf));
+ if (l3 < sizeof (buf) && strlen (buf) != l3)
+ {
+ puts ("C locale l3 test failed");
+ res = 1;
+ }
+
+ size_t l4 = strxfrm (buf, "ab", l1 + 1);
+ if (l4 < l1 + 1 && strlen (buf) != l4)
+ {
+ puts ("C locale l4 test failed");
+ res = 1;
+ }
+
+ buf[l1] = 'Z';
+ size_t l5 = strxfrm (buf, "ab", l1);
+ if (buf[l1] != 'Z')
+ {
+ puts ("C locale l5 test failed");
+ res = 1;
+ }
+
+ if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
+ {
+ puts ("C locale retval test failed");
+ res = 1;
+ }
+
+ if (setlocale (LC_ALL, test_locale) == NULL)
+ {
+ printf ("cannot set locale \"%s\"\n", test_locale);
+ res = 1;
+ }
+ else
+ {
+ l1 = strxfrm (NULL, "ab", 0);
+ l2 = strxfrm (buf, "ab", 1);
+ l3 = strxfrm (buf, "ab", sizeof (buf));
+ if (l3 < sizeof (buf) && strlen (buf) != l3)
+ {
+ puts ("UTF-8 locale l3 test failed");
+ res = 1;
+ }
+
+ l4 = strxfrm (buf, "ab", l1 + 1);
+ if (l4 < l1 + 1 && strlen (buf) != l4)
+ {
+ puts ("UTF-8 locale l4 test failed");
+ res = 1;
+ }
+
+ buf[l1] = 'Z';
+ l5 = strxfrm (buf, "ab", l1);
+ if (buf[l1] != 'Z')
+ {
+ puts ("UTF-8 locale l5 test failed");
+ res = 1;
+ }
+
+ if (l1 != l2 || l1 != l3 || l1 != l4 || l1 != l5)
+ {
+ puts ("UTF-8 locale retval test failed");
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-svc.c b/REORG.TODO/string/tst-svc.c
new file mode 100644
index 0000000000..d5cf2c19c9
--- /dev/null
+++ b/REORG.TODO/string/tst-svc.c
@@ -0,0 +1,47 @@
+/* Test for strverscmp() */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_STRINGS 256
+#define MAX_LINE_SIZE 32
+
+static int
+compare (const void *p1, const void *p2)
+{
+ return strverscmp (*((char **) p1), *((char **) p2));
+}
+
+int
+do_test (void)
+{
+ char line[MAX_LINE_SIZE + 1];
+ char *str[MAX_STRINGS];
+ int count = 0;
+ int i, n;
+
+ while (count < MAX_STRINGS && fgets (line, MAX_LINE_SIZE, stdin) != NULL)
+ {
+ n = strlen (line) - 1;
+
+ if (line[n] == '\n')
+ line[n] = '\0';
+
+ str[count] = strdup (line);
+
+ if (str[count] == NULL)
+ exit (EXIT_FAILURE);
+
+ ++count;
+ }
+
+ qsort (str, count, sizeof (char *), compare);
+
+ for (i = 0; i < count; ++i)
+ puts (str[i]);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-svc.expect b/REORG.TODO/string/tst-svc.expect
new file mode 100644
index 0000000000..6240112772
--- /dev/null
+++ b/REORG.TODO/string/tst-svc.expect
@@ -0,0 +1,33 @@
+000
+001
+00
+00a
+01
+01a
+0
+0a
+2.6.20
+2.6.21
+2.8
+2.8-0.4
+20
+21
+22
+212
+CP037
+CP345
+CP1257
+foo
+foo-0.4
+foo-0.4a
+foo-0.4b
+foo-0.5
+foo-0.10.5
+foo-3.01
+foo-3.0
+foo-3.0.0
+foo-3.0.1
+foo-3.2
+foo-3.10
+foo00
+foo0
diff --git a/REORG.TODO/string/tst-svc.input b/REORG.TODO/string/tst-svc.input
new file mode 100644
index 0000000000..247b1c48f9
--- /dev/null
+++ b/REORG.TODO/string/tst-svc.input
@@ -0,0 +1,33 @@
+0a
+00
+0
+01
+001
+01a
+00a
+000
+2.6.21
+20
+212
+21
+22
+foo0
+foo00
+foo-0.4
+foo-3.0
+foo
+foo-3.0.0
+foo-3.0.1
+foo-0.5
+2.6.20
+foo-0.4b
+foo-3.10
+foo-3.2
+foo-3.01
+foo-0.4a
+foo-0.10.5
+CP037
+CP1257
+CP345
+2.8-0.4
+2.8
diff --git a/REORG.TODO/string/tst-svc2.c b/REORG.TODO/string/tst-svc2.c
new file mode 100644
index 0000000000..c0aa03dc18
--- /dev/null
+++ b/REORG.TODO/string/tst-svc2.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static struct
+{
+ const char *str1;
+ const char *str2;
+} tests[] =
+ {
+ { "B0075022800016.gbp.corp.com", "B007502280067.gbp.corp.com" },
+ { "B0075022800016.gbp.corp.com", "B007502357019.GBP.CORP.COM" },
+ { "B007502280067.gbp.corp.com", "B007502357019.GBP.CORP.COM" }
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+compare (const char *str1, const char *str2, int exp)
+{
+ int c = strverscmp (str1, str2);
+ if (c != 0)
+ c /= abs (c);
+ return c != exp;
+}
+
+
+int
+do_test (void)
+{
+ int res = 0;
+ for (int i = 0; i < ntests; ++i)
+ {
+ if (compare (tests[i].str1, tests[i].str2, -1))
+ {
+ printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str1, tests[i].str2);
+ res = 1;
+ }
+ if (compare (tests[i].str2, tests[i].str1, +1))
+ {
+ printf ("FAIL: \"%s\" > \"%s\"\n", tests[i].str2, tests[i].str1);
+ res = 1;
+ }
+ char *copy1 = strdupa (tests[i].str1);
+ if (compare (tests[i].str1, copy1, 0))
+ {
+ printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str1, copy1);
+ res = 1;
+ }
+ char *copy2 = strdupa (tests[i].str2);
+ if (compare (tests[i].str2, copy2, 0))
+ {
+ printf ("FAIL: \"%s\" != \"%s\"\n", tests[i].str2, copy2);
+ res = 1;
+ }
+ }
+ return res;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/tst-xbzero-opt.c b/REORG.TODO/string/tst-xbzero-opt.c
new file mode 100644
index 0000000000..7c25632724
--- /dev/null
+++ b/REORG.TODO/string/tst-xbzero-opt.c
@@ -0,0 +1,298 @@
+/* Test that explicit_bzero block clears are not optimized out.
+ Copyright (C) 2016-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test is conceptually based on a test designed by Matthew
+ Dempsky for the OpenBSD regression suite:
+ <openbsd>/src/regress/lib/libc/explicit_bzero/explicit_bzero.c.
+ The basic idea is, we have a function that contains a
+ block-clearing operation (not necessarily explicit_bzero), after
+ which the block is dead, in the compiler-jargon sense. Execute
+ that function while running on a user-allocated alternative
+ stack. Then we have another pointer to the memory region affected
+ by the block clear -- namely, the original allocation for the
+ alternative stack -- and can find out whether it actually happened.
+
+ The OpenBSD test uses sigaltstack and SIGUSR1 to get onto an
+ alternative stack. This causes a number of awkward problems; some
+ operating systems (e.g. Solaris and OSX) wipe the signal stack upon
+ returning to the normal stack, there's no way to be sure that other
+ processes running on the same system will not interfere, and the
+ signal stack is very small so it's not safe to call printf there.
+ This implementation instead uses the <ucontext.h> coroutine
+ interface. The coroutine stack is still too small to safely use
+ printf, but we know the OS won't erase it, so we can do all the
+ checks and printing from the normal stack. */
+
+#define _GNU_SOURCE 1
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+/* A byte pattern that is unlikely to occur by chance: the first 16
+ prime numbers (OEIS A000040). */
+static const unsigned char test_pattern[16] =
+{
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53
+};
+
+/* Immediately after each subtest returns, we call swapcontext to get
+ back onto the main stack. That call might itself overwrite the
+ test pattern, so we fill a modest-sized buffer with copies of it
+ and check whether any of them survived. */
+
+#define PATTERN_SIZE (sizeof test_pattern)
+#define PATTERN_REPS 32
+#define TEST_BUFFER_SIZE (PATTERN_SIZE * PATTERN_REPS)
+
+/* There are three subtests, two of which are sanity checks.
+ Each test follows this sequence:
+
+ main coroutine
+ ---- --------
+ advance cur_subtest
+ swap
+ call setup function
+ prepare test buffer
+ swap
+ verify that buffer
+ was filled in
+ swap
+ possibly clear buffer
+ return
+ swap
+ check buffer again,
+ according to test
+ expectation
+
+ In the "no_clear" case, we don't do anything to the test buffer
+ between preparing it and letting it go out of scope, and we expect
+ to find it. This confirms that the test buffer does get filled in
+ and we can find it from the stack buffer. In the "ordinary_clear"
+ case, we clear it using memset. Depending on the target, the
+ compiler may not be able to apply dead store elimination to the
+ memset call, so the test does not fail if the memset is not
+ eliminated. Finally, the "explicit_clear" case uses explicit_bzero
+ and expects _not_ to find the test buffer, which is the real
+ test. */
+
+static ucontext_t uc_main, uc_co;
+
+/* Always check the test buffer immediately after filling it; this
+ makes externally visible side effects depend on the buffer existing
+ and having been filled in. */
+static inline __attribute__ ((always_inline)) void
+prepare_test_buffer (unsigned char *buf)
+{
+ for (unsigned int i = 0; i < PATTERN_REPS; i++)
+ memcpy (buf + i*PATTERN_SIZE, test_pattern, PATTERN_SIZE);
+
+ if (swapcontext (&uc_co, &uc_main))
+ abort ();
+}
+
+static void
+setup_no_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+}
+
+static void
+setup_ordinary_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+ memset (buf, 0, TEST_BUFFER_SIZE);
+}
+
+static void
+setup_explicit_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+ explicit_bzero (buf, TEST_BUFFER_SIZE);
+}
+
+enum test_expectation
+ {
+ EXPECT_NONE, EXPECT_SOME, EXPECT_ALL, NO_EXPECTATIONS
+ };
+struct subtest
+{
+ void (*setup_subtest) (void);
+ const char *label;
+ enum test_expectation expected;
+};
+static const struct subtest *cur_subtest;
+
+static const struct subtest subtests[] =
+{
+ { setup_no_clear, "no clear", EXPECT_SOME },
+ /* The memset may happen or not, depending on compiler
+ optimizations. */
+ { setup_ordinary_clear, "ordinary clear", NO_EXPECTATIONS },
+ { setup_explicit_clear, "explicit clear", EXPECT_NONE },
+ { 0, 0, -1 }
+};
+
+static void
+test_coroutine (void)
+{
+ while (cur_subtest->setup_subtest)
+ {
+ cur_subtest->setup_subtest ();
+ if (swapcontext (&uc_co, &uc_main))
+ abort ();
+ }
+}
+
+/* All the code above this point runs on the coroutine stack.
+ All the code below this point runs on the main stack. */
+
+static int test_status;
+static unsigned char *co_stack_buffer;
+static size_t co_stack_size;
+
+static unsigned int
+count_test_patterns (unsigned char *buf, size_t bufsiz)
+{
+ unsigned char *first = memmem (buf, bufsiz, test_pattern, PATTERN_SIZE);
+ if (!first)
+ return 0;
+ unsigned int cnt = 0;
+ for (unsigned int i = 0; i < PATTERN_REPS; i++)
+ {
+ unsigned char *p = first + i*PATTERN_SIZE;
+ if (p + PATTERN_SIZE - buf > bufsiz)
+ break;
+ if (memcmp (p, test_pattern, PATTERN_SIZE) == 0)
+ cnt++;
+ }
+ return cnt;
+}
+
+static void
+check_test_buffer (enum test_expectation expected,
+ const char *label, const char *stage)
+{
+ unsigned int cnt = count_test_patterns (co_stack_buffer, co_stack_size);
+ switch (expected)
+ {
+ case EXPECT_NONE:
+ if (cnt == 0)
+ printf ("PASS: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ test_status = 1;
+ }
+ break;
+
+ case EXPECT_SOME:
+ if (cnt > 0)
+ printf ("PASS: %s/%s: expected some got %d\n", label, stage, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected some got 0\n", label, stage);
+ test_status = 1;
+ }
+ break;
+
+ case EXPECT_ALL:
+ if (cnt == PATTERN_REPS)
+ printf ("PASS: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ test_status = 1;
+ }
+ break;
+
+ case NO_EXPECTATIONS:
+ printf ("INFO: %s/%s: found %d patterns%s\n", label, stage, cnt,
+ cnt == 0 ? " (memset not eliminated)" : "");
+ break;
+
+ default:
+ printf ("ERROR: %s/%s: invalid value for 'expected' = %d\n",
+ label, stage, (int)expected);
+ test_status = 1;
+ }
+}
+
+static void
+test_loop (void)
+{
+ cur_subtest = subtests;
+ while (cur_subtest->setup_subtest)
+ {
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+ check_test_buffer (EXPECT_ALL, cur_subtest->label, "prepare");
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+ check_test_buffer (cur_subtest->expected, cur_subtest->label, "test");
+ cur_subtest++;
+ }
+ /* Terminate the coroutine. */
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+}
+
+int
+do_test (void)
+{
+ size_t page_alignment = sysconf (_SC_PAGESIZE);
+ if (page_alignment < sizeof (void *))
+ page_alignment = sizeof (void *);
+
+ co_stack_size = SIGSTKSZ + TEST_BUFFER_SIZE;
+ if (co_stack_size < page_alignment * 4)
+ co_stack_size = page_alignment * 4;
+
+ void *p;
+ int err = posix_memalign (&p, page_alignment, co_stack_size);
+ if (err || !p)
+ {
+ printf ("ERROR: allocating alt stack: %s\n", strerror (err));
+ return 2;
+ }
+ co_stack_buffer = p;
+
+ if (getcontext (&uc_co))
+ {
+ printf ("ERROR: allocating coroutine context: %s\n", strerror (err));
+ return 2;
+ }
+ uc_co.uc_stack.ss_sp = co_stack_buffer;
+ uc_co.uc_stack.ss_size = co_stack_size;
+ uc_co.uc_link = &uc_main;
+ makecontext (&uc_co, test_coroutine, 0);
+
+ test_loop ();
+ return test_status;
+}
+
+#include <support/test-driver.c>
diff --git a/REORG.TODO/string/wordcopy.c b/REORG.TODO/string/wordcopy.c
new file mode 100644
index 0000000000..65961cd03a
--- /dev/null
+++ b/REORG.TODO/string/wordcopy.c
@@ -0,0 +1,416 @@
+/* _memcopy.c -- subroutines for memory copy functions.
+ Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* 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. */
+
+#ifndef WORDCOPY_FWD_ALIGNED
+# define WORDCOPY_FWD_ALIGNED _wordcopy_fwd_aligned
+#endif
+
+void
+WORDCOPY_FWD_ALIGNED (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. */
+
+#ifndef WORDCOPY_FWD_DEST_ALIGNED
+# define WORDCOPY_FWD_DEST_ALIGNED _wordcopy_fwd_dest_aligned
+#endif
+
+void
+WORDCOPY_FWD_DEST_ALIGNED (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. */
+
+#ifndef WORDCOPY_BWD_ALIGNED
+# define WORDCOPY_BWD_ALIGNED _wordcopy_bwd_aligned
+#endif
+
+void
+WORDCOPY_BWD_ALIGNED (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. */
+
+#ifndef WORDCOPY_BWD_DEST_ALIGNED
+# define WORDCOPY_BWD_DEST_ALIGNED _wordcopy_bwd_dest_aligned
+#endif
+
+void
+WORDCOPY_BWD_DEST_ALIGNED (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/REORG.TODO/string/xpg-strerror.c b/REORG.TODO/string/xpg-strerror.c
new file mode 100644
index 0000000000..4a5e59d5ab
--- /dev/null
+++ b/REORG.TODO/string/xpg-strerror.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1991-2017 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+/* Fill buf with a string describing the errno code in ERRNUM. */
+int
+__xpg_strerror_r (int errnum, char *buf, size_t buflen)
+{
+ const char *estr = __strerror_r (errnum, buf, buflen);
+
+ /* We know that __strerror_r returns buf (with a dynamically computed
+ string) if errnum is invalid, otherwise it returns a string whose
+ storage has indefinite extent. */
+ if (estr == buf)
+ {
+ assert (errnum < 0 || errnum >= _sys_nerr_internal
+ || _sys_errlist_internal[errnum] == NULL);
+ return EINVAL;
+ }
+ else
+ {
+ assert (errnum >= 0 && errnum < _sys_nerr_internal
+ && _sys_errlist_internal[errnum] != NULL);
+
+ size_t estrlen = strlen (estr);
+
+ /* Terminate the string in any case. */
+ if (buflen > 0)
+ *((char *) __mempcpy (buf, estr, MIN (buflen - 1, estrlen))) = '\0';
+
+ return buflen <= estrlen ? ERANGE : 0;
+ }
+}