+strcasestr
-/
-
- The function is only available as fastcall function, so it may only
be used in presence of a prototype.
,
+[,
+][
+]
+
+
+
+strstr
+
+
+
+/
+
+- The function is only available as fastcall function, so it may only
+be used in presence of a prototype.
+
+
,
[,
][
] we're done
+
+; Search for the beginning of the string (this is not an optimal search
+; strategy [in fact, it's pretty dumb], but it's simple to implement).
+
+ jsr tolowerdirect ; Lowercase
+ sta tmp1 ; Save start of needle
+@L1: lda (ptr1),y ; Get next char from haystack
+ beq @NotFound ; Jump if end
+
+ jsr tolowerdirect ; Lowercase
+ cmp tmp1 ; Start of needle found?
+ beq @L2 ; Jump if so
+ iny ; Next char
+ bne @L1
+ inc ptr1+1 ; Bump high byte
+ bne @L1 ; Branch always
+
+; We found the start of needle in haystack
+
+@L2: tya ; Get offset
+ clc
+ adc ptr1
+ sta ptr1 ; Make ptr1 point to start
+ bcc @L3
+ inc ptr1+1
+
+; ptr1 points to the start of needle in haystack now. Setup temporary pointers for the
+; search. The low byte of ptr4 is already set.
+
+@L3: sta ptr3
+ lda ptr1+1
+ sta ptr3+1
+ lda ptr2+1
+ sta ptr4+1
+ ldy #1 ; First char is identical, so start on second
+
+; Do the compare
+
+@L4: lda (ptr4),y ; Get char from needle
+ beq @Found ; Jump if end of needle (-> found)
+
+ jsr tolowerdirect ; Lowercase
+ sta tmp2
+
+ lda (ptr3),y ; Compare with haystack
+
+ jsr tolowerdirect ; Lowercase
+ cmp tmp2
+ bne @L5 ; Jump if not equal
+ iny ; Next char
+ bne @L4
+ inc ptr3+1
+ inc ptr4+1 ; Bump hi byte of pointers
+ bne @L4 ; Next char (branch always)
+
+; The strings did not compare equal, search next start of needle
+
+@L5: ldy #1 ; Start after this char
+ bne @L1 ; Branch always
+
+; We found the start of needle
+
+@Found: lda ptr1
+ ldx ptr1+1
+ rts
+
+; We reached end of haystack without finding needle
+
+@NotFound:
+ jmp return0 ; return NULL
diff --git a/libsrc/common/strstr.s b/libsrc/common/strstr.s
index 84f633245..691e5ba5c 100644
--- a/libsrc/common/strstr.s
+++ b/libsrc/common/strstr.s
@@ -82,14 +82,3 @@ _strstr:
lda #$00 ; return NULL
tax
rts
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libsrc/common/tolower.s b/libsrc/common/tolower.s
index 828be1cb1..9c143f1ce 100644
--- a/libsrc/common/tolower.s
+++ b/libsrc/common/tolower.s
@@ -10,19 +10,20 @@
; int tolower (int c);
;
- .export _tolower
+ .export _tolower, tolowerdirect
.include "ctype.inc"
.import ctypemaskdirect
_tolower:
cpx #$00 ; out of range?
- bne @L2 ; if so, return the argument unchanged
- tay ; save char
+ bne out ; if so, return the argument unchanged
+tolowerdirect:
+ pha ; save char
jsr ctypemaskdirect ; get character classification
and #CT_UPPER ; upper case char?
beq @L1 ; jump if no
- tya ; restore char
+ pla ; restore char
adc #<('a'-'A') ; make lower case char (ctypemaskdirect ensures carry clear)
rts
-@L1: tya ; restore char
-@L2: rts
+@L1: pla ; restore char
+out: rts
diff --git a/test/val/strstr-test.c b/test/val/strstr-test.c
new file mode 100644
index 000000000..5c8a147b0
--- /dev/null
+++ b/test/val/strstr-test.c
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+
+int fails = 0;
+
+#define STRSTR_TEST(needle,expected) \
+ if (strstr(haystack, (needle)) != (expected)) { \
+ printf("strstr failure: expected %p for \"%s\", " \
+ "got %p\n", \
+ expected, needle, strstr(haystack, (needle)));\
+ fails++; \
+ }
+
+#define STRCASESTR_TEST(needle,expected) \
+ if (strcasestr(haystack, (needle)) != (expected)) { \
+ printf("strcasestr failure: expected %p for \"%s\", " \
+ "got %p\n", \
+ expected, needle, strcasestr(haystack, (needle)));\
+ fails++; \
+ }
+
+int main (void)
+{
+ const char *haystack = "This is a string to search in";
+
+ STRSTR_TEST("This is", haystack + 0);
+ STRSTR_TEST("a string", haystack + 8);
+ STRSTR_TEST("This is a string to search in", haystack);
+ STRSTR_TEST("search in", haystack + 20);
+ STRSTR_TEST("This is a string to search in with extra chars", NULL);
+ STRSTR_TEST("nowhere", NULL);
+
+ STRCASESTR_TEST("this is", haystack + 0);
+ STRCASESTR_TEST("a STRING", haystack + 8);
+ STRCASESTR_TEST("this is a string TO search in", haystack);
+ STRCASESTR_TEST("This is a string to search in with extra chars", NULL);
+ STRCASESTR_TEST("search IN", haystack + 20);
+
+ return fails;
+}