Skip to content

Commit 92638bf

Browse files
nitinseshadrimateoconlechuga
authored andcommitted
Implement strlcpy
1 parent 7d8a4d4 commit 92638bf

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

src/libc/strlcpy.src

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
assume adl=1
2+
3+
section .text
4+
public _strlcpy
5+
6+
; BSD variant of strncpy that ensures the destination is null-terminated.
7+
; OpenBSD reference: https://github.com/openbsd/src/blob/master/lib/libc/string/strlcpy.c
8+
; size_t strlcpy(char *dst, const char *src, size_t dsize)
9+
10+
_strlcpy:
11+
12+
ld iy, 0
13+
add iy, sp
14+
15+
; do min(strlen(src), dsize-1)
16+
17+
ld bc, (iy + 9) ; bc = dsize
18+
19+
; check if dsize is zero
20+
xor a,a ; clear carry and set a to 0
21+
ld hl, 0
22+
sbc hl, bc
23+
jr z, .strlcpy_done ; do nothing if dsize is zero
24+
25+
dec bc ; bc = dsize - 1
26+
27+
push bc ; cpir-based strlen touches bc, so put it on the stack
28+
29+
; strlen(src)
30+
ld hl, (iy + 6) ; hl = pointer to src
31+
xor a,a ; clear carry and set a to 0
32+
ld bc, 0
33+
cpir ; dec bc until byte at (hl) matches a (= NUL)
34+
; calculate HL=-BC-1
35+
sbc hl,hl
36+
scf
37+
sbc hl,bc
38+
; now hl = strlen(src)
39+
40+
pop bc ; get bc back from the stack
41+
42+
; dsize is not zero, compare them
43+
; hl = strlen(src)
44+
; bc = dsize - 1
45+
46+
; https://www.msx.org/forum/development/msx-development/how-compare-16bits-registers-z80
47+
or a ; clear carry flag
48+
sbc hl, bc
49+
add hl, bc
50+
51+
; if hl >= bc, c = 0; keep bc as is
52+
; if strlen(src) >= (dsize - 1), c = 0; keep bc as is
53+
jr nc, .ready_for_ldir
54+
55+
; hl < bc, so strlen(src) < (dsize - 1); set bc to the value in hl
56+
push hl
57+
pop bc
58+
59+
.ready_for_ldir:
60+
ld de, (iy + 3) ; put dst in de
61+
62+
; check if bc is zero
63+
xor a,a ; clear carry and set a to 0
64+
ld hl, 0
65+
sbc hl, bc
66+
jr z, .null_terminate ; null terminate if bc is zero
67+
68+
ld hl, (iy + 6) ; put src in hl
69+
; bc is filled already
70+
71+
; at this point we are set up for an ldir:
72+
; hl has the start address
73+
; de has the destination address
74+
; bc has the length
75+
76+
ldir
77+
78+
.null_terminate:
79+
; dsize is nonzero, null terminate dst
80+
xor a,a ; clear carry and set a to 0 (= NUL)
81+
ld (de), a ; store null terminator at the address pointed to by de
82+
83+
.strlcpy_done:
84+
; return strlen(src)
85+
86+
; strlen(src)
87+
ld hl, (iy + 6) ; hl = pointer to src
88+
xor a,a ; clear carry and set a to 0
89+
ld bc, 0
90+
cpir ; dec bc until byte at (hl) matches a (= NUL)
91+
; calculate HL=-BC-1
92+
sbc hl,hl
93+
scf
94+
sbc hl,bc
95+
; now hl = strlen(src)
96+
97+
ret

0 commit comments

Comments
 (0)