Back to index

glibc  2.9
tcvn5712-1.c
Go to the documentation of this file.
00001 /* Conversion to and from TCVN5712-1.
00002    Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <dlfcn.h>
00022 #include <stdint.h>
00023 #include <stdlib.h>
00024 
00025 #define NELEMS(arr) (sizeof (arr) / sizeof (arr[0]))
00026 
00027 /* Definitions used in the body of the `gconv' function.  */
00028 #define CHARSET_NAME        "TCVN5712-1//"
00029 #define FROM_LOOP           from_tcvn5712_1
00030 #define TO_LOOP                    to_tcvn5712_1
00031 #define DEFINE_INIT         1
00032 #define DEFINE_FINI         1
00033 #define FROM_LOOP_MIN_NEEDED_FROM  1
00034 #define FROM_LOOP_MAX_NEEDED_FROM  1
00035 #define FROM_LOOP_MIN_NEEDED_TO           4
00036 #define FROM_LOOP_MAX_NEEDED_TO           4
00037 #define TO_LOOP_MIN_NEEDED_FROM           4
00038 #define TO_LOOP_MAX_NEEDED_FROM           4
00039 #define TO_LOOP_MIN_NEEDED_TO             1
00040 #define TO_LOOP_MAX_NEEDED_TO             2
00041 #define PREPARE_LOOP \
00042   int saved_state;                                                   \
00043   int *statep = &data->__statep->__count;
00044 #define EXTRA_LOOP_ARGS            , statep
00045 
00046 
00047 /* Since we might have to reset input pointer we must be able to save
00048    and restore the state.  */
00049 #define SAVE_RESET_STATE(Save) \
00050   if (Save)                                                          \
00051     saved_state = *statep;                                           \
00052   else                                                               \
00053     *statep = saved_state
00054 
00055 
00056 /* During TCVN5712-1 to UCS4 conversion, the COUNT element of the state
00057    contains the last UCS4 character, shifted by 3 bits.  */
00058 
00059 
00060 /* Since this is a stateful encoding we have to provide code which resets
00061    the output state to the initial state.  This has to be done during the
00062    flushing.  */
00063 #define EMIT_SHIFT_TO_INIT \
00064   if (data->__statep->__count != 0)                                         \
00065     {                                                                \
00066       if (FROM_DIRECTION)                                            \
00067        {                                                             \
00068          if (__builtin_expect (outbuf + 4 <= outend, 1))                    \
00069            {                                                         \
00070              /* Write out the last character.  */                           \
00071              *((uint32_t *) outbuf) = data->__statep->__count >> 3;         \
00072              outbuf += sizeof (uint32_t);                            \
00073              data->__statep->__count = 0;                            \
00074            }                                                         \
00075          else                                                        \
00076            /* We don't have enough room in the output buffer.  */           \
00077            status = __GCONV_FULL_OUTPUT;                             \
00078        }                                                             \
00079       else                                                           \
00080        /* We don't use shift states in the TO_DIRECTION.  */                \
00081        data->__statep->__count = 0;                                         \
00082     }
00083 
00084 
00085 static const uint16_t map_from_tcvn_low[0x18] =
00086   {
00087     0x0000, 0x00da, 0x1ee4, 0x0003, 0x1eea, 0x1eec, 0x1eee, 0x0007,
00088     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
00089     0x0010, 0x1ee8, 0x1ef0, 0x1ef2, 0x1ef6, 0x1ef8, 0x00dd, 0x1ef4
00090   };
00091 
00092 static const uint16_t map_from_tcvn_high[0x80] =
00093   {
00094     0x00c0, 0x1ea2, 0x00c3, 0x00c1, 0x1ea0, 0x1eb6, 0x1eac, 0x00c8,
00095     0x1eba, 0x1ebc, 0x00c9, 0x1eb8, 0x1ec6, 0x00cc, 0x1ec8, 0x0128,
00096     0x00cd, 0x1eca, 0x00d2, 0x1ece, 0x00d5, 0x00d3, 0x1ecc, 0x1ed8,
00097     0x1edc, 0x1ede, 0x1ee0, 0x1eda, 0x1ee2, 0x00d9, 0x1ee6, 0x0168,
00098     0x00a0, 0x0102, 0x00c2, 0x00ca, 0x00d4, 0x01a0, 0x01af, 0x0110,
00099     0x0103, 0x00e2, 0x00ea, 0x00f4, 0x01a1, 0x01b0, 0x0111, 0x1eb0,
00100     0x0300, 0x0309, 0x0303, 0x0301, 0x0323, 0x00e0, 0x1ea3, 0x00e3,
00101     0x00e1, 0x1ea1, 0x1eb2, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eaf, 0x1eb4,
00102     0x1eae, 0x1ea6, 0x1ea8, 0x1eaa, 0x1ea4, 0x1ec0, 0x1eb7, 0x1ea7,
00103     0x1ea9, 0x1eab, 0x1ea5, 0x1ead, 0x00e8, 0x1ec2, 0x1ebb, 0x1ebd,
00104     0x00e9, 0x1eb9, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ebf, 0x1ec7, 0x00ec,
00105     0x1ec9, 0x1ec4, 0x1ebe, 0x1ed2, 0x0129, 0x00ed, 0x1ecb, 0x00f2,
00106     0x1ed4, 0x1ecf, 0x00f5, 0x00f3, 0x1ecd, 0x1ed3, 0x1ed5, 0x1ed7,
00107     0x1ed1, 0x1ed9, 0x1edd, 0x1edf, 0x1ee1, 0x1edb, 0x1ee3, 0x00f9,
00108     0x1ed6, 0x1ee7, 0x0169, 0x00fa, 0x1ee5, 0x1eeb, 0x1eed, 0x1eef,
00109     0x1ee9, 0x1ef1, 0x1ef3, 0x1ef7, 0x1ef9, 0x00fd, 0x1ef5, 0x1ed0
00110   };
00111 
00112 
00113 /* TCVN5712-1 contains five combining characters:
00114    0x0300, 0x0301, 0x0303, 0x0309, 0x0323.  */
00115 
00116 /* Composition tables for each of the relevant combining characters.  */
00117 static const struct
00118 {
00119   uint16_t base;
00120   uint16_t composed;
00121 } comp_table_data[] =
00122   {
00123 #define COMP_TABLE_IDX_0300 0
00124 #define COMP_TABLE_LEN_0300 28
00125     { 0x0041, 0x00C0 },
00126     { 0x0045, 0x00C8 },
00127     { 0x0049, 0x00CC },
00128     { 0x004E, 0x01F8 },
00129     { 0x004F, 0x00D2 },
00130     { 0x0055, 0x00D9 },
00131     { 0x0057, 0x1E80 },
00132     { 0x0059, 0x1EF2 },
00133     { 0x0061, 0x00E0 },
00134     { 0x0065, 0x00E8 },
00135     { 0x0069, 0x00EC },
00136     { 0x006E, 0x01F9 },
00137     { 0x006F, 0x00F2 },
00138     { 0x0075, 0x00F9 },
00139     { 0x0077, 0x1E81 },
00140     { 0x0079, 0x1EF3 },
00141   /*{ 0x00A8, 0x1FED },*/
00142     { 0x00C2, 0x1EA6 },
00143     { 0x00CA, 0x1EC0 },
00144     { 0x00D4, 0x1ED2 },
00145   /*{ 0x00DC, 0x01DB },*/
00146     { 0x00E2, 0x1EA7 },
00147     { 0x00EA, 0x1EC1 },
00148     { 0x00F4, 0x1ED3 },
00149   /*{ 0x00FC, 0x01DC },*/
00150     { 0x0102, 0x1EB0 },
00151     { 0x0103, 0x1EB1 },
00152   /*{ 0x0112, 0x1E14 },*/
00153   /*{ 0x0113, 0x1E15 },*/
00154   /*{ 0x014C, 0x1E50 },*/
00155   /*{ 0x014D, 0x1E51 },*/
00156     { 0x01A0, 0x1EDC },
00157     { 0x01A1, 0x1EDD },
00158     { 0x01AF, 0x1EEA },
00159     { 0x01B0, 0x1EEB },
00160 #define COMP_TABLE_IDX_0301 (COMP_TABLE_IDX_0300 + COMP_TABLE_LEN_0300)
00161 #define COMP_TABLE_LEN_0301 51
00162     { 0x0041, 0x00C1 },
00163     { 0x0043, 0x0106 },
00164     { 0x0045, 0x00C9 },
00165     { 0x0047, 0x01F4 },
00166     { 0x0049, 0x00CD },
00167     { 0x004B, 0x1E30 },
00168     { 0x004C, 0x0139 },
00169     { 0x004D, 0x1E3E },
00170     { 0x004E, 0x0143 },
00171     { 0x004F, 0x00D3 },
00172     { 0x0050, 0x1E54 },
00173     { 0x0052, 0x0154 },
00174     { 0x0053, 0x015A },
00175     { 0x0055, 0x00DA },
00176     { 0x0057, 0x1E82 },
00177     { 0x0059, 0x00DD },
00178     { 0x005A, 0x0179 },
00179     { 0x0061, 0x00E1 },
00180     { 0x0063, 0x0107 },
00181     { 0x0065, 0x00E9 },
00182     { 0x0067, 0x01F5 },
00183     { 0x0069, 0x00ED },
00184     { 0x006B, 0x1E31 },
00185     { 0x006C, 0x013A },
00186     { 0x006D, 0x1E3F },
00187     { 0x006E, 0x0144 },
00188     { 0x006F, 0x00F3 },
00189     { 0x0070, 0x1E55 },
00190     { 0x0072, 0x0155 },
00191     { 0x0073, 0x015B },
00192     { 0x0075, 0x00FA },
00193     { 0x0077, 0x1E83 },
00194     { 0x0079, 0x00FD },
00195     { 0x007A, 0x017A },
00196     { 0x00A5, 0x0385 },
00197   /*{ 0x00A8, 0x1FEE },*/
00198     { 0x00C2, 0x1EA4 },
00199   /*{ 0x00C5, 0x01FA },*/
00200   /*{ 0x00C6, 0x01FC },*/
00201   /*{ 0x00C7, 0x1E08 },*/
00202     { 0x00CA, 0x1EBE },
00203   /*{ 0x00CF, 0x1E2E },*/
00204     { 0x00D4, 0x1ED0 },
00205     { 0x00D5, 0x1E4C },
00206   /*{ 0x00D8, 0x01FE },*/
00207   /*{ 0x00DC, 0x01D7 },*/
00208     { 0x00E2, 0x1EA5 },
00209   /*{ 0x00E5, 0x01FB },*/
00210   /*{ 0x00E6, 0x01FD },*/
00211   /*{ 0x00E7, 0x1E09 },*/
00212     { 0x00EA, 0x1EBF },
00213   /*{ 0x00EF, 0x1E2F },*/
00214     { 0x00F4, 0x1ED1 },
00215     { 0x00F5, 0x1E4D },
00216   /*{ 0x00F8, 0x01FF },*/
00217   /*{ 0x00FC, 0x01D8 },*/
00218     { 0x0102, 0x1EAE },
00219     { 0x0103, 0x1EAF },
00220   /*{ 0x0112, 0x1E16 },*/
00221   /*{ 0x0113, 0x1E17 },*/
00222   /*{ 0x014C, 0x1E52 },*/
00223   /*{ 0x014D, 0x1E53 },*/
00224     { 0x0168, 0x1E78 },
00225     { 0x0169, 0x1E79 },
00226     { 0x01A0, 0x1EDA },
00227     { 0x01A1, 0x1EDB },
00228     { 0x01AF, 0x1EE8 },
00229     { 0x01B0, 0x1EE9 },
00230 #define COMP_TABLE_IDX_0303 (COMP_TABLE_IDX_0301 + COMP_TABLE_LEN_0301)
00231 #define COMP_TABLE_LEN_0303 34
00232     { 0x0041, 0x00C3 },
00233     { 0x0045, 0x1EBC },
00234     { 0x0049, 0x0128 },
00235     { 0x004E, 0x00D1 },
00236     { 0x004F, 0x00D5 },
00237     { 0x0055, 0x0168 },
00238     { 0x0056, 0x1E7C },
00239     { 0x0059, 0x1EF8 },
00240     { 0x0061, 0x00E3 },
00241     { 0x0065, 0x1EBD },
00242     { 0x0069, 0x0129 },
00243     { 0x006E, 0x00F1 },
00244     { 0x006F, 0x00F5 },
00245     { 0x0075, 0x0169 },
00246     { 0x0076, 0x1E7D },
00247     { 0x0079, 0x1EF9 },
00248     { 0x00C2, 0x1EAA },
00249     { 0x00CA, 0x1EC4 },
00250     { 0x00D3, 0x1E4C },
00251     { 0x00D4, 0x1ED6 },
00252     { 0x00D6, 0x1E4E },
00253     { 0x00DA, 0x1E78 },
00254     { 0x00E2, 0x1EAB },
00255     { 0x00EA, 0x1EC5 },
00256     { 0x00F3, 0x1E4D },
00257     { 0x00F4, 0x1ED7 },
00258     { 0x00F6, 0x1E4F },
00259     { 0x00FA, 0x1E79 },
00260     { 0x0102, 0x1EB4 },
00261     { 0x0103, 0x1EB5 },
00262     { 0x01A0, 0x1EE0 },
00263     { 0x01A1, 0x1EE1 },
00264     { 0x01AF, 0x1EEE },
00265     { 0x01B0, 0x1EEF },
00266 #define COMP_TABLE_IDX_0309 (COMP_TABLE_IDX_0303 + COMP_TABLE_LEN_0303)
00267 #define COMP_TABLE_LEN_0309 24
00268     { 0x0041, 0x1EA2 },
00269     { 0x0045, 0x1EBA },
00270     { 0x0049, 0x1EC8 },
00271     { 0x004F, 0x1ECE },
00272     { 0x0055, 0x1EE6 },
00273     { 0x0059, 0x1EF6 },
00274     { 0x0061, 0x1EA3 },
00275     { 0x0065, 0x1EBB },
00276     { 0x0069, 0x1EC9 },
00277     { 0x006F, 0x1ECF },
00278     { 0x0075, 0x1EE7 },
00279     { 0x0079, 0x1EF7 },
00280     { 0x00C2, 0x1EA8 },
00281     { 0x00CA, 0x1EC2 },
00282     { 0x00D4, 0x1ED4 },
00283     { 0x00E2, 0x1EA9 },
00284     { 0x00EA, 0x1EC3 },
00285     { 0x00F4, 0x1ED5 },
00286     { 0x0102, 0x1EB2 },
00287     { 0x0103, 0x1EB3 },
00288     { 0x01A0, 0x1EDE },
00289     { 0x01A1, 0x1EDF },
00290     { 0x01AF, 0x1EEC },
00291     { 0x01B0, 0x1EED },
00292 #define COMP_TABLE_IDX_0323 (COMP_TABLE_IDX_0309 + COMP_TABLE_LEN_0309)
00293 #define COMP_TABLE_LEN_0323 50
00294     { 0x0041, 0x1EA0 },
00295     { 0x0042, 0x1E04 },
00296     { 0x0044, 0x1E0C },
00297     { 0x0045, 0x1EB8 },
00298     { 0x0048, 0x1E24 },
00299     { 0x0049, 0x1ECA },
00300     { 0x004B, 0x1E32 },
00301     { 0x004C, 0x1E36 },
00302     { 0x004D, 0x1E42 },
00303     { 0x004E, 0x1E46 },
00304     { 0x004F, 0x1ECC },
00305     { 0x0052, 0x1E5A },
00306     { 0x0053, 0x1E62 },
00307     { 0x0054, 0x1E6C },
00308     { 0x0055, 0x1EE4 },
00309     { 0x0056, 0x1E7E },
00310     { 0x0057, 0x1E88 },
00311     { 0x0059, 0x1EF4 },
00312     { 0x005A, 0x1E92 },
00313     { 0x0061, 0x1EA1 },
00314     { 0x0062, 0x1E05 },
00315     { 0x0064, 0x1E0D },
00316     { 0x0065, 0x1EB9 },
00317     { 0x0068, 0x1E25 },
00318     { 0x0069, 0x1ECB },
00319     { 0x006B, 0x1E33 },
00320     { 0x006C, 0x1E37 },
00321     { 0x006D, 0x1E43 },
00322     { 0x006E, 0x1E47 },
00323     { 0x006F, 0x1ECD },
00324     { 0x0072, 0x1E5B },
00325     { 0x0073, 0x1E63 },
00326     { 0x0074, 0x1E6D },
00327     { 0x0075, 0x1EE5 },
00328     { 0x0076, 0x1E7F },
00329     { 0x0077, 0x1E89 },
00330     { 0x0079, 0x1EF5 },
00331     { 0x007A, 0x1E93 },
00332     { 0x00C2, 0x1EAC },
00333     { 0x00CA, 0x1EC6 },
00334     { 0x00D4, 0x1ED8 },
00335     { 0x00E2, 0x1EAD },
00336     { 0x00EA, 0x1EC7 },
00337     { 0x00F4, 0x1ED9 },
00338     { 0x0102, 0x1EB6 },
00339     { 0x0103, 0x1EB7 },
00340     { 0x01A0, 0x1EE2 },
00341     { 0x01A1, 0x1EE3 },
00342     { 0x01AF, 0x1EF0 },
00343     { 0x01B0, 0x1EF1 },
00344 #define COMP_TABLE_IDX_END (COMP_TABLE_IDX_0323 + COMP_TABLE_LEN_0323)
00345   };
00346 /* Compile-time verification of table size.  */
00347 typedef int verify1[(NELEMS (comp_table_data) == COMP_TABLE_IDX_END) - 1];
00348 
00349 static const struct
00350 {
00351   unsigned int idx;
00352   unsigned int len;
00353 } comp_table[5] =
00354   {
00355     { COMP_TABLE_IDX_0300, COMP_TABLE_LEN_0300 },
00356     { COMP_TABLE_IDX_0301, COMP_TABLE_LEN_0301 },
00357     { COMP_TABLE_IDX_0303, COMP_TABLE_LEN_0303 },
00358     { COMP_TABLE_IDX_0309, COMP_TABLE_LEN_0309 },
00359     { COMP_TABLE_IDX_0323, COMP_TABLE_LEN_0323 },
00360   };
00361 
00362 
00363 /* First define the conversion function from TCVN5712-1 to UCS4.  */
00364 #define MIN_NEEDED_INPUT    FROM_LOOP_MIN_NEEDED_FROM
00365 #define MAX_NEEDED_INPUT    FROM_LOOP_MAX_NEEDED_FROM
00366 #define MIN_NEEDED_OUTPUT   FROM_LOOP_MIN_NEEDED_TO
00367 #define MAX_NEEDED_OUTPUT   FROM_LOOP_MAX_NEEDED_TO
00368 #define LOOPFCT                    FROM_LOOP
00369 #define BODY \
00370   {                                                                  \
00371     uint32_t ch = *inptr;                                            \
00372     uint32_t last_ch;                                                       \
00373     int must_buffer_ch;                                                     \
00374                                                                      \
00375     if (ch < 0x18)                                                   \
00376       ch = map_from_tcvn_low[ch];                                    \
00377     else if (ch >= 0x80)                                             \
00378       ch = map_from_tcvn_high[ch - 0x80];                            \
00379                                                                      \
00380     /* Determine whether there is a buffered character pending.  */         \
00381     last_ch = *statep >> 3;                                          \
00382                                                                      \
00383     /* We have to buffer ch if it is a possible match in comp_table_data.  */ \
00384     must_buffer_ch = (ch >= 0x0041 && ch <= 0x01b0);                        \
00385                                                                      \
00386     if (last_ch)                                                     \
00387       {                                                                     \
00388        if (ch >= 0x0300 && ch < 0x0340)                              \
00389          {                                                           \
00390            /* See whether last_ch and ch can be combined.  */               \
00391            unsigned int i;                                           \
00392            unsigned int i1;                                          \
00393            unsigned int i2;                                          \
00394                                                                      \
00395            switch (ch)                                                      \
00396              {                                                              \
00397              case 0x0300:                                            \
00398               i = 0;                                                 \
00399               break;                                                 \
00400              case 0x0301:                                            \
00401               i = 1;                                                 \
00402               break;                                                 \
00403              case 0x0303:                                            \
00404               i = 2;                                                 \
00405               break;                                                 \
00406              case 0x0309:                                            \
00407               i = 3;                                                 \
00408               break;                                                 \
00409              case 0x0323:                                            \
00410               i = 4;                                                 \
00411               break;                                                 \
00412              default:                                                       \
00413               abort ();                                              \
00414              }                                                              \
00415                                                                      \
00416            i1 = comp_table[i].idx;                                   \
00417            i2 = i1 + comp_table[i].len - 1;                                 \
00418                                                                      \
00419            if (last_ch >= comp_table_data[i1].base                          \
00420               && last_ch <= comp_table_data[i2].base)                       \
00421              {                                                              \
00422               for (;;)                                               \
00423                 {                                                    \
00424                   i = (i1 + i2) >> 1;                                       \
00425                   if (last_ch == comp_table_data[i].base)                   \
00426                     break;                                           \
00427                   if (last_ch < comp_table_data[i].base)                    \
00428                     {                                                       \
00429                      if (i1 == i)                                    \
00430                        goto not_combining;                                  \
00431                      i2 = i;                                                \
00432                     }                                                       \
00433                   else                                               \
00434                     {                                                       \
00435                      if (i1 != i)                                    \
00436                        i1 = i;                                       \
00437                      else                                            \
00438                        {                                             \
00439                          i = i2;                                     \
00440                          if (last_ch == comp_table_data[i].base)            \
00441                            break;                                    \
00442                          goto not_combining;                                \
00443                        }                                             \
00444                     }                                                       \
00445                 }                                                    \
00446               last_ch = comp_table_data[i].composed;                        \
00447               /* Output the combined character.  */                         \
00448               put32 (outptr, last_ch);                               \
00449               outptr += 4;                                           \
00450               *statep = 0;                                           \
00451               ++inptr;                                               \
00452               continue;                                              \
00453              }                                                              \
00454          }                                                           \
00455                                                                      \
00456       not_combining:                                                 \
00457        /* Output the buffered character.  */                                \
00458        put32 (outptr, last_ch);                                      \
00459        outptr += 4;                                                  \
00460        *statep = 0;                                                  \
00461                                                                      \
00462        /* If we don't have enough room to output ch as well, then deal             \
00463           with it in another round.  */                              \
00464        if (!must_buffer_ch && __builtin_expect (outptr + 4 > outend, 0))     \
00465          continue;                                                   \
00466       }                                                                     \
00467                                                                      \
00468     if (must_buffer_ch)                                                     \
00469       *statep = ch << 3;                                             \
00470     else                                                             \
00471       {                                                                     \
00472        put32 (outptr, ch);                                           \
00473        outptr += 4;                                                  \
00474       }                                                                     \
00475     ++inptr;                                                         \
00476   }
00477 #define EXTRA_LOOP_DECLS    , int *statep
00478 #define ONEBYTE_BODY \
00479   {                                                                  \
00480     uint32_t ch;                                                     \
00481                                                                      \
00482     if (c < 0x18)                                                    \
00483       ch = map_from_tcvn_low[c];                                     \
00484     else if (c >= 0x80)                                                     \
00485       ch = map_from_tcvn_high[c - 0x80];                             \
00486     else                                                             \
00487       ch = c;                                                        \
00488     if (ch >= 0x0041 && ch <= 0x01b0)                                       \
00489       return WEOF;                                                   \
00490     return ch;                                                              \
00491   }
00492 #include <iconv/loop.c>
00493 
00494 
00495 /* Next, define the conversion function from UCS4 to CP1258.  */
00496 
00497 static const unsigned char from_ucs4[] =
00498   {
00499 #define FROM_IDX_00 0
00500     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, /* 0x0001-0x0007 */
00501     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x0008-0x000f */
00502     0x10,                                           /* 0x0010-0x0010 */
00503 
00504 #define FROM_IDX_01 (FROM_IDX_00 + 16)
00505     0x80, 0x83, 0xa2, 0x82, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00c7 */
00506     0x87, 0x8a, 0xa3, 0x00, 0x8d, 0x90, 0x00, 0x00, /* 0x00c8-0x00cf */
00507     0x00, 0x00, 0x92, 0x95, 0xa4, 0x94, 0x00, 0x00, /* 0x00d0-0x00d7 */
00508     0x00, 0x9d, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, /* 0x00d8-0x00df */
00509     0xb5, 0xb8, 0xa9, 0xb7, 0x00, 0x00, 0x00, 0x00, /* 0x00e0-0x00e7 */
00510     0xcc, 0xd0, 0xaa, 0x00, 0xd7, 0xdd, 0x00, 0x00, /* 0x00e8-0x00ef */
00511     0x00, 0x00, 0xdf, 0xe3, 0xab, 0xe2, 0x00, 0x00, /* 0x00f0-0x00f7 */
00512     0x00, 0xef, 0xf3, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0x00f8-0x00ff */
00513     0x00, 0x00, 0xa1, 0xa8, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x0107 */
00514     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0108-0x010f */
00515     0xa7, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0110-0x0117 */
00516     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0118-0x011f */
00517     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0120-0x0127 */
00518     0x8f, 0xdc,                                     /* 0x0128-0x0129 */
00519 
00520 #define FROM_IDX_02 (FROM_IDX_01 + 106)
00521     0x9f, 0xf2,                                     /* 0x0168-0x0169 */
00522 
00523 #define FROM_IDX_03 (FROM_IDX_02 + 2)
00524     0xa5, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01a0-0x01a7 */
00525     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, /* 0x01a8-0x01af */
00526     0xad,                                           /* 0x01b0-0x01b0 */
00527 
00528 #define FROM_IDX_04 (FROM_IDX_03 + 17)
00529     0xb0, 0xb3, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x0300-0x0307 */
00530     0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0308-0x030f */
00531     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0310-0x0317 */
00532     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0318-0x031f */
00533     0x00, 0x00, 0x00, 0xb4,                         /* 0x0320-0x0323 */
00534 
00535 #define FROM_IDX_05 (FROM_IDX_04 + 36)
00536     0x84, 0xb9, 0x81, 0xb6, 0xc4, 0xca, 0xc1, 0xc7, /* 0x1ea0-0x1ea7 */
00537     0xc2, 0xc8, 0xc3, 0xc9, 0x86, 0xcb, 0xc0, 0xbe, /* 0x1ea8-0x1eaf */
00538     0xaf, 0xbb, 0xba, 0xbc, 0xbf, 0xbd, 0x85, 0xc6, /* 0x1eb0-0x1eb7 */
00539     0x8b, 0xd1, 0x88, 0xce, 0x89, 0xcf, 0xda, 0xd5, /* 0x1eb8-0x1ebf */
00540     0xc5, 0xd2, 0xcd, 0xd3, 0xd9, 0xd4, 0x8c, 0xd6, /* 0x1ec0-0x1ec7 */
00541     0x8e, 0xd8, 0x91, 0xde, 0x96, 0xe4, 0x93, 0xe1, /* 0x1ec8-0x1ecf */
00542     0xff, 0xe8, 0xdb, 0xe5, 0xe0, 0xe6, 0xf0, 0xe7, /* 0x1ed0-0x1ed7 */
00543     0x97, 0xe9, 0x9b, 0xed, 0x98, 0xea, 0x99, 0xeb, /* 0x1ed8-0x1edf */
00544     0x9a, 0xec, 0x9c, 0xee, 0x02, 0xf4, 0x9e, 0xf1, /* 0x1ee0-0x1ee7 */
00545     0x11, 0xf8, 0x04, 0xf5, 0x05, 0xf6, 0x06, 0xf7, /* 0x1ee8-0x1eef */
00546     0x12, 0xf9, 0x13, 0xfa, 0x17, 0xfe, 0x14, 0xfb, /* 0x1ef0-0x1ef7 */
00547     0x15, 0xfc                                      /* 0x1ef8-0x1ef9 */
00548 #define FROM_IDX_END (FROM_IDX_05 + 90)
00549   };
00550 /* Compile-time verification of table size.  */
00551 typedef int verify2[(NELEMS (from_ucs4) == FROM_IDX_END) - 1];
00552 
00553 /* Decomposition table for the relevant Unicode characters. */
00554 static const struct
00555 {
00556   uint16_t composed;
00557   uint32_t base:8;
00558   uint32_t comb1:8;
00559 } decomp_table[] =
00560   {
00561     { 0x00d1, 0x4e, 0xb2 },
00562     { 0x00f1, 0x6e, 0xb2 },
00563     { 0x0106, 0x43, 0xb3 },
00564     { 0x0107, 0x63, 0xb3 },
00565     { 0x0139, 0x4c, 0xb3 },
00566     { 0x013a, 0x6c, 0xb3 },
00567     { 0x0143, 0x4e, 0xb3 },
00568     { 0x0144, 0x6e, 0xb3 },
00569     { 0x0154, 0x52, 0xb3 },
00570     { 0x0155, 0x72, 0xb3 },
00571     { 0x015a, 0x53, 0xb3 },
00572     { 0x015b, 0x73, 0xb3 },
00573     { 0x0179, 0x5a, 0xb3 },
00574     { 0x017a, 0x7a, 0xb3 },
00575     { 0x01f4, 0x47, 0xb3 },
00576     { 0x01f5, 0x67, 0xb3 },
00577     { 0x01f8, 0x4e, 0xb0 },
00578     { 0x01f9, 0x6e, 0xb0 },
00579     { 0x1e04, 0x42, 0xb4 },
00580     { 0x1e05, 0x62, 0xb4 },
00581     { 0x1e0c, 0x44, 0xb4 },
00582     { 0x1e0d, 0x64, 0xb4 },
00583     { 0x1e24, 0x48, 0xb4 },
00584     { 0x1e25, 0x68, 0xb4 },
00585     { 0x1e30, 0x4b, 0xb3 },
00586     { 0x1e31, 0x6b, 0xb3 },
00587     { 0x1e32, 0x4b, 0xb4 },
00588     { 0x1e33, 0x6b, 0xb4 },
00589     { 0x1e36, 0x4c, 0xb4 },
00590     { 0x1e37, 0x6c, 0xb4 },
00591     { 0x1e3e, 0x4d, 0xb3 },
00592     { 0x1e3f, 0x6d, 0xb3 },
00593     { 0x1e42, 0x4d, 0xb4 },
00594     { 0x1e43, 0x6d, 0xb4 },
00595     { 0x1e46, 0x4e, 0xb4 },
00596     { 0x1e47, 0x6e, 0xb4 },
00597     { 0x1e54, 0x50, 0xb3 },
00598     { 0x1e55, 0x70, 0xb3 },
00599     { 0x1e5a, 0x52, 0xb4 },
00600     { 0x1e5b, 0x72, 0xb4 },
00601     { 0x1e62, 0x53, 0xb4 },
00602     { 0x1e63, 0x73, 0xb4 },
00603     { 0x1e6c, 0x54, 0xb4 },
00604     { 0x1e6d, 0x74, 0xb4 },
00605     { 0x1e7c, 0x56, 0xb2 },
00606     { 0x1e7d, 0x76, 0xb2 },
00607     { 0x1e7e, 0x56, 0xb4 },
00608     { 0x1e7f, 0x76, 0xb4 },
00609     { 0x1e80, 0x57, 0xb0 },
00610     { 0x1e81, 0x77, 0xb0 },
00611     { 0x1e82, 0x57, 0xb3 },
00612     { 0x1e83, 0x77, 0xb3 },
00613     { 0x1e88, 0x57, 0xb4 },
00614     { 0x1e89, 0x77, 0xb4 },
00615     { 0x1e92, 0x5a, 0xb4 },
00616     { 0x1e93, 0x7a, 0xb4 },
00617   };
00618 
00619 
00620 /* Next, define the other direction.  */
00621 #define MIN_NEEDED_INPUT    TO_LOOP_MIN_NEEDED_FROM
00622 #define MAX_NEEDED_INPUT    TO_LOOP_MAX_NEEDED_FROM
00623 #define MIN_NEEDED_OUTPUT   TO_LOOP_MIN_NEEDED_TO
00624 #define MAX_NEEDED_OUTPUT   TO_LOOP_MAX_NEEDED_TO
00625 #define LOOPFCT                    TO_LOOP
00626 #define BODY \
00627   {                                                                  \
00628     uint32_t ch = get32 (inptr);                                     \
00629                                                                      \
00630     if (ch == 0x00 || (ch >= 0x18 && ch < 0x80) || ch == 0xa0)              \
00631       {                                                                     \
00632        *outptr++ = ch;                                                      \
00633        inptr += 4;                                                   \
00634       }                                                                     \
00635     else                                                             \
00636       {                                                                     \
00637        unsigned char res;                                            \
00638                                                                      \
00639        if (ch <= 0x0010)                                             \
00640          res = from_ucs4[ch - 0x0001 + FROM_IDX_00];                        \
00641        else if (ch >= 0x00c0 && ch <= 0x0129)                               \
00642          res = from_ucs4[ch - 0x00c0 + FROM_IDX_01];                        \
00643        else if (ch >= 0x0168 && ch <= 0x0169)                               \
00644          res = from_ucs4[ch - 0x0168 + FROM_IDX_02];                        \
00645        else if (ch >= 0x01a0 && ch <= 0x01b0)                               \
00646          res = from_ucs4[ch - 0x01a0 + FROM_IDX_03];                        \
00647        else if (ch >= 0x0300 && ch <= 0x0323)                               \
00648          res = from_ucs4[ch - 0x0300 + FROM_IDX_04];                        \
00649        else if (ch >= 0x1ea0 && ch <= 0x1ef9)                               \
00650          res = from_ucs4[ch - 0x1ea0 + FROM_IDX_05];                        \
00651        else                                                          \
00652          {                                                           \
00653            UNICODE_TAG_HANDLER (ch, 4);                              \
00654            res = 0;                                                  \
00655          }                                                           \
00656                                                                      \
00657        if (__builtin_expect (res != 0, 1))                                  \
00658          {                                                           \
00659            *outptr++ = res;                                          \
00660            inptr += 4;                                                      \
00661          }                                                           \
00662        else                                                          \
00663          {                                                           \
00664            /* Try canonical decomposition.  */                              \
00665            unsigned int i1;                                          \
00666            unsigned int i2;                                          \
00667                                                                      \
00668            i1 = 0;                                                   \
00669            i2 = sizeof (decomp_table) / sizeof (decomp_table[0]) - 1;       \
00670            if (ch >= decomp_table[i1].composed                              \
00671               && ch <= decomp_table[i2].composed)                           \
00672              {                                                              \
00673               unsigned int i;                                               \
00674                                                                      \
00675               for (;;)                                               \
00676                 {                                                    \
00677                   i = (i1 + i2) >> 1;                                       \
00678                   if (ch == decomp_table[i].composed)                       \
00679                     break;                                           \
00680                   if (ch < decomp_table[i].composed)                        \
00681                     {                                                       \
00682                      if (i1 == i)                                    \
00683                        goto failed;                                         \
00684                      i2 = i;                                                \
00685                     }                                                       \
00686                   else                                               \
00687                     {                                                       \
00688                      if (i1 != i)                                    \
00689                        i1 = i;                                       \
00690                      else                                            \
00691                        {                                             \
00692                          i = i2;                                     \
00693                          if (ch == decomp_table[i].composed)                \
00694                            break;                                    \
00695                          goto failed;                                \
00696                        }                                             \
00697                     }                                                       \
00698                 }                                                    \
00699                                                                      \
00700               /* See whether we have room for two bytes.  */                \
00701               if (__builtin_expect (outptr + 1 >= outend, 0))               \
00702                 {                                                    \
00703                   result = __GCONV_FULL_OUTPUT;                      \
00704                   break;                                             \
00705                 }                                                    \
00706                                                                      \
00707               /* Found a canonical decomposition.  */                       \
00708               *outptr++ = decomp_table[i].base;                      \
00709               *outptr++ = decomp_table[i].comb1;                     \
00710               inptr += 4;                                            \
00711               continue;                                              \
00712              }                                                              \
00713                                                                      \
00714          failed:                                                     \
00715            /* This is an illegal character.  */                      \
00716            STANDARD_TO_LOOP_ERR_HANDLER (4);                                \
00717          }                                                           \
00718       }                                                                     \
00719   }
00720 #define LOOP_NEED_FLAGS
00721 #define EXTRA_LOOP_DECLS    , int *statep
00722 #include <iconv/loop.c>
00723 
00724 
00725 /* Now define the toplevel functions.  */
00726 #include <iconv/skeleton.c>