Skip to content

Commit 4e9055d

Browse files
committed
implemented strlcat
1 parent d9d0f24 commit 4e9055d

File tree

3 files changed

+148
-33
lines changed

3 files changed

+148
-33
lines changed

src/libc/strlcat.src

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _strlcat
6+
7+
_strlcat:
8+
push ix
9+
ld ix, 0
10+
lea bc, ix
11+
add ix, sp
12+
ld hl, (ix + 9) ; src
13+
xor a, a
14+
cpir
15+
sbc hl, hl
16+
scf
17+
sbc hl, bc
18+
push hl ; src_len
19+
20+
ld de, (ix + 12) ; max_size
21+
sbc hl, hl
22+
adc hl, de
23+
; Allows dst to be NULL when max_size is zero
24+
jr z, .zero_size
25+
26+
push de
27+
ld hl, (ix + 6) ; dst
28+
push hl
29+
call _strnlen
30+
pop af
31+
pop af
32+
33+
ex de, hl
34+
ld hl, (ix + 12) ; max_size
35+
; (copy_size + 1) = max_size - dst_len
36+
xor a, a
37+
sbc hl, de
38+
pop bc ; src_len
39+
push bc
40+
jr z, .no_room
41+
; (copy_size + 1) - src_len - 1
42+
scf
43+
sbc hl, bc
44+
45+
jr c, .copy_size_lt_src_len
46+
; (copy_size + 1 - 1) >= src_len
47+
; copy_size >= src_len
48+
sbc hl, hl
49+
.copy_size_lt_src_len:
50+
xor a, a
51+
adc hl, bc
52+
jr z, .zero_copy_size
53+
push de ; dst_len
54+
push hl
55+
pop bc
56+
ld hl, (ix + 6) ; dst
57+
add hl, de ; dst + dst_len
58+
ex de, hl
59+
ld hl, (ix + 9) ; src
60+
ldir
61+
ld (de), a ; null terminate
62+
pop de ; dst_len
63+
.zero_copy_size:
64+
.no_room:
65+
.zero_size:
66+
pop hl ; src_len
67+
add hl, de
68+
pop ix
69+
ret
70+
71+
extern _strnlen

test/standalone/asprintf_fprintf/src/main.c

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#define C(expr) if (!(expr)) { return __LINE__; }
2424

25+
#define TEST(test) { ret = test; if (ret != 0) { return ret; }}
26+
2527
#define SINK (char*)0xE40000
2628

2729
/* pass NULL into functions without triggering -Wnonnull */
@@ -54,6 +56,9 @@ void *T_memrchr(const void *s, int c, size_t n)
5456
char *T_stpcpy(char *__restrict dest, const char *__restrict src)
5557
__attribute__((nonnull(1, 2)));
5658

59+
size_t T_strlcat(void *__restrict dest, const void *__restrict src, size_t n)
60+
__attribute__((nonnull(1, 2)));
61+
5762
size_t T_strlen(const char *s)
5863
__attribute__((nonnull(1)));
5964

@@ -75,6 +80,7 @@ void T_bzero(void* s, size_t n);
7580
#define T_mempcpy mempcpy
7681
#define T_memrchr memrchr
7782
#define T_stpcpy stpcpy
83+
#define T_strlcat strlcat
7884
#define T_strlen strlen
7985
#define T_strcmp strcmp
8086
#define T_strncmp strncmp
@@ -159,7 +165,7 @@ int boot_sprintf_tests(void) {
159165
printf("E: %d != %d\n", len_3, pos_3);
160166
return __LINE__;
161167
}
162-
168+
163169
// large string test
164170
static char const * const s = "Hello";
165171
int len_4 = boot_snprintf(SINK, 300,
@@ -271,7 +277,7 @@ int nano_tests(void) {
271277
printf("E: %d != %d\n", len_3s, pos_3);
272278
return __LINE__;
273279
}
274-
280+
275281
// https://en.cppreference.com/w/c/io/fprintf
276282
static char const * const s = "Hello";
277283
int len_4 = snprintf(SINK, 300,
@@ -360,7 +366,7 @@ int memccpy_tests(void) {
360366
return __LINE__;
361367
}
362368
file = fopen(file_name, "wb");
363-
369+
364370
// Check if the file was opened successfully
365371
if (file == NULL) {
366372
perror("Error opening file");
@@ -371,32 +377,32 @@ int memccpy_tests(void) {
371377
const char terminal[] = {':', ' ', ',', '.', '!'};
372378
char dest[sizeof src];
373379
const char alt = '@';
374-
380+
375381
for (size_t i = 0; i != sizeof terminal; ++i)
376382
{
377383
void* to = T_memccpy(dest, src, terminal[i], sizeof dest);
378-
384+
379385
fprintf(file,"Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent");
380-
386+
381387
// if `terminal` character was not found - print the whole `dest`
382388
to = to ? to : dest + sizeof dest;
383-
389+
384390
for (char* from = dest; from != to; ++from) {
385391
fputc(isprint(*from) ? *from : alt, file);
386392
}
387-
393+
388394
fputs("\"\n", file);
389395
}
390-
391-
396+
397+
392398
fprintf(file, "%c%s", '\n', "Separate star names from distances (ly):\n");
393399
const char *star_distance[] = {
394400
"Arcturus : 37", "Vega : 25", "Capella : 43", "Rigel : 860", "Procyon : 11"
395401
};
396402
char names_only[64];
397403
char *first = names_only;
398404
char *last = names_only + sizeof names_only;
399-
405+
400406
for (size_t t = 0; t != (sizeof star_distance) / (sizeof star_distance[0]); ++t)
401407
{
402408
if (first) {
@@ -597,6 +603,56 @@ int memmove_test(void) {
597603
return 0;
598604
}
599605

606+
static bool strcmp_exact(const char* x, const char* y) {
607+
if (strlen(x) != strlen(y)) {
608+
return false;
609+
}
610+
if (strcmp(x, y) != 0) {
611+
return false;
612+
}
613+
return true;
614+
}
615+
616+
int strlcat_test(void) {
617+
const char* src1 = "Foo";
618+
const char* src2 = "Bar";
619+
char dst[10];
620+
621+
strcpy(dst, src1); C(T_strlcat(dst , src2, 0) == 3); C(strcmp_exact(dst, "Foo"));
622+
strcpy(dst, src1); C(T_strlcat(dst , src2, 1) == 4); C(strcmp_exact(dst, "Foo"));
623+
strcpy(dst, src1); C(T_strlcat(dst , src2, 2) == 5); C(strcmp_exact(dst, "Foo"));
624+
strcpy(dst, src1); C(T_strlcat(dst , src2, 3) == 6); C(strcmp_exact(dst, "Foo"));
625+
strcpy(dst, src1); C(T_strlcat(dst , src2, 4) == 6); C(strcmp_exact(dst, "Foo"));
626+
strcpy(dst, src1); C(T_strlcat(dst , src2, 5) == 6); C(strcmp_exact(dst, "FooB"));
627+
strcpy(dst, src1); C(T_strlcat(dst , src2, 6) == 6); C(strcmp_exact(dst, "FooBa"));
628+
strcpy(dst, src1); C(T_strlcat(dst , src2, 7) == 6); C(strcmp_exact(dst, "FooBar"));
629+
strcpy(dst, src1); C(T_strlcat(dst , src2, 8) == 6); C(strcmp_exact(dst, "FooBar"));
630+
strcpy(dst, src1); C(T_strlcat(dst , src2, 9) == 6); C(strcmp_exact(dst, "FooBar"));
631+
632+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 0) == 0); C(strcmp_exact(dst, src1));
633+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 1) == 1); C(strcmp_exact(dst, src1));
634+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 2) == 2); C(strcmp_exact(dst, src1));
635+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 3) == 3); C(strcmp_exact(dst, src1));
636+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 4) == 3); C(strcmp_exact(dst, src1));
637+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 5) == 3); C(strcmp_exact(dst, src1));
638+
639+
C(T_strlcat(NULL_ptr, SINK, 0) == 0);
640+
C(T_strlcat(NULL_ptr, src1, 0) == 3);
641+
642+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 0) == 0); C(dst[0] == '\0');
643+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 1) == 0); C(dst[0] == '\0');
644+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 2) == 0); C(dst[0] == '\0');
645+
646+
dst[0] = '\0'; C(T_strlcat(dst, src1, 0) == 3); C(strcmp_exact(dst, ""));
647+
dst[0] = '\0'; C(T_strlcat(dst, src1, 1) == 3); C(strcmp_exact(dst, ""));
648+
dst[0] = '\0'; C(T_strlcat(dst, src1, 2) == 3); C(strcmp_exact(dst, "F"));
649+
dst[0] = '\0'; C(T_strlcat(dst, src1, 3) == 3); C(strcmp_exact(dst, "Fo"));
650+
dst[0] = '\0'; C(T_strlcat(dst, src1, 4) == 3); C(strcmp_exact(dst, "Foo"));
651+
dst[0] = '\0'; C(T_strlcat(dst, src1, 5) == 3); C(strcmp_exact(dst, "Foo"));
652+
653+
return 0;
654+
}
655+
600656
int run_tests(void) {
601657
int ret = 0;
602658
/* boot_asprintf */
@@ -618,25 +674,12 @@ int run_tests(void) {
618674
}
619675
if (ret != 0) { return ret; }
620676

621-
/* mempcpy */
622-
ret = mempcpy_test();
623-
if (ret != 0) { return ret; }
624-
625-
/* bzero */
626-
ret = bzero_test();
627-
if (ret != 0) { return ret; }
628-
629-
/* strncmp */
630-
ret = strncmp_test();
631-
if (ret != 0) { return ret; }
632-
633-
/* memrchr */
634-
ret = memrchr_test();
635-
if (ret != 0) { return ret; }
636-
637-
/* memrchr */
638-
ret = memmove_test();
639-
if (ret != 0) { return ret; }
677+
TEST(mempcpy_test());
678+
TEST(bzero_test());
679+
TEST(strncmp_test());
680+
TEST(memrchr_test());
681+
TEST(memmove_test());
682+
TEST(strlcat_test());
640683

641684
return 0;
642685
}
@@ -675,7 +718,7 @@ int main(void)
675718
printf("All tests %s", "passed");
676719
#endif
677720
}
678-
721+
679722
while (!os_GetCSC());
680723

681724
return 0;

test/standalone/asprintf_fprintf/src/rename.asm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
section .text
44

55
public _T_memset, _T_memcpy, _T_memmove, _T_memcmp, _T_memccpy, _T_mempcpy, _T_memrchr
6-
public _T_strlen, _T_strcmp, _T_strncmp, _T_stpcpy
6+
public _T_strlen, _T_strcmp, _T_strncmp, _T_stpcpy, _T_strlcat
77
public _T_bzero
88

99
_T_memset := _memset
@@ -18,6 +18,7 @@ _T_strlen := _strlen
1818
_T_strcmp := _strcmp
1919
_T_strncmp := _strncmp
2020
_T_stpcpy := _stpcpy
21+
_T_strlcat := _strlcat
2122

2223
_T_bzero := _bzero
2324

@@ -28,5 +29,5 @@ _NULL_ptr:
2829
db $00, $00, $00
2930

3031
extern _memset, _memcpy, _memmove, _memcmp, _memccpy, _mempcpy, _memrchr
31-
extern _strlen, _strcmp, _strncmp, _stpcpy
32+
extern _strlen, _strcmp, _strncmp, _stpcpy, _strlcat
3233
extern _bzero

0 commit comments

Comments
 (0)