summaryrefslogtreecommitdiffstats
path: root/libc/string
diff options
context:
space:
mode:
Diffstat (limited to 'libc/string')
-rw-r--r--libc/string/generic/bp-checks.h129
-rw-r--r--libc/string/generic/memcmp.c17
-rw-r--r--libc/string/generic/strcpy.c28
-rw-r--r--libc/string/i386/memchr.c50
-rw-r--r--libc/string/i386/memcpy.c6
-rw-r--r--libc/string/i386/memmove.c52
-rw-r--r--libc/string/i386/memset.c1
-rw-r--r--libc/string/i386/strchr.c32
-rw-r--r--libc/string/i386/strcpy.c2
-rw-r--r--libc/string/i386/strlen.c20
-rw-r--r--libc/string/i386/strncat.c73
-rw-r--r--libc/string/i386/strncmp.c41
-rw-r--r--libc/string/i386/strncpy.c55
-rw-r--r--libc/string/i386/strnlen.c51
-rw-r--r--libc/string/i386/strrchr.c29
-rw-r--r--libc/string/ia64/memchr.S8
-rw-r--r--libc/string/memchr.c1
-rw-r--r--libc/string/memcpy.c1
-rw-r--r--libc/string/mempcpy.c1
-rw-r--r--libc/string/memset.c2
-rw-r--r--libc/string/sparc/sparc32/memchr.S2
21 files changed, 278 insertions, 323 deletions
diff --git a/libc/string/generic/bp-checks.h b/libc/string/generic/bp-checks.h
deleted file mode 100644
index 08c70aa5d..000000000
--- a/libc/string/generic/bp-checks.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Bounded-pointer checking macros for C.
- Copyright (C) 2000 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Greg McGary <greg@mcgary.org>
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _bp_checks_h_
-#define _bp_checks_h_ 1
-
-#if __BOUNDED_POINTERS__
-
-# define BOUNDS_VIOLATED (__builtin_trap (), 0)
-
-/* Verify that pointer's value >= low. Return pointer value. */
-# define CHECK_BOUNDS_LOW(ARG) \
- (((__ptrvalue (ARG) < __ptrlow (ARG)) && BOUNDS_VIOLATED), \
- __ptrvalue (ARG))
-
-/* Verify that pointer's value < high. Return pointer value. */
-# define CHECK_BOUNDS_HIGH(ARG) \
- (((__ptrvalue (ARG) > __ptrhigh (ARG)) && BOUNDS_VIOLATED), \
- __ptrvalue (ARG))
-
-# define _CHECK_N(ARG, N, COND) \
- (((COND) \
- && (__ptrvalue (ARG) < __ptrlow (ARG) \
- || __ptrvalue (ARG) + (N) > __ptrhigh (ARG)) \
- && BOUNDS_VIOLATED), \
- __ptrvalue (ARG))
-
-extern void *__unbounded __ubp_memchr (const void *__unbounded, int, unsigned);
-
-# define _CHECK_STRING(ARG, COND) \
- (((COND) \
- && (__ptrvalue (ARG) < __ptrlow (ARG) \
- || !__ubp_memchr (__ptrvalue (ARG), '\0', \
- (__ptrhigh (ARG) - __ptrvalue (ARG)))) \
- && BOUNDS_VIOLATED), \
- __ptrvalue (ARG))
-
-/* Check bounds of a pointer seated to an array of N objects. */
-# define CHECK_N(ARG, N) _CHECK_N ((ARG), (N), 1)
-/* Same as CHECK_N, but tolerate ARG == NULL. */
-# define CHECK_N_NULL_OK(ARG, N) _CHECK_N ((ARG), (N), __ptrvalue (ARG))
-
-/* Check bounds of a pointer seated to a single object. */
-# define CHECK_1(ARG) CHECK_N ((ARG), 1)
-/* Same as CHECK_1, but tolerate ARG == NULL. */
-# define CHECK_1_NULL_OK(ARG) CHECK_N_NULL_OK ((ARG), 1)
-
-/* Check for NUL-terminator within string's bounds. */
-# define CHECK_STRING(ARG) _CHECK_STRING ((ARG), 1)
-/* Same as CHECK_STRING, but tolerate ARG == NULL. */
-# define CHECK_STRING_NULL_OK(ARG) _CHECK_STRING ((ARG), __ptrvalue (ARG))
-
-/* Check bounds of signal syscall args with type sigset_t. */
-# define CHECK_SIGSET(SET) CHECK_N ((SET), _NSIG / (8 * sizeof *(SET)))
-/* Same as CHECK_SIGSET, but tolerate SET == NULL. */
-# define CHECK_SIGSET_NULL_OK(SET) CHECK_N_NULL_OK ((SET), _NSIG / (8 * sizeof *(SET)))
-
-# if defined (_IOC_SIZESHIFT) && defined (_IOC_SIZEBITS)
-/* Extract the size of the ioctl data and check its bounds. */
-# define CHECK_IOCTL(ARG, CMD) \
- CHECK_N ((const char *) (ARG), \
- (((CMD) >> _IOC_SIZESHIFT) & ((1 << _IOC_SIZEBITS) - 1)))
-# else
-/* We don't know the size of the ioctl data, so the best we can do
- is check that the first byte is within bounds. */
-# define CHECK_IOCTL(ARG, CMD) CHECK_1 ((const char *) ARG)
-# endif
-
-/* Check bounds of `struct flock *' for the locking fcntl commands. */
-# define CHECK_FCNTL(ARG, CMD) \
- (((CMD) == F_GETLK || (CMD) == F_SETLK || (CMD) == F_SETLKW) \
- ? CHECK_1 ((struct flock *) ARG) : (unsigned long) (ARG))
-
-/* Check bounds of an array of mincore residency-status flags that
- cover a region of NBYTES. Such a vector occupies one byte per page
- of memory. */
-# define CHECK_N_PAGES(ARG, NBYTES) \
- ({ int _page_size_ = __sysconf (_SC_PAGE_SIZE); \
- CHECK_N ((const char *) (ARG), \
- ((NBYTES) + _page_size_ - 1) / _page_size_); })
-
-/* Return a bounded pointer with value PTR that satisfies CHECK_N (PTR, N). */
-# define BOUNDED_N(PTR, N) \
- ({ __typeof (PTR) __bounded _p_; \
- __ptrvalue _p_ = __ptrlow _p_ = __ptrvalue (PTR); \
- __ptrhigh _p_ = __ptrvalue _p_ + (N); \
- _p_; })
-
-#else /* !__BOUNDED_POINTERS__ */
-
-/* Do nothing if not compiling with -fbounded-pointers. */
-
-# define BOUNDS_VIOLATED
-# define CHECK_BOUNDS_LOW(ARG) (ARG)
-# define CHECK_BOUNDS_HIGH(ARG) (ARG)
-# define CHECK_1(ARG) (ARG)
-# define CHECK_1_NULL_OK(ARG) (ARG)
-# define CHECK_N(ARG, N) (ARG)
-# define CHECK_N_NULL_OK(ARG, N) (ARG)
-# define CHECK_STRING(ARG) (ARG)
-# define CHECK_SIGSET(SET) (SET)
-# define CHECK_SIGSET_NULL_OK(SET) (SET)
-# define CHECK_IOCTL(ARG, CMD) (ARG)
-# define CHECK_FCNTL(ARG, CMD) (ARG)
-# define CHECK_N_PAGES(ARG, NBYTES) (ARG)
-# define BOUNDED_N(PTR, N) (PTR)
-
-#endif /* !__BOUNDED_POINTERS__ */
-
-#define BOUNDED_1(PTR) BOUNDED_N (PTR, 1)
-
-#endif /* _bp_checks_h_ */
diff --git a/libc/string/generic/memcmp.c b/libc/string/generic/memcmp.c
index fc63a2eae..27db6b3d3 100644
--- a/libc/string/generic/memcmp.c
+++ b/libc/string/generic/memcmp.c
@@ -26,10 +26,6 @@
#include <endian.h>
#if __BYTE_ORDER == __BIG_ENDIAN
-# define WORDS_BIGENDIAN
-#endif
-
-#ifdef WORDS_BIGENDIAN
# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
#else
# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
@@ -48,17 +44,12 @@
3. Compare the few remaining bytes. */
-#ifndef WORDS_BIGENDIAN
+#if __BYTE_ORDER != __BIG_ENDIAN
/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine.
A and B are known to be different.
This is needed only on little-endian machines. */
-static int memcmp_bytes __P((op_t, op_t));
-
-# ifdef __GNUC__
-__inline
-# endif
-static int
+static __inline__ int
memcmp_bytes (op_t a, op_t b)
{
long int srcp1 = (long int) &a;
@@ -77,8 +68,6 @@ memcmp_bytes (op_t a, op_t b)
}
#endif
-static int memcmp_common_alignment __P((long, long, size_t));
-
/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for
memory operations on `op_t's. */
@@ -161,8 +150,6 @@ memcmp_common_alignment (long int srcp1, long int srcp2, size_t len)
return 0;
}
-static int memcmp_not_common_alignment __P((long, long, size_t));
-
/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
`op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory
operations on `op_t', but SRCP1 *should be unaligned*. */
diff --git a/libc/string/generic/strcpy.c b/libc/string/generic/strcpy.c
index 99e077139..b9a0a286a 100644
--- a/libc/string/generic/strcpy.c
+++ b/libc/string/generic/strcpy.c
@@ -20,28 +20,18 @@
#include <stddef.h>
#include "memcopy.h"
-#include "bp-checks.h"
/* Experimentally off - libc_hidden_proto(strcpy) */
/* Copy SRC to DEST. */
-char *strcpy (char *dest, const char *src)
+char *strcpy(char *dest, const char *src)
{
- reg_char c;
- char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
- const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
- size_t n;
-
- do
- {
- c = *s++;
- s[off] = c;
- }
- while (c != '\0');
-
- n = s - src;
- (void) CHECK_BOUNDS_HIGH (src + n);
- (void) CHECK_BOUNDS_HIGH (dest + n);
-
- return dest;
+ char *dst = dest;
+
+ while ((*dst = *src) != '\0') {
+ src++;
+ dst++;
+ }
+
+ return dest;
}
libc_hidden_def(strcpy)
diff --git a/libc/string/i386/memchr.c b/libc/string/i386/memchr.c
index 5c64445e0..c2fc44b4a 100644
--- a/libc/string/i386/memchr.c
+++ b/libc/string/i386/memchr.c
@@ -33,19 +33,43 @@
#include <string.h>
#undef memchr
-void *memchr(const void *cs, int c, size_t count)
+//#define memchr TESTING
+void *memchr(const void *s, int c, size_t count)
{
- int d0;
- register void * __res;
- if (!count)
- return NULL;
- __asm__ __volatile__(
- "repne\n\t"
- "scasb\n\t"
- "je 1f\n\t"
- "movl $1,%0\n"
- "1:\tdecl %0"
- :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
- return __res;
+ void *edi;
+ int ecx;
+ __asm__ __volatile__(
+ " jecxz 1f\n"
+ " repne; scasb\n"
+ " leal -1(%%edi), %%edi\n"
+ " je 2f\n"
+ "1:\n"
+ " xorl %%edi, %%edi\n" /* NULL */
+ "2:\n"
+ : "=&D" (edi), "=&c" (ecx)
+ : "a" (c), "0" (s), "1" (count)
+ /* : no clobbers */
+ );
+ return edi;
}
+#ifndef memchr
libc_hidden_def(memchr)
+#else
+/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memchr.c -o memchr
+ * and run ./memchr
+ */
+int main()
+{
+ static const char str[] = "abc.def";
+ printf((char*)memchr(str, '.',-2) - str == 3 ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.',-1) - str == 3 ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 0) == NULL ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 1) == NULL ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 2) == NULL ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 3) == NULL ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 4) - str == 3 ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str, '.', 5) - str == 3 ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str+3, '.', 0) == NULL ? "ok\n" : "BAD!\n");
+ printf((char*)memchr(str+3, '.', 5) - str == 3 ? "ok\n" : "BAD!\n");
+}
+#endif
diff --git a/libc/string/i386/memcpy.c b/libc/string/i386/memcpy.c
index af86cf255..697d0bdc2 100644
--- a/libc/string/i386/memcpy.c
+++ b/libc/string/i386/memcpy.c
@@ -38,11 +38,11 @@ void *memcpy(void * to, const void * from, size_t n)
int d0, d1, d2;
__asm__ __volatile__(
" rep; movsl\n"
- " movl %4,%%ecx\n"
- " andl $3,%%ecx\n"
+ " movl %4, %%ecx\n"
+ " andl $3, %%ecx\n"
/* jz is optional. avoids "rep; movsb" with ecx == 0,
* but adds a branch, which is currently (2008) faster */
- " jz 1f\n"
+ " jz 1f\n"
" rep; movsb\n"
"1:\n"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
diff --git a/libc/string/i386/memmove.c b/libc/string/i386/memmove.c
index a924efcbc..72d8002a5 100644
--- a/libc/string/i386/memmove.c
+++ b/libc/string/i386/memmove.c
@@ -32,28 +32,40 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(memmove) */
+#undef memmove
+//#define memmove TESTING
void *memmove(void *dest, const void *src, size_t n)
{
- int d0, d1, d2;
- if (dest<src)
+ int eax, ecx, esi, edi;
__asm__ __volatile__(
- "rep\n\t"
- "movsb"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- :"0" (n),"1" (src),"2" (dest)
- : "memory");
- else
- __asm__ __volatile__(
- "std\n\t"
- "rep\n\t"
- "movsb\n\t"
- "cld"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- :"0" (n),
- "1" (n-1+(const char *)src),
- "2" (n-1+(char *)dest)
- :"memory");
- return dest;
+ " movl %%eax, %%edi\n"
+ " cmpl %%esi, %%eax\n"
+ " je 2f\n" /* (optional) src == dest -> NOP */
+ " jb 1f\n" /* src > dest -> simple copy */
+ " leal -1(%%esi,%%ecx), %%esi\n"
+ " leal -1(%%eax,%%ecx), %%edi\n"
+ " std\n"
+ "1: rep; movsb\n"
+ " cld\n"
+ "2:\n"
+ : "=&c" (ecx), "=&S" (esi), "=&a" (eax), "=&D" (edi)
+ : "0" (n), "1" (src), "2" (dest)
+ : "memory"
+ );
+ return (void*)eax;
}
+#ifndef memmove
libc_hidden_def(memmove)
+#else
+/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memmove.c -o memmove
+ * and run ./memmove
+ */
+int main()
+{
+ static char str[] = "abcdef.123";
+ memmove(str + 1, str, 5);
+ printf(strcmp(str, "aabcde.123") == 0 ? "ok\n" : "BAD!\n");
+ memmove(str, str + 1, 5);
+ printf(strcmp(str, "abcdee.123") == 0 ? "ok\n" : "BAD!\n");
+}
+#endif
diff --git a/libc/string/i386/memset.c b/libc/string/i386/memset.c
index 779725f2f..cfc16983c 100644
--- a/libc/string/i386/memset.c
+++ b/libc/string/i386/memset.c
@@ -32,6 +32,7 @@
#include <string.h>
+/* Experimentally off - libc_hidden_proto(memset) */
#undef memset
void *memset(void *s, int c, size_t count)
{
diff --git a/libc/string/i386/strchr.c b/libc/string/i386/strchr.c
index 46b1dfb6e..93cc9583e 100644
--- a/libc/string/i386/strchr.c
+++ b/libc/string/i386/strchr.c
@@ -32,23 +32,25 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strchr) */
+#undef strchr
char *strchr(const char *s, int c)
{
- int d0;
- register char * __res;
- __asm__ __volatile__(
- "movb %%al,%%ah\n"
- "1:\tlodsb\n\t"
- "cmpb %%ah,%%al\n\t"
- "je 2f\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n\t"
- "movl $1,%1\n"
- "2:\tmovl %1,%0\n\t"
- "decl %0"
- :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
- return __res;
+ int esi;
+ register char * eax;
+ __asm__ __volatile__(
+ " movb %%al, %%ah\n"
+ "1: lodsb\n"
+ " cmpb %%ah, %%al\n"
+ " je 2f\n"
+ " testb %%al, %%al\n"
+ " jnz 1b\n"
+ " movl $1, %%esi\n" /* can use shorter xor + inc */
+ "2: leal -1(%%esi), %%eax\n"
+ : "=a" (eax), "=&S" (esi)
+ : "0" (c), "1" (s)
+ /* no clobbers */
+ );
+ return eax;
}
libc_hidden_def(strchr)
#ifdef __UCLIBC_SUSV3_LEGACY__
diff --git a/libc/string/i386/strcpy.c b/libc/string/i386/strcpy.c
index 09065a9b7..fff1bd006 100644
--- a/libc/string/i386/strcpy.c
+++ b/libc/string/i386/strcpy.c
@@ -32,7 +32,7 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strcpy) */
+#undef strcpy
char *strcpy(char * dest, const char * src)
{
int d0, d1, d2;
diff --git a/libc/string/i386/strlen.c b/libc/string/i386/strlen.c
index 61a178393..ff2baeb38 100644
--- a/libc/string/i386/strlen.c
+++ b/libc/string/i386/strlen.c
@@ -32,17 +32,17 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strlen) */
+#undef strlen
size_t strlen(const char *s)
{
- int d0;
- register int __res;
- __asm__ __volatile__(
- "repne\n\t"
- "scasb\n\t"
- "notl %0\n\t"
- "decl %0"
- :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
- return __res;
+ int eax, ecx, edi;
+ __asm__ __volatile__(
+ " repne; scasb\n"
+ " notl %%ecx\n"
+ " leal -1(%%ecx), %%eax\n"
+ : "=&c" (ecx), "=&D" (edi), "=&a" (eax)
+ : "0" (0xffffffff), "1" (s), "2" (0)
+ );
+ return eax;
}
libc_hidden_def(strlen)
diff --git a/libc/string/i386/strncat.c b/libc/string/i386/strncat.c
index 3872679d5..640b0d213 100644
--- a/libc/string/i386/strncat.c
+++ b/libc/string/i386/strncat.c
@@ -32,30 +32,55 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strncat) */
-char *strncat(char * dest,
- const char * src, size_t count)
+#undef strncat
+//#define strncat TESTING
+char *strncat(char * dest, const char * src, size_t count)
{
- int d0, d1, d2, d3;
- __asm__ __volatile__(
- "repne\n\t"
- "scasb\n\t"
- "decl %1\n\t"
- "movl %8,%3\n"
- "incl %3\n"
- "1:\tdecl %3\n\t"
- "jz 2f\n"
- "lodsb\n\t"
- "stosb\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n"
- "jmp 3f\n"
- "2:\txorl %2,%2\n\t"
- "stosb\n"
- "3:"
- : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
- : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
- : "memory");
- return dest;
+ int esi, edi, eax, ecx, edx;
+ __asm__ __volatile__(
+ " xorl %%eax, %%eax\n"
+ " incl %%edx\n"
+ " pushl %%edi\n" /* save dest */
+ " repne; scasb\n"
+ " decl %%edi\n" /* edi => NUL in dest */
+ /* count-- */
+ "1: decl %%edx\n"
+ /* if count reached 0, store NUL and bail out */
+ " movl %%edx, %%eax\n"
+ " jz 2f\n"
+ /* else copy a char */
+ " lodsb\n"
+ "2: stosb\n"
+ " testb %%al, %%al\n"
+ " jnz 1b\n"
+ /* end of loop */
+ " popl %%eax\n" /* restore dest into eax */
+ : "=&S" (esi), "=&D" (edi), "=&a" (eax), "=&c" (ecx), "=&d" (edx)
+ : "0" (src), "1" (dest), "3" (0xffffffff), "4" (count)
+ : "memory"
+ );
+ return (char *)eax;
}
+#ifndef strncat
libc_hidden_def(strncat)
+#else
+/* Uncomment TESTING, gcc -m32 -Os strncat.c -o strncat
+ * and run ./strncat
+ */
+int main()
+{
+ char buf[99];
+
+ strcpy(buf, "abc"); buf[4] = '*'; strncat(buf, "def", 0);
+ printf(strcmp(buf, "abc") == 0 && buf[4] == '*' ? "ok\n" : "BAD!\n");
+
+ strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", 50);
+ printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n");
+
+ strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", -1);
+ printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n");
+
+ strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def123", 3);
+ printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n");
+}
+#endif
diff --git a/libc/string/i386/strncmp.c b/libc/string/i386/strncmp.c
index a14bb503b..bfb20c307 100644
--- a/libc/string/i386/strncmp.c
+++ b/libc/string/i386/strncmp.c
@@ -32,27 +32,28 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strncmp) */
+#undef strncmp
int strncmp(const char *cs, const char *ct, size_t count)
{
- register int __res;
- int d0, d1, d2;
- __asm__ __volatile__(
- "incl %3\n"
- "1:\tdecl %3\n\t"
- "jz 2f\n"
- "lodsb\n\t"
- "scasb\n\t"
- "jne 3f\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n"
- "2:\txorl %%eax,%%eax\n\t"
- "jmp 4f\n"
- "3:\tsbbl %%eax,%%eax\n\t"
- "orb $1,%%al\n"
- "4:"
- :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
- :"1" (cs),"2" (ct),"3" (count));
- return __res;
+ int eax;
+ int esi, edi, ecx;
+ __asm__ __volatile__(
+ " incl %%ecx\n"
+ "1: decl %%ecx\n"
+ " jz 2f\n"
+ " lodsb\n"
+ " scasb\n"
+ " jne 3f\n"
+ " testb %%al, %%al\n"
+ " jnz 1b\n"
+ "2: xorl %%eax, %%eax\n"
+ " jmp 4f\n"
+ "3: sbbl %%eax, %%eax\n"
+ " orb $1, %%al\n"
+ "4:\n"
+ : "=a" (eax), "=&S" (esi), "=&D" (edi), "=&c" (ecx)
+ : "1" (cs), "2" (ct), "3" (count)
+ );
+ return eax;
}
libc_hidden_weak(strncmp)
diff --git a/libc/string/i386/strncpy.c b/libc/string/i386/strncpy.c
index 76aa6ae1b..e1c7f1dcf 100644
--- a/libc/string/i386/strncpy.c
+++ b/libc/string/i386/strncpy.c
@@ -32,25 +32,44 @@
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strncpy) */
+#undef strncpy
+//#define strncpy TESTING
char *strncpy(char * dest, const char * src, size_t count)
{
- int d0, d1, d2, d3;
- __asm__ __volatile__(
- "incl %2\n"
- "1:\n"
- "decl %2\n"
- "jz 2f\n"
- "lodsb\n\t"
- "stosb\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n\t"
- "decl %2\n"
- "rep\n\t"
- "stosb\n"
- "2:"
- : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
- :"0" (src),"1" (dest),"2" (count) : "memory");
- return dest;
+ int esi, edi, ecx, eax;
+ __asm__ __volatile__(
+ "1: subl $1, %%ecx\n" /* not dec! it doesnt set CF */
+ " jc 2f\n"
+ " lodsb\n"
+ " stosb\n"
+ " testb %%al, %%al\n"
+ " jnz 1b\n"
+ " rep; stosb\n"
+ "2:\n"
+ : "=&S" (esi), "=&D" (edi), "=&c" (ecx), "=&a" (eax)
+ : "0" (src), "1" (dest), "2" (count)
+ : "memory"
+ );
+ return dest;
}
+#ifndef strncpy
libc_hidden_def(strncpy)
+#else
+/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strncpy.c -o strncpy
+ * and run ./strncpy
+ */
+int main()
+{
+ static char str[99];
+
+ str[3] = '*'; str[4] = 0; strncpy(str, "abc", 3);
+ printf(strcmp(str, "abc*") == 0 ? "ok\n" : "BAD!\n");
+
+ str[4] = '*'; str[5] = '+'; strncpy(str, "abc", 5);
+ printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ?
+ "ok\n" : "BAD!\n");
+ strncpy(str, "def", 0); /* should do nothing */
+ printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ?
+ "ok\n" : "BAD!\n");
+}
+#endif
diff --git a/libc/string/i386/strnlen.c b/libc/string/i386/strnlen.c
index 02c72f530..3abde48e2 100644
--- a/libc/string/i386/strnlen.c
+++ b/libc/string/i386/strnlen.c
@@ -33,24 +33,43 @@
#include <string.h>
#ifdef __USE_GNU
-/* Experimentally off - libc_hidden_proto(strnlen) */
+
+#undef strnlen
+//#define strnlen TESTING
size_t strnlen(const char *s, size_t count)
{
- int d0;
- register int __res;
- __asm__ __volatile__(
- "movl %2,%0\n\t"
- "incl %1\n"
- "jmp 2f\n"
- "1:\tcmpb $0,(%0)\n\t"
- "je 3f\n\t"
- "incl %0\n"
- "2:\tdecl %1\n\t"
- "jne 1b\n"
- "3:\tsubl %2,%0"
- :"=a" (__res), "=&d" (d0)
- :"c" (s),"1" (count));
- return __res;
+ int edx;
+ int eax;
+ __asm__ __volatile__(
+ " leal -1(%%ecx), %%eax\n"
+ "1: incl %%eax\n"
+ " decl %%edx\n"
+ " jz 3f\n"
+ " cmpb $0, (%%eax)\n"
+ " jnz 1b\n"
+ "3: subl %%ecx, %%eax"
+ : "=a" (eax), "=&d" (edx)
+ : "c" (s), "1" (count + 1)
+ );
+ return eax;
}
+#ifndef strnlen
libc_hidden_def(strnlen)
+#else
+/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strnlen.c -o strnlen
+ * and run ./strnlen
+ */
+int main()
+{
+ printf(strnlen("abc\0def", -2) == 3 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", -1) == 3 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 0) == 0 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 1) == 1 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 2) == 2 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 3) == 3 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 4) == 3 ? "ok\n" : "BAD!\n");
+ printf(strnlen("abc\0def", 5) == 3 ? "ok\n" : "BAD!\n");
+}
+#endif
+
#endif
diff --git a/libc/string/i386/strrchr.c b/libc/string/i386/strrchr.c
index ef378685b..9f2c74923 100644
--- a/libc/string/i386/strrchr.c
+++ b/libc/string/i386/strrchr.c
@@ -35,18 +35,23 @@
/* Experimentally off - libc_hidden_proto(strrchr) */
char *strrchr(const char *s, int c)
{
- int d0, d1;
- register char * __res;
- __asm__ __volatile__(
- "movb %%al,%%ah\n"
- "1:\tlodsb\n\t"
- "cmpb %%ah,%%al\n\t"
- "jne 2f\n\t"
- "leal -1(%%esi),%0\n"
- "2:\ttestb %%al,%%al\n\t"
- "jne 1b"
- :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
- return __res;
+ char *eax;
+
+ __asm__ __volatile__(
+ " movb %%cl, %%ch\n"
+ "1: movb (%1), %%cl\n" /* load char */
+ " cmpb %%cl, %%ch\n" /* char == c? */
+ " jne 2f\n"
+ " movl %1, %%eax\n"
+ "2: incl %1\n"
+ " testb %%cl, %%cl\n" /* char == NUL? */
+ " jnz 1b\n"
+ /* "=c": use ecx, not ebx (-fpic uses it). */
+ : "=a" (eax), "=r" (s), "=c" (c)
+ : "0" (0), "1" (s), "2" (c)
+ /* : no clobbers */
+ );
+ return eax;
}
libc_hidden_def(strrchr)
#ifdef __UCLIBC_SUSV3_LEGACY__
diff --git a/libc/string/ia64/memchr.S b/libc/string/ia64/memchr.S
index 0246b5997..f25e80302 100644
--- a/libc/string/ia64/memchr.S
+++ b/libc/string/ia64/memchr.S
@@ -126,8 +126,6 @@ ENTRY(__memchr)
END(__memchr)
-weak_alias (__memchr, memchr)
-#if !__BOUNDED_POINTERS__
-weak_alias (__memchr, __ubp_memchr)
-#endif
-libc_hidden_def (memchr)
+weak_alias(__memchr, memchr)
+weak_alias(__memchr, __ubp_memchr)
+libc_hidden_def(memchr)
diff --git a/libc/string/memchr.c b/libc/string/memchr.c
index 5e60f6554..438f4fa4a 100644
--- a/libc/string/memchr.c
+++ b/libc/string/memchr.c
@@ -10,6 +10,7 @@
#ifdef WANT_WIDE
# define Wmemchr wmemchr
#else
+# undef memchr
# define Wmemchr memchr
#endif
diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c
index aa8d4ee38..cbb6e633a 100644
--- a/libc/string/memcpy.c
+++ b/libc/string/memcpy.c
@@ -10,6 +10,7 @@
#ifdef WANT_WIDE
# define Wmemcpy wmemcpy
#else
+# undef memcpy
# define Wmemcpy memcpy
#endif
diff --git a/libc/string/mempcpy.c b/libc/string/mempcpy.c
index e7605146a..d79bd1937 100644
--- a/libc/string/mempcpy.c
+++ b/libc/string/mempcpy.c
@@ -12,6 +12,7 @@
#ifdef WANT_WIDE
# define Wmempcpy wmempcpy
#else
+# undef mempcpy
# define Wmempcpy mempcpy
#endif
diff --git a/libc/string/memset.c b/libc/string/memset.c
index 6dd20d668..9daf59f69 100644
--- a/libc/string/memset.c
+++ b/libc/string/memset.c
@@ -10,7 +10,7 @@
#ifdef WANT_WIDE
# define Wmemset wmemset
#else
-/* Experimentally off - libc_hidden_proto(memset) */
+# undef memset
# define Wmemset memset
#endif
diff --git a/libc/string/sparc/sparc32/memchr.S b/libc/string/sparc/sparc32/memchr.S
index 4d57a553b..d926e9787 100644
--- a/libc/string/sparc/sparc32/memchr.S
+++ b/libc/string/sparc/sparc32/memchr.S
@@ -139,6 +139,4 @@ ENTRY(memchr)
END(memchr)
libc_hidden_def(memchr)
-#if !__BOUNDED_POINTERS__
weak_alias(memchr,__ubp_memchr)
-#endif