Skip to content

Commit be0f1bb

Browse files
committed
implemented strlcat
1 parent 0d032c5 commit be0f1bb

File tree

3 files changed

+149
-33
lines changed

3 files changed

+149
-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: 75 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,57 @@ 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+
{
618+
const char* src1 = "Foo";
619+
const char* src2 = "Bar";
620+
char dst[10];
621+
622+
strcpy(dst, src1); C(T_strlcat(dst , src2, 0) == 3); C(strcmp_exact(dst, "Foo"));
623+
strcpy(dst, src1); C(T_strlcat(dst , src2, 1) == 4); C(strcmp_exact(dst, "Foo"));
624+
strcpy(dst, src1); C(T_strlcat(dst , src2, 2) == 5); C(strcmp_exact(dst, "Foo"));
625+
strcpy(dst, src1); C(T_strlcat(dst , src2, 3) == 6); C(strcmp_exact(dst, "Foo"));
626+
strcpy(dst, src1); C(T_strlcat(dst , src2, 4) == 6); C(strcmp_exact(dst, "Foo"));
627+
strcpy(dst, src1); C(T_strlcat(dst , src2, 5) == 6); C(strcmp_exact(dst, "FooB"));
628+
strcpy(dst, src1); C(T_strlcat(dst , src2, 6) == 6); C(strcmp_exact(dst, "FooBa"));
629+
strcpy(dst, src1); C(T_strlcat(dst , src2, 7) == 6); C(strcmp_exact(dst, "FooBar"));
630+
strcpy(dst, src1); C(T_strlcat(dst , src2, 8) == 6); C(strcmp_exact(dst, "FooBar"));
631+
strcpy(dst, src1); C(T_strlcat(dst , src2, 9) == 6); C(strcmp_exact(dst, "FooBar"));
632+
633+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 0) == 0); C(strcmp_exact(dst, src1));
634+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 1) == 1); C(strcmp_exact(dst, src1));
635+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 2) == 2); C(strcmp_exact(dst, src1));
636+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 3) == 3); C(strcmp_exact(dst, src1));
637+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 4) == 3); C(strcmp_exact(dst, src1));
638+
strcpy(dst, src1); C(T_strlcat(dst , SINK, 5) == 3); C(strcmp_exact(dst, src1));
639+
640+
C(T_strlcat(NULL_ptr, SINK, 0) == 0);
641+
C(T_strlcat(NULL_ptr, src1, 0) == 3);
642+
643+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 0) == 0); C(dst[0] == '\0');
644+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 1) == 0); C(dst[0] == '\0');
645+
dst[0] = '\0'; C(T_strlcat(dst, SINK, 2) == 0); C(dst[0] == '\0');
646+
647+
dst[0] = '\0'; C(T_strlcat(dst, src1, 0) == 3); C(strcmp_exact(dst, ""));
648+
dst[0] = '\0'; C(T_strlcat(dst, src1, 1) == 3); C(strcmp_exact(dst, ""));
649+
dst[0] = '\0'; C(T_strlcat(dst, src1, 2) == 3); C(strcmp_exact(dst, "F"));
650+
dst[0] = '\0'; C(T_strlcat(dst, src1, 3) == 3); C(strcmp_exact(dst, "Fo"));
651+
dst[0] = '\0'; C(T_strlcat(dst, src1, 4) == 3); C(strcmp_exact(dst, "Foo"));
652+
dst[0] = '\0'; C(T_strlcat(dst, src1, 5) == 3); C(strcmp_exact(dst, "Foo"));
653+
654+
return 0;
655+
}
656+
600657
int run_tests(void) {
601658
int ret = 0;
602659
/* boot_asprintf */
@@ -618,25 +675,12 @@ int run_tests(void) {
618675
}
619676
if (ret != 0) { return ret; }
620677

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; }
678+
TEST(mempcpy_test());
679+
TEST(bzero_test());
680+
TEST(strncmp_test());
681+
TEST(memrchr_test());
682+
TEST(memmove_test());
683+
TEST(strlcat_test());
640684

641685
return 0;
642686
}
@@ -675,7 +719,7 @@ int main(void)
675719
printf("All tests %s", "passed");
676720
#endif
677721
}
678-
722+
679723
while (!os_GetCSC());
680724

681725
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)