diff options
Diffstat (limited to 'libc/string')
-rw-r--r-- | libc/string/Makefile | 6 | ||||
-rw-r--r-- | libc/string/memrchr.c | 11 | ||||
-rw-r--r-- | libc/string/stratcliff.c | 35 | ||||
-rw-r--r-- | libc/string/strncat.c | 1 | ||||
-rw-r--r-- | libc/string/strnlen.c | 13 | ||||
-rw-r--r-- | libc/string/test-memcmp.c | 125 | ||||
-rw-r--r-- | libc/string/test-rawmemchr.c | 189 | ||||
-rw-r--r-- | libc/string/test-strchr.c | 137 | ||||
-rw-r--r-- | libc/string/test-strcmp.c | 89 | ||||
-rw-r--r-- | libc/string/test-strlen.c | 85 | ||||
-rw-r--r-- | libc/string/test-wcscmp.c | 2 |
11 files changed, 525 insertions, 168 deletions
diff --git a/libc/string/Makefile b/libc/string/Makefile index 699ccce0a..46d32188b 100644 --- a/libc/string/Makefile +++ b/libc/string/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2002, 2005-2008, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 1991-2002, 2005-2010, 2011 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -50,11 +50,11 @@ routines-$(OPTION_EGLIBC_ENVZ) += envz # for -fbounded-pointer compiles. Glibc uses memchr for explicit checks. o-objects.ob := memcpy.o memset.o memchr.o -strop-tests := wcscmp memchr memcmp memcpy memmove mempcpy memset memccpy \ +strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ strlen strncmp strncpy strpbrk strrchr strspn memmem \ strstr strcasestr strnlen strcasecmp strncasecmp \ - strncat + strncat rawmemchr tests := tester inl-tester noinl-tester testcopy test-ffs \ tst-strlen stratcliff tst-svc tst-inlcall \ bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \ diff --git a/libc/string/memrchr.c b/libc/string/memrchr.c index 21662b1bd..498a4376e 100644 --- a/libc/string/memrchr.c +++ b/libc/string/memrchr.c @@ -63,7 +63,12 @@ /* Search no more than N bytes of S for C. */ __ptr_t -__memrchr (s, c_in, n) +#ifndef MEMRCHR +__memrchr +#else +MEMRCHR +#endif + (s, c_in, n) const __ptr_t s; int c_in; size_t n; @@ -205,6 +210,8 @@ __memrchr (s, c_in, n) return 0; } -#ifdef weak_alias +#ifndef MEMRCHR +# ifdef weak_alias weak_alias (__memrchr, memrchr) +# endif #endif diff --git a/libc/string/stratcliff.c b/libc/string/stratcliff.c index 5165be2d1..5176409c5 100644 --- a/libc/string/stratcliff.c +++ b/libc/string/stratcliff.c @@ -1,5 +1,5 @@ /* Test for string function add boundaries of usable memory. - Copyright (C) 1996,1997,1999-2003,2007,2009,2010 + Copyright (C) 1996,1997,1999-2003,2007,2009,2010,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -240,7 +240,7 @@ do_test (void) } } - /* This function only exists for single-byte characters. */ + /* These functions only exist for single-byte characters. */ #ifndef WCSTEST /* rawmemchr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) @@ -261,6 +261,37 @@ do_test (void) adr[middle] = L('T'); } } + + /* memrchr test */ + for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) + { + for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) + { + adr[middle] = L('V'); + + CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer); + + if (cp - &adr[outer] != middle - outer) + { + printf ("%s flunked for outer = %d, middle = %d\n", + STRINGIFY (memrchr), outer, middle); + result = 1; + } + + adr[middle] = L('T'); + } + } + for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) + { + CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer); + + if (cp != NULL) + { + printf ("%s flunked for outer = %d\n", + STRINGIFY (memrchr), outer); + result = 1; + } + } #endif /* strcpy/wcscpy test */ diff --git a/libc/string/strncat.c b/libc/string/strncat.c index 0a3d4af70..bf6f99b27 100644 --- a/libc/string/strncat.c +++ b/libc/string/strncat.c @@ -25,6 +25,7 @@ typedef char reg_char; #endif #ifndef STRNCAT +# undef strncat # define STRNCAT strncat #endif diff --git a/libc/string/strnlen.c b/libc/string/strnlen.c index 454257b2b..d083ec29e 100644 --- a/libc/string/strnlen.c +++ b/libc/string/strnlen.c @@ -1,5 +1,5 @@ /* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 1991,1993,1997,2000,2001,2005 Free Software Foundation, Inc. + Copyright (C) 1991, 1993, 1997, 2000, 2001, 2005, 2011 Free Software Foundation, Inc. Contributed by Jakub Jelinek <jakub@redhat.com>. Based on strlen written by Torbjorn Granlund (tege@sics.se), @@ -26,12 +26,17 @@ /* Find the length of S, but scan at most MAXLEN characters. If no '\0' terminator is found in that many characters, return MAXLEN. */ + +#ifdef STRNLEN +# define __strnlen STRNLEN +#endif + size_t __strnlen (const char *str, size_t maxlen) { const char *char_ptr, *end_ptr = str + maxlen; const unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, himagic, lomagic; + unsigned long int longword, himagic, lomagic; if (maxlen == 0) return 0; @@ -65,14 +70,12 @@ __strnlen (const char *str, size_t maxlen) The 1-bits make sure that carries propagate to the next 0-bit. The 0-bits provide holes for carries to fall into. */ - magic_bits = 0x7efefeffL; himagic = 0x80808080L; lomagic = 0x01010101L; if (sizeof (longword) > 4) { /* 64-bit version of the magic. */ /* Do the shift in two steps to avoid a warning if long has 32 bits. */ - magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; himagic = ((himagic << 16) << 16) | himagic; lomagic = ((lomagic << 16) << 16) | lomagic; } @@ -157,5 +160,7 @@ __strnlen (const char *str, size_t maxlen) char_ptr = end_ptr; return char_ptr - str; } +#ifndef STRNLEN weak_alias (__strnlen, strnlen) +#endif libc_hidden_def (strnlen) diff --git a/libc/string/test-memcmp.c b/libc/string/test-memcmp.c index 3040e212a..f246d3a78 100644 --- a/libc/string/test-memcmp.c +++ b/libc/string/test-memcmp.c @@ -1,7 +1,8 @@ /* Test and measure memcmp functions. - Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2003, 2005, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. + Added wmemcmp support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -20,25 +21,57 @@ #define TEST_MAIN #include "test-string.h" - -typedef int (*proto_t) (const char *, const char *, size_t); -int simple_memcmp (const char *, const char *, size_t); - -IMPL (simple_memcmp, 0) -IMPL (memcmp, 1) +#ifdef WIDE +# include <inttypes.h> +# include <wchar.h> + +# define MEMCMP wmemcmp +# define MEMCPY wmemcpy +# define SIMPLE_MEMCMP simple_wmemcmp +# define CHAR wchar_t +# define UCHAR wchar_t +# define CHARBYTES 4 +# define CHAR__MIN WCHAR_MIN +# define CHAR__MAX WCHAR_MAX +int +simple_wmemcmp (const wchar_t *s1, const wchar_t *s2, size_t n) +{ + int ret = 0; + /* Warning! + wmemcmp has to use SIGNED comparison for elements. + memcmp has to use UNSIGNED comparison for elemnts. + */ + while (n-- && (ret = *s1 < *s2 ? -1 : *s1 == *s2 ? 0 : 1) == 0) {s1++; s2++;} + return ret; +} +#else +# define MEMCMP memcmp +# define MEMCPY memcpy +# define SIMPLE_MEMCMP simple_memcmp +# define CHAR char +# define MAX_CHAR 255 +# define UCHAR unsigned char +# define CHARBYTES 1 +# define CHAR__MIN CHAR_MIN +# define CHAR__MAX CHAR_MAX int simple_memcmp (const char *s1, const char *s2, size_t n) { int ret = 0; - while (n-- - && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0); + while (n-- && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0); return ret; } +#endif + +typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); + +IMPL (SIMPLE_MEMCMP, 0) +IMPL (MEMCMP, 1) static int -check_result (impl_t *impl, const char *s1, const char *s2, size_t len, +check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len, int exp_result) { int result = CALL (impl, s1, s2, len); @@ -56,7 +89,7 @@ check_result (impl_t *impl, const char *s1, const char *s2, size_t len, } static void -do_one_test (impl_t *impl, const char *s1, const char *s2, size_t len, +do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len, int exp_result) { if (check_result (impl, s1, s2, len, exp_result) < 0) @@ -85,24 +118,24 @@ static void do_test (size_t align1, size_t align2, size_t len, int exp_result) { size_t i; - char *s1, *s2; + CHAR *s1, *s2; if (len == 0) return; - align1 &= 7; - if (align1 + len >= page_size) + align1 &= 63; + if (align1 + (len + 1) * CHARBYTES >= page_size) return; - align2 &= 7; - if (align2 + len >= page_size) + align2 &= 63; + if (align2 + (len + 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 < len; i++) - s1[i] = s2[i] = 1 + 23 * i % 255; + s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % CHAR__MAX; s1[len] = align1; s2[len] = align2; @@ -124,12 +157,12 @@ do_random_tests (void) size_t i, j, n, align1, align2, pos, len; 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++) { - align1 = random () & 31; + align1 = random () & 31; if (random () & 1) align2 = random () & 31; else @@ -142,7 +175,7 @@ do_random_tests (void) pos = 511 - j - (random () & 7); len = random () & 511; if (len + j >= 512) - len = 511 - j - (random () & 7); + len = 511 - j - (random () & 7); j = len + align1 + 64; if (j > 512) j = 512; for (i = 0; i < j; ++i) @@ -152,10 +185,10 @@ do_random_tests (void) result = 0; if (pos >= len) - memcpy (p2 + align2, p1 + align1, len); + MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, len); else { - memcpy (p2 + align2, p1 + align1, pos); + MEMCPY ((CHAR *) p2 + align2, (const CHAR *) p1 + align1, pos); if (p2[align2 + pos] == p1[align1 + pos]) { p2[align2 + pos] = random () & 255; @@ -171,16 +204,14 @@ do_random_tests (void) FOR_EACH_IMPL (impl, 1) { - r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2), len); - /* Test whether on 64-bit architectures where ABI requires - callee to promote has the promotion been done. */ - asm ("" : "=g" (r) : "0" (r)); + r = CALL (impl, (CHAR *) p1 + align1, (const CHAR *) p2 + align2, + len); if ((r == 0 && result) || (r < 0 && result >= 0) || (r > 0 && result <= 0)) { error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p", - n, impl->name, align1, align2, len, pos, r, result, p1, p2); + n, impl->name, align1 * CHARBYTES & 63, align2 * CHARBYTES & 63, len, pos, r, result, p1, p2); ret = 1; } } @@ -190,7 +221,7 @@ do_random_tests (void) static void check1 (void) { - char s1[116], s2[116]; + CHAR s1[116], s2[116]; int n, exp_result; s1[0] = -108; @@ -395,8 +426,8 @@ check1 (void) s2[99] = 1; s1[100] = 116; s2[100] = 116; - s1[101] = -13; - s2[101] = -13; + s1[101] = CHAR__MIN; + s2[101] = CHAR__MAX; s1[102] = -109; s2[102] = -109; s1[103] = 1; @@ -417,8 +448,8 @@ check1 (void) s2[110] = -109; s1[111] = 1; s2[111] = 1; - s1[112] = 20; - s2[112] = 20; + s1[112] = CHAR__MAX; + s2[112] = CHAR__MIN; s1[113] = -13; s2[113] = -13; s1[114] = -109; @@ -427,9 +458,12 @@ check1 (void) s2[115] = 1; n = 116; - exp_result = simple_memcmp (s1, s2, n); - FOR_EACH_IMPL (impl, 0) - check_result (impl, s1, s2, n, exp_result); + for (size_t i = 0; i < n; i++) + { + exp_result = SIMPLE_MEMCMP (s1 + i, s2 + i, n - i); + FOR_EACH_IMPL (impl, 0) + check_result (impl, s1 + i, s2 + i, n - i, exp_result); + } } int @@ -448,9 +482,9 @@ test_main (void) for (i = 1; i < 16; ++i) { - do_test (i, i, i, 0); - do_test (i, i, i, 1); - do_test (i, i, i, -1); + do_test (i * CHARBYTES, i * CHARBYTES, i, 0); + do_test (i * CHARBYTES, i * CHARBYTES, i, 1); + do_test (i * CHARBYTES, i * CHARBYTES, i, -1); } for (i = 0; i < 16; ++i) @@ -466,20 +500,19 @@ test_main (void) do_test (0, 0, 2 << i, 1); do_test (0, 0, 2 << i, -1); do_test (0, 0, 16 << i, 0); - do_test (8 - i, 2 * i, 16 << i, 0); + do_test ((8 - i) * CHARBYTES, (2 * i) * CHARBYTES, 16 << i, 0); do_test (0, 0, 16 << i, 1); do_test (0, 0, 16 << i, -1); } for (i = 1; i < 8; ++i) { - do_test (i, 2 * i, 8 << i, 0); - do_test (i, 2 * i, 8 << i, 1); - do_test (i, 2 * i, 8 << i, -1); + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 0); + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 1); + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, -1); } do_random_tests (); return ret; } - #include "../test-skeleton.c" diff --git a/libc/string/test-rawmemchr.c b/libc/string/test-rawmemchr.c new file mode 100644 index 000000000..58c1b158f --- /dev/null +++ b/libc/string/test-rawmemchr.c @@ -0,0 +1,189 @@ +/* Test and measure memchr functions. + Copyright (C) 1999,2002,2003,2005,2009,2011 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jakub Jelinek <jakub@redhat.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> + +#define TEST_MAIN +#include "test-string.h" + +typedef char *(*proto_t) (const char *, int); +char *simple_rawmemchr (const char *, int); + +IMPL (simple_rawmemchr, 0) +IMPL (rawmemchr, 1) + +char * +simple_rawmemchr (const char *s, int c) +{ + while (1) + if (*s++ == (char) c) + return (char *) s - 1; + return NULL; +} + +static void +do_one_test (impl_t *impl, const char *s, int c, char *exp_res) +{ + char *res = CALL (impl, s, c); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = 1 + 23 * i % 127; + if (buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 1; + } + buf1[align + len] = 0; + + assert (pos < len); + + buf1[align + pos] = seek_char; + buf1[align + len] = -seek_char; + result = (char *) (buf1 + align + pos); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char *) (buf1 + align), seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + size_t i, j, n, align, pos, len; + int seek_char; + char *result; + unsigned char *p = buf1 + page_size - 512; + + for (n = 0; n < ITERATIONS; n++) + { + align = random () & 15; + pos = random () & 511; + if (pos + align >= 512) + pos = 511 - align - (random () & 7); + len = random () & 511; + if (len + align >= 512) + len = 512 - align - (random () & 7); + if (pos >= len) + continue; + seek_char = random () & 255; + j = len + align + 64; + if (j > 512) + j = 512; + + for (i = 0; i < j; i++) + { + if (i == pos + align) + p[i] = seek_char; + else + { + p[i] = random () & 255; + if (i < pos + align && p[i] == seek_char) + p[i] = seek_char + 13; + } + } + + assert (pos < len); + size_t r = random (); + if ((r & 31) == 0) + len = ~(uintptr_t) (p + align) - ((r >> 5) & 31); + result = (char *) (p + pos + align); + + FOR_EACH_IMPL (impl, 1) + if (CALL (impl, (char *) (p + align), seek_char) != result) + { + error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p", + n, impl->name, align, seek_char, len, pos, + CALL (impl, (char *) (p + align), seek_char), + result, p); + ret = 1; + } + } +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 7; ++i) + { + do_test (0, 16 << i, 2048, 23); + do_test (i, 64, 256, 23); + do_test (0, 16 << i, 2048, 0); + do_test (i, 64, 256, 0); + } + for (i = 1; i < 32; ++i) + { + do_test (0, i, i + 1, 23); + do_test (0, i, i + 1, 0); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/libc/string/test-strchr.c b/libc/string/test-strchr.c index cf25b449d..518a4dce3 100644 --- a/libc/string/test-strchr.c +++ b/libc/string/test-strchr.c @@ -1,7 +1,8 @@ -/* Test and measure strchr functions. - Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. +/* Test and measure STRCHR functions. + Copyright (C) 1999, 2002, 2003, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. + Added wcschr support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011 The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -21,38 +22,55 @@ #define TEST_MAIN #include "test-string.h" -typedef char *(*proto_t) (const char *, int); -char *simple_strchr (const char *, int); -char *stupid_strchr (const char *, int); - -IMPL (stupid_strchr, 0) -IMPL (simple_strchr, 0) -IMPL (strchr, 1) - -char * -simple_strchr (const char *s, int c) +#ifndef WIDE +# define STRCHR strchr +# define STRLEN strlen +# define CHAR char +# define BIG_CHAR CHAR_MAX +# define MIDDLE_CHAR 127 +# define SMALL_CHAR 23 +# define UCHAR unsigned char +#else +# include <wchar.h> +# define STRCHR wcschr +# define STRLEN wcslen +# define CHAR wchar_t +# define BIG_CHAR WCHAR_MAX +# define MIDDLE_CHAR 1121 +# define SMALL_CHAR 851 +# define UCHAR wchar_t +#endif + +typedef CHAR *(*proto_t) (const CHAR *, int); + +CHAR * +simple_STRCHR (const CHAR *s, int c) { - for (; *s != (char) c; ++s) + for (; *s != (CHAR) c; ++s) if (*s == '\0') return NULL; - return (char *) s; + return (CHAR *) s; } -char * -stupid_strchr (const char *s, int c) +CHAR * +stupid_STRCHR (const CHAR *s, int c) { - size_t n = strlen (s) + 1; + size_t n = STRLEN (s) + 1; while (n--) - if (*s++ == (char) c) - return (char *) s - 1; + if (*s++ == (CHAR) c) + return (CHAR *) s - 1; return NULL; } +IMPL (stupid_STRCHR, 1) +IMPL (simple_STRCHR, 1) +IMPL (STRCHR, 1) + static void -do_one_test (impl_t *impl, const char *s, int c, char *exp_res) +do_one_test (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res) { - char *res = CALL (impl, s, c); + CHAR *res = CALL (impl, s, c); if (res != exp_res) { error (0, 0, "Wrong result in function %s %p %p", impl->name, @@ -82,37 +100,40 @@ do_one_test (impl_t *impl, const char *s, int c, char *exp_res) static void do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +/* for wcschr: align here means align not in bytes, + * but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) + * len for wcschr here isn't in bytes but it's number of wchar_t symbols */ { size_t i; - char *result; - - align &= 7; - if (align + len >= page_size) + CHAR *result; + CHAR *buf = (CHAR *) (buf1); + align &= 15; + if ((align + len) * sizeof(CHAR) >= page_size) return; for (i = 0; i < len; ++i) { - buf1[align + i] = 32 + 23 * i % (max_char - 32); - if (buf1[align + i] == seek_char) - buf1[align + i] = seek_char + 1; + buf[align + i] = 32 + 23 * i % max_char; + if (buf[align + i] == seek_char) + buf[align + i] = seek_char + 1; } - buf1[align + len] = 0; + buf[align + len] = 0; if (pos < len) { - buf1[align + pos] = seek_char; - result = (char *) (buf1 + align + pos); + buf[align + pos] = seek_char; + result = buf + align + pos; } else if (seek_char == 0) - result = (char *) (buf1 + align + len); + result = buf + align + len; else result = NULL; if (HP_TIMING_AVAIL) - printf ("Length %4zd, alignment %2zd:", pos, align); + printf ("Length %4zd, alignment in bytes %2zd:", pos, align * sizeof (CHAR)); FOR_EACH_IMPL (impl, 0) - do_one_test (impl, (char *) (buf1 + align), seek_char, result); + do_one_test (impl, buf + align, seek_char, result); if (HP_TIMING_AVAIL) putchar ('\n'); @@ -123,27 +144,30 @@ do_random_tests (void) { size_t i, j, n, align, pos, len; int seek_char; - char *result; - unsigned char *p = buf1 + page_size - 512; + CHAR *result; + UCHAR *p = (UCHAR *) (buf1 + page_size - 512 * sizeof (CHAR)); for (n = 0; n < ITERATIONS; n++) { +/* for wcschr: align here means align not in bytes, but in wchar_ts, + * in bytes it will equal to align * (sizeof (wchar_t)) */ align = random () & 15; pos = random () & 511; seek_char = random () & 255; if (pos + align >= 511) pos = 510 - align - (random () & 7); +/* len for wcschr here isn't in bytes but it's number of wchar_t symbols */ len = random () & 511; if ((pos == len && seek_char) || (pos > len && (random () & 1))) len = pos + 1 + (random () & 7); if (len + align >= 512) - len = 511 - align - (random () & 7); + len = 511 - align - (random () & 7); if (pos == len && seek_char) len = pos + 1; j = (pos > len ? pos : len) + align + 64; if (j > 512) - j = 512; + j = 512; for (i = 0; i < j; i++) { @@ -166,18 +190,19 @@ do_random_tests (void) } if (pos <= len) - result = (char *) (p + pos + align); + result = (CHAR *) (p + pos + align); else if (seek_char == 0) - result = (char *) (p + len + align); + result = (CHAR *) (p + len + align); else result = NULL; FOR_EACH_IMPL (impl, 1) - if (CALL (impl, (char *) (p + align), seek_char) != result) + if (CALL (impl, (CHAR *) (p + align), seek_char) != result) { - error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p", - n, impl->name, align, seek_char, len, pos, - CALL (impl, (char *) (p + align), seek_char), result, p); + error (0, 0, "Iteration %zd - wrong result in function \ + %s (align in bytes: %zd, seek_char: %d, len: %zd, pos: %zd) %p != %p, p %p", + n, impl->name, align * sizeof (CHAR), seek_char, len, pos, + CALL (impl, (CHAR *) (p + align), seek_char), result, p); ret = 1; } } @@ -197,38 +222,38 @@ test_main (void) for (i = 1; i < 8; ++i) { - do_test (0, 16 << i, 2048, 23, 127); - do_test (i, 16 << i, 2048, 23, 127); + do_test (0, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR); + do_test (i, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR); } for (i = 1; i < 8; ++i) { - do_test (i, 64, 256, 23, 127); - do_test (i, 64, 256, 23, 255); + do_test (i, 64, 256, SMALL_CHAR, MIDDLE_CHAR); + do_test (i, 64, 256, SMALL_CHAR, BIG_CHAR); } for (i = 0; i < 32; ++i) { - do_test (0, i, i + 1, 23, 127); - do_test (0, i, i + 1, 23, 255); + do_test (0, i, i + 1, SMALL_CHAR, MIDDLE_CHAR); + do_test (0, i, i + 1, SMALL_CHAR, BIG_CHAR); } for (i = 1; i < 8; ++i) { - do_test (0, 16 << i, 2048, 0, 127); - do_test (i, 16 << i, 2048, 0, 127); + do_test (0, 16 << i, 2048, 0, MIDDLE_CHAR); + do_test (i, 16 << i, 2048, 0, MIDDLE_CHAR); } for (i = 1; i < 8; ++i) { - do_test (i, 64, 256, 0, 127); - do_test (i, 64, 256, 0, 255); + do_test (i, 64, 256, 0, MIDDLE_CHAR); + do_test (i, 64, 256, 0, BIG_CHAR); } for (i = 0; i < 32; ++i) { - do_test (0, i, i + 1, 0, 127); - do_test (0, i, i + 1, 0, 255); + do_test (0, i, i + 1, 0, MIDDLE_CHAR); + do_test (0, i, i + 1, 0, BIG_CHAR); } do_random_tests (); diff --git a/libc/string/test-strcmp.c b/libc/string/test-strcmp.c index b8d85dca7..9ea4df759 100644 --- a/libc/string/test-strcmp.c +++ b/libc/string/test-strcmp.c @@ -1,4 +1,4 @@ -/* Test and measure STRCMP functions. +/* Test and measure strcmp and wcscmp functions. Copyright (C) 1999, 2002, 2003, 2005, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. @@ -23,7 +23,6 @@ #include "test-string.h" #ifdef WIDE -# include <inttypes.h> # include <wchar.h> # define L(str) L##str @@ -34,12 +33,53 @@ # define SIMPLE_STRCMP simple_wcscmp # define STUPID_STRCMP stupid_wcscmp # define CHAR wchar_t -# define UCHAR uint32_t +# define UCHAR wchar_t # define CHARBYTES 4 # define CHARBYTESLOG 2 # define CHARALIGN __alignof__ (CHAR) # define MIDCHAR 0x7fffffff # define LARGECHAR 0xfffffffe +# define CHAR__MAX WCHAR_MAX +# define CHAR__MIN WCHAR_MIN + +/* Wcscmp uses signed semantics for comparison, not unsigned */ +/* Avoid using substraction since possible overflow */ + +int +simple_wcscmp (const wchar_t *s1, const wchar_t *s2) +{ + wchar_t c1, c2; + do + { + c1 = *s1++; + c2 = *s2++; + if (c2 == L'\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 < c2 ? -1 : 1; +} + +int +stupid_wcscmp (const wchar_t *s1, const wchar_t *s2) +{ + size_t ns1 = wcslen (s1) + 1; + size_t ns2 = wcslen (s2) + 1; + size_t n = ns1 < ns2 ? ns1 : ns2; + int ret = 0; + + wchar_t c1, c2; + + while (n--) { + c1 = *s1++; + c2 = *s2++; + if ((ret = c1 < c2 ? -1 : c1 == c2 ? 0 : 1) != 0) + break; + } + return ret; +} + #else # define L(str) str # define STRCMP strcmp @@ -55,31 +95,35 @@ # define CHARALIGN 1 # define MIDCHAR 0x7f # define LARGECHAR 0xfe -#endif -typedef int (*proto_t) (const CHAR *, const CHAR *); +# define CHAR__MAX CHAR_MAX +# define CHAR__MIN CHAR_MIN +/* Strcmp uses unsigned semantics for comparison. */ int -SIMPLE_STRCMP (const CHAR *s1, const CHAR *s2) +simple_strcmp (const char *s1, const char *s2) { int ret; - while ((ret = *(UCHAR *) s1 - *(UCHAR *) s2++) == 0 && *s1++); + while ((ret = *(unsigned char *) s1 - *(unsigned char*) s2++) == 0 && *s1++); return ret; } int -STUPID_STRCMP (const CHAR *s1, const CHAR *s2) +stupid_strcmp (const char *s1, const char *s2) { - size_t ns1 = STRLEN (s1) + 1; - size_t ns2 = STRLEN (s2) + 1; + size_t ns1 = strlen (s1) + 1; + size_t ns2 = strlen (s2) + 1; size_t n = ns1 < ns2 ? ns1 : ns2; int ret = 0; while (n--) - if ((ret = *(UCHAR *) s1++ - *(UCHAR *) s2++) != 0) + if ((ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) != 0) break; return ret; } +#endif + +typedef int (*proto_t) (const CHAR *, const CHAR *); IMPL (STUPID_STRCMP, 1) IMPL (SIMPLE_STRCMP, 1) @@ -276,14 +320,31 @@ check (void) STRCPY(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs")); STRCPY(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV")); + /* Check correct working for negatives values */ + + s1[0] = 1; + s2[0] = 1; + s1[1] = 1; + s2[1] = 1; + s1[2] = -1; + s2[2] = 3; + s1[3] = 0; + s2[3] = -1; + + /* Check possible overflow bug, actual more for wcscmp */ + + s1[7] = CHAR__MIN; + s2[7] = CHAR__MAX; + size_t l1 = STRLEN (s1); size_t l2 = STRLEN (s2); + for (size_t i1 = 0; i1 < l1; i1++) for (size_t i2 = 0; i2 < l2; i2++) { - int exp_result = SIMPLE_STRCMP (s1 + i1, s2 + i2); - FOR_EACH_IMPL (impl, 0) - check_result (impl, s1 + i1, s2 + i2, exp_result); + int exp_result = SIMPLE_STRCMP (s1 + i1, s2 + i2); + FOR_EACH_IMPL (impl, 0) + check_result (impl, s1 + i1, s2 + i2, exp_result); } } diff --git a/libc/string/test-strlen.c b/libc/string/test-strlen.c index e01befbf4..f12d3ba9d 100644 --- a/libc/string/test-strlen.c +++ b/libc/string/test-strlen.c @@ -1,7 +1,8 @@ -/* Test and measure strlen functions. - Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc. +/* Test and measure STRLEN functions. + Copyright (C) 1999, 2002, 2003, 2005, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Jakub Jelinek <jakub@redhat.com>, 1999. + Added wcslen support by Liubov Dmitrieva <liubov.dmitrieva@gmail.com>, 2011 The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -21,31 +22,43 @@ #define TEST_MAIN #include "test-string.h" -typedef size_t (*proto_t) (const char *); -size_t simple_strlen (const char *); -size_t builtin_strlen (const char *); +#ifndef WIDE +# define STRLEN strlen +# define CHAR char +# define MAX_CHAR CHAR_MAX +#else +# include <wchar.h> +# define STRLEN wcslen +# define CHAR wchar_t +# define MAX_CHAR WCHAR_MAX +#endif -IMPL (simple_strlen, 0) -IMPL (builtin_strlen, 0) -IMPL (strlen, 1) +typedef size_t (*proto_t) (const CHAR *); size_t -simple_strlen (const char *s) +simple_STRLEN (const CHAR *s) { - const char *p; + const CHAR *p; for (p = s; *p; ++p); return p - s; } +#ifndef WIDE size_t -builtin_strlen (const char *p) +builtin_strlen (const CHAR *p) { return __builtin_strlen (p); } +IMPL (builtin_strlen, 0) +#endif + +IMPL (simple_STRLEN, 0) +IMPL (STRLEN, 1) + static void -do_one_test (impl_t *impl, const char *s, size_t exp_len) +do_one_test (impl_t *impl, const CHAR *s, size_t exp_len) { size_t len = CALL (impl, s); if (len != exp_len) @@ -76,23 +89,25 @@ do_one_test (impl_t *impl, const char *s, size_t exp_len) } static void -do_test (size_t align, size_t len, int max_char) +do_test (size_t align, size_t len) { size_t i; - align &= 7; - if (align + len >= page_size) + align &= 63; + if (align + sizeof(CHAR) * len >= page_size) return; + CHAR *buf = (CHAR *) (buf1); + for (i = 0; i < len; ++i) - buf1[align + i] = 1 + 7 * i % max_char; - buf1[align + len] = 0; + buf[align + i] = 1 + 11111 * i % MAX_CHAR; + buf[align + len] = 0; if (HP_TIMING_AVAIL) printf ("Length %4zd, alignment %2zd:", len, align); FOR_EACH_IMPL (impl, 0) - do_one_test (impl, (char *) (buf1 + align), len); + do_one_test (impl, (CHAR *) (buf + align), len); if (HP_TIMING_AVAIL) putchar ('\n'); @@ -102,7 +117,7 @@ static void do_random_tests (void) { size_t i, j, n, align, len; - unsigned char *p = buf1 + page_size - 512; + CHAR *p = (CHAR *) (buf1 + page_size - 512 * sizeof(CHAR)); for (n = 0; n < ITERATIONS; n++) { @@ -127,10 +142,10 @@ do_random_tests (void) } FOR_EACH_IMPL (impl, 1) - if (CALL (impl, (char *) (p + align)) != len) + if (CALL (impl, (CHAR *) (p + align)) != len) { error (0, 0, "Iteration %zd - wrong result in function %s (%zd) %zd != %zd, p %p", - n, impl->name, align, CALL (impl, (char *) (p + align)), + n, impl->name, align, CALL (impl, (CHAR *) (p + align)), len, p); ret = 1; } @@ -149,28 +164,20 @@ test_main (void) printf ("\t%s", impl->name); putchar ('\n'); - for (i = 1; i < 8; ++i) - do_test (0, i, 127); - - for (i = 1; i < 8; ++i) - do_test (i, i, 127); - - for (i = 2; i <= 10; ++i) - { - do_test (0, 1 << i, 127); - do_test (1, 1 << i, 127); - } - - for (i = 1; i < 8; ++i) - do_test (0, i, 255); + /* Checking with only 4 * N alignments for wcslen, other alignments are wrong for wchar_t type arrays*/ for (i = 1; i < 8; ++i) - do_test (i, i, 255); + { + do_test (sizeof(CHAR) * i, i); + do_test (0, i); + } - for (i = 2; i <= 10; ++i) + for (i = 2; i <= 12; ++i) { - do_test (0, 1 << i, 255); - do_test (1, 1 << i, 255); + do_test (0, 1 << i); + do_test (sizeof(CHAR) * 7, 1 << i); + do_test (sizeof(CHAR) * i, 1 << i); + do_test (sizeof(CHAR) * i, (size_t)((1 << i) / 1.5)); } do_random_tests (); diff --git a/libc/string/test-wcscmp.c b/libc/string/test-wcscmp.c deleted file mode 100644 index ac98e6d1d..000000000 --- a/libc/string/test-wcscmp.c +++ /dev/null @@ -1,2 +0,0 @@ -#define WIDE 1 -#include "test-strcmp.c" |