tests/libc: Add 0042-mbsrtowc - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 36606c7df70f2465a4305395c529e7ea1add693f
 (DIR) parent 01921365fc084e3b592c00bdd090d0d457502904
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Fri, 21 Mar 2025 19:23:17 +0100
       
       tests/libc: Add 0042-mbsrtowc
       
       Diffstat:
         M src/libc/wchar/mbsrtowcs.c          |      26 +++++++++++++++++++++-----
         M tests/libc/execute/.gitignore       |       1 +
         A tests/libc/execute/0042-mbsrtowcs.c |     126 +++++++++++++++++++++++++++++++
         M tests/libc/execute/libc-tests.lst   |       1 +
       
       4 files changed, 149 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/src/libc/wchar/mbsrtowcs.c b/src/libc/wchar/mbsrtowcs.c
       @@ -1,4 +1,5 @@
        #include <limits.h>
       +#include <string.h>
        #include <wchar.h>
        
        #undef mbsrtowcs
       @@ -8,24 +9,39 @@ mbsrtowcs(wchar_t *restrict dest, const char **restrict src, size_t len,
                  mbstate_t *restrict ps)
        {
                wchar_t wc;
       +        const char *s = *src;
                size_t cnt, n;
       +        static mbstate_t st;
       +
       +        if (!ps)
       +                ps = &st;
        
                for (n = 0; ; n++) {
       -                cnt = mbrtowc(&wc, *src, MB_LEN_MAX, ps);
       +                cnt = mbrtowc(&wc, s, MB_LEN_MAX, ps);
       +                if (cnt == (size_t) -2) {
       +                        s += MB_LEN_MAX;
       +                        continue;
       +                }
                        if (cnt == (size_t) -1)
                                return -1;
        
                        if (dest) {
       -                        if (n == len)
       +                        if (n == len) {
       +                                *src = s;
                                        return n;
       +                        }
                                *dest++ = wc;
                        }
       -                *src += cnt;
       +                s += cnt;
        
       -                if (wc == L'\0')
       +                if (wc == 0)
                                break;
                }
       -        *src = NULL;
       +
       +        if (dest) {
       +                memset(ps, 0, sizeof(mbstate_t));
       +                *src = NULL;
       +        }
        
                return n;
        }
 (DIR) diff --git a/tests/libc/execute/.gitignore b/tests/libc/execute/.gitignore
       @@ -39,6 +39,7 @@
        0039-mbrtowc
        0040-wcrtomb
        0041-mbrlen
       +0042-mbsrtowcs
        0044-wcslen
        0045-wcscmp
        0046-wcsncmp
 (DIR) diff --git a/tests/libc/execute/0042-mbsrtowcs.c b/tests/libc/execute/0042-mbsrtowcs.c
       @@ -0,0 +1,126 @@
       +#include <assert.h>
       +#include <errno.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <wchar.h>
       +
       +/*
       +output:
       +testing
       +testing mbsrtowcs1
       +testing mbsrtowcs2
       +testing mbstowcs
       +done
       +end:
       +*/
       +
       +#define NELEM(x) (sizeof(x)/sizeof(x[0]))
       +
       +static char str[20];
       +static wchar_t wcs[20];
       +static struct mbstests {
       +        char *s;
       +        char *sexp;
       +
       +        wchar_t *wcs;
       +        wchar_t *wcsexp;
       +
       +        size_t n;
       +        int r;
       +        int syserr;
       +        int mbstate;
       +} tests[] = {
       +        /* s       sexp    wcs  wcsexp                      n  r  syserr  mbstate */
       +        {"\0",     NULL,   wcs, (wchar_t[]) {0},            1, 0,      0,       1},
       +        {"\0",      str,   wcs, (wchar_t[]) {0},            0, 0,      0,       1},
       +        {"\0",      str,  NULL, (wchar_t[]) {0},            1, 0,      0,       1},
       +        {"\0",      str,  NULL, (wchar_t[]) {0},            0, 0,      0,       1},
       +
       +        {"\x31",   NULL,   wcs, (wchar_t[]) {0x31, 0},      2, 1,      0,       1},
       +        {"\x31",  str+1,   wcs, (wchar_t[]) {0x31, 0},      1, 1,      0,       1},
       +        {"\x31",    str,  NULL, (wchar_t[]) {0x31, 0},      1, 1,      0,       1},
       +        {"\x31",    str,  NULL, (wchar_t[]) {0x31, 0},      0, 1,      0,       1},
       +
       +        {"\x21\xc2\xa1\xe2\x80\x94\xf0\x9f\x92\xa9",
       +               NULL,   wcs,
       +               (wchar_t[]) {0x21,0xa1,0x2014,0x1f4A9}, 20, 4,      0,       1},
       +
       +        {"\xf0\x9f",str,  wcs, NULL,                       20,-1, EILSEQ,       0},
       +};
       +
       +void
       +tests_mbsrtowcs(void)
       +{
       +        int r;
       +        const char *s;
       +        mbstate_t st;
       +        struct mbstests *tp;
       +
       +        puts("testing mbsrtowcs1");
       +        for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
       +                errno = 0;
       +                if (tp->s != NULL)
       +                        s = strcpy(str, tp->s);                        
       +                memset(wcs, -1, sizeof(wcs));
       +
       +                r = mbsrtowcs(tp->wcs, &s, tp->n, NULL);
       +                assert(tp->r == r);
       +                assert(tp->syserr == errno);
       +                if (tp->r >= 0) {
       +                        assert(s == tp->sexp);
       +                        if (tp->wcs)
       +                                assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
       +                }
       +        }
       +
       +        puts("testing mbsrtowcs2");
       +        for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
       +                errno = 0;
       +                if (tp->s != NULL)
       +                        s = strcpy(str, tp->s);                        
       +                memset(wcs, -1, sizeof(wcs));
       +                memset(&st, 0, sizeof(st));
       +
       +                r = mbsrtowcs(tp->wcs, &s, tp->n, &st);
       +                assert(tp->r == r);
       +                assert(tp->syserr == errno);
       +                if (tp->r >= 0) {
       +                        assert(s == tp->sexp);
       +                        if (tp->wcs)
       +                                assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
       +                        assert(mbsinit(&st) != 0 == tp->mbstate);
       +                }
       +        }
       +}
       +
       +void
       +tests_mbstowcs(void)
       +{
       +        int r;
       +        struct mbstests *tp;
       +
       +        puts("testing mbstowcs");
       +        for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
       +                errno = 0;
       +                memset(wcs, -1, sizeof(wcs));
       +
       +                r = mbstowcs(tp->wcs, tp->s, tp->n);
       +                assert(tp->r == r);
       +                assert(tp->syserr == errno);
       +                if (tp->r >= 0) {
       +                        if (tp->wcs)
       +                                assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
       +                }
       +        }
       +}
       +
       +int
       +main(void)
       +{
       +        puts("testing");
       +        tests_mbsrtowcs();
       +        tests_mbstowcs();
       +        puts("done");
       +        return 0;
       +}
 (DIR) diff --git a/tests/libc/execute/libc-tests.lst b/tests/libc/execute/libc-tests.lst
       @@ -38,6 +38,7 @@
        0039-mbrtowc
        0040-wcrtomb
        0041-mbrlen
       +0042-mbsrtowcs
        0044-wcslen
        0045-wcscmp
        0046-wcsncmp