commit 3b42911841f616a37e3fa7bd5f4ad7177ce959cf parent b96ef460770e7d0bf335cbadbed7efd2db08199e Author: Roberto E. Vargas Caballero <k0ga@shike2.com> Date: Tue, 25 Mar 2025 10:52:47 +0100 Merge remote-tracking branch 'origin/master' into wchar Diffstat:
52 files changed, 895 insertions(+), 177 deletions(-)
diff --git a/include/bits/darwin/sys/cdefs.h b/include/bits/darwin/sys/cdefs.h @@ -1,9 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef struct { - unsigned char state[4]; - size_t count; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing fpr darwin */ diff --git a/include/bits/dragonfly/sys/cdefs.h b/include/bits/dragonfly/sys/cdefs.h @@ -1,8 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef union { - char __mbstate8[128]; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing for dragonfly */ diff --git a/include/bits/freebsd/sys/cdefs.h b/include/bits/freebsd/sys/cdefs.h @@ -1,8 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef union { - char __mbstate8[128]; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing for Openbsd */ diff --git a/include/bits/linux/sys/cdefs.h b/include/bits/linux/sys/cdefs.h @@ -1,8 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef struct __mbstate_t { - unsigned __opaque1, __opaque2; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing for Linux */ diff --git a/include/bits/netbsd/sys/cdefs.h b/include/bits/netbsd/sys/cdefs.h @@ -1,8 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef union { - char __mbstate8[128]; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing for netbsd */ diff --git a/include/bits/openbsd/sys/cdefs.h b/include/bits/openbsd/sys/cdefs.h @@ -1,8 +1 @@ -#ifdef _NEED_MBSTATE_T -#ifndef _MBSTATE_T -typedef union { - char __mbstate8[128]; -} mbstate_t; -#define _MBSTATE_T -#endif -#endif +/* nothing for Openbsd */ diff --git a/include/stdlib.h b/include/stdlib.h @@ -66,6 +66,4 @@ extern int wctomb(char *, wchar_t); extern size_t mbstowcs(wchar_t *restrict, const char *restrict, size_t); extern size_t wcstombs(char *restrict, const wchar_t *restrict, size_t); -#define mblen(s,n) mbtowc(NULL, s, n) - #endif diff --git a/include/wchar.h b/include/wchar.h @@ -8,10 +8,15 @@ #define _NEED_WCHARLIM #define _NEED_WINT #define _NEED_VA_LIST -#define _NEED_MBSTATE_T #include <arch/cdefs.h> #include <sys/cdefs.h> +typedef struct { + unsigned char oc; + unsigned char sh; + wchar_t wc; +} mbstate_t; + struct tm; struct _FILE; @@ -30,8 +35,11 @@ extern wint_t fgetwc(struct _FILE *); extern wint_t fputwc(wchar_t c, struct _FILE *); extern wint_t getwc(struct _FILE *); extern wint_t putwc(wchar_t, struct _FILE *); -extern int fwide(struct _FILE *, int); +extern wint_t getwchar(void); +extern wint_t putwchar(wchar_t); extern wint_t ungetwc(wint_t, struct _FILE *); + +extern int fwide(struct _FILE *, int); extern wchar_t *fgetws(wchar_t *restrict, int, struct _FILE *restrict); extern int fputws(const wchar_t *restrict, struct _FILE *restrict); @@ -40,9 +48,6 @@ extern int swscanf(const wchar_t *restrict, const wchar_t *restrict, ...); extern int wprintf(const wchar_t *restrict, ...); extern int wscanf(const wchar_t *restrict, ...); -extern wint_t getwchar(void); -extern wint_t putwchar(wchar_t); - extern double wcstod(const wchar_t *restrict, wchar_t **restrict); extern float wcstof(const wchar_t *restrict, wchar_t **restrict); extern long double wcstold(const wchar_t *restrict, wchar_t **restrict); @@ -57,13 +62,17 @@ extern wchar_t *wcsncpy(wchar_t *restrict, const wchar_t *restrict, size_t); extern wchar_t *wmemcpy(wchar_t *restrict, const wchar_t *restrict, size_t); extern wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t); +extern wchar_t *wmemset(wchar_t *, wchar_t, size_t); +extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t); +extern int wmemcmp(const wchar_t *, const wchar_t *, size_t); + +extern size_t wcslen(const wchar_t *); +extern int wcscmp(const wchar_t *, const wchar_t *); extern wchar_t *wcscat(wchar_t *restrict, const wchar_t *restrict); extern wchar_t *wcsncat(wchar_t *restrict, const wchar_t *restrict, size_t); -extern int wcscmp(const wchar_t *, const wchar_t *); extern int wcscoll(const wchar_t *, const wchar_t *); extern int wcsncmp(const wchar_t *, const wchar_t *, size_t); extern size_t wcsxfrm(wchar_t *restrict, const wchar_t *restrict, size_t); -extern int wmemcmp(const wchar_t *, const wchar_t *, size_t); extern wchar_t *wcschr(const wchar_t *, wchar_t); extern size_t wcscspn(const wchar_t *, const wchar_t *); extern wchar_t *wcspbrk(const wchar_t *, const wchar_t *); @@ -71,12 +80,11 @@ extern wchar_t *wcsrchr(const wchar_t *, wchar_t); extern size_t wcsspn(const wchar_t *, const wchar_t *); extern wchar_t *wcsstr(const wchar_t *, const wchar_t *); extern wchar_t *wcstok(wchar_t *restrict, const wchar_t *restrict, wchar_t **restrict); -extern wchar_t *wmemchr(const wchar_t *, wchar_t, size_t); -extern size_t wcslen(const wchar_t *); -extern wchar_t *wmemset(wchar_t *, wchar_t, size_t); + extern size_t wcsftime(wchar_t *restrict, size_t, const wchar_t *restrict, const struct tm *restrict); extern wint_t btowc(int); extern int wctob(wint_t); + extern int mbsinit(const mbstate_t *); extern size_t mbrlen(const char *restrict, size_t, mbstate_t *restrict); extern size_t mbrtowc(wchar_t *restrict, const char *restrict, size_t, mbstate_t *restrict); @@ -85,7 +93,7 @@ extern size_t mbsrtowcs(wchar_t *restrict, const char **restrict, size_t, mbstat extern size_t wcsrtombs(char *restrict, const wchar_t **restrict, size_t, mbstate_t *restrict); extern int wcwidth(wchar_t); -#define mbrlen(s, n, ps) mbrtowc(NULL, s, n, ps) #define putwc(wc, fp) fputwc(wc, fp) +#define getwc(fp) fgetwc(fp) #endif diff --git a/src/cmd/scc-make/rules.c b/src/cmd/scc-make/rules.c @@ -506,7 +506,7 @@ rebuild(Target *tp, int *buildp) q = *p; debug("checking dependency %s", q->name); - if (q->actions) + if (strcmp(q->name, tp->name) == 0 && q->actions) def = 1; build = 0; @@ -526,10 +526,14 @@ rebuild(Target *tp, int *buildp) } } - if (tp->stamp == -1) - need = 1; - else if (!def && inference(tp, NOFORCE)) + if (tp->stamp == -1) { need = 1; + } else if (!def) { + debug("no action found for %s, looking a inference rule", + tp->name); + if (inference(tp, NOFORCE)) + need = 1; + } if (err) { warning("target %s not remade because of errors", tp->name); @@ -537,6 +541,7 @@ rebuild(Target *tp, int *buildp) } else if (need) { *buildp = 1; + debug("target %s needs updating", tp->name); r = update(tp); if (r == 0) return 0; diff --git a/src/libc/arch/bsd/Makefile b/src/libc/arch/bsd/Makefile @@ -4,8 +4,6 @@ include $(PROJECTDIR)/scripts/rules.mk include ../../rules.mk OBJS=\ - _mbsget.$O\ - _mbsset.$O\ - _waitpid.$O\ + _waitpid.$O\ all: $(OBJS) diff --git a/src/libc/arch/bsd/_mbsget.c b/src/libc/arch/bsd/_mbsget.c @@ -1,9 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsget(mbstate_t *ps) -{ - return ps->__mbstate8[0]; -} diff --git a/src/libc/arch/bsd/_mbsset.c b/src/libc/arch/bsd/_mbsset.c @@ -1,9 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsset(mbstate_t *ps, int ch) -{ - return ps->__mbstate8[0] = ch; -} diff --git a/src/libc/arch/darwin/Makefile b/src/libc/arch/darwin/Makefile @@ -5,7 +5,5 @@ include ../../rules.mk OBJS=\ _getheap.$O\ - _mbsget.$O\ - _mbsset.$O\ all: $(OBJS) diff --git a/src/libc/arch/darwin/_mbsget.c b/src/libc/arch/darwin/_mbsget.c @@ -1,9 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsget(mbstate_t *ps) -{ - return ps->state[0]; -} diff --git a/src/libc/arch/darwin/_mbsset.c b/src/libc/arch/darwin/_mbsset.c @@ -1,10 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsset(mbstate_t *ps, int ch) -{ - ps-count = 1; - return ps->state[0] = ch; -} diff --git a/src/libc/arch/linux/Makefile b/src/libc/arch/linux/Makefile @@ -6,8 +6,6 @@ include ../../rules.mk OBJS=\ _brk.$O\ _getheap.$O\ - _mbsget.$O\ - _mbsset.$O\ _sigaction.$O\ _waitpid.$O\ diff --git a/src/libc/arch/linux/_mbsget.c b/src/libc/arch/linux/_mbsget.c @@ -1,9 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsget(mbstate_t *ps) -{ - return ps->__opaque1; -} diff --git a/src/libc/arch/linux/_mbsset.c b/src/libc/arch/linux/_mbsset.c @@ -1,9 +0,0 @@ -#include <wchar.h> - -#include "../../libc.h" - -int -_mbsset(mbstate_t *ps, int ch) -{ - return ps->__opaque1 = ch; -} diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -20,6 +20,7 @@ enum { #define SECDAY (24 * SECHOUR) /* 86400 */ struct tm; +struct _FILE; struct tzone { char *name; @@ -61,9 +62,5 @@ extern void (*_atexithdl)(void); #ifdef _WCHAR_H extern int _validutf8(wchar_t, int *); -extern int _mbsset(mbstate_t *, int); -extern int _mbsget(mbstate_t *); -#ifdef _STDIO_H -extern wint_t _fputwc(wchar_t, FILE *, int *); -#endif +extern wint_t _fputwc(wchar_t, struct _FILE *, int *); #endif diff --git a/src/libc/objs/amd64-linux.mk b/src/libc/objs/amd64-linux.mk @@ -36,8 +36,6 @@ OBJS =\ arch/amd64/strcpy.$O\ arch/linux/_brk.$O\ arch/linux/_getheap.$O\ - arch/linux/_mbsget.$O\ - arch/linux/_mbsset.$O\ arch/linux/_sigaction.$O\ arch/linux/_waitpid.$O\ arch/posix/_open.$O\ diff --git a/src/libc/objs/amd64-netbsd.mk b/src/libc/objs/amd64-netbsd.mk @@ -28,8 +28,6 @@ OBJS =\ arch/amd64/strcmp.$O\ arch/amd64/strcpy.$O\ arch/bsd/_waitpid.$O\ - arch/bsd/_mbsget.$O\ - arch/bsd/_mbsset.$O\ arch/netbsd/_sigaction.$O\ arch/posix/_getheap.$O\ arch/posix/_open.$O\ diff --git a/src/libc/objs/amd64-openbsd.mk b/src/libc/objs/amd64-openbsd.mk @@ -33,8 +33,6 @@ OBJS =\ arch/amd64/strcmp.$O\ arch/amd64/strcpy.$O\ arch/bsd/_waitpid.$O\ - arch/bsd/_mbsget.$O\ - arch/bsd/_mbsset.$O\ arch/posix/_getheap.$O\ arch/posix/_open.$O\ arch/posix/_systime.$O\ diff --git a/src/libc/objs/common-objs.mk b/src/libc/objs/common-objs.mk @@ -127,6 +127,10 @@ COMMON_OBJS =\ wchar/mbsrtowcs.$O\ wchar/wcrtomb.$O\ wchar/wcslen.$O\ + wchar/wcscmp.$O\ + wchar/wcscoll.$O\ + wchar/wcsncmp.$O\ + wchar/wcscpy.$O\ wchar/wcsrtombs.$O\ wchar/wcwidth.$O\ wchar/putwc.$O\ diff --git a/src/libc/stdlib/mblen.c b/src/libc/stdlib/mblen.c @@ -1,9 +1,16 @@ #include <stdlib.h> +#include <wchar.h> #undef mblen int mblen(const char *s, size_t n) { - return mbtowc(NULL, s, n); + int ret; + static mbstate_t st; + + ret = mbrtowc(NULL, s, n, &st); + if (ret < 0) + ret = -1; + return ret; } diff --git a/src/libc/stdlib/mbstowcs.c b/src/libc/stdlib/mbstowcs.c @@ -7,5 +7,7 @@ size_t mbstowcs(wchar_t *restrict dest, const char *restrict src, size_t n) { - return mbsrtowcs(dest, (void *) &src, n, NULL); + static mbstate_t st; + + return mbsrtowcs(dest, (void *) &src, n, &st); } diff --git a/src/libc/stdlib/mbtowc.c b/src/libc/stdlib/mbtowc.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <string.h> #include <wchar.h> #undef mbtowc @@ -6,5 +7,12 @@ int mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n) { - return mbrtowc(pwc, s, n, NULL); + static mbstate_t st; + int ret; + + ret = mbrtowc(pwc, s, n, &st); + if (ret < 0) + ret = -1; + + return ret; } diff --git a/src/libc/stdlib/wcstombs.c b/src/libc/stdlib/wcstombs.c @@ -6,5 +6,7 @@ size_t wcstombs(char *restrict dest, const wchar_t *restrict src, size_t n) { - return wcsrtombs(dest, (void *) &src, n, NULL); + static mbstate_t st; + + return wcsrtombs(dest, (void *) &src, n, &st); } diff --git a/src/libc/stdlib/wctomb.c b/src/libc/stdlib/wctomb.c @@ -6,5 +6,7 @@ int wctomb(char *s, wchar_t wc) { - return wcrtomb(s, wc, NULL); + static mbstate_t st; + + return wcrtomb(s, wc, &st); } diff --git a/src/libc/string/strcmp.c b/src/libc/string/strcmp.c @@ -5,7 +5,7 @@ int strcmp(const char *s1, const char *s2) { - while (*s1 && *s2 && *s1 == *s2) + while (*s1 && *s1 == *s2) ++s1, ++s2; return *(unsigned char *) s1 - *(unsigned char *) s2; } diff --git a/src/libc/wchar/_validutf8.c b/src/libc/wchar/_validutf8.c @@ -19,7 +19,7 @@ _validutf8(wchar_t wc, int *nbytes) {0xD800, 0xDD00, 0, 3}, {0xDD00, 0x10000, 1, 3}, {0x10000, 0x110000, 1, 4}, - {0x11000, -1ul, 0, 0}, + {0x110000, -1ul, 0, 0}, }; struct range *bp; diff --git a/src/libc/wchar/mbrlen.c b/src/libc/wchar/mbrlen.c @@ -5,5 +5,9 @@ size_t mbrlen(const char *restrict s, size_t n, mbstate_t *restrict ps) { + static mbstate_t st; + + if (!ps) + ps = &st; return mbrtowc(NULL, s, n, ps); } diff --git a/src/libc/wchar/mbrtowc.c b/src/libc/wchar/mbrtowc.c @@ -1,5 +1,6 @@ #include <errno.h> #include <stdlib.h> +#include <string.h> #include <wchar.h> #include "../libc.h" @@ -10,43 +11,88 @@ size_t mbrtowc(wchar_t *restrict pwc, const char *restrict s, size_t n, mbstate_t *restrict ps) { + static mbstate_t state; const unsigned char *t = (const unsigned char *) s; + wchar_t dummy; unsigned long wc; - unsigned c; - int i, len, maxlen; - - if (t == NULL) - return 0; - if ((wc = *t) == 0) - goto return_code; - - c = *t++; - for (len = 0; n > 0 && c & 0x80; --n, ++len) - c <<= 1; - if (n == 0 && c & 0x80) + unsigned c, oc; + int sh, max; + + if (!ps) + ps = &state; + + if (t == NULL) { + if (ps->sh != 0) + goto return_error; + pwc = &dummy; + goto return_code_set; + } + if (n == 0) return -2; - if (len == 1 || len > MB_CUR_MAX) - goto return_error; - if (len == 0) - goto return_code; - - wc = (c & 0xFF) >> len; - for (i = 0; i < len-1; i++) { - if (((c = *t++) & 0xC0) != 0x80) + + oc = ps->oc; + wc = ps->wc; + sh = ps->sh; + + /* initial state? */ + if (sh == 0) { + /* NUL character? */ + if ((c = wc = *t) == 0) + goto return_code; + t++; + n--; + + /* fast track for ascii? */ + if (c < 0x80) + goto return_code; + + /* out of sequence multibyte? */ + if ((c & 0xc0) != 0xc0) goto return_error; + + /* in sequence multibyte! */ + oc = c << 1; + wc = 0; + sh = 1; + } + + for ( ; n > 0; --n) { + if (sh > MB_CUR_MAX) + goto return_error; + + c = *t++; + if ((c & 0xc0) != 0x80) + goto return_error; + wc <<= 6; - wc |= c & 0x3F; + wc |= c & 0x3f; + oc <<= 1; + sh++; + + if ((oc & 0x80) == 0) { + oc = (oc & 0xff) >> sh; + wc |= oc << (sh-1) * 6; + + if (!_validutf8(wc, &max) || sh != max) + goto return_error; + goto return_code_set; + } } - if (!_validutf8(wc, &maxlen) || len != maxlen) - goto return_error; + ps->sh = sh; + ps->oc = oc; + ps->wc = wc; + return -2; +return_code_set: + memset(ps, 0, sizeof(*ps)); return_code: if (pwc) *pwc = wc; return t - (unsigned char *) s; return_error: + memset(ps, 0, sizeof(*ps)); errno = EILSEQ; return -1; } diff --git a/src/libc/wchar/mbsinit.c b/src/libc/wchar/mbsinit.c @@ -1,7 +1,5 @@ #include <wchar.h> -#include "../libc.h" - #undef mbsinit int @@ -9,5 +7,5 @@ mbsinit(const mbstate_t *ps) { if (!ps) return 1; - return _mbsget(ps) == 0; + return ps->oc == 0; } 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; } diff --git a/src/libc/wchar/wcscmp.c b/src/libc/wchar/wcscmp.c @@ -0,0 +1,15 @@ +#include <wchar.h> + +#undef wcscmp + +int +wcscmp(const wchar_t *s1, const wchar_t *s2) +{ + unsigned long l1, l2; + + while (*s1 && *s1 == *s2) + ++s1, ++s2; + l1 = *s1, l2 = *s2; + + return l1 - l2; +} diff --git a/src/libc/wchar/wcscoll.c b/src/libc/wchar/wcscoll.c @@ -0,0 +1,9 @@ +#include <wchar.h> + +#undef wcscoll + +int +wcscoll(const wchar_t *s1, const wchar_t *s2) +{ + return wcscmp(s1, s2); +} diff --git a/src/libc/wchar/wcscpy.c b/src/libc/wchar/wcscpy.c @@ -0,0 +1,16 @@ +#include <wchar.h> + +#undef wcscpy + +wchar_t * +wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2) +{ + wchar_t *ret = s1; + + while ((*s1++ = *s2++) != '\0') + ; + + return ret; + +} + diff --git a/src/libc/wchar/wcsncmp.c b/src/libc/wchar/wcsncmp.c @@ -0,0 +1,18 @@ +#include <wchar.h> + +#undef wcsncmp + +int +wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) +{ + unsigned long l1, l2; + + for ( ; n > 0 && *s1 == *s2; --n) + ++s1, ++s2; + + if (n == 0) + return 0; + l1 = *s1, l2 = *s2; + + return l1 - l2; +} diff --git a/tests/libc/execute/.gitignore b/tests/libc/execute/.gitignore @@ -35,4 +35,14 @@ 0035-setlocale 0036-localeconv 0037-malloc +0038-mbsinit +0039-mbrtowc +0040-wcrtomb +0041-mbrlen +0042-mbsrtowcs +0044-wcslen +0045-wcscmp +0046-wcsncmp +0047-wcscoll +0048-wcscpy test.log diff --git a/tests/libc/execute/0038-mbsinit.c b/tests/libc/execute/0038-mbsinit.c @@ -0,0 +1,29 @@ +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> + +/* +output: +testing +done +end: +*/ + +void +tests_mbsinit(void) +{ + mbstate_t s; + + assert(mbsinit(NULL) != 0); + assert(mbsinit(memset(&s, 0, sizeof(s))) != 0); +} + +int +main() +{ + puts("testing"); + tests_mbsinit(); + puts("done"); + return 0; +} diff --git a/tests/libc/execute/0039-mbrtowc.c b/tests/libc/execute/0039-mbrtowc.c @@ -0,0 +1,84 @@ +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "mbtest.h" + +/* +output: +testing +testing mbrtowc1 +testing mbrtowc2 +testing mbtowc +done +end: +*/ + +#define NELEM(x) (sizeof(x)/sizeof(x[0])) + +void +tests_mbrtowc(void) +{ + struct mbtest *tp; + int r; + mbstate_t s; + + puts("testing mbrtowc1"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mbrtowc(tp->pwc, tp->s, tp->l, NULL); + assert(tp->r == r); + assert(tp->syserr == errno); + if (tp->r != -1) + assert(tp->wc == wc); + } + + puts("testing mbrtowc2"); + memset(&s, 0, sizeof(s)); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mbrtowc(tp->pwc, tp->s, tp->l, &s); + assert(tp->r == r); + assert(tp->syserr == errno); + if (tp->r != -1) + assert(tp->wc == wc); + assert(mbsinit(&s) != 0 == tp->mbstate); + } +} + +void +tests_mbtowc(void) +{ + struct mbtest *tp; + int r, rt; + + puts("testing mbtowc"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mbtowc(tp->pwc, tp->s, tp->l); + assert(tp->syserr == errno); + if (tp->r >= 0) { + rt = tp->r; + assert(tp->wc == wc); + } else { + rt = -1; + } + assert(rt == r); + } +} + +int +main() +{ + puts("testing"); + tests_mbrtowc(); + tests_mbtowc(); + puts("done"); + return 0; +} diff --git a/tests/libc/execute/0040-wcrtomb.c b/tests/libc/execute/0040-wcrtomb.c @@ -0,0 +1,102 @@ +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +/* +output: +testing +testing wcrtomb1 +testing wcrtomb2 +testing wctomb +done +end: +*/ + +#define NELEM(x) (sizeof(x)/sizeof(x[0])) + +static char str[MB_CUR_MAX+1]; + +static struct wctest { + wchar_t wc; + char *s; + char exp[MB_CUR_MAX+1]; + int r; + int syserr; + int mbstate; +} tests[] = { + {0, NULL, "", 1, 0, 1}, + {0, str, "\0", 1, 0, 1}, + {0x21, str, "\x21", 1, 0, 1}, + {0x00A1, str, "\xc2\xa1", 2, 0, 1}, + {0x2014, str, "\xe2\x80\x94", 3, 0, 1}, + {0x01F4A9, str, "\xf0\x9f\x92\xa9", 4, 0, 1}, + + {0xd800, str, "", -1, EILSEQ, 1}, + {0xDCFF, str, "", -1, EILSEQ, 1}, + {0xDD00, str, "\xed\xb4\x80", 3, 0, 1}, + {0x10ffff, str, "\xf4\x8f\xbf\xbf", 4, 0, 1}, + {0x110000, str, "", -1, EILSEQ, 1}, +}; + +void +tests_wcrtomb(void) +{ + struct wctest *tp; + int r; + mbstate_t s; + + puts("testing wcrtomb1"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + memset(str, 0, MB_CUR_MAX+1); + errno = 0; + r = wcrtomb(tp->s, tp->wc, NULL); + assert(tp->r == r); + assert(tp->syserr == errno); + if (tp->s && tp->r != -1) + assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1)); + } + + puts("testing wcrtomb2"); + memset(&s, 0, sizeof(s)); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + memset(str, 0, MB_CUR_MAX+1); + errno = 0; + r = wcrtomb(tp->s, tp->wc, &s); + assert(tp->r == r); + assert(tp->syserr == errno); + if (tp->s && tp->r != -1) + assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1)); + assert(mbsinit(&s) != 0 == tp->mbstate); + } +} + +void +tests_wctomb(void) +{ + struct wctest *tp; + int r; + + puts("testing wctomb"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + memset(str, 0, MB_CUR_MAX+1); + errno = 0; + r = wctomb(tp->s, tp->wc); + assert(tp->r == r); + assert(tp->syserr == errno); + if (tp->s && tp->r != -1) + assert(!memcmp(tp->s, tp->exp, MB_CUR_MAX+1)); + } +} + +int +main(void) +{ + puts("testing"); + tests_wcrtomb(); + tests_wctomb(); + puts("done"); + return 0; +} diff --git a/tests/libc/execute/0041-mbrlen.c b/tests/libc/execute/0041-mbrlen.c @@ -0,0 +1,75 @@ +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "mbtest.h" + +/* +output: +testing +testing mbrlen1 +testing mbrlen2 +testing mblen +done +end: +*/ + +#define NELEM(x) (sizeof(x)/sizeof(x[0])) + +void +tests_mbrlen(void) +{ + struct mbtest *tp; + int r; + mbstate_t s; + + puts("testing mbrlen1"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mbrlen(tp->s, tp->l, NULL); + assert(tp->r == r); + assert(tp->syserr == errno); + } + + puts("testing mbrlen2"); + memset(&s, 0, sizeof(s)); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mbrlen(tp->s, tp->l, &s); + assert(tp->r == r); + assert(tp->syserr == errno); + assert(mbsinit(&s) != 0 == tp->mbstate); + } +} + +void +tests_mblen(void) +{ + struct mbtest *tp; + int r, rt; + + puts("testing mblen"); + for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) { + wc = -1; + errno = 0; + r = mblen(tp->s, tp->l); + assert(tp->syserr == errno); + rt = (tp->r >= 0) ? tp->r : -1; + assert(rt == r); + } +} + +int +main() +{ + puts("testing"); + tests_mbrlen(); + tests_mblen(); + puts("done"); + return 0; +} 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; +} diff --git a/tests/libc/execute/0044-wcslen.c b/tests/libc/execute/0044-wcslen.c @@ -0,0 +1,28 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +/* +output: +testing +done +end: +*/ + +int +main(void) +{ + wchar_t t1[] = {0, 0}; + wchar_t t2[] = {0}; + wchar_t t3[] = {0x31, 0}; + wchar_t t4[] = {0x31, 0x32, 0, 0x33, 0}; + + puts("testing"); + assert(wcslen(t1) == 0); + assert(wcslen(t2) == 0); + assert(wcslen(t3) == 1); + assert(wcslen(t4) == 2); + puts("done"); + + return 0; +} diff --git a/tests/libc/execute/0045-wcscmp.c b/tests/libc/execute/0045-wcscmp.c @@ -0,0 +1,36 @@ +#include <assert.h> +#include <stdio.h> +#include <wchar.h> + +/* +output: +testing +done +end: +*/ + +int +main(void) +{ + wchar_t t1[] = {0}; + wchar_t t2[] = {0}; + wchar_t t3[] = {0x31, 0}; + wchar_t t4[] = {0x31, 0}; + wchar_t t5[] = {0x31, 0x32, 0}; + wchar_t t6[] = {0, 0x31, 0}; + + puts("testing"); + assert(wcscmp(t1, t1) == 0); + assert(wcscmp(t1, t2) == 0); + assert(wcscmp(t1, t3) < 0); + assert(wcscmp(t3, t1) > 0); + assert(wcscmp(t3, t3) == 0); + assert(wcscmp(t3, t4) == 0); + assert(wcscmp(t3, t5) < 0); + assert(wcscmp(t5, t3) > 0); + assert(wcscmp(t3, t6) > 0); + assert(wcscmp(t6, t3) < 0); + puts("done"); + + return 0; +} diff --git a/tests/libc/execute/0046-wcsncmp.c b/tests/libc/execute/0046-wcsncmp.c @@ -0,0 +1,30 @@ +#include <assert.h> +#include <stdio.h> +#include <wchar.h> + +/* +output: +testing +done +end: +*/ + +int +main(void) +{ + wchar_t t1[] = {0}; + wchar_t t2[] = {0}; + wchar_t t3[] = {0x31, 0}; + wchar_t t4[] = {0x31, 0}; + wchar_t t5[] = {0x32, 0x33, 0}; + + puts("testing"); + assert(wcsncmp(t1, t1, 0) == 0); + assert(wcsncmp(t1, t2, 0) == 0); + assert(wcsncmp(t3, t4, 1) == 0); + assert(wcsncmp(t3, t5, 1) < 0); + assert(wcsncmp(t5, t3, 1) > 0); + puts("done"); + + return 0; +} diff --git a/tests/libc/execute/0047-wcscoll.c b/tests/libc/execute/0047-wcscoll.c @@ -0,0 +1,36 @@ +#include <assert.h> +#include <stdio.h> +#include <wchar.h> + +/* +output: +testing +done +end: +*/ + +int +main(void) +{ + wchar_t t1[] = {0}; + wchar_t t2[] = {0}; + wchar_t t3[] = {0x31, 0}; + wchar_t t4[] = {0x31, 0}; + wchar_t t5[] = {0x31, 0x32, 0}; + wchar_t t6[] = {0, 0x31, 0}; + + puts("testing"); + assert(wcscoll(t1, t1) == 0); + assert(wcscoll(t1, t2) == 0); + assert(wcscoll(t1, t3) < 0); + assert(wcscoll(t3, t1) > 0); + assert(wcscoll(t3, t3) == 0); + assert(wcscoll(t3, t4) == 0); + assert(wcscoll(t3, t5) < 0); + assert(wcscoll(t5, t3) > 0); + assert(wcscoll(t3, t6) > 0); + assert(wcscoll(t6, t3) < 0); + puts("done"); + + return 0; +} diff --git a/tests/libc/execute/0048-wcscpy.c b/tests/libc/execute/0048-wcscpy.c @@ -0,0 +1,31 @@ +#include <assert.h> +#include <stdio.h> +#include <wchar.h> + +/* +output: +testing +done +end: +*/ + +int +main() +{ + wchar_t test[]= {'t', 'e', 's', 't', 0}; + wchar_t *s, buf[40]; + + puts("testing"); + + s = wcscpy(buf, test); + assert(s == buf); + assert(!wcscmp(s, test)); + + s = wcscpy(buf, ""); + assert(s == buf); + assert(!wcscmp(s, "")); + + puts("done"); + + return 0; +} +\ No newline at end of file diff --git a/tests/libc/execute/libc-tests.lst b/tests/libc/execute/libc-tests.lst @@ -34,3 +34,13 @@ 0035-setlocale 0036-localeconv 0037-malloc [TODO] +0038-mbsinit +0039-mbrtowc +0040-wcrtomb +0041-mbrlen +0042-mbsrtowcs +0044-wcslen +0045-wcscmp +0046-wcsncmp +0047-wcscoll +0048-wcscpy diff --git a/tests/libc/execute/mbtest.h b/tests/libc/execute/mbtest.h @@ -0,0 +1,44 @@ +static wchar_t wc; +static struct mbtest { + char *s; + int l; + int r; + int mbstate; + int syserr; + wchar_t *pwc; + wchar_t wc; +} tests[] = { + {"\0", 2, 0, 1, 0, &wc, 0}, + {"\x21", 2, 1, 1, 0, &wc, 0x21}, + {"\xc2\xa1", 3, 2, 1, 0, &wc, 0x00A1}, + {"\xc2\xa1", 2, 2, 1, 0, &wc, 0x00A1}, + {"\xe2\x80\x94", 4, 3, 1, 0, &wc, 0x2014}, + {"\xf0\x9f\x92\xa9", 5, 4, 1, 0, &wc, 0x01F4A9}, + {"\xf0\x9f\x92\xa9", 5, 4, 1, 0, NULL, -1}, + {"\xf0\x9f\x92\xa9", -1, 4, 1, 0, &wc, 0x01F4A9}, + + {NULL, 4, 0, 1, 0, NULL, -1}, + {"\xed\x9f\xbf", 4, 3, 1, 0, &wc, 0xd7ff}, + {"\xed\xa0\x80", 4, -1, 1, EILSEQ, &wc, -1}, + {"\xed\xb3\xbf", 4, -1, 1, EILSEQ, &wc, -1}, + {"\xed\xb4\x80", 4, 3, 1, 0, &wc, 0xdd00}, + + {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1}, + {"\xa9", 2, 1, 1, 0, &wc, 0x01F4A9}, + {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1}, + {NULL, 4, -1, 1, EILSEQ, &wc, -1}, + {"\xa9", 2, -1, 1, EILSEQ, &wc, -1}, + {"\xf0\x9f\x92\xa9", 3, -2, 0, 0, &wc, -1}, + {NULL, 4, -1, 1, EILSEQ, &wc, -1}, + {"\x21", 2, 1, 1, 0, &wc, 0x21}, + {"\xf0\x9f\x92\xa9", 2, -2, 0, 0, &wc, -1}, + {"\xf0\x9f\x92\xa9", 0, -2, 0, 0, &wc, -1}, + {"\x92\xa9", 2, 2, 1, 0, &wc, 0x01F4A9}, + + {"\x80", 2, -1, 1, EILSEQ, &wc, -1}, + {"\xc0\x80", 2, -1, 1, EILSEQ, &wc, -1}, + {"\xc0\x00", 2, -1, 1, EILSEQ, &wc, -1}, + {"\xc1\x81", 2, -1, 1, EILSEQ, &wc, -1}, + {"\xf8\x81\x82\x83\x84\x85", -1, -1, 1, EILSEQ, &wc, -1}, + {"\xfe\x81\x82\x83\x84\x85\x86", 8, -1, 1, EILSEQ, &wc, -1}, +}; diff --git a/tests/make/execute/0107-inference.sh b/tests/make/execute/0107-inference.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +trap 'rm -f $tmp1 $tmp2 f f.?' EXIT INT TERM QUIT HUP + +tmp1=tmp1.$$ +tmp2=tmp2.$$ + +cat >$tmp1 <<EOF +c99 -O -o f f.c +EOF + +cat >f.c <<'EOF' +int +main(void) +{ + return 0; +} +EOF + +touch -d '1970-01-01 00:00:01' f.h +touch -d '1970-01-01 00:00:03' f +touch -d '1970-01-01 00:00:04' f.c + +scc make -f- <<'EOF' > $tmp2 2>&1 +f: f.h + +f.h: + touch $@ +EOF + +diff $tmp1 $tmp2