Branch data Line data Source code
1 : : /* Test of conversion of wide character to multibyte character.
2 : : Copyright (C) 2008-2012 Free Software Foundation, Inc.
3 : :
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.
8 : :
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.
13 : :
14 : : You should have received a copy of the GNU General Public License
15 : : along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 : :
17 : : #include <config.h>
18 : :
19 : : #include <wchar.h>
20 : :
21 : : #include <locale.h>
22 : : #include <stdio.h>
23 : : #include <stdlib.h>
24 : : #include <string.h>
25 : :
26 : : #include "macros.h"
27 : :
28 : : #if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
29 : :
30 : : static int
31 : : test_one_locale (const char *name, int codepage)
32 : : {
33 : : char buf[64];
34 : : size_t ret;
35 : :
36 : : # if 1
37 : : /* Portable code to set the locale. */
38 : : {
39 : : char name_with_codepage[1024];
40 : :
41 : : sprintf (name_with_codepage, "%s.%d", name, codepage);
42 : :
43 : : /* Set the locale. */
44 : : if (setlocale (LC_ALL, name_with_codepage) == NULL)
45 : : return 77;
46 : : }
47 : : # else
48 : : /* Hacky way to set a locale.codepage combination that setlocale() refuses
49 : : to set. */
50 : : {
51 : : /* Codepage of the current locale, set with setlocale().
52 : : Not necessarily the same as GetACP(). */
53 : : extern __declspec(dllimport) unsigned int __lc_codepage;
54 : :
55 : : /* Set the locale. */
56 : : if (setlocale (LC_ALL, name) == NULL)
57 : : return 77;
58 : :
59 : : /* Clobber the codepage and MB_CUR_MAX, both set by setlocale(). */
60 : : __lc_codepage = codepage;
61 : : switch (codepage)
62 : : {
63 : : case 1252:
64 : : case 1256:
65 : : MB_CUR_MAX = 1;
66 : : break;
67 : : case 932:
68 : : case 950:
69 : : case 936:
70 : : MB_CUR_MAX = 2;
71 : : break;
72 : : case 54936:
73 : : case 65001:
74 : : MB_CUR_MAX = 4;
75 : : break;
76 : : }
77 : :
78 : : /* Test whether the codepage is really available. */
79 : : {
80 : : mbstate_t state;
81 : : wchar_t wc;
82 : :
83 : : memset (&state, '\0', sizeof (mbstate_t));
84 : : if (mbrtowc (&wc, " ", 1, &state) == (size_t)(-1))
85 : : return 77;
86 : : }
87 : : }
88 : : # endif
89 : :
90 : : /* Test NUL character. */
91 : : {
92 : : buf[0] = 'x';
93 : : ret = wcrtomb (buf, 0, NULL);
94 : : ASSERT (ret == 1);
95 : : ASSERT (buf[0] == '\0');
96 : : }
97 : :
98 : : /* Test single bytes. */
99 : : {
100 : : int c;
101 : :
102 : : for (c = 0; c < 0x100; c++)
103 : : switch (c)
104 : : {
105 : : case '\t': case '\v': case '\f':
106 : : case ' ': case '!': case '"': case '#': case '%':
107 : : case '&': case '\'': case '(': case ')': case '*':
108 : : case '+': case ',': case '-': case '.': case '/':
109 : : case '0': case '1': case '2': case '3': case '4':
110 : : case '5': case '6': case '7': case '8': case '9':
111 : : case ':': case ';': case '<': case '=': case '>':
112 : : case '?':
113 : : case 'A': case 'B': case 'C': case 'D': case 'E':
114 : : case 'F': case 'G': case 'H': case 'I': case 'J':
115 : : case 'K': case 'L': case 'M': case 'N': case 'O':
116 : : case 'P': case 'Q': case 'R': case 'S': case 'T':
117 : : case 'U': case 'V': case 'W': case 'X': case 'Y':
118 : : case 'Z':
119 : : case '[': case '\\': case ']': case '^': case '_':
120 : : case 'a': case 'b': case 'c': case 'd': case 'e':
121 : : case 'f': case 'g': case 'h': case 'i': case 'j':
122 : : case 'k': case 'l': case 'm': case 'n': case 'o':
123 : : case 'p': case 'q': case 'r': case 's': case 't':
124 : : case 'u': case 'v': case 'w': case 'x': case 'y':
125 : : case 'z': case '{': case '|': case '}': case '~':
126 : : /* c is in the ISO C "basic character set". */
127 : : ret = wcrtomb (buf, btowc (c), NULL);
128 : : ASSERT (ret == 1);
129 : : ASSERT (buf[0] == (char) c);
130 : : break;
131 : : }
132 : : }
133 : :
134 : : /* Test special calling convention, passing a NULL pointer. */
135 : : {
136 : : ret = wcrtomb (NULL, '\0', NULL);
137 : : ASSERT (ret == 1);
138 : : ret = wcrtomb (NULL, btowc ('x'), NULL);
139 : : ASSERT (ret == 1);
140 : : }
141 : :
142 : : switch (codepage)
143 : : {
144 : : case 1252:
145 : : /* Locale encoding is CP1252, an extension of ISO-8859-1. */
146 : : {
147 : : /* Convert "B\374\337er": "Büßer" */
148 : : memset (buf, 'x', 8);
149 : : ret = wcrtomb (buf, 0x00FC, NULL);
150 : : ASSERT (ret == 1);
151 : : ASSERT (memcmp (buf, "\374", 1) == 0);
152 : : ASSERT (buf[1] == 'x');
153 : :
154 : : memset (buf, 'x', 8);
155 : : ret = wcrtomb (buf, 0x00DF, NULL);
156 : : ASSERT (ret == 1);
157 : : ASSERT (memcmp (buf, "\337", 1) == 0);
158 : : ASSERT (buf[1] == 'x');
159 : : }
160 : : return 0;
161 : :
162 : : case 1256:
163 : : /* Locale encoding is CP1256, not the same as ISO-8859-6. */
164 : : {
165 : : /* Convert "x\302\341\346y": "xآلوy" */
166 : : memset (buf, 'x', 8);
167 : : ret = wcrtomb (buf, 0x0622, NULL);
168 : : ASSERT (ret == 1);
169 : : ASSERT (memcmp (buf, "\302", 1) == 0);
170 : : ASSERT (buf[1] == 'x');
171 : :
172 : : memset (buf, 'x', 8);
173 : : ret = wcrtomb (buf, 0x0644, NULL);
174 : : ASSERT (ret == 1);
175 : : ASSERT (memcmp (buf, "\341", 1) == 0);
176 : : ASSERT (buf[1] == 'x');
177 : :
178 : : memset (buf, 'x', 8);
179 : : ret = wcrtomb (buf, 0x0648, NULL);
180 : : ASSERT (ret == 1);
181 : : ASSERT (memcmp (buf, "\346", 1) == 0);
182 : : ASSERT (buf[1] == 'x');
183 : : }
184 : : return 0;
185 : :
186 : : case 932:
187 : : /* Locale encoding is CP932, similar to Shift_JIS. */
188 : : {
189 : : /* Convert "<\223\372\226\173\214\352>": "<日本語>" */
190 : : memset (buf, 'x', 8);
191 : : ret = wcrtomb (buf, 0x65E5, NULL);
192 : : ASSERT (ret == 2);
193 : : ASSERT (memcmp (buf, "\223\372", 2) == 0);
194 : : ASSERT (buf[2] == 'x');
195 : :
196 : : memset (buf, 'x', 8);
197 : : ret = wcrtomb (buf, 0x672C, NULL);
198 : : ASSERT (ret == 2);
199 : : ASSERT (memcmp (buf, "\226\173", 2) == 0);
200 : : ASSERT (buf[2] == 'x');
201 : :
202 : : memset (buf, 'x', 8);
203 : : ret = wcrtomb (buf, 0x8A9E, NULL);
204 : : ASSERT (ret == 2);
205 : : ASSERT (memcmp (buf, "\214\352", 2) == 0);
206 : : ASSERT (buf[2] == 'x');
207 : : }
208 : : return 0;
209 : :
210 : : case 950:
211 : : /* Locale encoding is CP950, similar to Big5. */
212 : : {
213 : : /* Convert "<\244\351\245\273\273\171>": "<日本語>" */
214 : : memset (buf, 'x', 8);
215 : : ret = wcrtomb (buf, 0x65E5, NULL);
216 : : ASSERT (ret == 2);
217 : : ASSERT (memcmp (buf, "\244\351", 2) == 0);
218 : : ASSERT (buf[2] == 'x');
219 : :
220 : : memset (buf, 'x', 8);
221 : : ret = wcrtomb (buf, 0x672C, NULL);
222 : : ASSERT (ret == 2);
223 : : ASSERT (memcmp (buf, "\245\273", 2) == 0);
224 : : ASSERT (buf[2] == 'x');
225 : :
226 : : memset (buf, 'x', 8);
227 : : ret = wcrtomb (buf, 0x8A9E, NULL);
228 : : ASSERT (ret == 2);
229 : : ASSERT (memcmp (buf, "\273\171", 2) == 0);
230 : : ASSERT (buf[2] == 'x');
231 : : }
232 : : return 0;
233 : :
234 : : case 936:
235 : : /* Locale encoding is CP936 = GBK, an extension of GB2312. */
236 : : {
237 : : /* Convert "<\310\325\261\276\325\132>": "<日本語>" */
238 : : memset (buf, 'x', 8);
239 : : ret = wcrtomb (buf, 0x65E5, NULL);
240 : : ASSERT (ret == 2);
241 : : ASSERT (memcmp (buf, "\310\325", 2) == 0);
242 : : ASSERT (buf[2] == 'x');
243 : :
244 : : memset (buf, 'x', 8);
245 : : ret = wcrtomb (buf, 0x672C, NULL);
246 : : ASSERT (ret == 2);
247 : : ASSERT (memcmp (buf, "\261\276", 2) == 0);
248 : : ASSERT (buf[2] == 'x');
249 : :
250 : : memset (buf, 'x', 8);
251 : : ret = wcrtomb (buf, 0x8A9E, NULL);
252 : : ASSERT (ret == 2);
253 : : ASSERT (memcmp (buf, "\325\132", 2) == 0);
254 : : ASSERT (buf[2] == 'x');
255 : : }
256 : : return 0;
257 : :
258 : : case 54936:
259 : : /* Locale encoding is CP54936 = GB18030. */
260 : : {
261 : : /* Convert "B\250\271\201\060\211\070er": "Büßer" */
262 : : memset (buf, 'x', 8);
263 : : ret = wcrtomb (buf, 0x00FC, NULL);
264 : : ASSERT (ret == 2);
265 : : ASSERT (memcmp (buf, "\250\271", 2) == 0);
266 : : ASSERT (buf[2] == 'x');
267 : :
268 : : memset (buf, 'x', 8);
269 : : ret = wcrtomb (buf, 0x00DF, NULL);
270 : : ASSERT (ret == 4);
271 : : ASSERT (memcmp (buf, "\201\060\211\070", 4) == 0);
272 : : ASSERT (buf[4] == 'x');
273 : : }
274 : : return 0;
275 : :
276 : : case 65001:
277 : : /* Locale encoding is CP65001 = UTF-8. */
278 : : {
279 : : /* Convert "B\303\274\303\237er": "Büßer" */
280 : : memset (buf, 'x', 8);
281 : : ret = wcrtomb (buf, 0x00FC, NULL);
282 : : ASSERT (ret == 2);
283 : : ASSERT (memcmp (buf, "\303\274", 2) == 0);
284 : : ASSERT (buf[2] == 'x');
285 : :
286 : : memset (buf, 'x', 8);
287 : : ret = wcrtomb (buf, 0x00DF, NULL);
288 : : ASSERT (ret == 2);
289 : : ASSERT (memcmp (buf, "\303\237", 2) == 0);
290 : : ASSERT (buf[2] == 'x');
291 : : }
292 : : return 0;
293 : :
294 : : default:
295 : : return 1;
296 : : }
297 : : }
298 : :
299 : : int
300 : : main (int argc, char *argv[])
301 : : {
302 : : int codepage = atoi (argv[argc - 1]);
303 : : int result;
304 : : int i;
305 : :
306 : : result = 77;
307 : : for (i = 1; i < argc - 1; i++)
308 : : {
309 : : int ret = test_one_locale (argv[i], codepage);
310 : :
311 : : if (ret != 77)
312 : : result = ret;
313 : : }
314 : :
315 : : if (result == 77)
316 : : {
317 : : fprintf (stderr, "Skipping test: found no locale with codepage %d\n",
318 : : codepage);
319 : : }
320 : : return result;
321 : : }
322 : :
323 : : #else
324 : :
325 : : int
326 : 5 : main (int argc, char *argv[])
327 : : {
328 : 5 : fputs ("Skipping test: not a native Windows system\n", stderr);
329 : 5 : return 77;
330 : : }
331 : :
332 : : #endif
|