Compare commits

...

2 Commits

Author SHA1 Message Date
Colin Leroy-Mira 793aa48a49 Add doc 2024-04-19 08:13:41 +02:00
Colin Leroy-Mira a823d90082 Separated versions 2024-04-19 07:57:47 +02:00
3 changed files with 135 additions and 31 deletions

View File

@ -780,6 +780,7 @@ communication, see also <tt>testcode/lib/ser-test.c</tt>.
<item><ref id="strqtok" name="strqtok"> <item><ref id="strqtok" name="strqtok">
<item><ref id="strrchr" name="strrchr"> <item><ref id="strrchr" name="strrchr">
<item><ref id="strspn" name="strspn"> <item><ref id="strspn" name="strspn">
<item><ref id="strcasestr" name="strcasestr">
<item><ref id="strstr" name="strstr"> <item><ref id="strstr" name="strstr">
<item><ref id="strtok" name="strtok"> <item><ref id="strtok" name="strtok">
<item><ref id="strxfrm" name="strxfrm"> <item><ref id="strxfrm" name="strxfrm">
@ -7899,22 +7900,47 @@ be used in presence of a prototype.
</quote> </quote>
<sect1>strstr<label id="strstr"><p> <sect1>strcasestr<label id="strcasestr"><p>
<quote> <quote>
<descrip> <descrip>
<tag/Function/Find a substring. <tag/Function/Find a substring, case-insensitive.
<tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Header/<tt/<ref id="string.h" name="string.h">/
<tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/ <tag/Declaration/<tt/char* __fastcall__ strcasestr (const char* str, const char* substr);/
<tag/Description/<tt/strstr/ searches for the first occurrence of the string <tag/Description/<tt/strcasestr/ searches for the first occurrence of the string
<tt/substr/ within <tt/str/. If found, it returns a pointer to the copy, <tt/substr/ within <tt/str/. If found, it returns a pointer to the start of the
otherwise it returns <tt/NULL/. match in <tt/str/, otherwise it returns <tt/NULL/.
<tag/Notes/<itemize> <tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only <item>The function is only available as fastcall function, so it may only
be used in presence of a prototype. be used in presence of a prototype.
</itemize> </itemize>
<tag/Availability/ISO 9899 <tag/Availability/ISO 9899
<tag/See also/ <tag/See also/
<ref id="strstr" name="strstr">,
<ref id="strcspn" name="strcspn">,
<ref id="strspn" name="strspn">
<tag/Example/None.
</descrip>
</quote>
<sect1>strstr<label id="strstr"><p>
<quote>
<descrip>
<tag/Function/Find a substring, case-sensitive.
<tag/Header/<tt/<ref id="string.h" name="string.h">/
<tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/
<tag/Description/<tt/strstr/ searches for the first occurrence of the string
<tt/substr/ within <tt/str/. If found, it returns a pointer to the start of the
match in <tt/str/, otherwise it returns <tt/NULL/.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
</itemize>
<tag/Availability/ISO 9899
<tag/See also/
<ref id="strcasestr" name="strcasestr">,
<ref id="strcspn" name="strcspn">, <ref id="strcspn" name="strcspn">,
<ref id="strspn" name="strspn"> <ref id="strspn" name="strspn">
<tag/Example/None. <tag/Example/None.

View File

@ -0,0 +1,95 @@
;
; Ullrich von Bassewitz, 11.12.1998
;
; char* strcasestr (const char* haystack, const char* needle);
;
.export _strcasestr
.import popptr1, return0, tolowerdirect
.importzp ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4
.include "ctype.inc"
.segment "LOWCODE"
_strcasestr:
sta ptr2 ; Save needle
stx ptr2+1
sta ptr4 ; Setup temp copy for later
jsr popptr1 ; Get haystack to ptr1
; If needle is empty, return haystack
; ldy #$00 Y=0 guaranteed by popptr1
lda (ptr2),y ; Get first byte of needle
beq @Found ; Needle is empty --> 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

View File

@ -4,20 +4,11 @@
; char* strstr (const char* haystack, const char* needle); ; char* strstr (const char* haystack, const char* needle);
; ;
.export _strstr, _strcasestr .export _strstr
.import popptr1, return0, tolowerdirect .import popptr1
.importzp ptr1, ptr2, ptr3, ptr4, tmp1, tmp2 .importzp ptr1, ptr2, ptr3, ptr4, tmp1
maybe_lower: ; Lowercase char in A if needed
jmp tolowerdirect ; patched on entry with either JMP or RTS
_strstr: _strstr:
ldy #$60 ; RTS
bne :+
_strcasestr:
ldy #$4C ; JMP absolute
: sty maybe_lower
sta ptr2 ; Save needle sta ptr2 ; Save needle
stx ptr2+1 stx ptr2+1
sta ptr4 ; Setup temp copy for later sta ptr4 ; Setup temp copy for later
@ -33,12 +24,9 @@ _strcasestr:
; Search for the beginning of the string (this is not an optimal search ; 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). ; strategy [in fact, it's pretty dumb], but it's simple to implement).
jsr maybe_lower ; Lowercase if needed
sta tmp1 ; Save start of needle sta tmp1 ; Save start of needle
@L1: lda (ptr1),y ; Get next char from haystack @L1: lda (ptr1),y ; Get next char from haystack
beq @NotFound ; Jump if end beq @NotFound ; Jump if end
jsr maybe_lower ; Lowercase if needed
cmp tmp1 ; Start of needle found? cmp tmp1 ; Start of needle found?
beq @L2 ; Jump if so beq @L2 ; Jump if so
iny ; Next char iny ; Next char
@ -55,7 +43,7 @@ _strcasestr:
bcc @L3 bcc @L3
inc ptr1+1 inc ptr1+1
; ptr1 points to the start of needle in haystack now. Setup temporary pointers for the ; ptr1 points to the start of needle now. Setup temporary pointers for the
; search. The low byte of ptr4 is already set. ; search. The low byte of ptr4 is already set.
@L3: sta ptr3 @L3: sta ptr3
@ -69,14 +57,7 @@ _strcasestr:
@L4: lda (ptr4),y ; Get char from needle @L4: lda (ptr4),y ; Get char from needle
beq @Found ; Jump if end of needle (-> found) beq @Found ; Jump if end of needle (-> found)
cmp (ptr3),y ; Compare with haystack
jsr maybe_lower ; Lowercase if needed
sta tmp2
lda (ptr3),y ; Compare with haystack
jsr maybe_lower ; Lowercase if needed
cmp tmp2
bne @L5 ; Jump if not equal bne @L5 ; Jump if not equal
iny ; Next char iny ; Next char
bne @L4 bne @L4
@ -98,4 +79,6 @@ _strcasestr:
; We reached end of haystack without finding needle ; We reached end of haystack without finding needle
@NotFound: @NotFound:
jmp return0 ; return NULL lda #$00 ; return NULL
tax
rts