summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/string/i386/strchrnul.c47
-rw-r--r--libc/string/i386/strncpy.c2
2 files changed, 48 insertions, 1 deletions
diff --git a/libc/string/i386/strchrnul.c b/libc/string/i386/strchrnul.c
new file mode 100644
index 000000000..c4da2b587
--- /dev/null
+++ b/libc/string/i386/strchrnul.c
@@ -0,0 +1,47 @@
+/*
+ * Adapted from strchr.c code
+ *
+ * Copyright (C) 2008 Denys Vlasenko <vda.linux@googlemail.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <string.h>
+
+#undef strchrnul
+//#define strchrnul TESTING
+char *strchrnul(const char *s, int c)
+{
+ int esi;
+ 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"
+ /* with this, we'd get strchr(): */
+ /* " movl $1, %%esi\n" */
+ "2: leal -1(%%esi), %%eax\n"
+ : "=a" (eax), "=&S" (esi)
+ : "0" (c), "1" (s)
+ /* no clobbers */
+ );
+ return eax;
+}
+#ifndef strchrnul
+libc_hidden_def(strchrnul)
+#else
+/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strchrnul.c -o strchrnul
+ * and run ./strchrnul
+ */
+int main()
+{
+ static const char str[] = "abc.def";
+ printf((char*)strchrnul(str, '.') - str == 3 ? "ok\n" : "BAD!\n");
+ printf((char*)strchrnul(str, '*') - str == 7 ? "ok\n" : "BAD!\n");
+ printf((char*)strchrnul(str, 0) - str == 7 ? "ok\n" : "BAD!\n");
+ printf((char*)strchrnul(str+3, '.') - str == 3 ? "ok\n" : "BAD!\n");
+}
+#endif
diff --git a/libc/string/i386/strncpy.c b/libc/string/i386/strncpy.c
index ba0c41063..e1c7f1dcf 100644
--- a/libc/string/i386/strncpy.c
+++ b/libc/string/i386/strncpy.c
@@ -68,7 +68,7 @@ int main()
str[4] = '*'; str[5] = '+'; strncpy(str, "abc", 5);
printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ?
"ok\n" : "BAD!\n");
- strncpy(str, "abc", 0); /* should do nothing */
+ strncpy(str, "def", 0); /* should do nothing */
printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ?
"ok\n" : "BAD!\n");
}