1 /* Test of conversion of wide character to multibyte character.
2 Copyright (C) 2008-2020 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
26 #include "localcharset.h"
29 #if defined _WIN32 && !defined __CYGWIN__
32 test_one_locale (const char *name
, int codepage
)
38 /* Portable code to set the locale. */
40 char name_with_codepage
[1024];
42 sprintf (name_with_codepage
, "%s.%d", name
, codepage
);
45 if (setlocale (LC_ALL
, name_with_codepage
) == NULL
)
49 /* Hacky way to set a locale.codepage combination that setlocale() refuses
52 /* Codepage of the current locale, set with setlocale().
53 Not necessarily the same as GetACP(). */
54 extern __declspec(dllimport
) unsigned int __lc_codepage
;
57 if (setlocale (LC_ALL
, name
) == NULL
)
60 /* Clobber the codepage and MB_CUR_MAX, both set by setlocale(). */
61 __lc_codepage
= codepage
;
79 /* Test whether the codepage is really available. */
84 memset (&state
, '\0', sizeof (mbstate_t));
85 if (mbrtowc (&wc
, " ", 1, &state
) == (size_t)(-1))
91 /* Test NUL character. */
94 ret
= c32rtomb (buf
, 0, NULL
);
96 ASSERT (buf
[0] == '\0');
99 /* Test single bytes. */
103 for (c
= 0; c
< 0x100; c
++)
106 case '\t': case '\v': case '\f':
107 case ' ': case '!': case '"': case '#': case '%':
108 case '&': case '\'': case '(': case ')': case '*':
109 case '+': case ',': case '-': case '.': case '/':
110 case '0': case '1': case '2': case '3': case '4':
111 case '5': case '6': case '7': case '8': case '9':
112 case ':': case ';': case '<': case '=': case '>':
114 case 'A': case 'B': case 'C': case 'D': case 'E':
115 case 'F': case 'G': case 'H': case 'I': case 'J':
116 case 'K': case 'L': case 'M': case 'N': case 'O':
117 case 'P': case 'Q': case 'R': case 'S': case 'T':
118 case 'U': case 'V': case 'W': case 'X': case 'Y':
120 case '[': case '\\': case ']': case '^': case '_':
121 case 'a': case 'b': case 'c': case 'd': case 'e':
122 case 'f': case 'g': case 'h': case 'i': case 'j':
123 case 'k': case 'l': case 'm': case 'n': case 'o':
124 case 'p': case 'q': case 'r': case 's': case 't':
125 case 'u': case 'v': case 'w': case 'x': case 'y':
126 case 'z': case '{': case '|': case '}': case '~':
127 /* c is in the ISO C "basic character set". */
128 ret
= c32rtomb (buf
, btoc32 (c
), NULL
);
130 ASSERT (buf
[0] == (char) c
);
135 /* Test special calling convention, passing a NULL pointer. */
137 ret
= c32rtomb (NULL
, '\0', NULL
);
139 ret
= c32rtomb (NULL
, btoc32 ('x'), NULL
);
146 /* Locale encoding is CP1252, an extension of ISO-8859-1. */
148 /* Convert "B\374\337er": "Büßer" */
149 memset (buf
, 'x', 8);
150 ret
= c32rtomb (buf
, 0x00FC, NULL
);
152 ASSERT (memcmp (buf
, "\374", 1) == 0);
153 ASSERT (buf
[1] == 'x');
155 memset (buf
, 'x', 8);
156 ret
= c32rtomb (buf
, 0x00DF, NULL
);
158 ASSERT (memcmp (buf
, "\337", 1) == 0);
159 ASSERT (buf
[1] == 'x');
164 /* Locale encoding is CP1256, not the same as ISO-8859-6. */
166 /* Convert "x\302\341\346y": "xآلوy" */
167 memset (buf
, 'x', 8);
168 ret
= c32rtomb (buf
, 0x0622, NULL
);
170 ASSERT (memcmp (buf
, "\302", 1) == 0);
171 ASSERT (buf
[1] == 'x');
173 memset (buf
, 'x', 8);
174 ret
= c32rtomb (buf
, 0x0644, NULL
);
176 ASSERT (memcmp (buf
, "\341", 1) == 0);
177 ASSERT (buf
[1] == 'x');
179 memset (buf
, 'x', 8);
180 ret
= c32rtomb (buf
, 0x0648, NULL
);
182 ASSERT (memcmp (buf
, "\346", 1) == 0);
183 ASSERT (buf
[1] == 'x');
188 /* Locale encoding is CP932, similar to Shift_JIS. */
190 /* Convert "<\223\372\226\173\214\352>": "<日本語>" */
191 memset (buf
, 'x', 8);
192 ret
= c32rtomb (buf
, 0x65E5, NULL
);
194 ASSERT (memcmp (buf
, "\223\372", 2) == 0);
195 ASSERT (buf
[2] == 'x');
197 memset (buf
, 'x', 8);
198 ret
= c32rtomb (buf
, 0x672C, NULL
);
200 ASSERT (memcmp (buf
, "\226\173", 2) == 0);
201 ASSERT (buf
[2] == 'x');
203 memset (buf
, 'x', 8);
204 ret
= c32rtomb (buf
, 0x8A9E, NULL
);
206 ASSERT (memcmp (buf
, "\214\352", 2) == 0);
207 ASSERT (buf
[2] == 'x');
212 /* Locale encoding is CP950, similar to Big5. */
214 /* Convert "<\244\351\245\273\273\171>": "<日本語>" */
215 memset (buf
, 'x', 8);
216 ret
= c32rtomb (buf
, 0x65E5, NULL
);
218 ASSERT (memcmp (buf
, "\244\351", 2) == 0);
219 ASSERT (buf
[2] == 'x');
221 memset (buf
, 'x', 8);
222 ret
= c32rtomb (buf
, 0x672C, NULL
);
224 ASSERT (memcmp (buf
, "\245\273", 2) == 0);
225 ASSERT (buf
[2] == 'x');
227 memset (buf
, 'x', 8);
228 ret
= c32rtomb (buf
, 0x8A9E, NULL
);
230 ASSERT (memcmp (buf
, "\273\171", 2) == 0);
231 ASSERT (buf
[2] == 'x');
236 /* Locale encoding is CP936 = GBK, an extension of GB2312. */
238 /* Convert "<\310\325\261\276\325\132>": "<日本語>" */
239 memset (buf
, 'x', 8);
240 ret
= c32rtomb (buf
, 0x65E5, NULL
);
242 ASSERT (memcmp (buf
, "\310\325", 2) == 0);
243 ASSERT (buf
[2] == 'x');
245 memset (buf
, 'x', 8);
246 ret
= c32rtomb (buf
, 0x672C, NULL
);
248 ASSERT (memcmp (buf
, "\261\276", 2) == 0);
249 ASSERT (buf
[2] == 'x');
251 memset (buf
, 'x', 8);
252 ret
= c32rtomb (buf
, 0x8A9E, NULL
);
254 ASSERT (memcmp (buf
, "\325\132", 2) == 0);
255 ASSERT (buf
[2] == 'x');
260 /* Locale encoding is CP54936 = GB18030. */
261 if (strcmp (locale_charset (), "GB18030") != 0)
264 /* Convert "s\250\271\201\060\211\070\224\071\375\067!"; "süß😋!" */
265 memset (buf
, 'x', 8);
266 ret
= c32rtomb (buf
, 0x00FC, NULL
);
268 ASSERT (memcmp (buf
, "\250\271", 2) == 0);
269 ASSERT (buf
[2] == 'x');
271 memset (buf
, 'x', 8);
272 ret
= c32rtomb (buf
, 0x00DF, NULL
);
274 ASSERT (memcmp (buf
, "\201\060\211\070", 4) == 0);
275 ASSERT (buf
[4] == 'x');
277 memset (buf
, 'x', 8);
278 ret
= c32rtomb (buf
, 0x1F60B, NULL
);
280 ASSERT (memcmp (buf
, "\224\071\375\067", 4) == 0);
281 ASSERT (buf
[4] == 'x');
286 /* Locale encoding is CP65001 = UTF-8. */
287 if (strcmp (locale_charset (), "UTF-8") != 0)
290 /* Convert "s\303\274\303\237\360\237\230\213!"; "süß😋!" */
291 memset (buf
, 'x', 8);
292 ret
= c32rtomb (buf
, 0x00FC, NULL
);
294 ASSERT (memcmp (buf
, "\303\274", 2) == 0);
295 ASSERT (buf
[2] == 'x');
297 memset (buf
, 'x', 8);
298 ret
= c32rtomb (buf
, 0x00DF, NULL
);
300 ASSERT (memcmp (buf
, "\303\237", 2) == 0);
301 ASSERT (buf
[2] == 'x');
303 memset (buf
, 'x', 8);
304 ret
= c32rtomb (buf
, 0x1F60B, NULL
);
306 ASSERT (memcmp (buf
, "\360\237\230\213", 4) == 0);
307 ASSERT (buf
[4] == 'x');
317 main (int argc
, char *argv
[])
319 int codepage
= atoi (argv
[argc
- 1]);
324 for (i
= 1; i
< argc
- 1; i
++)
326 int ret
= test_one_locale (argv
[i
], codepage
);
334 fprintf (stderr
, "Skipping test: found no locale with codepage %d\n",
343 main (int argc
, char *argv
[])
345 fputs ("Skipping test: not a native Windows system\n", stderr
);