summaryrefslogtreecommitdiff
path: root/libc/string
diff options
context:
space:
mode:
Diffstat (limited to 'libc/string')
-rw-r--r--libc/string/Makefile6
-rw-r--r--libc/string/memrchr.c11
-rw-r--r--libc/string/stratcliff.c35
-rw-r--r--libc/string/strncat.c1
-rw-r--r--libc/string/strnlen.c13
-rw-r--r--libc/string/test-memcmp.c125
-rw-r--r--libc/string/test-rawmemchr.c189
-rw-r--r--libc/string/test-strchr.c137
-rw-r--r--libc/string/test-strcmp.c89
-rw-r--r--libc/string/test-strlen.c85
-rw-r--r--libc/string/test-wcscmp.c2
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"