diff --git a/include/string.h b/include/string.h index 2f5953196..83970493e 100644 --- a/include/string.h +++ b/include/string.h @@ -78,6 +78,7 @@ int __fastcall__ stricmp (const char* s1, const char* s2); /* DOS/Windows */ int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */ int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count); /* DOS/Windows */ int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count); /* Same for Unix */ +size_t __fastcall__ strnlen (const char* s, size_t maxlen); /* POSIX.1-2008 */ char* __fastcall__ strlwr (char* s); char* __fastcall__ strlower (char* s); char* __fastcall__ strupr (char* s); diff --git a/libsrc/common/strnlen.s b/libsrc/common/strnlen.s new file mode 100644 index 000000000..eb2c16006 --- /dev/null +++ b/libsrc/common/strnlen.s @@ -0,0 +1,54 @@ +; size_t __fastcall__ strnlen (const char* s, size_t maxlen); + +.export _strnlen +.import popax +.importzp ptr1, tmp1, tmp2, tmp3, tmp4 + +.proc _strnlen + ; Get maximum length. + tay + iny + sty tmp3 + inx + stx tmp4 + + ; Fetch string pointer. + jsr popax + sta ptr1 + stx ptr1+1 + + ; Clear return value. + ldy #0 + sty tmp1 + sty tmp2 + + + ;;; Loop over string. + ; Decrement maximum length. +next: dec tmp3 + bne l2 + dec tmp4 + beq done +l2: + + lda (ptr1),y + beq done + + ; Step to next character. + iny + bne l1 + inc ptr1+1 +l1: + + ; Increment return value. + inc tmp1 + bne next + inc tmp2 + + bne next ; (jmp) + + +done: lda tmp1 + ldx tmp2 + rts +.endproc diff --git a/targettest/Makefile b/targettest/Makefile index f3694335c..44933949a 100644 --- a/targettest/Makefile +++ b/targettest/Makefile @@ -160,6 +160,7 @@ EXELIST_c64 = \ scanf-test \ ser-test \ strdup-test \ + strnlen \ stroserror-test \ strqtok-test \ tinyshell \ @@ -190,6 +191,7 @@ EXELIST_vic20 = \ rename-test \ scanf-test \ strdup-test \ + strnlen \ stroserror-test \ strqtok-test \ tinyshell \ @@ -222,6 +224,7 @@ EXELIST_apple2 = \ seek \ ser-test \ strdup-test \ + strnlen \ stroserror-test \ strqtok-test \ tinyshell \ @@ -257,6 +260,7 @@ EXELIST_atari = \ seek \ ser-test \ strdup-test \ + strnlen \ stroserror-test \ strqtok-test \ tinyshell \ diff --git a/targettest/strnlen.c b/targettest/strnlen.c new file mode 100644 index 000000000..ac39f2396 --- /dev/null +++ b/targettest/strnlen.c @@ -0,0 +1,32 @@ +#include +#include +#include + +const char * str = "0123456789"; + +void +check (size_t result, size_t expected) +{ + if (result != expected) { + printf ("Expected strnlen() to return %u, got %u.\n", + expected, result); + exit (EXIT_FAILURE); + } +} + +int +main (void) +{ + size_t maxlen = strlen (str); + size_t result; + size_t expected; + + for (expected = 0; expected < maxlen; expected++) + check (strnlen (str, expected), expected); + + check (strnlen (str, maxlen << 1), maxlen); + + printf ("strnlen() OK.\n"); + + return EXIT_SUCCESS; +}