1#include <stdio.h>
2#include <string.h>
3#include <wchar.h>
4#include <stdlib.h>
5#include <locale.h>
6#include <langinfo.h>
7#include "test.h"
8
9/*
10 * f = function call to test (or any expression)
11 * x = expected result
12 * m = message to print on failure
13 */
14#define T(f, x, m) (void)( \
15	memset(&st, 0, sizeof st), \
16	(i = (f)) == (x) || \
17		t_error("%s failed (%s) got %d want %d\n", #f, m, i, x) )
18#define TCHAR(f, x, m) (void)( \
19	memset(&st, 0, sizeof st), \
20	(i = (f)) == (x) || \
21		t_error("%s failed (%s) got 0x%04x want 0x%04x\n", #f, m, i, x) )
22
23int main(void)
24{
25	const char *cs;
26	int i;
27	mbstate_t st, st2;
28	wchar_t wc, wcs[32];
29
30	(void)(
31	setlocale(LC_CTYPE, "en_US.UTF-8") ||
32	setlocale(LC_CTYPE, "en_GB.UTF-8") ||
33	setlocale(LC_CTYPE, "en.UTF-8") ||
34	setlocale(LC_CTYPE, "POSIX.UTF-8") ||
35	setlocale(LC_CTYPE, "C.UTF-8") ||
36	setlocale(LC_CTYPE, "UTF-8") ||
37	setlocale(LC_CTYPE, "") );
38
39	T(mbsrtowcs(wcs, (cs="abcdef",&cs), 3, &st), 3, "wrong semantics for wcs buf len");
40	T(mbsrtowcs(wcs, (cs="abcdef",&cs), 8, &st), 6, "wrong semantics for wcs buf len");
41	T(mbsrtowcs(NULL, (cs="abcdef",&cs), 2, &st), 6, "wrong semantics for NULL wcs");
42
43	if (strcmp(nl_langinfo(CODESET), "UTF-8"))
44		return t_error("cannot set UTF-8 locale for test (codeset=%s)\n", nl_langinfo(CODESET));
45
46	T(mbrtowc(&wc, "\x80", 1, &st), -1, "failed to catch error");
47	T(mbrtowc(&wc, "\xc0", 1, &st), -1, "failed to catch illegal initial");
48
49	T(mbrtowc(&wc, "\xc0\x80", 2, &st), -1, "aliasing nul");
50	T(mbrtowc(&wc, "\xc0\xaf", 2, &st), -1, "aliasing slash");
51	T(mbrtowc(&wc, "\xe0\x80\xaf", 3, &st), -1, "aliasing slash");
52	T(mbrtowc(&wc, "\xf0\x80\x80\xaf", 4, &st), -1, "aliasing slash");
53	T(mbrtowc(&wc, "\xf8\x80\x80\x80\xaf", 5, &st), -1, "aliasing slash");
54	T(mbrtowc(&wc, "\xfc\x80\x80\x80\x80\xaf", 6, &st), -1, "aliasing slash");
55	T(mbrtowc(&wc, "\xe0\x82\x80", 3, &st), -1, "aliasing U+0080");
56	T(mbrtowc(&wc, "\xe0\x9f\xbf", 3, &st), -1, "aliasing U+07FF");
57	T(mbrtowc(&wc, "\xf0\x80\xa0\x80", 4, &st), -1, "aliasing U+0800");
58	T(mbrtowc(&wc, "\xf0\x8f\xbf\xbd", 4, &st), -1, "aliasing U+FFFD");
59
60	T(mbrtowc(&wc, "\xed\xa0\x80", 3, &st), -1, "failed to catch surrogate");
61	T(mbrtowc(&wc, "\xef\xbf\xbe", 3, &st), 3, "failed to accept U+FFFE");
62	T(mbrtowc(&wc, "\xef\xbf\xbf", 3, &st), 3, "failed to accept U+FFFF");
63	T(mbrtowc(&wc, "\xf4\x8f\xbf\xbe", 4, &st), 4, "failed to accept U+10FFFE");
64	T(mbrtowc(&wc, "\xf4\x8f\xbf\xbf", 4, &st), 4, "failed to accept U+10FFFF");
65
66	T(mbrtowc(&wc, "\xc2\x80", 2, &st), 2, "wrong length");
67	TCHAR((mbrtowc(&wc, "\xc2\x80", 2, &st),wc), 0x80, "wrong char");
68	T(mbrtowc(&wc, "\xe0\xa0\x80", 3, &st), 3, "wrong length");
69	TCHAR((mbrtowc(&wc, "\xe0\xa0\x80", 3, &st),wc), 0x800, "wrong char");
70	T(mbrtowc(&wc, "\xf0\x90\x80\x80", 4, &st), 4, "wrong length");
71	TCHAR((mbrtowc(&wc, "\xf0\x90\x80\x80", 4, &st),wc), 0x10000, "wrong char");
72
73	memset(&st2, 0, sizeof st2);
74	T(mbrtowc(&wc, "\xc2", 1, &st2), -2, "failed to accept initial byte");
75	T(mbrtowc(&wc, "\x80", 1, &st2), 1, "failed to resume");
76	TCHAR(wc, 0x80, "wrong char");
77
78	memset(&st2, 0, sizeof st2);
79	T(mbrtowc(&wc, "\xc2", 1, &st2), -2, "failed to accept initial byte");
80	T(mbsrtowcs(wcs, (cs="\xa0""abc",&cs), 32, &st2), 4, "failed to resume");
81	TCHAR(wcs[0], 0xa0, "wrong char");
82	TCHAR(wcs[1], 'a', "wrong char");
83	T(!cs, 1, "wrong final position");
84	return t_status;
85}
86