diff options
Diffstat (limited to 'string')
123 files changed, 991 insertions, 1043 deletions
diff --git a/string/Makefile b/string/Makefile index ffc02efa00..8424a6162d 100644 --- a/string/Makefile +++ b/string/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2014 Free Software Foundation, Inc. +# Copyright (C) 1991-2015 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 @@ -20,6 +20,8 @@ # 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 @@ -56,16 +58,12 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ xtests = tst-strcoll-overflow +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-svc-cmp.out +endif + include ../Rules -tester-ENV = LANGUAGE=C -inl-tester-ENV = LANGUAGE=C -noinl-tester-ENV = LANGUAGE=C -tst-strxfrm-ENV = LOCPATH=$(common-objpfx)localedata -tst-strxfrm2-ENV = LOCPATH=$(common-objpfx)localedata -bug-strcoll1-ENV = LOCPATH=$(common-objpfx)localedata -test-strcasecmp-ENV = LOCPATH=$(common-objpfx)localedata -test-strncasecmp-ENV = LOCPATH=$(common-objpfx)localedata CFLAGS-inl-tester.c = -fno-builtin CFLAGS-noinl-tester.c = -fno-builtin CFLAGS-tst-strlen.c = -fno-builtin @@ -74,9 +72,7 @@ CFLAGS-test-ffs.c = -fno-builtin CFLAGS-tst-inlcall.c = -fno-builtin ifeq ($(run-built-tests),yes) -tests: $(objpfx)tst-svc.out -$(objpfx)tst-svc.out: tst-svc.input $(objpfx)tst-svc - GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \ - $(test-program-cmd) < $(word 1,$^) > $@ - @cmp tst-svc.expect $(objpfx)tst-svc.out +$(objpfx)tst-svc-cmp.out: tst-svc.expect $(objpfx)tst-svc.out + cmp $^ > $@; \ + $(evaluate-test) endif diff --git a/string/_strerror.c b/string/_strerror.c index d171044cba..efe113e195 100644 --- a/string/_strerror.c +++ b/string/_strerror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/argz-addsep.c b/string/argz-addsep.c index 90478b070b..9240db2107 100644 --- a/string/argz-addsep.c +++ b/string/argz-addsep.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. diff --git a/string/argz-append.c b/string/argz-append.c index 5efa379596..d16edfbb77 100644 --- a/string/argz-append.c +++ b/string/argz-append.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu> diff --git a/string/argz-count.c b/string/argz-count.c index d33d4f6ea7..0dca5c2f6d 100644 --- a/string/argz-count.c +++ b/string/argz-count.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu> diff --git a/string/argz-create.c b/string/argz-create.c index ae971dee11..96a45f61ac 100644 --- a/string/argz-create.c +++ b/string/argz-create.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu> diff --git a/string/argz-ctsep.c b/string/argz-ctsep.c index 0a2f58c4db..0b732d72d4 100644 --- a/string/argz-ctsep.c +++ b/string/argz-ctsep.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996. diff --git a/string/argz-delete.c b/string/argz-delete.c index 398c7a663b..8176a7cbed 100644 --- a/string/argz-delete.c +++ b/string/argz-delete.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.org> diff --git a/string/argz-extract.c b/string/argz-extract.c index 795a4325af..757146b180 100644 --- a/string/argz-extract.c +++ b/string/argz-extract.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.org> diff --git a/string/argz-insert.c b/string/argz-insert.c index f95948ff8f..e161e22923 100644 --- a/string/argz-insert.c +++ b/string/argz-insert.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu> diff --git a/string/argz-next.c b/string/argz-next.c index 0be19f2015..b1531fe96d 100644 --- a/string/argz-next.c +++ b/string/argz-next.c @@ -1,5 +1,5 @@ /* Iterate through the elements of an argz block. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.org> diff --git a/string/argz-replace.c b/string/argz-replace.c index e07f8a6a61..26b0682ed4 100644 --- a/string/argz-replace.c +++ b/string/argz-replace.c @@ -1,5 +1,5 @@ /* String replacement in an argz vector - Copyright (C) 1997-2014 Free Software Foundation, Inc. + Copyright (C) 1997-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.ai.mit.edu> diff --git a/string/argz-stringify.c b/string/argz-stringify.c index 43a6d5f526..398cabcf1a 100644 --- a/string/argz-stringify.c +++ b/string/argz-stringify.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.org> diff --git a/string/argz.h b/string/argz.h index f43271fa0c..bb62a31995 100644 --- a/string/argz.h +++ b/string/argz.h @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated arg vectors. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 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 diff --git a/string/basename.c b/string/basename.c index 29b84eecb4..4caabca8f0 100644 --- a/string/basename.c +++ b/string/basename.c @@ -1,5 +1,5 @@ /* Return the name-within-directory of a file name. - Copyright (C) 1996-2014 Free Software Foundation, Inc. + Copyright (C) 1996-2015 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 @@ -16,26 +16,14 @@ 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 -/* We cannot generally use the name `basename' since XPG defines an unusable - variant of the function but we cannot use it. */ -# define basename gnu_basename -#endif - - char * -basename (filename) - const char *filename; +__basename (const char *filename) { char *p = strrchr (filename, '/'); return p ? p + 1 : (char *) filename; } -#ifdef _LIBC -libc_hidden_def (basename) -#endif +libc_hidden_def (__basename) +weak_alias (__basename, basename) +libc_hidden_weak (basename) diff --git a/string/bcopy.c b/string/bcopy.c index 7c1225c4d7..f74e589449 100644 --- a/string/bcopy.c +++ b/string/bcopy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -17,12 +17,8 @@ #include <string.h> -#define memmove bcopy -#define rettype void -#define RETURN(s) return -#define a1 src -#define a1const const -#define a2 dest -#define a2const - -#include <memmove.c> +void +bcopy (const void *src, void *dest, size_t len) +{ + memmove (dest, src, len); +} diff --git a/string/bits/string2.h b/string/bits/string2.h index b3df7089a9..764517689b 100644 --- a/string/bits/string2.h +++ b/string/bits/string2.h @@ -1,5 +1,5 @@ /* Machine-independant string function optimizations. - Copyright (C) 1997-2014 Free Software Foundation, Inc. + Copyright (C) 1997-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -1167,7 +1167,7 @@ __strtok_r_1c (char *__s, char __sep, char **__nextp) *__nextp = __s; return __result; } -# if defined __USE_POSIX || defined __USE_MISC +# ifdef __USE_POSIX # define strtok_r(s, sep, nextp) __strtok_r (s, sep, nextp) # endif #endif @@ -1258,7 +1258,7 @@ __strsep_3c (char **__s, char __reject1, char __reject2, char __reject3) } return __retval; } -# ifdef __USE_BSD +# ifdef __USE_MISC # define strsep(s, reject) __strsep (s, reject) # endif #endif @@ -1287,7 +1287,7 @@ extern char *__strdup (const char *__string) __THROW __attribute_malloc__; __retval; })) \ : __strdup (s))) -# if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +# if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 # define strdup(s) __strdup (s) # endif # endif @@ -1315,7 +1315,7 @@ extern char *__strndup (const char *__string, size_t __n) __retval; })) \ : __strndup (s, n))) -# ifdef __USE_GNU +# ifdef __USE_XOPEN2K8 # define strndup(s, n) __strndup (s, n) # endif # endif diff --git a/string/bits/string3.h b/string/bits/string3.h index acd2577406..f48293595a 100644 --- a/string/bits/string3.h +++ b/string/bits/string3.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2014 Free Software Foundation, Inc. +/* Copyright (C) 2004-2015 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 @@ -19,8 +19,10 @@ # 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 @@ -37,7 +39,7 @@ __warndecl (__warn_memset_zero_len, # undef mempcpy # undef stpcpy # endif -# ifdef __USE_BSD +# ifdef __USE_MISC # undef bcopy # undef bzero # endif @@ -75,16 +77,20 @@ __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src, __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_BSD +#ifdef __USE_MISC __fortify_function void __NTH (bcopy (const void *__src, void *__dest, size_t __len)) { diff --git a/string/byteswap.h b/string/byteswap.h index cd76b449be..99a8969e40 100644 --- a/string/byteswap.h +++ b/string/byteswap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997-2014 Free Software Foundation, Inc. +/* Copyright (C) 1997-2015 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 diff --git a/string/bzero.c b/string/bzero.c index 9c220b9c13..43e2b38780 100644 --- a/string/bzero.c +++ b/string/bzero.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). @@ -17,66 +17,13 @@ <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <memcopy.h> #undef __bzero /* Set N bytes of S to 0. */ void -__bzero (s, len) - void *s; - size_t len; +__bzero (void *s, size_t len) { - long int dstp = (long int) s; - const op_t zero = 0; - - if (len >= 8) - { - size_t xlen; - - /* There are at least some bytes to zero. No need to test - for LEN == 0 in this alignment loop. */ - while (dstp % OPSIZ != 0) - { - ((byte *) dstp)[0] = 0; - dstp += 1; - len -= 1; - } - - /* Write 8 op_t per iteration until less than 8 op_t remain. */ - xlen = len / (OPSIZ * 8); - while (xlen != 0) - { - ((op_t *) dstp)[0] = zero; - ((op_t *) dstp)[1] = zero; - ((op_t *) dstp)[2] = zero; - ((op_t *) dstp)[3] = zero; - ((op_t *) dstp)[4] = zero; - ((op_t *) dstp)[5] = zero; - ((op_t *) dstp)[6] = zero; - ((op_t *) dstp)[7] = zero; - dstp += 8 * OPSIZ; - xlen -= 1; - } - len %= OPSIZ * 8; - - /* Write 1 op_t per iteration until less than op_t remain. */ - xlen = len / OPSIZ; - while (xlen != 0) - { - ((op_t *) dstp)[0] = zero; - dstp += OPSIZ; - xlen -= 1; - } - len %= OPSIZ; - } - - /* Write the last few bytes. */ - while (len != 0) - { - ((byte *) dstp)[0] = 0; - dstp += 1; - len -= 1; - } + memset (s, '\0', len); } weak_alias (__bzero, bzero) diff --git a/string/endian.h b/string/endian.h index 875fea3778..c0a5ddd5f1 100644 --- a/string/endian.h +++ b/string/endian.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 @@ -41,7 +41,7 @@ # define __FLOAT_WORD_ORDER __BYTE_ORDER #endif -#ifdef __USE_BSD +#ifdef __USE_MISC # define LITTLE_ENDIAN __LITTLE_ENDIAN # define BIG_ENDIAN __BIG_ENDIAN # define PDP_ENDIAN __PDP_ENDIAN @@ -55,7 +55,7 @@ #endif -#if defined __USE_BSD && !defined __ASSEMBLER__ +#if defined __USE_MISC && !defined __ASSEMBLER__ /* Conversion interfaces. */ # include <bits/byteswap.h> diff --git a/string/envz.c b/string/envz.c index 8a79484f32..fc999525b0 100644 --- a/string/envz.c +++ b/string/envz.c @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated environment vectors - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader <miles@gnu.org> diff --git a/string/envz.h b/string/envz.h index f51931cee8..d1066fa977 100644 --- a/string/envz.h +++ b/string/envz.h @@ -1,5 +1,5 @@ /* Routines for dealing with '\0' separated environment vectors - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 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 diff --git a/string/ffs.c b/string/ffs.c index 392d5044c5..a30deeb36a 100644 --- a/string/ffs.c +++ b/string/ffs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). diff --git a/string/ffsll.c b/string/ffsll.c index 5b54b33c28..2c89171d03 100644 --- a/string/ffsll.c +++ b/string/ffsll.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). diff --git a/string/memccpy.c b/string/memccpy.c index 793f68ee1c..d9ed6975ef 100644 --- a/string/memccpy.c +++ b/string/memccpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -24,11 +24,7 @@ Return the position in DEST one byte past where C was copied, or NULL if C was not found in the first N bytes of SRC. */ void * -__memccpy (dest, src, c, n) - void *dest; - const void *src; - int c; - size_t n; +__memccpy (void *dest, const void *src, int c, size_t n) { const char *s = src; char *d = dest; diff --git a/string/memchr.c b/string/memchr.c index 7408f33b22..6896465600 100644 --- a/string/memchr.c +++ b/string/memchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -20,186 +20,141 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#ifdef HAVE_CONFIG_H -#include <config.h> +#ifndef _LIBC +# include <config.h> #endif -#undef __ptr_t -#define __ptr_t void * +#include <string.h> -#if defined _LIBC -# include <string.h> -# include <memcopy.h> -#endif +#include <stddef.h> -#if HAVE_STDLIB_H || defined _LIBC -# include <stdlib.h> -#endif +#include <limits.h> -#if HAVE_LIMITS_H || defined _LIBC -# include <limits.h> +#undef __memchr +#ifdef _LIBC +# undef memchr #endif -#define LONG_MAX_32_BITS 2147483647 - -#ifndef LONG_MAX -#define LONG_MAX LONG_MAX_32_BITS +#ifndef weak_alias +# define __memchr memchr #endif -#include <sys/types.h> - -#undef memchr -#undef __memchr - #ifndef MEMCHR # define MEMCHR __memchr #endif /* Search no more than N bytes of S for C. */ -__ptr_t -MEMCHR (s, c_in, n) - const __ptr_t s; - int c_in; - size_t n; +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 unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, charmask; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; unsigned char c; c = (unsigned char) c_in; - /* Handle the first few characters by reading one character at a time. + /* 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 && ((unsigned long int) char_ptr - & (sizeof (longword) - 1)) != 0; + n > 0 && (size_t) char_ptr % sizeof (longword) != 0; --n, ++char_ptr) if (*char_ptr == c) - return (__ptr_t) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to 8-byte longwords. */ - - longword_ptr = (unsigned long int *) char_ptr; - - /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits - the "holes." Note that there is a hole just to the left of - each byte, with an extra at the end: + return (void *) char_ptr; - bits: 01111110 11111110 11111110 11111111 - bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + longword_ptr = (const longword *) char_ptr; - The 1-bits make sure that carries propagate to the next 0-bit. - The 0-bits provide holes for carries to fall into. */ - - if (sizeof (longword) != 4 && sizeof (longword) != 8) - abort (); + /* 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; -#if LONG_MAX <= LONG_MAX_32_BITS - magic_bits = 0x7efefeff; -#else - magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; -#endif + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } - /* 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 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. */ - /* Instead of the traditional loop which tests each character, - we will test a longword at a time. The tricky part is testing - if *any of the four* bytes in the longword in question are zero. */ while (n >= sizeof (longword)) { - /* We tentatively exit the loop if adding MAGIC_BITS to - LONGWORD fails to change any of the hole bits of LONGWORD. - - 1) Is this safe? Will it catch all the zero bytes? - Suppose there is a byte with all zeros. Any carry bits - propagating from its left will fall into the hole at its - least significant bit and stop. Since there will be no - carry from its most significant bit, the LSB of the - byte to the left will be unchanged, and the zero will be - detected. - - 2) Is this worthwhile? Will it ignore everything except - zero bytes? Suppose every byte of LONGWORD has a bit set - somewhere. There will be a carry into bit 8. If bit 8 - is set, this will carry into bit 16. If bit 8 is clear, - one of bits 9-15 must be set, so there will be a carry - into bit 16. Similarly, there will be a carry into bit - 24. If one of bits 24-30 is set, there will be a carry - into bit 31, so all of the hole bits will be changed. - - The one misfire occurs when bits 24-30 are clear and bit - 31 is set; in this case, the hole at bit 31 is not - changed. If we had access to the processor carry flag, - we could close this loophole by putting the fourth hole - at bit 32! - - So it ignores everything except 128's, when they're aligned - properly. - - 3) But wait! Aren't we looking for C, not zero? - Good point. So what we do is XOR LONGWORD with a longword, - each of whose bytes is C. This turns each byte that is C - into a zero. */ - - longword = *longword_ptr++ ^ charmask; - - /* Add MAGIC_BITS to LONGWORD. */ - if ((((longword + magic_bits) - - /* Set those bits that were unchanged by the addition. */ - ^ ~longword) - - /* Look at only the hole bits. If any of the hole bits - are unchanged, most likely one of the bytes was a - zero. */ - & ~magic_bits) != 0) - { - /* Which of the bytes was C? If none of them were, it was - a misfire; continue the search. */ - - const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); - - if (cp[0] == c) - return (__ptr_t) cp; - if (cp[1] == c) - return (__ptr_t) &cp[1]; - if (cp[2] == c) - return (__ptr_t) &cp[2]; - if (cp[3] == c) - return (__ptr_t) &cp[3]; -#if LONG_MAX > 2147483647 - if (cp[4] == c) - return (__ptr_t) &cp[4]; - if (cp[5] == c) - return (__ptr_t) &cp[5]; - if (cp[6] == c) - return (__ptr_t) &cp[6]; - if (cp[7] == c) - return (__ptr_t) &cp[7]; -#endif - } + 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; - while (n-- > 0) + /* 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 (__ptr_t) char_ptr; - else - ++char_ptr; + return (void *) char_ptr; } - return 0; + return NULL; } #ifdef weak_alias weak_alias (__memchr, memchr) diff --git a/string/memcmp.c b/string/memcmp.c index ce9e897e2a..41e058629d 100644 --- a/string/memcmp.c +++ b/string/memcmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). diff --git a/string/memcpy.c b/string/memcpy.c index c19bad3b67..4a585086fc 100644 --- a/string/memcpy.c +++ b/string/memcpy.c @@ -1,6 +1,6 @@ /* Copy memory to memory until the specified number of bytes has been copied. Overlap is NOT handled correctly. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). @@ -20,7 +20,6 @@ #include <string.h> #include <memcopy.h> -#include <pagecopy.h> #undef memcpy diff --git a/string/memfrob.c b/string/memfrob.c index 4841309874..ef4bcf0a15 100644 --- a/string/memfrob.c +++ b/string/memfrob.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 @@ -18,9 +18,7 @@ #include <string.h> void * -memfrob (s, n) - void *s; - size_t n; +memfrob (void *s, size_t n) { char *p = (char *) s; diff --git a/string/memmem.c b/string/memmem.c index 93e5e18c66..8a81f6574f 100644 --- a/string/memmem.c +++ b/string/memmem.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -26,6 +26,7 @@ #ifndef _LIBC # define __builtin_expect(expr, val) (expr) +# define __memmem memmem #endif #define RETURN_TYPE void * @@ -38,8 +39,8 @@ 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) +__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. */ @@ -53,7 +54,7 @@ memmem (const void *haystack_start, size_t haystack_len, /* Sanity check, otherwise the loop might search through the whole memory. */ - if (__builtin_expect (haystack_len < needle_len, 0)) + if (__glibc_unlikely (haystack_len < needle_len)) return NULL; /* Use optimizations in memchr when possible, to reduce the search @@ -73,6 +74,8 @@ memmem (const void *haystack_start, size_t haystack_len, else return two_way_long_needle (haystack, haystack_len, needle, needle_len); } -libc_hidden_def (memmem) +libc_hidden_def (__memmem) +weak_alias (__memmem, memmem) +libc_hidden_weak (memmem) #undef LONG_NEEDLE_THRESHOLD diff --git a/string/memmove.c b/string/memmove.c index 3373401721..5748256519 100644 --- a/string/memmove.c +++ b/string/memmove.c @@ -1,6 +1,6 @@ /* Copy memory to memory until the specified number of bytes has been copied. Overlap is handled correctly. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). @@ -20,7 +20,6 @@ #include <string.h> #include <memcopy.h> -#include <pagecopy.h> /* All this is so that bcopy.c can #include this file after defining some things. */ diff --git a/string/memory.h b/string/memory.h index 6d3c3d506e..e65629661d 100644 --- a/string/memory.h +++ b/string/memory.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/mempcpy.c b/string/mempcpy.c index 9749863eaf..03f5d0d0a2 100644 --- a/string/mempcpy.c +++ b/string/mempcpy.c @@ -1,7 +1,7 @@ /* 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-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). @@ -19,6 +19,7 @@ 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 diff --git a/string/memrchr.c b/string/memrchr.c index a0bde92789..0c8fd84901 100644 --- a/string/memrchr.c +++ b/string/memrchr.c @@ -1,5 +1,5 @@ /* memrchr -- find the last occurrence of a byte in a memory block - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 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 diff --git a/string/memset.c b/string/memset.c index 275ff42331..18faf06e42 100644 --- a/string/memset.c +++ b/string/memset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/rawmemchr.c b/string/rawmemchr.c index 110a6bc45e..05b22be24e 100644 --- a/string/rawmemchr.c +++ b/string/rawmemchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/stpcpy.c b/string/stpcpy.c index fc5ae5534f..ecfb8d9255 100644 --- a/string/stpcpy.c +++ b/string/stpcpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 @@ -19,6 +19,7 @@ # include <config.h> #endif +#define NO_MEMPCPY_STPCPY_REDIRECT #include <string.h> #undef __stpcpy @@ -34,14 +35,8 @@ __stpcpy (dest, src) char *dest; const char *src; { - char *d = dest; - const char *s = src; - - do - *d++ = *s; - while (*s++ != '\0'); - - return d - 1; + size_t len = strlen (src); + return memcpy (dest, src, len + 1) + len; } #ifdef libc_hidden_def libc_hidden_def (__stpcpy) diff --git a/string/stpncpy.c b/string/stpncpy.c index fad747e7aa..eb65a5f46f 100644 --- a/string/stpncpy.c +++ b/string/stpncpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2014 Free Software Foundation, Inc. +/* Copyright (C) 1993-2015 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 diff --git a/string/str-two-way.h b/string/str-two-way.h index f15b9d368d..f32df4a6f2 100644 --- a/string/str-two-way.h +++ b/string/str-two-way.h @@ -1,5 +1,5 @@ /* Byte-wise substring search, using the Two-Way algorithm. - Copyright (C) 2008-2014 Free Software Foundation, Inc. + Copyright (C) 2008-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Eric Blake <ebb9@byu.net>, 2008. diff --git a/string/stratcliff.c b/string/stratcliff.c index 596c61ef86..e161307542 100644 --- a/string/stratcliff.c +++ b/string/stratcliff.c @@ -1,5 +1,5 @@ /* Test for string function add boundaries of usable memory. - Copyright (C) 1996-2014 Free Software Foundation, Inc. + Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. diff --git a/string/strcasecmp.c b/string/strcasecmp.c index 510caa2ab2..6b14912a8b 100644 --- a/string/strcasecmp.c +++ b/string/strcasecmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/strcasecmp_l.c b/string/strcasecmp_l.c index 25c419e330..4debd1bc9d 100644 --- a/string/strcasecmp_l.c +++ b/string/strcasecmp_l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997-2014 Free Software Foundation, Inc. +/* Copyright (C) 1997-2015 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 diff --git a/string/strcasestr.c b/string/strcasestr.c index 4bd6d415f7..400fab874d 100644 --- a/string/strcasestr.c +++ b/string/strcasestr.c @@ -1,5 +1,5 @@ /* Return the offset of one string within another. - Copyright (C) 1994-2014 Free Software Foundation, Inc. + Copyright (C) 1994-2015 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 diff --git a/string/strcat.c b/string/strcat.c index bb7c0a9909..6e1f1ab932 100644 --- a/string/strcat.c +++ b/string/strcat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -16,36 +16,14 @@ <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <memcopy.h> #undef strcat /* Append SRC on the end of DEST. */ char * -strcat (dest, src) - char *dest; - const char *src; +strcat (char *dest, const char *src) { - char *s1 = dest; - const char *s2 = src; - char c; - - /* Find the end of the string. */ - do - c = *s1++; - while (c != '\0'); - - /* Make S1 point before the next character, so we can increment - it while memory is read (wins on pipelined cpus). */ - s1 -= 2; - - do - { - c = *s2++; - *++s1 = c; - } - while (c != '\0'); - + strcpy (dest + strlen (dest), src); return dest; } libc_hidden_builtin_def (strcat) diff --git a/string/strchr.c b/string/strchr.c index da69ed2353..5f900750a3 100644 --- a/string/strchr.c +++ b/string/strchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -21,16 +21,13 @@ <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <memcopy.h> #include <stdlib.h> #undef strchr /* Find the first occurrence of C in S. */ char * -strchr (s, c_in) - const char *s; - int c_in; +strchr (const char *s, int c_in) { const unsigned char *char_ptr; const unsigned long int *longword_ptr; diff --git a/string/strchrnul.c b/string/strchrnul.c index 2aec3144e9..2678f1de0a 100644 --- a/string/strchrnul.c +++ b/string/strchrnul.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/strcmp.c b/string/strcmp.c index 212f20cc1c..4d4c044660 100644 --- a/string/strcmp.c +++ b/string/strcmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -16,7 +16,6 @@ <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <memcopy.h> #undef strcmp @@ -24,9 +23,7 @@ greater than zero if S1 is lexicographically less than, equal to or greater than S2. */ int -strcmp (p1, p2) - const char *p1; - const char *p2; +strcmp (const char *p1, const char *p2) { const unsigned char *s1 = (const unsigned char *) p1; const unsigned char *s2 = (const unsigned char *) p2; diff --git a/string/strcoll.c b/string/strcoll.c index 779ba1309c..aba64158cd 100644 --- a/string/strcoll.c +++ b/string/strcoll.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2014 Free Software Foundation, Inc. +/* Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@cygnus.com>, 1995. @@ -29,9 +29,7 @@ int -STRCOLL (s1, s2) - const STRING_TYPE *s1; - const STRING_TYPE *s2; +STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2) { return STRCOLL_L (s1, s2, _NL_CURRENT_LOCALE); } diff --git a/string/strcoll_l.c b/string/strcoll_l.c index 10ce4a67ce..8f1225fc7a 100644 --- a/string/strcoll_l.c +++ b/string/strcoll_l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2014 Free Software Foundation, Inc. +/* Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@gnu.org>, 1995. @@ -22,7 +22,6 @@ #include <locale.h> #include <stddef.h> #include <stdint.h> -#include <stdlib.h> #include <string.h> #include <sys/param.h> @@ -30,8 +29,8 @@ # define STRING_TYPE char # define USTRING_TYPE unsigned char # define STRCOLL __strcoll_l +# define STRDIFF __strdiff # define STRCMP strcmp -# define STRLEN strlen # define WEIGHT_H "../locale/weight.h" # define SUFFIX MB # define L(arg) arg @@ -41,6 +40,21 @@ #define CONCAT1(a,b) a##b #include "../locale/localeinfo.h" +#include WEIGHT_H + +#define MASK_UTF8_7BIT (1 << 7) +#define MASK_UTF8_START (3 << 6) + +size_t +STRDIFF (const STRING_TYPE *s, const STRING_TYPE *t) +{ + size_t n; + + for (n = 0; *s != '\0' && *s++ == *t++; ++n) + continue; + + return n; +} /* Track status while looking for sequences in a string. */ typedef struct @@ -48,14 +62,11 @@ 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 idxnow; /* Current index in sequences. */ 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. */ - int32_t *idxarr; /* Array to cache weight indices. */ - unsigned char *rulearr; /* Array to cache rules. */ 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 @@ -64,185 +75,13 @@ typedef struct const USTRING_TYPE *back_us; /* Beginning of the backward sequence. */ } coll_seq; -/* Get next sequence. The weight indices are cached, so we don't need to - traverse the string. */ -static void -get_next_seq_cached (coll_seq *seq, int nrules, int pass, - const unsigned char *rulesets, - const USTRING_TYPE *weights) -{ - 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; - size_t idxnow = seq->idxnow; - unsigned char *rulearr = seq->rulearr; - int32_t *idxarr = seq->idxarr; - - 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) - { - idxnow = idxcnt; - backw_stop = ~0ul; - } - else - { - /* Nothing any more. The backward sequence - ended with the last sequence in the string. */ - idxnow = ~0ul; - break; - } - } - else - idxnow = --backw; - } - else - { - backw_stop = idxcnt; - - while (idxcnt < idxmax) - { - if ((rulesets[rulearr[idxcnt] * 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) - /* Note that LEN is still zero. */ - break; - - backw_stop = ~0ul; - idxnow = idxcnt++; - } - else - /* We pushed backward sequences. */ - idxnow = backw = idxcnt - 1; - } - len = weights[idxarr[idxnow]++]; - } - - /* Update the structure. */ - seq->val = val; - seq->len = len; - seq->backw_stop = backw_stop; - seq->backw = backw; - seq->idxcnt = idxcnt; - seq->idxnow = idxnow; -} - /* Get next sequence. Traverse the string as required. */ -static void +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) -{ -#include WEIGHT_H - 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; - size_t idxnow = seq->idxnow; - unsigned char *rulearr = seq->rulearr; - int32_t *idxarr = seq->idxarr; - 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) - { - idxnow = idxcnt; - backw_stop = ~0ul; - } - else - /* Nothing any more. The backward sequence ended with - the last sequence in the string. Note that LEN - is still zero. */ - break; - } - else - idxnow = --backw; - } - else - { - backw_stop = idxmax; - - while (*us != L('\0')) - { - int32_t tmp = findidx (&us, -1); - rulearr[idxmax] = tmp >> 24; - idxarr[idxmax] = tmp & 0xffffff; - idxcnt = idxmax++; - - if ((rulesets[rulearr[idxcnt] * nrules] - & 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; - idxnow = idxcnt; - } - else - /* We pushed backward sequences. */ - idxnow = backw = idxcnt - 1; - } - len = weights[idxarr[idxnow]++]; - } - - /* Update the structure. */ - seq->val = val; - seq->len = len; - seq->backw_stop = backw_stop; - seq->backw = backw; - seq->idxcnt = idxcnt; - seq->idxmax = idxmax; - seq->idxnow = idxnow; - seq->us = us; -} - -/* Get next sequence. Traverse the string as required. This function does not - set or use any index or rule cache. */ -static void -get_next_seq_nocache (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) + const USTRING_TYPE *extra, const int32_t *indirect, + int pass) { -#include WEIGHT_H size_t val = seq->val = 0; int len = seq->len; size_t backw_stop = seq->backw_stop; @@ -285,7 +124,7 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets, us = seq->back_us; while (i < backw) { - int32_t tmp = findidx (&us, -1); + int32_t tmp = findidx (table, indirect, extra, &us, -1); idx = tmp & 0xffffff; i++; } @@ -300,7 +139,7 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets, while (*us != L('\0')) { - int32_t tmp = findidx (&us, -1); + int32_t tmp = findidx (table, indirect, extra, &us, -1); unsigned char rule = tmp >> 24; prev_idx = idx; idx = tmp & 0xffffff; @@ -367,11 +206,10 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets, seq->idx = idx; } -/* Compare two sequences. This version does not use the index and rules - cache. */ -static int -do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position, - const USTRING_TYPE *weights) +/* 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; @@ -418,56 +256,6 @@ out: return result; } -/* Compare two sequences using the index cache. */ -static 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; - int32_t *idx1arr = seq1->idxarr; - int32_t *idx2arr = seq2->idxarr; - int idx1now = seq1->idxnow; - int idx2now = seq2->idxnow; - 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[idx1arr[idx1now]] != weights[idx2arr[idx2now]]) - { - /* The sequences differ. */ - result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]]; - goto out; - } - - /* Increment the offsets. */ - ++idx1arr[idx1now]; - ++idx2arr[idx2now]; - - --seq1len; - --seq2len; - } - while (seq1len > 0 && seq2len > 0); - - if (position && seq1len != seq2len) - result = seq1len - seq2len; - -out: - seq1->len = seq1len; - seq2->len = seq2len; - return result; -} - int STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) { @@ -481,9 +269,33 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) const USTRING_TYPE *extra; const int32_t *indirect; + /* In case there is no locale specific sort order (C / POSIX). */ if (nrules == 0) return STRCMP (s1, s2); + /* Fast forward to the position of the first difference. Needs to be + encoding aware as the byte-by-byte comparison can stop in the middle + of a char sequence for multibyte encodings like UTF-8. */ + uint_fast32_t encoding = + current->values[_NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)].word; + if (encoding != __cet_other) + { + size_t diff = STRDIFF (s1, s2); + if (diff > 0) + { + if (encoding == __cet_utf8 && (*(s1 + diff) & MASK_UTF8_7BIT) != 0) + do + diff--; + while (diff > 0 && (*(s1 + diff) & MASK_UTF8_START) != MASK_UTF8_START); + s1 += diff; + s2 += diff; + } + } + + /* 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 *) @@ -500,65 +312,15 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0); assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0); - /* We need this a few times. */ - size_t s1len = STRLEN (s1); - size_t s2len = STRLEN (s2); - - /* Catch empty strings. */ - if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0)) - return (s1len != 0) - (s2len != 0); - - /* Perform the first pass over the string and while doing this find - and store the weights for each character. Since we want this to - be as fast as possible we are using `alloca' to store the temporary - values. But since there is no limit on the length of the string - we have to use `malloc' if the string is too long. We should be - very conservative here. - - Please note that the localedef programs makes sure that `position' - is not used at the first level. */ + int result = 0, rule = 0; coll_seq seq1, seq2; - bool use_malloc = false; - int result = 0; - - memset (&seq1, 0, sizeof (seq1)); - seq2 = seq1; - - size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1); + seq1.len = 0; + seq1.idxmax = 0; + seq1.rule = 0; + seq2.len = 0; + seq2.idxmax = 0; - if (MIN (s1len, s2len) > size_max - || MAX (s1len, s2len) > size_max - MIN (s1len, s2len)) - { - /* If the strings are long enough to cause overflow in the size request, - then skip the allocation and proceed with the non-cached routines. */ - } - else if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1))) - { - seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1)); - - /* If we failed to allocate memory, we leave everything as NULL so that - we use the nocache version of traversal and comparison functions. */ - if (seq1.idxarr != NULL) - { - seq2.idxarr = &seq1.idxarr[s1len]; - seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len]; - seq2.rulearr = &seq1.rulearr[s1len]; - use_malloc = true; - } - } - else - { - seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t)); - seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t)); - seq1.rulearr = (unsigned char *) alloca (s1len); - seq2.rulearr = (unsigned char *) alloca (s2len); - } - - int rule = 0; - - /* Cache values in the first pass and if needed, use them in subsequent - passes. */ for (int pass = 0; pass < nrules; ++pass) { seq1.idxcnt = 0; @@ -576,64 +338,46 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) 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. */ + 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) { - if (__glibc_unlikely (seq1.idxarr == NULL)) - { - get_next_seq_nocache (&seq1, nrules, rulesets, weights, table, + get_next_seq (&seq1, nrules, rulesets, weights, table, extra, indirect, pass); - get_next_seq_nocache (&seq2, nrules, rulesets, weights, table, + get_next_seq (&seq2, nrules, rulesets, weights, table, extra, indirect, pass); - } - else if (pass == 0) - { - get_next_seq (&seq1, nrules, rulesets, weights, table, extra, - indirect); - get_next_seq (&seq2, nrules, rulesets, weights, table, extra, - indirect); - } - else - { - get_next_seq_cached (&seq1, nrules, pass, rulesets, weights); - get_next_seq_cached (&seq2, nrules, pass, rulesets, weights); - } - /* See whether any or both strings are empty. */ if (seq1.len == 0 || seq2.len == 0) { if (seq1.len == seq2.len) - /* Both ended. So far so good, both strings are equal - at this level. */ - break; + { + /* 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 && encoding == __cet_other && + 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. */ - result = seq1.len == 0 ? -1 : 1; - goto free_and_return; + return seq1.len == 0 ? -1 : 1; } - if (__glibc_unlikely (seq1.idxarr == NULL)) - result = do_compare_nocache (&seq1, &seq2, position, weights); - else - result = do_compare (&seq1, &seq2, position, weights); + result = do_compare (&seq1, &seq2, position, weights); if (result != 0) - goto free_and_return; + return result; } - if (__glibc_likely (seq1.rulearr != NULL)) - rule = seq1.rulearr[0]; - else - rule = seq1.rule; + rule = seq1.rule; } - /* Free the memory if needed. */ - free_and_return: - if (use_malloc) - free (seq1.idxarr); - return result; } libc_hidden_def (STRCOLL) diff --git a/string/strcpy.c b/string/strcpy.c index f136916437..3ebb51bfd9 100644 --- a/string/strcpy.c +++ b/string/strcpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -17,27 +17,13 @@ #include <stddef.h> #include <string.h> -#include <memcopy.h> #undef strcpy /* Copy SRC to DEST. */ char * -strcpy (dest, src) - char *dest; - const char *src; +strcpy (char *dest, const char *src) { - char c; - char *s = (char *) src; - const ptrdiff_t off = dest - s - 1; - - do - { - c = *s++; - s[off] = c; - } - while (c != '\0'); - - return dest; + return memcpy (dest, src, strlen (src) + 1); } libc_hidden_builtin_def (strcpy) diff --git a/string/strcspn.c b/string/strcspn.c index 7c39f793ea..2694d2ab0e 100644 --- a/string/strcspn.c +++ b/string/strcspn.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -15,27 +15,18 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#if HAVE_CONFIG_H -# include <config.h> -#endif - -#if defined _LIBC || HAVE_STRING_H -# include <string.h> -#else -# include <strings.h> -# ifndef strchr -# define strchr index -# endif -#endif +#include <string.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 (s, reject) - const char *s; - const char *reject; +STRCSPN (const char *s, const char *reject) { size_t count = 0; diff --git a/string/strdup.c b/string/strdup.c index cedffa0da2..8ba33babae 100644 --- a/string/strdup.c +++ b/string/strdup.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/strerror.c b/string/strerror.c index 5eed633e2b..824d09f759 100644 --- a/string/strerror.c +++ b/string/strerror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -32,7 +32,7 @@ strerror (errnum) char *ret = __strerror_r (errnum, NULL, 0); int saved_errno; - if (__builtin_expect (ret != NULL, 1)) + if (__glibc_likely (ret != NULL)) return ret; saved_errno = errno; if (buf == NULL) diff --git a/string/strerror_l.c b/string/strerror_l.c index 19f591e7c3..2ed78b5f83 100644 --- a/string/strerror_l.c +++ b/string/strerror_l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2014 Free Software Foundation, Inc. +/* Copyright (C) 2007-2015 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 diff --git a/string/strfry.c b/string/strfry.c index e448947d95..e4ecd3c757 100644 --- a/string/strfry.c +++ b/string/strfry.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 diff --git a/string/string-inlines.c b/string/string-inlines.c index 1e1e91ab49..0445be74cb 100644 --- a/string/string-inlines.c +++ b/string/string-inlines.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999-2014 Free Software Foundation, Inc. +/* Copyright (C) 1999-2015 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 diff --git a/string/string.h b/string/string.h index b127e8d9dd..54a4d39a53 100644 --- a/string/string.h +++ b/string/string.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -31,12 +31,8 @@ __BEGIN_DECLS #define __need_NULL #include <stddef.h> -/* Provide correct C++ prototypes, and indicate this to the caller. This - requires a compatible C++ standard library. As a heuristic, we provide - these when the compiler indicates full conformance with C++98 or later, - and for older GCC versions that are known to provide a compatible - libstdc++. */ -#if defined __cplusplus && (__cplusplus >= 199711L || __GNUC_PREREQ (4, 4)) +/* Tell the caller that we provide correct C++ prototypes. */ +#if defined __cplusplus && __GNUC_PREREQ (4, 4) # define __CORRECT_ISO_CPP_STRING_H_PROTO #endif @@ -54,11 +50,11 @@ __END_NAMESPACE_STD /* 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_SVID || defined __USE_BSD || defined __USE_XOPEN +#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 /* SVID. */ +#endif /* Misc || X/Open. */ __BEGIN_NAMESPACE_STD @@ -170,8 +166,7 @@ extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n, __locale_t __l) __THROW __nonnull ((2, 4)); #endif -#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED \ - || defined __USE_XOPEN2K8 +#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 /* Duplicate S, returning an identical malloc'd string. */ extern char *strdup (const char *__s) __THROW __attribute_malloc__ __nonnull ((1)); @@ -355,7 +350,7 @@ extern char *__strtok_r (char *__restrict __s, const char *__restrict __delim, char **__restrict __save_ptr) __THROW __nonnull ((2, 3)); -#if defined __USE_POSIX || defined __USE_MISC +#ifdef __USE_POSIX extern char *strtok_r (char *__restrict __s, const char *__restrict __delim, char **__restrict __save_ptr) __THROW __nonnull ((2, 3)); @@ -412,7 +407,7 @@ __BEGIN_NAMESPACE_STD /* Return a string describing the meaning of the `errno' code in ERRNUM. */ extern char *strerror (int __errnum) __THROW; __END_NAMESPACE_STD -#if defined __USE_XOPEN2K || defined __USE_MISC +#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 @@ -450,7 +445,7 @@ extern char *strerror_l (int __errnum, __locale_t __l) __THROW; the namespace rules does not allow this. */ extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1)); -#ifdef __USE_BSD +#ifdef __USE_MISC /* 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)); @@ -537,7 +532,7 @@ extern int strcasecmp (const char *__s1, const char *__s2) /* 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)); -#endif /* Use BSD. */ +#endif /* Use misc. */ #ifdef __USE_GNU /* Again versions of a few functions which use the given locale instead @@ -551,7 +546,7 @@ extern int strncasecmp_l (const char *__s1, const char *__s2, __THROW __attribute_pure__ __nonnull ((1, 2, 4)); #endif -#ifdef __USE_BSD +#ifdef __USE_MISC /* 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, diff --git a/string/strings.h b/string/strings.h index 994c4b048c..028361ac99 100644 --- a/string/strings.h +++ b/string/strings.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -19,20 +19,16 @@ #define _STRINGS_H 1 /* We don't need and should not read this file if <string.h> was already - read. The one exception being that if __USE_BSD isn't defined, then + read. The one exception being that if __USE_MISC isn't defined, then these aren't defined in string.h, so we need to define them here. */ -#if !defined _STRING_H || !defined __USE_BSD +#if !defined _STRING_H || !defined __USE_MISC # include <features.h> # define __need_size_t # include <stddef.h> -/* Provide correct C++ prototypes, and indicate this to the caller. This - requires a compatible C++ standard library. As a heuristic, we provide - these when the compiler indicates full conformance with C++98 or later, - and for older GCC versions that are known to provide a compatible - libstdc++. */ -# if defined __cplusplus && (__cplusplus >= 199711L || __GNUC_PREREQ (4, 4)) +/* Tell the caller that we provide correct C++ prototypes. */ +# if defined __cplusplus && __GNUC_PREREQ (4, 4) # define __CORRECT_ISO_CPP_STRINGS_H_PROTO # endif diff --git a/string/strlen.c b/string/strlen.c index 342c4a2b70..d066bde577 100644 --- a/string/strlen.c +++ b/string/strlen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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); @@ -26,8 +26,7 @@ /* Return the length of the null-terminated string STR. Scan for the null terminator quickly by testing four bytes at a time. */ size_t -strlen (str) - const char *str; +strlen (const char *str) { const char *char_ptr; const unsigned long int *longword_ptr; diff --git a/string/strncase.c b/string/strncase.c index a462a2a0e4..a8fc046c09 100644 --- a/string/strncase.c +++ b/string/strncase.c @@ -1,6 +1,6 @@ /* Compare at most N characters of two strings without taking care for the case. - Copyright (C) 1992-2014 Free Software Foundation, Inc. + Copyright (C) 1992-2015 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 diff --git a/string/strncase_l.c b/string/strncase_l.c index 01e1f0c7ca..b0e360d5cf 100644 --- a/string/strncase_l.c +++ b/string/strncase_l.c @@ -1,6 +1,6 @@ /* Compare at most N characters of two strings without taking care for the case using given locale. - Copyright (C) 1997-2014 Free Software Foundation, Inc. + Copyright (C) 1997-2015 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 diff --git a/string/strncat.c b/string/strncat.c index 7ac44561bd..12572aebdb 100644 --- a/string/strncat.c +++ b/string/strncat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -17,10 +17,6 @@ #include <string.h> -#ifdef _LIBC -# include <memcopy.h> -#endif - #ifndef STRNCAT # undef strncat # define STRNCAT strncat @@ -29,54 +25,15 @@ char * STRNCAT (char *s1, const char *s2, size_t n) { - char c; char *s = s1; /* Find the end of S1. */ - do - c = *s1++; - while (c != '\0'); - - /* Make S1 point before next character, so we can increment - it while memory is read (wins on pipelined cpus). */ - s1 -= 2; - - if (n >= 4) - { - size_t n4 = n >> 2; - do - { - c = *s2++; - *++s1 = c; - if (c == '\0') - return s; - c = *s2++; - *++s1 = c; - if (c == '\0') - return s; - c = *s2++; - *++s1 = c; - if (c == '\0') - return s; - c = *s2++; - *++s1 = c; - if (c == '\0') - return s; - } while (--n4 > 0); - n &= 3; - } + s1 += strlen (s1); - while (n > 0) - { - c = *s2++; - *++s1 = c; - if (c == '\0') - return s; - n--; - } + size_t ss = __strnlen (s2, n); - if (c != '\0') - *++s1 = '\0'; + s1[ss] = '\0'; + memcpy (s1, s2, ss); return s; } diff --git a/string/strncmp.c b/string/strncmp.c index 8a93373b97..2a1137aaf2 100644 --- a/string/strncmp.c +++ b/string/strncmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/strncpy.c b/string/strncpy.c index 0915e036d6..37af5aaad0 100644 --- a/string/strncpy.c +++ b/string/strncpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -57,10 +57,10 @@ STRNCPY (char *s1, const char *s2, size_t n) if (--n4 == 0) goto last_chars; } - n = n - (s1 - s) - 1; - if (n == 0) - return s; - goto zero_fill; + s1++; + n = n - (s1 - s); + memset (s1, '\0', n); + return s; } last_chars: @@ -77,11 +77,7 @@ STRNCPY (char *s1, const char *s2, size_t n) } while (c != '\0'); - zero_fill: - do - *++s1 = '\0'; - while (--n > 0); - + memset (s1 + 1, '\0', n); return s; } libc_hidden_builtin_def (strncpy) diff --git a/string/strndup.c b/string/strndup.c index e114a27208..15b19f720a 100644 --- a/string/strndup.c +++ b/string/strndup.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 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 diff --git a/string/strnlen.c b/string/strnlen.c index 8d53afbaf0..d2bb843fdd 100644 --- a/string/strnlen.c +++ b/string/strnlen.c @@ -1,5 +1,5 @@ /* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 Free Software Foundation, Inc. Contributed by Jakub Jelinek <jakub@redhat.com>. Based on strlen written by Torbjorn Granlund (tege@sics.se), @@ -40,7 +40,7 @@ __strnlen (const char *str, size_t maxlen) if (maxlen == 0) return 0; - if (__builtin_expect (end_ptr < str, 0)) + if (__glibc_unlikely (end_ptr < str)) end_ptr = (const char *) ~0UL; /* Handle the first few characters by reading one character at a time. @@ -160,6 +160,7 @@ __strnlen (const char *str, size_t maxlen) return char_ptr - str; } #ifndef STRNLEN +libc_hidden_def (__strnlen) weak_alias (__strnlen, strnlen) #endif libc_hidden_def (strnlen) diff --git a/string/strpbrk.c b/string/strpbrk.c index ce33b684ef..4f1d9b72bb 100644 --- a/string/strpbrk.c +++ b/string/strpbrk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -15,21 +15,17 @@ 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 HAVE_CONFIG_H -# include <string.h> -#endif +#include <string.h> #undef strpbrk +#ifndef STRPBRK +#define STRPBRK strpbrk +#endif + /* Find the first occurrence in S of any character in ACCEPT. */ char * -strpbrk (s, accept) - const char *s; - const char *accept; +STRPBRK (const char *s, const char *accept) { while (*s != '\0') { diff --git a/string/strrchr.c b/string/strrchr.c index b5b4bc6208..b70a832ddc 100644 --- a/string/strrchr.c +++ b/string/strrchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -19,9 +19,13 @@ #undef strrchr +#ifndef STRRCHR +# define STRRCHR strrchr +#endif + /* Find the last occurrence of C in S. */ char * -strrchr (const char *s, int c) +STRRCHR (const char *s, int c) { const char *found, *p; diff --git a/string/strsep.c b/string/strsep.c index dedd0f1073..e77fbf2905 100644 --- a/string/strsep.c +++ b/string/strsep.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 diff --git a/string/strsignal.c b/string/strsignal.c index 5806081a2d..01c01e2dc7 100644 --- a/string/strsignal.c +++ b/string/strsignal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 diff --git a/string/strspn.c b/string/strspn.c index 37e8161a28..4a1422bcea 100644 --- a/string/strspn.c +++ b/string/strspn.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -18,13 +18,14 @@ #include <string.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 (s, accept) - const char *s; - const char *accept; +STRSPN (const char *s, const char *accept) { const char *p; const char *a; diff --git a/string/strstr.c b/string/strstr.c index 2ae04c644f..045e878da3 100644 --- a/string/strstr.c +++ b/string/strstr.c @@ -1,5 +1,5 @@ /* Return the offset of one string within another. - Copyright (C) 1994-2014 Free Software Foundation, Inc. + Copyright (C) 1994-2015 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 diff --git a/string/strtok.c b/string/strtok.c index f7f709908f..97acd4a05a 100644 --- a/string/strtok.c +++ b/string/strtok.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 @@ -22,6 +22,10 @@ static char *olds; #undef strtok +#ifndef STRTOK +# define STRTOK strtok +#endif + /* Parse S into tokens separated by characters in DELIM. If S is NULL, the last string strtok() was called with is used. For example: @@ -32,9 +36,7 @@ static char *olds; // s = "abc\0=-def\0" */ char * -strtok (s, delim) - char *s; - const char *delim; +STRTOK (char *s, const char *delim) { char *token; diff --git a/string/strtok_r.c b/string/strtok_r.c index fb5ba8d7a2..9e558ee9bc 100644 --- a/string/strtok_r.c +++ b/string/strtok_r.c @@ -1,5 +1,5 @@ /* Reentrant string tokenizer. Generic version. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 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 diff --git a/string/strverscmp.c b/string/strverscmp.c index 7060afcc65..38bf5e2e6f 100644 --- a/string/strverscmp.c +++ b/string/strverscmp.c @@ -1,5 +1,5 @@ /* Compare strings while treating digits characters numerically. - Copyright (C) 1997-2014 Free Software Foundation, Inc. + Copyright (C) 1997-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997. diff --git a/string/strxfrm.c b/string/strxfrm.c index 22ed3761e3..65f8062940 100644 --- a/string/strxfrm.c +++ b/string/strxfrm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2014 Free Software Foundation, Inc. +/* Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@cygnus.com>, 1995. diff --git a/string/strxfrm_l.c b/string/strxfrm_l.c index 04b9338f05..8b61ea2b20 100644 --- a/string/strxfrm_l.c +++ b/string/strxfrm_l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2014 Free Software Foundation, Inc. +/* Copyright (C) 1995-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@gnu.org>, 1995. @@ -29,7 +29,6 @@ # define STRING_TYPE char # define USTRING_TYPE unsigned char # define STRXFRM __strxfrm_l -# define STRCMP strcmp # define STRLEN strlen # define STPNCPY __stpncpy # define WEIGHT_H "../locale/weight.h" @@ -40,8 +39,24 @@ #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 @@ -80,115 +95,325 @@ utf8_encode (char *buf, int val) } #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++]; + } -size_t -STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) + *weight_idx = idx; + return len; +} + +static int +find_position (const USTRING_TYPE *us, const locale_data_t *l_data, + const int pass) { - 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; + 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; + size_t needed = 0; size_t last_needed; - const USTRING_TYPE *usrc; - size_t srclen = STRLEN (src); - int32_t *idxarr; - unsigned char *rulearr; - size_t idxmax; - size_t idxcnt; - int use_malloc; - -#include WEIGHT_H - if (nrules == 0) + /* Now the passes over the weights. */ + for (pass = 0; pass < l_data->nrules; ++pass) { - if (n != 0) - STPNCPY (dest, src, MIN (srclen + 1, n)); + size_t backw_len = 0; + last_needed = needed; + const USTRING_TYPE *cur = usrc; + const USTRING_TYPE *backw_start = NULL; - return srclen; - } + /* 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); - 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; - use_malloc = 0; + 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]; - 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); + 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; + } - /* Handle an empty string as a special case. */ - if (srclen == 0) - { - if (n != 0) - *dest = L('\0'); - return 0; - } + needed += backw_len; + backw_start = NULL; + backw_len = 0; + } - /* We need the elements of the string as unsigned values since they - are used as indeces. */ - usrc = (const USTRING_TYPE *) src; - - /* Perform the first pass over the string and while doing this find - and store the weights for each character. Since we want this to - be as fast as possible we are using `alloca' to store the temporary - values. But since there is no limit on the length of the string - we have to use `malloc' if the string is too long. We should be - very conservative here. */ - if (! __libc_use_alloca ((srclen + 1) * (sizeof (int32_t) + 1))) - { - idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1)); - rulearr = (unsigned char *) &idxarr[srclen]; - - if (idxarr == NULL) - /* No memory. Well, go with the stack then. - - XXX Once this implementation is stable we will handle this - differently. Instead of precomputing the indeces we will - do this in time. This means, though, that this happens for - every pass again. */ - goto try_stack; - use_malloc = 1; - } - else - { - try_stack: - idxarr = (int32_t *) alloca (srclen * sizeof (int32_t)); - rulearr = (unsigned char *) alloca (srclen + 1); + /* 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; } - idxmax = 0; - do + /* 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) { - int32_t tmp = findidx (&usrc, -1); - rulearr[idxmax] = tmp >> 24; - idxarr[idxmax] = tmp & 0xffffff; - - ++idxmax; + /* Remove the \1 byte. */ + if (--needed <= n) + dest[needed - 1] = L('\0'); } - while (*usrc != L('\0')); - /* This element is only read, the value never used but to determine - another value which then is ignored. */ - rulearr[idxmax] = '\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. We now use the indeces we found - before. */ - needed = 0; + /* Now the passes over the weights. */ for (pass = 0; pass < nrules; ++pass) { size_t backw_stop = ~0ul; @@ -434,14 +659,87 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l) dest[needed - 1] = L('\0'); } - /* Free the memory if needed. */ - if (use_malloc) - free (idxarr); - /* 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 diff --git a/string/swab.c b/string/swab.c index 489eb042c2..f75e26f894 100644 --- a/string/swab.c +++ b/string/swab.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2014 Free Software Foundation, Inc. +/* Copyright (C) 1992-2015 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 diff --git a/string/test-bcopy.c b/string/test-bcopy.c index dc91f5e813..1f6af1528f 100644 --- a/string/test-bcopy.c +++ b/string/test-bcopy.c @@ -1,5 +1,5 @@ /* Test and measure bcopy functions. - Copyright (C) 2012-2014 Free Software Foundation, Inc. + Copyright (C) 2012-2015 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 diff --git a/string/test-bzero.c b/string/test-bzero.c index f0fd24fa87..f32173d07b 100644 --- a/string/test-bzero.c +++ b/string/test-bzero.c @@ -1,5 +1,5 @@ /* Test and measure bzero functions. - Copyright (C) 2012-2014 Free Software Foundation, Inc. + Copyright (C) 2012-2015 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 diff --git a/string/test-ffs.c b/string/test-ffs.c index 7ac1dd6bfd..afbaaf7b5d 100644 --- a/string/test-ffs.c +++ b/string/test-ffs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994-2014 Free Software Foundation, Inc. +/* Copyright (C) 1994-2015 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. @@ -21,8 +21,8 @@ #include <stdio.h> #include <string.h> -int -main (void) +static int +do_test (void) { int failures = 0; int i; @@ -61,3 +61,6 @@ main (void) return failures; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/test-memccpy.c b/string/test-memccpy.c index 725d64042e..f42de2fc9a 100644 --- a/string/test-memccpy.c +++ b/string/test-memccpy.c @@ -1,5 +1,5 @@ /* Test and measure memccpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-memchr.c b/string/test-memchr.c index 0ba79b8b07..19c89781b2 100644 --- a/string/test-memchr.c +++ b/string/test-memchr.c @@ -1,5 +1,5 @@ /* Test and measure memchr functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-memcmp.c b/string/test-memcmp.c index 14090edb35..488f9c1253 100644 --- a/string/test-memcmp.c +++ b/string/test-memcmp.c @@ -1,5 +1,5 @@ /* Test and measure memcmp functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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. diff --git a/string/test-memcpy.c b/string/test-memcpy.c index 136c985abd..51fbd92122 100644 --- a/string/test-memcpy.c +++ b/string/test-memcpy.c @@ -1,5 +1,5 @@ /* Test and measure memcpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-memmem.c b/string/test-memmem.c index 1b4e4b7ea0..9e8917ccc3 100644 --- a/string/test-memmem.c +++ b/string/test-memmem.c @@ -1,5 +1,5 @@ /* Test and measure memmem functions. - Copyright (C) 2008-2014 Free Software Foundation, Inc. + Copyright (C) 2008-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@redhat.com>, 2008. @@ -44,7 +44,7 @@ simple_memmem (const void *haystack, size_t haystack_len, const void *needle, /* Sanity check, otherwise the loop might search through the whole memory. */ - if (__builtin_expect (haystack_len < needle_len, 0)) + if (__glibc_unlikely (haystack_len < needle_len)) return NULL; for (begin = (const char *) haystack; begin <= last_possible; ++begin) diff --git a/string/test-memmove.c b/string/test-memmove.c index 7e1c41c64d..9742efaab9 100644 --- a/string/test-memmove.c +++ b/string/test-memmove.c @@ -1,5 +1,5 @@ /* Test and measure memmove functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c index ce853b09ec..6d25d87d6b 100644 --- a/string/test-mempcpy.c +++ b/string/test-mempcpy.c @@ -1,5 +1,5 @@ /* Test and measure mempcpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-memrchr.c b/string/test-memrchr.c index efe4e9fbf1..b06ea9ec68 100644 --- a/string/test-memrchr.c +++ b/string/test-memrchr.c @@ -1,5 +1,5 @@ /* Test and measure memrchr functions. - Copyright (C) 2013-2014 Free Software Foundation, Inc. + Copyright (C) 2013-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-memset.c b/string/test-memset.c index 2171b0d9e6..9f3af468b0 100644 --- a/string/test-memset.c +++ b/string/test-memset.c @@ -1,5 +1,5 @@ /* Test and measure memset functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-rawmemchr.c b/string/test-rawmemchr.c index c718a49dd8..9c952ef62f 100644 --- a/string/test-rawmemchr.c +++ b/string/test-rawmemchr.c @@ -1,5 +1,5 @@ /* Test and measure memchr functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-stpcpy.c b/string/test-stpcpy.c index 6c3d28c35f..3d138d9cae 100644 --- a/string/test-stpcpy.c +++ b/string/test-stpcpy.c @@ -1,5 +1,5 @@ /* Test and measure stpcpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-stpncpy.c b/string/test-stpncpy.c index ec7b72b4d5..1adab34e57 100644 --- a/string/test-stpncpy.c +++ b/string/test-stpncpy.c @@ -1,5 +1,5 @@ /* Test and measure stpncpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strcasecmp.c b/string/test-strcasecmp.c index 11bc65b0c6..382dcdcd81 100644 --- a/string/test-strcasecmp.c +++ b/string/test-strcasecmp.c @@ -1,5 +1,5 @@ /* Test and measure strcasecmp functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strcasestr.c b/string/test-strcasestr.c index 1c24506e3e..489dc84205 100644 --- a/string/test-strcasestr.c +++ b/string/test-strcasestr.c @@ -1,5 +1,5 @@ /* Test and measure strcasestr functions. - Copyright (C) 2010-2014 Free Software Foundation, Inc. + Copyright (C) 2010-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@redhat.com>, 2010. diff --git a/string/test-strcat.c b/string/test-strcat.c index 5b73b11b2a..0a97e25484 100644 --- a/string/test-strcat.c +++ b/string/test-strcat.c @@ -1,5 +1,5 @@ /* Test and measure strcat functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strchr.c b/string/test-strchr.c index 12cd9d84ec..ea06c43d7f 100644 --- a/string/test-strchr.c +++ b/string/test-strchr.c @@ -1,5 +1,5 @@ /* Test and measure STRCHR functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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 @@ -44,6 +44,7 @@ # define MIDDLE_CHAR 127 # define SMALL_CHAR 23 # define UCHAR unsigned char +# define L(s) s #else # include <wchar.h> # define STRCHR wcschr @@ -53,6 +54,7 @@ # define MIDDLE_CHAR 1121 # define SMALL_CHAR 851 # define UCHAR wchar_t +# define L(s) L ## s #endif #ifdef USE_FOR_STRCHRNUL @@ -219,9 +221,9 @@ do_random_tests (void) static void check1 (void) { - char s[] __attribute__((aligned(16))) = "\xff"; - char c = '\xfe'; - char *exp_result = stupid_STRCHR (s, c); + 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); diff --git a/string/test-strchrnul.c b/string/test-strchrnul.c index 9d5d819a72..8c6bb0fa7f 100644 --- a/string/test-strchrnul.c +++ b/string/test-strchrnul.c @@ -1,6 +1,6 @@ /* Test and measure strchrnul function. - Copyright (C) 2011-2014 Free Software Foundation, Inc. + Copyright (C) 2011-2015 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 diff --git a/string/test-strcmp.c b/string/test-strcmp.c index b395dc7fbe..dc4ba6f9b4 100644 --- a/string/test-strcmp.c +++ b/string/test-strcmp.c @@ -1,5 +1,5 @@ /* Test and measure strcmp and wcscmp functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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. @@ -329,6 +329,34 @@ check (void) 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); + } + } } diff --git a/string/test-strcpy.c b/string/test-strcpy.c index e244db5367..f0f1dddb40 100644 --- a/string/test-strcpy.c +++ b/string/test-strcpy.c @@ -1,5 +1,5 @@ /* Test and measure strcpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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 diff --git a/string/test-strcspn.c b/string/test-strcspn.c index 5ea50a6699..b60a048c5c 100644 --- a/string/test-strcspn.c +++ b/string/test-strcspn.c @@ -1,5 +1,5 @@ /* Test and measure strcspn functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-string.h b/string/test-string.h index 4d9a39de30..d8bd45b00b 100644 --- a/string/test-string.h +++ b/string/test-string.h @@ -1,5 +1,5 @@ /* Test and measure string and memory functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. @@ -18,7 +18,6 @@ <http://www.gnu.org/licenses/>. */ #include <sys/cdefs.h> -#define TEST_IFUNC typedef struct { @@ -105,7 +104,7 @@ size_t iterations = 100000; #define CALL(impl, ...) \ (* (proto_t) (impl)->fn) (__VA_ARGS__) -#if defined TEST_IFUNC && defined TEST_NAME +#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; @@ -164,7 +163,7 @@ static impl_t *impl_array; static void test_init (void) { -#if defined TEST_IFUNC && defined TEST_NAME +#ifdef TEST_NAME func_count = __libc_ifunc_impl_list (TEST_NAME, func_list, (sizeof func_list / sizeof func_list[0])); diff --git a/string/test-strlen.c b/string/test-strlen.c index 046a19435a..2c88efae4b 100644 --- a/string/test-strlen.c +++ b/string/test-strlen.c @@ -1,5 +1,5 @@ /* Test and measure STRLEN functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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 diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c index 6ad54e0916..de27d86779 100644 --- a/string/test-strncasecmp.c +++ b/string/test-strncasecmp.c @@ -1,5 +1,5 @@ /* Test and measure strncasecmp functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strncat.c b/string/test-strncat.c index 4915c59584..366e6fccb5 100644 --- a/string/test-strncat.c +++ b/string/test-strncat.c @@ -1,5 +1,5 @@ /* Test and measure strncat functions. - Copyright (C) 2011-2014 Free Software Foundation, Inc. + Copyright (C) 2011-2015 Free Software Foundation, Inc. Contributed by Intel Corporation. The GNU C Library is free software; you can redistribute it and/or diff --git a/string/test-strncmp.c b/string/test-strncmp.c index f3b2c68014..fb57a9bdc5 100644 --- a/string/test-strncmp.c +++ b/string/test-strncmp.c @@ -1,5 +1,5 @@ -/* Test and measure strncmp functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. +/* Test strncmp and wcsncmp functions. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. @@ -18,17 +18,80 @@ <http://www.gnu.org/licenses/>. */ #define TEST_MAIN -#define TEST_NAME "strncmp" +#ifdef WIDE +# define TEST_NAME "wcsncmp" +#else +# define TEST_NAME "strncmp" +#endif #include "test-string.h" -typedef int (*proto_t) (const char *, const char *, size_t); -int simple_strncmp (const char *, const char *, size_t); -int stupid_strncmp (const char *, const char *, size_t); +#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; +} -IMPL (stupid_strncmp, 0) -IMPL (simple_strncmp, 0) -IMPL (strncmp, 1) +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) { @@ -51,8 +114,17 @@ stupid_strncmp (const char *s1, const char *s2, size_t n) 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, +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n, int exp_result) { int result = CALL (impl, s1, s2, n); @@ -70,7 +142,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, size_t n, } static void -do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n, +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) @@ -82,12 +154,12 @@ 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; + CHAR *s1, *s2; if (n == 0) { - s1 = (char*)(buf1 + page_size); - s2 = (char*)(buf2 + page_size); + s1 = (CHAR *) (buf1 + page_size); + s2 = (CHAR *) (buf2 + page_size); FOR_EACH_IMPL (impl, 0) do_one_test (impl, s1, s2, n, 0); @@ -97,16 +169,16 @@ do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char, align1 &= 15; align2 &= 15; - align_n = (page_size - n) & 15; + align_n = (page_size - n * CHARBYTES) & 15; - s1 = (char*)(buf1 + page_size - n); - s2 = (char*)(buf2 + page_size - n); + s1 = (CHAR *) (buf1 + page_size - n * CHARBYTES); + s2 = (CHAR *) (buf2 + page_size - n * CHARBYTES); if (align1 < align_n) - s1 -= (align_n - align1); + s1 = (CHAR *) ((char *) s1 - (align_n - align1)); if (align2 < align_n) - s2 -= (align_n - align2); + s2 = (CHAR *) ((char *) s2 - (align_n - align2)); for (i = 0; i < n; i++) s1[i] = s2[i] = 1 + 23 * i % max_char; @@ -130,24 +202,24 @@ 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; + CHAR *s1, *s2; if (n == 0) return; - align1 &= 7; - if (align1 + n + 1 >= page_size) + align1 &= 63; + if (align1 + (n + 1) * CHARBYTES >= page_size) return; - align2 &= 7; - if (align2 + n + 1 >= page_size) + align2 &= 63; + if (align2 + (n + 1) * CHARBYTES >= page_size) return; - s1 = (char*)(buf1 + align1); - s2 = (char*)(buf2 + align2); + s1 = (CHAR *) (buf1 + align1); + s2 = (CHAR *) (buf2 + align2); for (i = 0; i < n; i++) - s1[i] = s2[i] = 1 + 23 * i % max_char; + s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char; s1[n] = 24 + exp_result; s2[n] = 23; @@ -161,19 +233,20 @@ do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char, s2[n - 1] -= exp_result; FOR_EACH_IMPL (impl, 0) - do_one_test (impl, (char*)s1, (char*)s2, n, exp_result); + do_one_test (impl, s1, s2, n, exp_result); } static void -do_page_test (size_t offset1, size_t offset2, char *s2) +do_page_test (size_t offset1, size_t offset2, CHAR *s2) { - char *s1; + CHAR *s1; int exp_result; - if (offset1 >= page_size || offset2 >= page_size) + if (offset1 * CHARBYTES >= page_size || offset2 * CHARBYTES >= page_size) return; - s1 = (char *) (buf1 + offset1); + s1 = (CHAR *) buf1; + s1 += offset1; s2 += offset2; exp_result= *s1; @@ -191,8 +264,8 @@ do_random_tests (void) size_t i, j, n, align1, align2, pos, len1, len2, size; int result; long r; - unsigned char *p1 = buf1 + page_size - 512; - unsigned char *p2 = buf2 + page_size - 512; + UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES); + UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES); for (n = 0; n < ITERATIONS; n++) { @@ -240,7 +313,7 @@ do_random_tests (void) } result = 0; - memcpy (p2 + align2, p1 + align1, pos); + MEMCPY (p2 + align2, p1 + align1, pos); if (pos < len1) { if (p2[align2 + pos] == p1[align1 + pos]) @@ -263,7 +336,7 @@ do_random_tests (void) FOR_EACH_IMPL (impl, 1) { - r = CALL (impl, (char*)(p1 + align1), (char*)(p2 + align2), size); + r = CALL (impl, (CHAR *) (p1 + align1), (CHAR *) (p2 + align2), size); /* Test whether on 64-bit architectures where ABI requires callee to promote has the promotion been done. */ asm ("" : "=g" (r) : "0" (r)); @@ -282,19 +355,26 @@ do_random_tests (void) static void check1 (void) { - char *s1 = (char *)(buf1 + 0xb2c); - char *s2 = (char *)(buf1 + 0xfd8); - size_t i; + CHAR *s1 = (CHAR *) (buf1 + 0xb2c); + CHAR *s2 = (CHAR *) (buf1 + 0xfd8); + size_t i, offset; int exp_result; - strcpy(s1, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"); - strcpy(s2, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV"); + STRCPY(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs")); + STRCPY(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV")); + + /* Check possible overflow bug for wcsncmp */ + s1[4] = CHAR__MAX; + s2[4] = CHAR__MIN; - for (i = 0; i < 80; i++) + for (offset = 0; offset < 6; offset++) { - exp_result = simple_strncmp (s1, s2, i); - FOR_EACH_IMPL (impl, 0) - check_result (impl, s1, s2, i, exp_result); + 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); + } } } @@ -302,17 +382,17 @@ static void check2 (void) { size_t i; - char *s1, *s2; + CHAR *s1, *s2; - s1 = (char *) buf1; - for (i = 0; i < page_size - 1; i++) + s1 = (CHAR *) buf1; + for (i = 0; i < (page_size / CHARBYTES) - 1; i++) s1[i] = 23; s1[i] = 0; - s2 = strdup (s1); + s2 = STRDUP (s1); for (i = 0; i < 64; ++i) - do_page_test (3990 + i, 2635, s2); + do_page_test ((3988 / CHARBYTES) + i, (2636 / CHARBYTES), s2); free (s2); } diff --git a/string/test-strncpy.c b/string/test-strncpy.c index 2326acc6fa..d1c312a3a2 100644 --- a/string/test-strncpy.c +++ b/string/test-strncpy.c @@ -1,5 +1,5 @@ /* Test and measure strncpy functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strnlen.c b/string/test-strnlen.c index be9edd2aae..96797e156b 100644 --- a/string/test-strnlen.c +++ b/string/test-strnlen.c @@ -1,5 +1,5 @@ /* Test and measure strlen functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c index bd981618a3..b4ac389a71 100644 --- a/string/test-strpbrk.c +++ b/string/test-strpbrk.c @@ -1,5 +1,5 @@ /* Test and measure strpbrk functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strrchr.c b/string/test-strrchr.c index 12d7c9f779..d8d826e536 100644 --- a/string/test-strrchr.c +++ b/string/test-strrchr.c @@ -1,5 +1,5 @@ /* Test and measure STRCHR functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 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>, diff --git a/string/test-strspn.c b/string/test-strspn.c index 56dcf5378a..89fef8726c 100644 --- a/string/test-strspn.c +++ b/string/test-strspn.c @@ -1,5 +1,5 @@ /* Test and measure strspn functions. - Copyright (C) 1999-2014 Free Software Foundation, Inc. + Copyright (C) 1999-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. diff --git a/string/test-strstr.c b/string/test-strstr.c index 5547186c9a..cb2c2f6164 100644 --- a/string/test-strstr.c +++ b/string/test-strstr.c @@ -1,5 +1,5 @@ /* Test and measure strstr functions. - Copyright (C) 2010-2014 Free Software Foundation, Inc. + Copyright (C) 2010-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@redhat.com>, 2010. diff --git a/string/testcopy.c b/string/testcopy.c index d0afdc868a..8302f8eeca 100644 --- a/string/testcopy.c +++ b/string/testcopy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1990-2014 Free Software Foundation, Inc. +/* Copyright (C) 1990-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). diff --git a/string/tester.c b/string/tester.c index 62905a7d24..f957ed29d4 100644 --- a/string/tester.c +++ b/string/tester.c @@ -1,5 +1,5 @@ /* Tester for string functions. - Copyright (C) 1995-2014 Free Software Foundation, Inc. + Copyright (C) 1995-2015 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 @@ -32,6 +32,7 @@ #include <string.h> #include <strings.h> #include <fcntl.h> +#include <libc-internal.h> #define STREQ(a, b) (strcmp((a), (b)) == 0) @@ -1303,8 +1304,15 @@ test_memset (void) 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. */ diff --git a/string/tst-bswap.c b/string/tst-bswap.c index cca704c0d2..ea4b195469 100644 --- a/string/tst-bswap.c +++ b/string/tst-bswap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2014 Free Software Foundation, Inc. +/* Copyright (C) 2000-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>. @@ -21,8 +21,8 @@ extern unsigned long long int wash (unsigned long long int a); -int -main (void) +static int +do_test (void) { int result = 0; @@ -71,3 +71,6 @@ wash (unsigned long long int a) regards the argument to the bswap_*() functions as constant. */ return a + 0; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/tst-inlcall.c b/string/tst-inlcall.c index 32d88631f5..79bf223af4 100644 --- a/string/tst-inlcall.c +++ b/string/tst-inlcall.c @@ -1,5 +1,5 @@ /* Tester for calling inline string functions. - Copyright (C) 1998-2014 Free Software Foundation, Inc. + Copyright (C) 1998-2015 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 @@ -31,8 +31,8 @@ #include <fcntl.h> -int -main (void) +static int +do_test (void) { int status; int errors = 0; @@ -80,3 +80,6 @@ main (void) } return status; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/tst-strcoll-overflow.c b/string/tst-strcoll-overflow.c index e7a43ea844..34d8a9cde3 100644 --- a/string/tst-strcoll-overflow.c +++ b/string/tst-strcoll-overflow.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2014 Free Software Foundation, Inc. +/* Copyright (C) 2013-2015 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 @@ -57,5 +57,6 @@ do_test (void) #define TIMEOUT 300 #define EXPECTED_SIGNAL SIGALRM +#define EXPECTED_STATUS 0 #define TEST_FUNCTION do_test () #include "../test-skeleton.c" diff --git a/string/tst-strtok.c b/string/tst-strtok.c index 7e34aeefaa..6fbef9f33e 100644 --- a/string/tst-strtok.c +++ b/string/tst-strtok.c @@ -2,8 +2,8 @@ #include <stdio.h> #include <string.h> -int -main (void) +static int +do_test (void) { char buf[1] = { 0 }; int result = 0; @@ -21,3 +21,6 @@ main (void) return result; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/tst-strtok_r.c b/string/tst-strtok_r.c index b1e89a425f..8d5e39162a 100644 --- a/string/tst-strtok_r.c +++ b/string/tst-strtok_r.c @@ -1,5 +1,5 @@ /* Test strtok_r regression for BZ #14229. - Copyright (C) 2012-2014 Free Software Foundation, Inc. + Copyright (C) 2012-2015 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 diff --git a/string/tst-strxfrm.c b/string/tst-strxfrm.c index 2ae2e2952f..f48cfc0da4 100644 --- a/string/tst-strxfrm.c +++ b/string/tst-strxfrm.c @@ -58,8 +58,8 @@ test (const char *locale) } -int -main (void) +static int +do_test (void) { int result = 0; @@ -69,3 +69,6 @@ main (void) return result; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/string/wordcopy.c b/string/wordcopy.c index ff4cce4702..c84eb68723 100644 --- a/string/wordcopy.c +++ b/string/wordcopy.c @@ -1,5 +1,5 @@ /* _memcopy.c -- subroutines for memory copy functions. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Torbjorn Granlund (tege@sics.se). diff --git a/string/xpg-strerror.c b/string/xpg-strerror.c index 36e2548dbb..7ca85405fe 100644 --- a/string/xpg-strerror.c +++ b/string/xpg-strerror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2014 Free Software Foundation, Inc. +/* Copyright (C) 1991-2015 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 |