struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / support / regression / tests / wchar.c.in
blob6145737d763f38d44dce477f9d0e2272081f131f
1 /* Tests wide character conversion functions.
2 test: wcharnorestart, wcharstringnorestart, wcharrestart, char16restart, char32restart
3 */
4 #include <testfwk.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <limits.h>
9 #include <string.h>
10 #include <errno.h>
11 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L
12 #include <wchar.h>
13 #endif
14 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
15 #if defined(__APPLE__) || defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
16 // Work around Apple's missing uchar.h
17 #include <stdint.h>
18 typedef int_least16_t char16_t;
19 typedef int_least32_t char32_t;
20 #else
21 #include <uchar.h> // For char16_t, char32_t
22 #endif
23 #endif
25 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
26 #include <stdint.h>
27 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
28 #ifdef __SDCC
29 _Static_assert(!WCHAR_MIN, "nonzero WCHAR_MIN");
30 _Static_assert(WEOF <= WINT_MAX, "WEOF out of wint_t range");
31 #endif
32 #endif
33 #endif
35 #define TEST_{test}
37 #ifdef TEST_wcharnorestart
38 static void
39 wcharnorestart(void)
41 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L && !defined(__SDCC_pdk14) // Not enough memory
42 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
43 wchar_t w;
44 char c[MB_LEN_MAX];
46 c[0] = 'C';
47 ASSERT(mbtowc(&w, c, 1) == 1);
48 ASSERT(wctomb(c, w) == 1);
49 ASSERT(c[0] == 'C');
50 ASSERT(wctob(btowc('C')) == 'C');
51 ASSERT(btowc(EOF) == WEOF);
52 ASSERT(wctob(WEOF) == EOF);
54 ASSERT(wctomb(c, L'W') == 1);
55 ASSERT(c[0] == 'W');
56 #ifdef __STDC_ISO_10646__
57 ASSERT(wctomb(c, 0x110000) == -1); // Invalid: Out of 21-bit Unicode range.
58 ASSERT(wctomb(c, 0xd800) == -1); // Invalid: Unpaired UTF-16 surrogate.
59 ASSERT(wctomb(c, 0xdfff) == -1); // Invalid: Unpaired UTF-16 surrogate.
60 #endif
61 #endif
62 #endif
64 #endif
66 #ifdef TEST_wcharstringnorestart
67 static void
68 wcharstringnorestart(void)
70 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L && !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Not enough memory
71 wchar_t wcs1[5] = L"Test";
72 wchar_t wcs2[5];
73 char mbs[5 * MB_LEN_MAX];
75 // Test basic functionality
76 ASSERT(wcslen (wcs1) == 4);
77 ASSERT(wcstombs(mbs, wcs1, 5 * MB_LEN_MAX) > 0);
78 ASSERT(mbstowcs(wcs2, mbs, 5) > 0);
79 ASSERT(wcs1[3] == L't');
80 ASSERT(wcs2[3] == L't');
81 ASSERT(!wcscmp(wcs1, wcs2));
83 // glibc with _FORTIFY_SOURCE == 2 is not standard-compliant (and fails the tests below)
84 // However, Ubuntu decided to make _FORTIFY_SOURCE = 2 the default for GCC.
85 // Ubuntu 24.04 LTS changed this to _FORTIFY_SOURCE = 3 when optimization is enabled
86 // https://bugs.launchpad.net/ubuntu/+source/gcc-13/+bug/2012440
87 #if !(defined(__GNUC__) && (_FORTIFY_SOURCE == 2 || _FORTIFY_SOURCE == 3))
88 // Test for 0-terminated strings
89 ASSERT(wcstombs(mbs, wcs1, 1000) > 0);
90 ASSERT(mbstowcs(wcs2, mbs, 1000) > 0);
91 ASSERT(!wcscmp(wcs1, wcs2));
92 #endif
94 // Test for unterminated strings
95 mbs[2] = 0;
96 wcs2[2] = 0;
97 ASSERT(wcstombs(mbs, wcs1, 2) == 2);
98 ASSERT(!strcmp("Te", mbs));
99 ASSERT(mbstowcs(wcs2, mbs, 2) == 2);
100 ASSERT(!wcscmp(L"Te", wcs2));
101 #endif
103 #endif
105 #ifdef TEST_wcharrestart
106 static void
107 wcharrestart(void)
109 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
110 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
111 static mbstate_t ps;
112 wchar_t w;
113 char c[MB_LEN_MAX];
115 c[0] = 'C';
116 ASSERT(mbrtowc(&w, c, 1, &ps) == 1);
117 ASSERT(w == (L"C")[0]);
118 ASSERT(wcrtomb(c, w, &ps) == 1);
119 ASSERT(c[0] == 'C');
120 ASSERT(mbrtowc(&w, c, 1, &ps) == mbrlen(c, 1, &ps));
121 #ifdef __STDC_ISO_10646__
122 errno = 0;
123 ASSERT(wcrtomb(c, 0x110000, 0) == -1); // Invalid: Out of 21-bit Unicode range.
124 ASSERT(errno == EILSEQ);
125 ASSERT(wcrtomb(c, 0xd800, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
126 ASSERT(wcrtomb(c, 0xdfff, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
127 #endif
128 #endif
129 #endif
131 #endif
133 #ifdef TEST_char16restart
134 static void
135 char16restart(void)
137 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
138 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !(defined(__SDCC_mcs51) && defined(__SDCC_MODEL_SMALL))
139 #if !defined(__APPLE__) && !defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
140 #if !defined(__FreeBSD__) || __FreeBSD_version >= 1302000 // Known FreeBSD 13.2 bug #272758.
141 static mbstate_t ps;
142 char16_t c16[3];
143 char c[MB_LEN_MAX];
145 c[0] = 'C';
146 ASSERT(mbrtoc16(c16, c, 1, &ps) == 1);
147 c[1] = 0;
148 ASSERT(mbrtoc16(c16 + 1, c + 1, 1, &ps) == 0); // Also puts ps back into the initial conversion state.
149 ASSERT(c16[0] == (u"C")[0]);
150 ASSERT(c16rtomb(c, c16[0], &ps) == 1);
151 ASSERT(c[0] == 'C');
153 ASSERT(c16rtomb(0, c16[0], 0) == 1);
155 #ifdef __STDC_UTF_16__
156 ASSERT(c16rtomb(c, 0xdc00, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
157 ASSERT(errno == EILSEQ);
159 errno = 0;
160 ASSERT(c16rtomb(c, u'\0', 0) == 1); // Converting a 0 character resets internal state.
162 #ifdef __SDCC // The standard was defective (fixed in C2X). SDCC always behaves according to the fixed standard.
163 ASSERT(c16rtomb(c, 0xd800, 0) == 0);
164 ASSERT(c16rtomb(c, 0xd800, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
166 ASSERT(errno == EILSEQ);
167 errno = 0;
168 ASSERT(c16rtomb(c, u'\0', 0) == 1); // Converting a 0 character resets internal state.
169 #endif
170 #endif
171 #endif
172 #endif
173 #endif
174 #endif
176 #endif
178 #ifdef TEST_char32restart
179 static void
180 char32restart(void)
182 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
183 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
184 #if !defined(__APPLE__) && !defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
185 #if !defined(__FreeBSD__) || __FreeBSD_version >= 1302000 // Known FreeBSD 13.2 bug #272758.
186 static mbstate_t ps;
187 char32_t c32[3];
188 char c[MB_LEN_MAX];
190 c[0] = 'C';
191 ASSERT(mbrtoc32(c32, c, 1, &ps) == 1);
192 c[1] = 0;
193 ASSERT(mbrtoc32(c32 + 1, c + 1, 1, &ps) == 0); // Also puts ps back into the initial conversion state.
194 ASSERT(c32[0] == (U"C")[0]);
195 ASSERT(c32rtomb(c, c32[0], &ps) == 1);
196 ASSERT(c[0] == 'C');
197 #endif
198 #endif
199 #endif
200 #endif
202 #endif
204 static void
205 testwchar(void)
207 {test}();