diff -Nrup a/NEWS b/NEWS --- a/NEWS 2012-09-14 14:31:29.000000000 -0600 +++ b/NEWS 2012-09-20 15:43:07.883932826 -0600 @@ -9,7 +9,7 @@ Version 2.17 * The following bugs are resolved with this release: - 1349, 3479, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 11607, 13412, + 1349, 3479, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 13412, 13542, 13717, 13696, 13939, 13966, 14042, 14090, 14166, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237, 14252, 14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349, 14459, 14476, 14505, @@ -27,9 +27,6 @@ Version 2.17 * SystemTap static probes have been added into the dynamic linker. Implemented by Gary Benson. -* Optimizations of string functions strstr, strcasestr and memmem. - Implemented by Maxim Kuvyrkov. - * The minimum Linux kernel version that this version of the GNU C Library can be used with is 2.6.16. diff -Nrup a/string/Makefile b/string/Makefile --- a/string/Makefile 2012-09-14 14:31:29.000000000 -0600 +++ b/string/Makefile 2012-09-20 15:42:02.189221257 -0600 @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2005-2011, 2012 Free Software Foundation, Inc. +# Copyright (C) 1991-2002, 2005-2010, 2011 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 @@ -56,7 +56,9 @@ tests := tester inl-tester noinl-tester tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ bug-strtok1 $(addprefix test-,$(strop-tests)) \ bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ - bug-strstr1 bug-strcasestr1 bug-strchr1 tst-strtok_r + bug-strstr1 bug-strchr1 +distribute := memcopy.h pagecopy.h tst-svc.expect test-string.h \ + str-two-way.h include ../Rules @@ -74,7 +76,6 @@ CFLAGS-stratcliff.c = -fno-builtin CFLAGS-test-ffs.c = -fno-builtin CFLAGS-tst-inlcall.c = -fno-builtin CFLAGS-bug-strstr1.c = -fno-builtin -CFLAGS-bug-strcasestr1.c = -fno-builtin ifeq ($(cross-compiling),no) tests: $(objpfx)tst-svc.out diff -Nrup a/string/bug-strcasestr1.c b/string/bug-strcasestr1.c --- a/string/bug-strcasestr1.c 2012-09-14 14:31:29.000000000 -0600 +++ b/string/bug-strcasestr1.c 1969-12-31 17:00:00.000000000 -0700 @@ -1,39 +0,0 @@ -/* Test for non-submitted strcasestr bug. - Copyright (C) 2012 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 - . */ - -#include -#include - -#define TEST_FUNCTION do_test () -static int -do_test (void) -{ - const char haystack[] = "AOKB"; - const char needle[] = "OK"; - const char *sub = strcasestr (haystack, needle); - - if (sub == NULL) - { - fprintf (stderr, "BUG: didn't find \"%s\" in \"%s\"\n", needle, haystack); - return 1; - } - - return 0; -} - -#include "../test-skeleton.c" diff -Nrup a/string/str-two-way.h b/string/str-two-way.h --- a/string/str-two-way.h 2012-09-14 14:31:29.000000000 -0600 +++ b/string/str-two-way.h 2012-09-20 15:41:31.478356212 -0600 @@ -1,5 +1,5 @@ /* Byte-wise substring search, using the Two-Way algorithm. - Copyright (C) 2008-2012 Free Software Foundation, Inc. + Copyright (C) 2008, 2010 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Eric Blake , 2008. @@ -43,7 +43,6 @@ #include #include -#include /* Defines MAX. */ /* We use the Two-Way string matching algorithm, which guarantees linear complexity with constant space. Additionally, for long @@ -68,6 +67,10 @@ # define LONG_NEEDLE_THRESHOLD SIZE_MAX #endif +#ifndef MAX +# define MAX(a, b) ((a < b) ? (b) : (a)) +#endif + #ifndef CANON_ELEMENT # define CANON_ELEMENT(c) c #endif @@ -75,19 +78,6 @@ # define CMP_FUNC memcmp #endif -#ifndef AVAILABLE1 -# define AVAILABLE1(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l) -#endif -#ifndef AVAILABLE2 -# define AVAILABLE2(h, h_l, j, n_l) (1) -#endif -#ifndef RET0_IF_0 -# define RET0_IF_0(a) /* nothing */ -#endif -#ifndef AVAILABLE1_USES_J -# define AVAILABLE1_USES_J (1) -#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. @@ -243,24 +233,17 @@ two_way_short_needle (const unsigned cha 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++))) + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) ++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--))) + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) --i; if (i + 1 < memory + 1) return (RETURN_TYPE) (haystack + j); @@ -278,81 +261,32 @@ two_way_short_needle (const unsigned cha } 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]); - /* 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 (AVAILABLE1 (haystack, haystack_len, j, needle_len)) + while (AVAILABLE (haystack, haystack_len, j, needle_len)) { - 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 AVAILABLE1_USES_J - ++j; -#endif - continue; - } - -#if !AVAILABLE1_USES_J - /* 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; - } + i = suffix; + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++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; - } + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; if (i == SIZE_MAX) return (RETURN_TYPE) (haystack + j); j += period; } else j += i - suffix + 1; - - if (!AVAILABLE2 (haystack, haystack_len, j, needle_len)) - break; - - phaystack = &haystack[suffix + j]; } } - ret0: __attribute__ ((unused)) return NULL; } @@ -404,9 +338,6 @@ two_way_long_needle (const unsigned char 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])]; @@ -426,19 +357,15 @@ two_way_long_needle (const unsigned char /* 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++))) + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) ++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--))) + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) --i; if (i + 1 < memory + 1) return (RETURN_TYPE) (haystack + j); @@ -463,9 +390,6 @@ two_way_long_needle (const unsigned char 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])]; @@ -477,19 +401,15 @@ two_way_long_needle (const unsigned char /* 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++))) + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) ++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--))) + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) --i; if (i == SIZE_MAX) return (RETURN_TYPE) (haystack + j); @@ -503,10 +423,6 @@ two_way_long_needle (const unsigned char } #undef AVAILABLE -#undef AVAILABLE1 -#undef AVAILABLE2 -#undef AVAILABLE1_USES_J #undef CANON_ELEMENT #undef CMP_FUNC -#undef RET0_IF_0 #undef RETURN_TYPE diff -Nrup a/string/strcasestr.c b/string/strcasestr.c --- a/string/strcasestr.c 2012-09-14 14:31:29.000000000 -0600 +++ b/string/strcasestr.c 2012-09-20 15:41:41.709311245 -0600 @@ -1,5 +1,6 @@ /* Return the offset of one string within another. - Copyright (C) 1994-2012 Free Software Foundation, Inc. + Copyright (C) 1994, 1996-2000, 2004, 2008, 2009, 2010 + 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 @@ -36,17 +37,13 @@ #include #include -#define TOLOWER(Ch) tolower (Ch) +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (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 AVAILABLE1(h, h_l, j, n_l) (true) -#define AVAILABLE2(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l) -#define RET0_IF_0(a) if (!a) goto ret0 -#define AVAILABLE1_USES_J (0) #define CANON_ELEMENT(c) TOLOWER (c) #define CMP_FUNC(p1, p2, l) \ __strncasecmp ((const char *) (p1), (const char *) (p2), l) diff -Nrup a/string/strstr.c b/string/strstr.c --- a/string/strstr.c 2012-09-14 14:31:29.000000000 -0600 +++ b/string/strstr.c 2012-09-20 15:42:15.661162080 -0600 @@ -1,5 +1,6 @@ /* Return the offset of one string within another. - Copyright (C) 1994-2012 Free Software Foundation, Inc. + Copyright (C) 1994,1996,1997,2000,2001,2003,2008,2009 + 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 @@ -35,10 +36,6 @@ #define AVAILABLE(h, h_l, j, n_l) \ (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ && ((h_l) = (j) + (n_l))) -#define AVAILABLE1(h, h_l, j, n_l) (true) -#define AVAILABLE2(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l) -#define RET0_IF_0(a) if (!a) goto ret0 -#define AVAILABLE1_USES_J (0) #include "str-two-way.h" #undef strstr