tizen 2.4 release
[framework/base/tizen-locale.git] / iconvdata / tcvn5712-1.c
1 /* Conversion to and from TCVN5712-1.
2    Copyright (C) 2001-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <dlfcn.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23
24 #define NELEMS(arr) (sizeof (arr) / sizeof (arr[0]))
25
26 /* Definitions used in the body of the `gconv' function.  */
27 #define CHARSET_NAME            "TCVN5712-1//"
28 #define FROM_LOOP               from_tcvn5712_1
29 #define TO_LOOP                 to_tcvn5712_1
30 #define DEFINE_INIT             1
31 #define DEFINE_FINI             1
32 #define ONE_DIRECTION           0
33 #define FROM_LOOP_MIN_NEEDED_FROM       1
34 #define FROM_LOOP_MAX_NEEDED_FROM       1
35 #define FROM_LOOP_MIN_NEEDED_TO         4
36 #define FROM_LOOP_MAX_NEEDED_TO         4
37 #define TO_LOOP_MIN_NEEDED_FROM         4
38 #define TO_LOOP_MAX_NEEDED_FROM         4
39 #define TO_LOOP_MIN_NEEDED_TO           1
40 #define TO_LOOP_MAX_NEEDED_TO           2
41 #define PREPARE_LOOP \
42   int saved_state;                                                            \
43   int *statep = &data->__statep->__count;
44 #define EXTRA_LOOP_ARGS         , statep
45
46
47 /* Since we might have to reset input pointer we must be able to save
48    and restore the state.  */
49 #define SAVE_RESET_STATE(Save) \
50   if (Save)                                                                   \
51     saved_state = *statep;                                                    \
52   else                                                                        \
53     *statep = saved_state
54
55
56 /* During TCVN5712-1 to UCS4 conversion, the COUNT element of the state
57    contains the last UCS4 character, shifted by 3 bits.  */
58
59
60 /* Since this is a stateful encoding we have to provide code which resets
61    the output state to the initial state.  This has to be done during the
62    flushing.  */
63 #define EMIT_SHIFT_TO_INIT \
64   if (data->__statep->__count != 0)                                           \
65     {                                                                         \
66       if (FROM_DIRECTION)                                                     \
67         {                                                                     \
68           if (__glibc_likely (outbuf + 4 <= outend))                          \
69             {                                                                 \
70               /* Write out the last character.  */                            \
71               *((uint32_t *) outbuf) = data->__statep->__count >> 3;          \
72               outbuf += sizeof (uint32_t);                                    \
73               data->__statep->__count = 0;                                    \
74             }                                                                 \
75           else                                                                \
76             /* We don't have enough room in the output buffer.  */            \
77             status = __GCONV_FULL_OUTPUT;                                     \
78         }                                                                     \
79       else                                                                    \
80         /* We don't use shift states in the TO_DIRECTION.  */                 \
81         data->__statep->__count = 0;                                          \
82     }
83
84
85 static const uint16_t map_from_tcvn_low[0x18] =
86   {
87     0x0000, 0x00da, 0x1ee4, 0x0003, 0x1eea, 0x1eec, 0x1eee, 0x0007,
88     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
89     0x0010, 0x1ee8, 0x1ef0, 0x1ef2, 0x1ef6, 0x1ef8, 0x00dd, 0x1ef4
90   };
91
92 static const uint16_t map_from_tcvn_high[0x80] =
93   {
94     0x00c0, 0x1ea2, 0x00c3, 0x00c1, 0x1ea0, 0x1eb6, 0x1eac, 0x00c8,
95     0x1eba, 0x1ebc, 0x00c9, 0x1eb8, 0x1ec6, 0x00cc, 0x1ec8, 0x0128,
96     0x00cd, 0x1eca, 0x00d2, 0x1ece, 0x00d5, 0x00d3, 0x1ecc, 0x1ed8,
97     0x1edc, 0x1ede, 0x1ee0, 0x1eda, 0x1ee2, 0x00d9, 0x1ee6, 0x0168,
98     0x00a0, 0x0102, 0x00c2, 0x00ca, 0x00d4, 0x01a0, 0x01af, 0x0110,
99     0x0103, 0x00e2, 0x00ea, 0x00f4, 0x01a1, 0x01b0, 0x0111, 0x1eb0,
100     0x0300, 0x0309, 0x0303, 0x0301, 0x0323, 0x00e0, 0x1ea3, 0x00e3,
101     0x00e1, 0x1ea1, 0x1eb2, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eaf, 0x1eb4,
102     0x1eae, 0x1ea6, 0x1ea8, 0x1eaa, 0x1ea4, 0x1ec0, 0x1eb7, 0x1ea7,
103     0x1ea9, 0x1eab, 0x1ea5, 0x1ead, 0x00e8, 0x1ec2, 0x1ebb, 0x1ebd,
104     0x00e9, 0x1eb9, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ebf, 0x1ec7, 0x00ec,
105     0x1ec9, 0x1ec4, 0x1ebe, 0x1ed2, 0x0129, 0x00ed, 0x1ecb, 0x00f2,
106     0x1ed4, 0x1ecf, 0x00f5, 0x00f3, 0x1ecd, 0x1ed3, 0x1ed5, 0x1ed7,
107     0x1ed1, 0x1ed9, 0x1edd, 0x1edf, 0x1ee1, 0x1edb, 0x1ee3, 0x00f9,
108     0x1ed6, 0x1ee7, 0x0169, 0x00fa, 0x1ee5, 0x1eeb, 0x1eed, 0x1eef,
109     0x1ee9, 0x1ef1, 0x1ef3, 0x1ef7, 0x1ef9, 0x00fd, 0x1ef5, 0x1ed0
110   };
111
112
113 /* TCVN5712-1 contains five combining characters:
114    0x0300, 0x0301, 0x0303, 0x0309, 0x0323.  */
115
116 /* Composition tables for each of the relevant combining characters.  */
117 static const struct
118 {
119   uint16_t base;
120   uint16_t composed;
121 } comp_table_data[] =
122   {
123 #define COMP_TABLE_IDX_0300 0
124 #define COMP_TABLE_LEN_0300 28
125     { 0x0041, 0x00C0 },
126     { 0x0045, 0x00C8 },
127     { 0x0049, 0x00CC },
128     { 0x004E, 0x01F8 },
129     { 0x004F, 0x00D2 },
130     { 0x0055, 0x00D9 },
131     { 0x0057, 0x1E80 },
132     { 0x0059, 0x1EF2 },
133     { 0x0061, 0x00E0 },
134     { 0x0065, 0x00E8 },
135     { 0x0069, 0x00EC },
136     { 0x006E, 0x01F9 },
137     { 0x006F, 0x00F2 },
138     { 0x0075, 0x00F9 },
139     { 0x0077, 0x1E81 },
140     { 0x0079, 0x1EF3 },
141   /*{ 0x00A8, 0x1FED },*/
142     { 0x00C2, 0x1EA6 },
143     { 0x00CA, 0x1EC0 },
144     { 0x00D4, 0x1ED2 },
145   /*{ 0x00DC, 0x01DB },*/
146     { 0x00E2, 0x1EA7 },
147     { 0x00EA, 0x1EC1 },
148     { 0x00F4, 0x1ED3 },
149   /*{ 0x00FC, 0x01DC },*/
150     { 0x0102, 0x1EB0 },
151     { 0x0103, 0x1EB1 },
152   /*{ 0x0112, 0x1E14 },*/
153   /*{ 0x0113, 0x1E15 },*/
154   /*{ 0x014C, 0x1E50 },*/
155   /*{ 0x014D, 0x1E51 },*/
156     { 0x01A0, 0x1EDC },
157     { 0x01A1, 0x1EDD },
158     { 0x01AF, 0x1EEA },
159     { 0x01B0, 0x1EEB },
160 #define COMP_TABLE_IDX_0301 (COMP_TABLE_IDX_0300 + COMP_TABLE_LEN_0300)
161 #define COMP_TABLE_LEN_0301 50
162     { 0x0041, 0x00C1 },
163     { 0x0043, 0x0106 },
164     { 0x0045, 0x00C9 },
165     { 0x0047, 0x01F4 },
166     { 0x0049, 0x00CD },
167     { 0x004B, 0x1E30 },
168     { 0x004C, 0x0139 },
169     { 0x004D, 0x1E3E },
170     { 0x004E, 0x0143 },
171     { 0x004F, 0x00D3 },
172     { 0x0050, 0x1E54 },
173     { 0x0052, 0x0154 },
174     { 0x0053, 0x015A },
175     { 0x0055, 0x00DA },
176     { 0x0057, 0x1E82 },
177     { 0x0059, 0x00DD },
178     { 0x005A, 0x0179 },
179     { 0x0061, 0x00E1 },
180     { 0x0063, 0x0107 },
181     { 0x0065, 0x00E9 },
182     { 0x0067, 0x01F5 },
183     { 0x0069, 0x00ED },
184     { 0x006B, 0x1E31 },
185     { 0x006C, 0x013A },
186     { 0x006D, 0x1E3F },
187     { 0x006E, 0x0144 },
188     { 0x006F, 0x00F3 },
189     { 0x0070, 0x1E55 },
190     { 0x0072, 0x0155 },
191     { 0x0073, 0x015B },
192     { 0x0075, 0x00FA },
193     { 0x0077, 0x1E83 },
194     { 0x0079, 0x00FD },
195     { 0x007A, 0x017A },
196   /*{ 0x00A8, 0x0385 },*//* prefer U+0385 over U+1FEE */
197     { 0x00C2, 0x1EA4 },
198   /*{ 0x00C5, 0x01FA },*/
199   /*{ 0x00C6, 0x01FC },*/
200   /*{ 0x00C7, 0x1E08 },*/
201     { 0x00CA, 0x1EBE },
202   /*{ 0x00CF, 0x1E2E },*/
203     { 0x00D4, 0x1ED0 },
204     { 0x00D5, 0x1E4C },
205   /*{ 0x00D8, 0x01FE },*/
206   /*{ 0x00DC, 0x01D7 },*/
207     { 0x00E2, 0x1EA5 },
208   /*{ 0x00E5, 0x01FB },*/
209   /*{ 0x00E6, 0x01FD },*/
210   /*{ 0x00E7, 0x1E09 },*/
211     { 0x00EA, 0x1EBF },
212   /*{ 0x00EF, 0x1E2F },*/
213     { 0x00F4, 0x1ED1 },
214     { 0x00F5, 0x1E4D },
215   /*{ 0x00F8, 0x01FF },*/
216   /*{ 0x00FC, 0x01D8 },*/
217     { 0x0102, 0x1EAE },
218     { 0x0103, 0x1EAF },
219   /*{ 0x0112, 0x1E16 },*/
220   /*{ 0x0113, 0x1E17 },*/
221   /*{ 0x014C, 0x1E52 },*/
222   /*{ 0x014D, 0x1E53 },*/
223     { 0x0168, 0x1E78 },
224     { 0x0169, 0x1E79 },
225     { 0x01A0, 0x1EDA },
226     { 0x01A1, 0x1EDB },
227     { 0x01AF, 0x1EE8 },
228     { 0x01B0, 0x1EE9 },
229 #define COMP_TABLE_IDX_0303 (COMP_TABLE_IDX_0301 + COMP_TABLE_LEN_0301)
230 #define COMP_TABLE_LEN_0303 34
231     { 0x0041, 0x00C3 },
232     { 0x0045, 0x1EBC },
233     { 0x0049, 0x0128 },
234     { 0x004E, 0x00D1 },
235     { 0x004F, 0x00D5 },
236     { 0x0055, 0x0168 },
237     { 0x0056, 0x1E7C },
238     { 0x0059, 0x1EF8 },
239     { 0x0061, 0x00E3 },
240     { 0x0065, 0x1EBD },
241     { 0x0069, 0x0129 },
242     { 0x006E, 0x00F1 },
243     { 0x006F, 0x00F5 },
244     { 0x0075, 0x0169 },
245     { 0x0076, 0x1E7D },
246     { 0x0079, 0x1EF9 },
247     { 0x00C2, 0x1EAA },
248     { 0x00CA, 0x1EC4 },
249     { 0x00D3, 0x1E4C },
250     { 0x00D4, 0x1ED6 },
251     { 0x00D6, 0x1E4E },
252     { 0x00DA, 0x1E78 },
253     { 0x00E2, 0x1EAB },
254     { 0x00EA, 0x1EC5 },
255     { 0x00F3, 0x1E4D },
256     { 0x00F4, 0x1ED7 },
257     { 0x00F6, 0x1E4F },
258     { 0x00FA, 0x1E79 },
259     { 0x0102, 0x1EB4 },
260     { 0x0103, 0x1EB5 },
261     { 0x01A0, 0x1EE0 },
262     { 0x01A1, 0x1EE1 },
263     { 0x01AF, 0x1EEE },
264     { 0x01B0, 0x1EEF },
265 #define COMP_TABLE_IDX_0309 (COMP_TABLE_IDX_0303 + COMP_TABLE_LEN_0303)
266 #define COMP_TABLE_LEN_0309 24
267     { 0x0041, 0x1EA2 },
268     { 0x0045, 0x1EBA },
269     { 0x0049, 0x1EC8 },
270     { 0x004F, 0x1ECE },
271     { 0x0055, 0x1EE6 },
272     { 0x0059, 0x1EF6 },
273     { 0x0061, 0x1EA3 },
274     { 0x0065, 0x1EBB },
275     { 0x0069, 0x1EC9 },
276     { 0x006F, 0x1ECF },
277     { 0x0075, 0x1EE7 },
278     { 0x0079, 0x1EF7 },
279     { 0x00C2, 0x1EA8 },
280     { 0x00CA, 0x1EC2 },
281     { 0x00D4, 0x1ED4 },
282     { 0x00E2, 0x1EA9 },
283     { 0x00EA, 0x1EC3 },
284     { 0x00F4, 0x1ED5 },
285     { 0x0102, 0x1EB2 },
286     { 0x0103, 0x1EB3 },
287     { 0x01A0, 0x1EDE },
288     { 0x01A1, 0x1EDF },
289     { 0x01AF, 0x1EEC },
290     { 0x01B0, 0x1EED },
291 #define COMP_TABLE_IDX_0323 (COMP_TABLE_IDX_0309 + COMP_TABLE_LEN_0309)
292 #define COMP_TABLE_LEN_0323 50
293     { 0x0041, 0x1EA0 },
294     { 0x0042, 0x1E04 },
295     { 0x0044, 0x1E0C },
296     { 0x0045, 0x1EB8 },
297     { 0x0048, 0x1E24 },
298     { 0x0049, 0x1ECA },
299     { 0x004B, 0x1E32 },
300     { 0x004C, 0x1E36 },
301     { 0x004D, 0x1E42 },
302     { 0x004E, 0x1E46 },
303     { 0x004F, 0x1ECC },
304     { 0x0052, 0x1E5A },
305     { 0x0053, 0x1E62 },
306     { 0x0054, 0x1E6C },
307     { 0x0055, 0x1EE4 },
308     { 0x0056, 0x1E7E },
309     { 0x0057, 0x1E88 },
310     { 0x0059, 0x1EF4 },
311     { 0x005A, 0x1E92 },
312     { 0x0061, 0x1EA1 },
313     { 0x0062, 0x1E05 },
314     { 0x0064, 0x1E0D },
315     { 0x0065, 0x1EB9 },
316     { 0x0068, 0x1E25 },
317     { 0x0069, 0x1ECB },
318     { 0x006B, 0x1E33 },
319     { 0x006C, 0x1E37 },
320     { 0x006D, 0x1E43 },
321     { 0x006E, 0x1E47 },
322     { 0x006F, 0x1ECD },
323     { 0x0072, 0x1E5B },
324     { 0x0073, 0x1E63 },
325     { 0x0074, 0x1E6D },
326     { 0x0075, 0x1EE5 },
327     { 0x0076, 0x1E7F },
328     { 0x0077, 0x1E89 },
329     { 0x0079, 0x1EF5 },
330     { 0x007A, 0x1E93 },
331     { 0x00C2, 0x1EAC },
332     { 0x00CA, 0x1EC6 },
333     { 0x00D4, 0x1ED8 },
334     { 0x00E2, 0x1EAD },
335     { 0x00EA, 0x1EC7 },
336     { 0x00F4, 0x1ED9 },
337     { 0x0102, 0x1EB6 },
338     { 0x0103, 0x1EB7 },
339     { 0x01A0, 0x1EE2 },
340     { 0x01A1, 0x1EE3 },
341     { 0x01AF, 0x1EF0 },
342     { 0x01B0, 0x1EF1 },
343 #define COMP_TABLE_IDX_END (COMP_TABLE_IDX_0323 + COMP_TABLE_LEN_0323)
344   };
345 /* Compile-time verification of table size.  */
346 typedef int verify1[(NELEMS (comp_table_data) == COMP_TABLE_IDX_END) - 1];
347
348 static const struct
349 {
350   unsigned int idx;
351   unsigned int len;
352 } comp_table[5] =
353   {
354     { COMP_TABLE_IDX_0300, COMP_TABLE_LEN_0300 },
355     { COMP_TABLE_IDX_0301, COMP_TABLE_LEN_0301 },
356     { COMP_TABLE_IDX_0303, COMP_TABLE_LEN_0303 },
357     { COMP_TABLE_IDX_0309, COMP_TABLE_LEN_0309 },
358     { COMP_TABLE_IDX_0323, COMP_TABLE_LEN_0323 },
359   };
360
361
362 /* First define the conversion function from TCVN5712-1 to UCS4.  */
363 #define MIN_NEEDED_INPUT        FROM_LOOP_MIN_NEEDED_FROM
364 #define MAX_NEEDED_INPUT        FROM_LOOP_MAX_NEEDED_FROM
365 #define MIN_NEEDED_OUTPUT       FROM_LOOP_MIN_NEEDED_TO
366 #define MAX_NEEDED_OUTPUT       FROM_LOOP_MAX_NEEDED_TO
367 #define LOOPFCT                 FROM_LOOP
368 #define BODY \
369   {                                                                           \
370     uint32_t ch = *inptr;                                                     \
371     uint32_t last_ch;                                                         \
372     int must_buffer_ch;                                                       \
373                                                                               \
374     if (ch < 0x18)                                                            \
375       ch = map_from_tcvn_low[ch];                                             \
376     else if (ch >= 0x80)                                                      \
377       ch = map_from_tcvn_high[ch - 0x80];                                     \
378                                                                               \
379     /* Determine whether there is a buffered character pending.  */           \
380     last_ch = *statep >> 3;                                                   \
381                                                                               \
382     /* We have to buffer ch if it is a possible match in comp_table_data.  */ \
383     must_buffer_ch = (ch >= 0x0041 && ch <= 0x01b0);                          \
384                                                                               \
385     if (last_ch)                                                              \
386       {                                                                       \
387         if (ch >= 0x0300 && ch < 0x0340)                                      \
388           {                                                                   \
389             /* See whether last_ch and ch can be combined.  */                \
390             unsigned int i;                                                   \
391             unsigned int i1;                                                  \
392             unsigned int i2;                                                  \
393                                                                               \
394             switch (ch)                                                       \
395               {                                                               \
396               case 0x0300:                                                    \
397                 i = 0;                                                        \
398                 break;                                                        \
399               case 0x0301:                                                    \
400                 i = 1;                                                        \
401                 break;                                                        \
402               case 0x0303:                                                    \
403                 i = 2;                                                        \
404                 break;                                                        \
405               case 0x0309:                                                    \
406                 i = 3;                                                        \
407                 break;                                                        \
408               case 0x0323:                                                    \
409                 i = 4;                                                        \
410                 break;                                                        \
411               default:                                                        \
412                 abort ();                                                     \
413               }                                                               \
414                                                                               \
415             i1 = comp_table[i].idx;                                           \
416             i2 = i1 + comp_table[i].len - 1;                                  \
417                                                                               \
418             if (last_ch >= comp_table_data[i1].base                           \
419                 && last_ch <= comp_table_data[i2].base)                       \
420               {                                                               \
421                 for (;;)                                                      \
422                   {                                                           \
423                     i = (i1 + i2) >> 1;                                       \
424                     if (last_ch == comp_table_data[i].base)                   \
425                       break;                                                  \
426                     if (last_ch < comp_table_data[i].base)                    \
427                       {                                                       \
428                         if (i1 == i)                                          \
429                           goto not_combining;                                 \
430                         i2 = i;                                               \
431                       }                                                       \
432                     else                                                      \
433                       {                                                       \
434                         if (i1 != i)                                          \
435                           i1 = i;                                             \
436                         else                                                  \
437                           {                                                   \
438                             i = i2;                                           \
439                             if (last_ch == comp_table_data[i].base)           \
440                               break;                                          \
441                             goto not_combining;                               \
442                           }                                                   \
443                       }                                                       \
444                   }                                                           \
445                 last_ch = comp_table_data[i].composed;                        \
446                 /* Output the combined character.  */                         \
447                 put32 (outptr, last_ch);                                      \
448                 outptr += 4;                                                  \
449                 *statep = 0;                                                  \
450                 ++inptr;                                                      \
451                 continue;                                                     \
452               }                                                               \
453           }                                                                   \
454                                                                               \
455       not_combining:                                                          \
456         /* Output the buffered character.  */                                 \
457         put32 (outptr, last_ch);                                              \
458         outptr += 4;                                                          \
459         *statep = 0;                                                          \
460                                                                               \
461         /* If we don't have enough room to output ch as well, then deal       \
462            with it in another round.  */                                      \
463         if (!must_buffer_ch && __builtin_expect (outptr + 4 > outend, 0))     \
464           continue;                                                           \
465       }                                                                       \
466                                                                               \
467     if (must_buffer_ch)                                                       \
468       *statep = ch << 3;                                                      \
469     else                                                                      \
470       {                                                                       \
471         put32 (outptr, ch);                                                   \
472         outptr += 4;                                                          \
473       }                                                                       \
474     ++inptr;                                                                  \
475   }
476 #define EXTRA_LOOP_DECLS        , int *statep
477 #define ONEBYTE_BODY \
478   {                                                                           \
479     uint32_t ch;                                                              \
480                                                                               \
481     if (c < 0x18)                                                             \
482       ch = map_from_tcvn_low[c];                                              \
483     else if (c >= 0x80)                                                       \
484       ch = map_from_tcvn_high[c - 0x80];                                      \
485     else                                                                      \
486       ch = c;                                                                 \
487     if (ch >= 0x0041 && ch <= 0x01b0)                                         \
488       return WEOF;                                                            \
489     return ch;                                                                \
490   }
491 #include <iconv/loop.c>
492
493
494 /* Next, define the conversion function from UCS4 to TCVN5712-1.  */
495
496 static const unsigned char from_ucs4[] =
497   {
498 #define FROM_IDX_00 0
499     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, /* 0x0001-0x0007 */
500     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x0008-0x000f */
501     0x10,                                           /* 0x0010-0x0010 */
502
503 #define FROM_IDX_01 (FROM_IDX_00 + 16)
504     0x80, 0x83, 0xa2, 0x82, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00c7 */
505     0x87, 0x8a, 0xa3, 0x00, 0x8d, 0x90, 0x00, 0x00, /* 0x00c8-0x00cf */
506     0x00, 0x00, 0x92, 0x95, 0xa4, 0x94, 0x00, 0x00, /* 0x00d0-0x00d7 */
507     0x00, 0x9d, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, /* 0x00d8-0x00df */
508     0xb5, 0xb8, 0xa9, 0xb7, 0x00, 0x00, 0x00, 0x00, /* 0x00e0-0x00e7 */
509     0xcc, 0xd0, 0xaa, 0x00, 0xd7, 0xdd, 0x00, 0x00, /* 0x00e8-0x00ef */
510     0x00, 0x00, 0xdf, 0xe3, 0xab, 0xe2, 0x00, 0x00, /* 0x00f0-0x00f7 */
511     0x00, 0xef, 0xf3, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0x00f8-0x00ff */
512     0x00, 0x00, 0xa1, 0xa8, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x0107 */
513     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0108-0x010f */
514     0xa7, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0110-0x0117 */
515     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0118-0x011f */
516     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0120-0x0127 */
517     0x8f, 0xdc,                                     /* 0x0128-0x0129 */
518
519 #define FROM_IDX_02 (FROM_IDX_01 + 106)
520     0x9f, 0xf2,                                     /* 0x0168-0x0169 */
521
522 #define FROM_IDX_03 (FROM_IDX_02 + 2)
523     0xa5, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01a0-0x01a7 */
524     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, /* 0x01a8-0x01af */
525     0xad,                                           /* 0x01b0-0x01b0 */
526
527 #define FROM_IDX_04 (FROM_IDX_03 + 17)
528     0xb0, 0xb3, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x0300-0x0307 */
529     0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0308-0x030f */
530     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0310-0x0317 */
531     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0318-0x031f */
532     0x00, 0x00, 0x00, 0xb4,                         /* 0x0320-0x0323 */
533
534 #define FROM_IDX_05 (FROM_IDX_04 + 36)
535     0x84, 0xb9, 0x81, 0xb6, 0xc4, 0xca, 0xc1, 0xc7, /* 0x1ea0-0x1ea7 */
536     0xc2, 0xc8, 0xc3, 0xc9, 0x86, 0xcb, 0xc0, 0xbe, /* 0x1ea8-0x1eaf */
537     0xaf, 0xbb, 0xba, 0xbc, 0xbf, 0xbd, 0x85, 0xc6, /* 0x1eb0-0x1eb7 */
538     0x8b, 0xd1, 0x88, 0xce, 0x89, 0xcf, 0xda, 0xd5, /* 0x1eb8-0x1ebf */
539     0xc5, 0xd2, 0xcd, 0xd3, 0xd9, 0xd4, 0x8c, 0xd6, /* 0x1ec0-0x1ec7 */
540     0x8e, 0xd8, 0x91, 0xde, 0x96, 0xe4, 0x93, 0xe1, /* 0x1ec8-0x1ecf */
541     0xff, 0xe8, 0xdb, 0xe5, 0xe0, 0xe6, 0xf0, 0xe7, /* 0x1ed0-0x1ed7 */
542     0x97, 0xe9, 0x9b, 0xed, 0x98, 0xea, 0x99, 0xeb, /* 0x1ed8-0x1edf */
543     0x9a, 0xec, 0x9c, 0xee, 0x02, 0xf4, 0x9e, 0xf1, /* 0x1ee0-0x1ee7 */
544     0x11, 0xf8, 0x04, 0xf5, 0x05, 0xf6, 0x06, 0xf7, /* 0x1ee8-0x1eef */
545     0x12, 0xf9, 0x13, 0xfa, 0x17, 0xfe, 0x14, 0xfb, /* 0x1ef0-0x1ef7 */
546     0x15, 0xfc                                      /* 0x1ef8-0x1ef9 */
547 #define FROM_IDX_END (FROM_IDX_05 + 90)
548   };
549 /* Compile-time verification of table size.  */
550 typedef int verify2[(NELEMS (from_ucs4) == FROM_IDX_END) - 1];
551
552 /* Decomposition table for the relevant Unicode characters. */
553 static const struct
554 {
555   uint16_t composed;
556   uint32_t base:8;
557   uint32_t comb1:8;
558 } decomp_table[] =
559   {
560     { 0x00d1, 0x4e, 0xb2 },
561     { 0x00f1, 0x6e, 0xb2 },
562     { 0x0106, 0x43, 0xb3 },
563     { 0x0107, 0x63, 0xb3 },
564     { 0x0139, 0x4c, 0xb3 },
565     { 0x013a, 0x6c, 0xb3 },
566     { 0x0143, 0x4e, 0xb3 },
567     { 0x0144, 0x6e, 0xb3 },
568     { 0x0154, 0x52, 0xb3 },
569     { 0x0155, 0x72, 0xb3 },
570     { 0x015a, 0x53, 0xb3 },
571     { 0x015b, 0x73, 0xb3 },
572     { 0x0179, 0x5a, 0xb3 },
573     { 0x017a, 0x7a, 0xb3 },
574     { 0x01f4, 0x47, 0xb3 },
575     { 0x01f5, 0x67, 0xb3 },
576     { 0x01f8, 0x4e, 0xb0 },
577     { 0x01f9, 0x6e, 0xb0 },
578     { 0x1e04, 0x42, 0xb4 },
579     { 0x1e05, 0x62, 0xb4 },
580     { 0x1e0c, 0x44, 0xb4 },
581     { 0x1e0d, 0x64, 0xb4 },
582     { 0x1e24, 0x48, 0xb4 },
583     { 0x1e25, 0x68, 0xb4 },
584     { 0x1e30, 0x4b, 0xb3 },
585     { 0x1e31, 0x6b, 0xb3 },
586     { 0x1e32, 0x4b, 0xb4 },
587     { 0x1e33, 0x6b, 0xb4 },
588     { 0x1e36, 0x4c, 0xb4 },
589     { 0x1e37, 0x6c, 0xb4 },
590     { 0x1e3e, 0x4d, 0xb3 },
591     { 0x1e3f, 0x6d, 0xb3 },
592     { 0x1e42, 0x4d, 0xb4 },
593     { 0x1e43, 0x6d, 0xb4 },
594     { 0x1e46, 0x4e, 0xb4 },
595     { 0x1e47, 0x6e, 0xb4 },
596     { 0x1e54, 0x50, 0xb3 },
597     { 0x1e55, 0x70, 0xb3 },
598     { 0x1e5a, 0x52, 0xb4 },
599     { 0x1e5b, 0x72, 0xb4 },
600     { 0x1e62, 0x53, 0xb4 },
601     { 0x1e63, 0x73, 0xb4 },
602     { 0x1e6c, 0x54, 0xb4 },
603     { 0x1e6d, 0x74, 0xb4 },
604     { 0x1e7c, 0x56, 0xb2 },
605     { 0x1e7d, 0x76, 0xb2 },
606     { 0x1e7e, 0x56, 0xb4 },
607     { 0x1e7f, 0x76, 0xb4 },
608     { 0x1e80, 0x57, 0xb0 },
609     { 0x1e81, 0x77, 0xb0 },
610     { 0x1e82, 0x57, 0xb3 },
611     { 0x1e83, 0x77, 0xb3 },
612     { 0x1e88, 0x57, 0xb4 },
613     { 0x1e89, 0x77, 0xb4 },
614     { 0x1e92, 0x5a, 0xb4 },
615     { 0x1e93, 0x7a, 0xb4 },
616   };
617
618
619 /* Next, define the other direction.  */
620 #define MIN_NEEDED_INPUT        TO_LOOP_MIN_NEEDED_FROM
621 #define MAX_NEEDED_INPUT        TO_LOOP_MAX_NEEDED_FROM
622 #define MIN_NEEDED_OUTPUT       TO_LOOP_MIN_NEEDED_TO
623 #define MAX_NEEDED_OUTPUT       TO_LOOP_MAX_NEEDED_TO
624 #define LOOPFCT                 TO_LOOP
625 #define BODY \
626   {                                                                           \
627     uint32_t ch = get32 (inptr);                                              \
628                                                                               \
629     if (ch == 0x00 || (ch >= 0x18 && ch < 0x80) || ch == 0xa0)                \
630       {                                                                       \
631         *outptr++ = ch;                                                       \
632         inptr += 4;                                                           \
633       }                                                                       \
634     else                                                                      \
635       {                                                                       \
636         unsigned char res;                                                    \
637                                                                               \
638         if (ch <= 0x0010)                                                     \
639           res = from_ucs4[ch - 0x0001 + FROM_IDX_00];                         \
640         else if (ch >= 0x00c0 && ch <= 0x0129)                                \
641           res = from_ucs4[ch - 0x00c0 + FROM_IDX_01];                         \
642         else if (ch >= 0x0168 && ch <= 0x0169)                                \
643           res = from_ucs4[ch - 0x0168 + FROM_IDX_02];                         \
644         else if (ch >= 0x01a0 && ch <= 0x01b0)                                \
645           res = from_ucs4[ch - 0x01a0 + FROM_IDX_03];                         \
646         else if (ch >= 0x0300 && ch <= 0x0323)                                \
647           res = from_ucs4[ch - 0x0300 + FROM_IDX_04];                         \
648         else if (ch >= 0x1ea0 && ch <= 0x1ef9)                                \
649           res = from_ucs4[ch - 0x1ea0 + FROM_IDX_05];                         \
650         else                                                                  \
651           {                                                                   \
652             UNICODE_TAG_HANDLER (ch, 4);                                      \
653             res = 0;                                                          \
654           }                                                                   \
655                                                                               \
656         if (__glibc_likely (res != 0))                                        \
657           {                                                                   \
658             *outptr++ = res;                                                  \
659             inptr += 4;                                                       \
660           }                                                                   \
661         else                                                                  \
662           {                                                                   \
663             /* Try canonical decomposition.  */                               \
664             unsigned int i1;                                                  \
665             unsigned int i2;                                                  \
666                                                                               \
667             i1 = 0;                                                           \
668             i2 = sizeof (decomp_table) / sizeof (decomp_table[0]) - 1;        \
669             if (ch >= decomp_table[i1].composed                               \
670                 && ch <= decomp_table[i2].composed)                           \
671               {                                                               \
672                 unsigned int i;                                               \
673                                                                               \
674                 for (;;)                                                      \
675                   {                                                           \
676                     i = (i1 + i2) >> 1;                                       \
677                     if (ch == decomp_table[i].composed)                       \
678                       break;                                                  \
679                     if (ch < decomp_table[i].composed)                        \
680                       {                                                       \
681                         if (i1 == i)                                          \
682                           goto failed;                                        \
683                         i2 = i;                                               \
684                       }                                                       \
685                     else                                                      \
686                       {                                                       \
687                         if (i1 != i)                                          \
688                           i1 = i;                                             \
689                         else                                                  \
690                           {                                                   \
691                             i = i2;                                           \
692                             if (ch == decomp_table[i].composed)               \
693                               break;                                          \
694                             goto failed;                                      \
695                           }                                                   \
696                       }                                                       \
697                   }                                                           \
698                                                                               \
699                 /* See whether we have room for two bytes.  */                \
700                 if (__glibc_unlikely (outptr + 1 >= outend))                  \
701                   {                                                           \
702                     result = __GCONV_FULL_OUTPUT;                             \
703                     break;                                                    \
704                   }                                                           \
705                                                                               \
706                 /* Found a canonical decomposition.  */                       \
707                 *outptr++ = decomp_table[i].base;                             \
708                 *outptr++ = decomp_table[i].comb1;                            \
709                 inptr += 4;                                                   \
710                 continue;                                                     \
711               }                                                               \
712                                                                               \
713           failed:                                                             \
714             /* This is an illegal character.  */                              \
715             STANDARD_TO_LOOP_ERR_HANDLER (4);                                 \
716           }                                                                   \
717       }                                                                       \
718   }
719 #define LOOP_NEED_FLAGS
720 #define EXTRA_LOOP_DECLS        , int *statep
721 #include <iconv/loop.c>
722
723
724 /* Now define the toplevel functions.  */
725 #include <iconv/skeleton.c>