mirror of
https://github.com/cc65/cc65.git
synced 2024-09-27 19:55:09 +00:00
Compare commits
2 Commits
71d82ab5d9
...
793aa48a49
Author | SHA1 | Date | |
---|---|---|---|
|
793aa48a49 | ||
|
a823d90082 |
@ -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.
|
||||||
|
95
libsrc/common/strcasestr.s
Normal file
95
libsrc/common/strcasestr.s
Normal 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
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user