1 /* Test mbrtoc8.
2    Copyright (C) 2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <locale.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <uchar.h>
24 #include <wchar.h>
25 #include <support/check.h>
26 #include <support/support.h>
27 
28 static int
test_utf8(void)29 test_utf8 (void)
30 {
31   xsetlocale (LC_ALL, "de_DE.UTF-8");
32 
33   /* No inputs.  */
34   {
35     const char *mbs = "";
36     char8_t buf[1] = { 0 };
37     mbstate_t s = { 0 };
38 
39     TEST_COMPARE (mbrtoc8 (buf, mbs, 0, &s), (size_t) -2); /* no input */
40     TEST_VERIFY (mbsinit (&s));
41   }
42 
43   /* Null character.  */
44   {
45     const char *mbs = "\x00"; /* 0x00 => U+0000 */
46     char8_t buf[1] = { 0 };
47     mbstate_t s = { 0 };
48 
49     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 0);
50     mbs += 1;
51     TEST_COMPARE (buf[0], 0x00);
52     TEST_VERIFY (mbsinit (&s));
53   }
54 
55   /* First non-null character in the code point range that maps to a single
56      code unit.  */
57   {
58     const char *mbs = "\x01"; /* 0x01 => U+0001 */
59     char8_t buf[1] = { 0 };
60     mbstate_t s = { 0 };
61 
62     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 1);
63     mbs += 1;
64     TEST_COMPARE (buf[0], 0x01);
65     TEST_VERIFY (mbsinit (&s));
66   }
67 
68   /* Last character in the code point range that maps to a single code unit.  */
69   {
70     const char *mbs = "\x7F"; /* 0x7F => U+007F */
71     char8_t buf[1] = { 0 };
72     mbstate_t s = { 0 };
73 
74     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 1);
75     mbs += 1;
76     TEST_COMPARE (buf[0], 0x7F);
77     TEST_VERIFY (mbsinit (&s));
78   }
79 
80   /* First character in the code point range that maps to two code units.  */
81   {
82     const char *mbs = "\xC2\x80"; /* 0xC2 0x80 => U+0080 */
83     char8_t buf[1] = { 0 };
84     mbstate_t s = { 0 };
85 
86     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 2);
87     mbs += 2;
88     TEST_COMPARE (buf[0], 0xC2);
89     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
90     TEST_COMPARE (buf[0], 0x80);
91     TEST_VERIFY (mbsinit (&s));
92   }
93 
94   /* Same as last test, but one code unit at a time.  */
95   {
96     const char *mbs = "\xC2\x80"; /* 0xC2 0x80 => U+0080 */
97     char8_t buf[1] = { 0 };
98     mbstate_t s = { 0 };
99 
100     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
101     mbs += 1;
102     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
103     mbs += 1;
104     TEST_COMPARE (buf[0], 0xC2);
105     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
106     TEST_COMPARE (buf[0], 0x80);
107     TEST_VERIFY (mbsinit (&s));
108   }
109 
110   /* Last character in the code point range that maps to two code units.  */
111   {
112     const char *mbs = "\xDF\xBF"; /* 0xDF 0xBF => U+07FF */
113     char8_t buf[1] = { 0 };
114     mbstate_t s = { 0 };
115 
116     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 2);
117     mbs += 2;
118     TEST_COMPARE (buf[0], 0xDF);
119     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
120     TEST_COMPARE (buf[0], 0xBF);
121     TEST_VERIFY (mbsinit (&s));
122   }
123 
124   /* Same as last test, but one code unit at a time.  */
125   {
126     const char *mbs = "\xDF\xBF"; /* 0xDF 0xBF => U+07FF */
127     char8_t buf[1] = { 0 };
128     mbstate_t s = { 0 };
129 
130     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
131     mbs += 1;
132     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
133     mbs += 1;
134     TEST_COMPARE (buf[0], 0xDF);
135     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
136     TEST_COMPARE (buf[0], 0xBF);
137     TEST_VERIFY (mbsinit (&s));
138   }
139 
140   /* First character in the code point range that maps to three code units.  */
141   {
142     const char *mbs = u8"\xE0\xA0\x80"; /* 0xE0 0xA0 0x80 => U+0800 */
143     char8_t buf[1] = { 0 };
144     mbstate_t s = { 0 };
145 
146     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
147     mbs += 3;
148     TEST_COMPARE (buf[0], 0xE0);
149     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
150     TEST_COMPARE (buf[0], 0xA0);
151     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
152     TEST_COMPARE (buf[0], 0x80);
153     TEST_VERIFY (mbsinit (&s));
154   }
155 
156   /* Same as last test, but one code unit at a time.  */
157   {
158     const char *mbs = u8"\xE0\xA0\x80"; /* 0xE0 0xA0 0x80 => U+0800 */
159     char8_t buf[1] = { 0 };
160     mbstate_t s = { 0 };
161 
162     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
163     mbs += 1;
164     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
165     mbs += 1;
166     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
167     mbs += 1;
168     TEST_COMPARE (buf[0], 0xE0);
169     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
170     TEST_COMPARE (buf[0], 0xA0);
171     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
172     TEST_COMPARE (buf[0], 0x80);
173     TEST_VERIFY (mbsinit (&s));
174   }
175 
176   /* Last character in the code point range that maps to three code units
177      before the surrogate code point range.  */
178   {
179     const char *mbs = "\xED\x9F\xBF"; /* 0xED 0x9F 0xBF => U+D7FF */
180     char8_t buf[1] = { 0 };
181     mbstate_t s = { 0 };
182 
183     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
184     mbs += 3;
185     TEST_COMPARE (buf[0], 0xED);
186     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
187     TEST_COMPARE (buf[0], 0x9F);
188     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
189     TEST_COMPARE (buf[0], 0xBF);
190     TEST_VERIFY (mbsinit (&s));
191   }
192 
193   /* Same as last test, but one code unit at a time.  */
194   {
195     const char *mbs = "\xED\x9F\xBF"; /* 0xED 0x9F 0xBF => U+D7FF */
196     char8_t buf[1] = { 0 };
197     mbstate_t s = { 0 };
198 
199     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
200     mbs += 1;
201     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
202     mbs += 1;
203     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
204     mbs += 1;
205     TEST_COMPARE (buf[0], 0xED);
206     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
207     TEST_COMPARE (buf[0], 0x9F);
208     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
209     TEST_COMPARE (buf[0], 0xBF);
210     TEST_VERIFY (mbsinit (&s));
211   }
212 
213   /* First character in the code point range that maps to three code units
214      after the surrogate code point range.  */
215   {
216     const char *mbs = "\xEE\x80\x80"; /* 0xEE 0x80 0x80 => U+E000 */
217     char8_t buf[1] = { 0 };
218     mbstate_t s = { 0 };
219 
220     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
221     mbs += 3;
222     TEST_COMPARE (buf[0], 0xEE);
223     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
224     TEST_COMPARE (buf[0], 0x80);
225     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
226     TEST_COMPARE (buf[0], 0x80);
227     TEST_VERIFY (mbsinit (&s));
228   }
229 
230   /* Same as last test, but one code unit at a time.  */
231   {
232     const char *mbs = "\xEE\x80\x80"; /* 0xEE 0x80 0x80 => U+E000 */
233     char8_t buf[1] = { 0 };
234     mbstate_t s = { 0 };
235 
236     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
237     mbs += 1;
238     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
239     mbs += 1;
240     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
241     mbs += 1;
242     TEST_COMPARE (buf[0], 0xEE);
243     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
244     TEST_COMPARE (buf[0], 0x80);
245     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
246     TEST_COMPARE (buf[0], 0x80);
247     TEST_VERIFY (mbsinit (&s));
248   }
249 
250   /* Not a BOM.  */
251   {
252     const char *mbs = "\xEF\xBB\xBF"; /* 0xEF 0xBB 0xBF => U+FEFF */
253     char8_t buf[1] = { 0 };
254     mbstate_t s = { 0 };
255 
256     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
257     mbs += 3;
258     TEST_COMPARE (buf[0], 0xEF);
259     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
260     TEST_COMPARE (buf[0], 0xBB);
261     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
262     TEST_COMPARE (buf[0], 0xBF);
263     TEST_VERIFY (mbsinit (&s));
264   }
265 
266   /* Same as last test, but one code unit at a time.  */
267   {
268     const char *mbs = "\xEF\xBB\xBF"; /* 0xEF 0xBB 0xBF => U+FEFF */
269     char8_t buf[1] = { 0 };
270     mbstate_t s = { 0 };
271 
272     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
273     mbs += 1;
274     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
275     mbs += 1;
276     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
277     mbs += 1;
278     TEST_COMPARE (buf[0], 0xEF);
279     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
280     TEST_COMPARE (buf[0], 0xBB);
281     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
282     TEST_COMPARE (buf[0], 0xBF);
283     TEST_VERIFY (mbsinit (&s));
284   }
285 
286   /* Replacement character.  */
287   {
288     const char *mbs = "\xEF\xBF\xBD"; /* 0xEF 0xBF 0xBD => U+FFFD */
289     char8_t buf[1] = { 0 };
290     mbstate_t s = { 0 };
291 
292     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
293     mbs += 3;
294     TEST_COMPARE (buf[0], 0xEF);
295     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
296     TEST_COMPARE (buf[0], 0xBF);
297     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
298     TEST_COMPARE (buf[0], 0xBD);
299     TEST_VERIFY (mbsinit (&s));
300   }
301 
302   /* Same as last test, but one code unit at a time.  */
303   {
304     const char *mbs = "\xEF\xBF\xBD"; /* 0xEF 0xBF 0xBD => U+FFFD */
305     char8_t buf[1] = { 0 };
306     mbstate_t s = { 0 };
307 
308     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
309     mbs += 1;
310     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
311     mbs += 1;
312     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
313     mbs += 1;
314     TEST_COMPARE (buf[0], 0xEF);
315     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
316     TEST_COMPARE (buf[0], 0xBF);
317     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
318     TEST_COMPARE (buf[0], 0xBD);
319     TEST_VERIFY (mbsinit (&s));
320   }
321 
322   /* Last character in the code point range that maps to three code units.  */
323   {
324     const char *mbs = "\xEF\xBF\xBF"; /* 0xEF 0xBF 0xBF => U+FFFF */
325     char8_t buf[1] = { 0 };
326     mbstate_t s = { 0 };
327 
328     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 3);
329     mbs += 3;
330     TEST_COMPARE (buf[0], 0xEF);
331     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
332     TEST_COMPARE (buf[0], 0xBF);
333     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
334     TEST_COMPARE (buf[0], 0xBF);
335     TEST_VERIFY (mbsinit (&s));
336   }
337 
338   /* Same as last test, but one code unit at a time.  */
339   {
340     const char *mbs = "\xEF\xBF\xBF"; /* 0xEF 0xBF 0xBF => U+FFFF */
341     char8_t buf[1] = { 0 };
342     mbstate_t s = { 0 };
343 
344     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
345     mbs += 1;
346     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
347     mbs += 1;
348     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
349     mbs += 1;
350     TEST_COMPARE (buf[0], 0xEF);
351     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
352     TEST_COMPARE (buf[0], 0xBF);
353     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
354     TEST_COMPARE (buf[0], 0xBF);
355     TEST_VERIFY (mbsinit (&s));
356   }
357 
358   /* First character in the code point range that maps to four code units.  */
359   {
360     const char *mbs = "\xF0\x90\x80\x80"; /* 0xF0 0x90 0x80 0x80 => U+10000 */
361     char8_t buf[1] = { 0 };
362     mbstate_t s = { 0 };
363 
364     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 4);
365     mbs += 4;
366     TEST_COMPARE (buf[0], 0xF0);
367     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
368     TEST_COMPARE (buf[0], 0x90);
369     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
370     TEST_COMPARE (buf[0], 0x80);
371     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
372     TEST_COMPARE (buf[0], 0x80);
373     TEST_VERIFY (mbsinit (&s));
374   }
375 
376   /* Same as last test, but one code unit at a time.  */
377   {
378     const char *mbs = "\xF0\x90\x80\x80"; /* 0xF0 0x90 0x80 0x80 => U+10000 */
379     char8_t buf[1] = { 0 };
380     mbstate_t s = { 0 };
381 
382     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
383     mbs += 1;
384     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
385     mbs += 1;
386     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
387     mbs += 1;
388     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
389     mbs += 1;
390     TEST_COMPARE (buf[0], 0xF0);
391     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
392     TEST_COMPARE (buf[0], 0x90);
393     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
394     TEST_COMPARE (buf[0], 0x80);
395     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
396     TEST_COMPARE (buf[0], 0x80);
397     TEST_VERIFY (mbsinit (&s));
398   }
399 
400   /* Last character in the code point range that maps to four code units.  */
401   {
402     const char *mbs = "\xF4\x8F\xBF\xBF"; /* 0xF4 0x8F 0xBF 0xBF => U+10FFFF */
403     char8_t buf[1] = { 0 };
404     mbstate_t s = { 0 };
405 
406     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 4);
407     mbs += 4;
408     TEST_COMPARE (buf[0], 0xF4);
409     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
410     TEST_COMPARE (buf[0], 0x8F);
411     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
412     TEST_COMPARE (buf[0], 0xBF);
413     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
414     TEST_COMPARE (buf[0], 0xBF);
415     TEST_VERIFY (mbsinit (&s));
416   }
417 
418   /* Same as last test, but one code unit at a time.  */
419   {
420     const char *mbs = "\xF4\x8F\xBF\xBF"; /* 0xF4 0x8F 0xBF 0xBF => U+10FFFF */
421     char8_t buf[1] = { 0 };
422     mbstate_t s = { 0 };
423 
424     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
425     mbs += 1;
426     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
427     mbs += 1;
428     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
429     mbs += 1;
430     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
431     mbs += 1;
432     TEST_COMPARE (buf[0], 0xF4);
433     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
434     TEST_COMPARE (buf[0], 0x8F);
435     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
436     TEST_COMPARE (buf[0], 0xBF);
437     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
438     TEST_COMPARE (buf[0], 0xBF);
439     TEST_VERIFY (mbsinit (&s));
440   }
441 
442   return 0;
443 }
444 
445 static int
test_big5_hkscs(void)446 test_big5_hkscs (void)
447 {
448   xsetlocale (LC_ALL, "zh_HK.BIG5-HKSCS");
449 
450   /* A double byte character that maps to a pair of two byte UTF-8 code unit
451      sequences.  */
452   {
453     const char *mbs = "\x88\x62"; /* 0x88 0x62 => U+00CA U+0304 */
454     char8_t buf[1] = { 0 };
455     mbstate_t s = { 0 };
456 
457     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 2);
458     mbs += 2;
459     TEST_COMPARE (buf[0], 0xC3);
460     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
461     TEST_COMPARE (buf[0], 0x8A);
462     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
463     TEST_COMPARE (buf[0], 0xCC);
464     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
465     TEST_COMPARE (buf[0], 0x84);
466     TEST_VERIFY (mbsinit (&s));
467   }
468 
469   /* Same as last test, but one code unit at a time.  */
470   {
471     const char *mbs = "\x88\x62"; /* 0x88 0x62 => U+00CA U+0304 */
472     char8_t buf[1] = { 0 };
473     mbstate_t s = { 0 };
474 
475     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
476     mbs += 1;
477     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
478     mbs += 1;
479     TEST_COMPARE (buf[0], 0xC3);
480     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
481     TEST_COMPARE (buf[0], 0x8A);
482     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
483     TEST_COMPARE (buf[0], 0xCC);
484     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
485     TEST_COMPARE (buf[0], 0x84);
486     TEST_VERIFY (mbsinit (&s));
487   }
488 
489   /* Another double byte character that maps to a pair of two byte UTF-8 code
490      unit sequences.  */
491   {
492     const char *mbs = "\x88\xA5"; /* 0x88 0xA5 => U+00EA U+030C */
493     char8_t buf[1] = { 0 };
494     mbstate_t s = { 0 };
495 
496     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) 2);
497     mbs += 2;
498     TEST_COMPARE (buf[0], 0xC3);
499     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
500     TEST_COMPARE (buf[0], 0xAA);
501     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
502     TEST_COMPARE (buf[0], 0xCC);
503     TEST_COMPARE (mbrtoc8 (buf, mbs, strlen (mbs) + 1, &s), (size_t) -3);
504     TEST_COMPARE (buf[0], 0x8C);
505     TEST_VERIFY (mbsinit (&s));
506   }
507 
508   /* Same as last test, but one code unit at a time.  */
509   {
510     const char *mbs = "\x88\xA5"; /* 0x88 0xA5 => U+00EA U+030C */
511     char8_t buf[1] = { 0 };
512     mbstate_t s = { 0 };
513 
514     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -2);
515     mbs += 1;
516     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) 1);
517     mbs += 1;
518     TEST_COMPARE (buf[0], 0xC3);
519     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
520     TEST_COMPARE (buf[0], 0xAA);
521     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
522     TEST_COMPARE (buf[0], 0xCC);
523     TEST_COMPARE (mbrtoc8 (buf, mbs, 1, &s), (size_t) -3);
524     TEST_COMPARE (buf[0], 0x8C);
525     TEST_VERIFY (mbsinit (&s));
526   }
527 
528   return 0;
529 }
530 
531 static int
do_test(void)532 do_test (void)
533 {
534   test_utf8 ();
535   test_big5_hkscs ();
536   return 0;
537 }
538 
539 #include <support/test-driver.c>
540