Back to index

glibc  2.9
cp1258.c
Go to the documentation of this file.
00001 /* Conversion from and to CP1258.
00002    Copyright (C) 1998, 2001, 2002, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
00005    and Bruno Haible <haible@clisp.cons.org>, 2001.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <dlfcn.h>
00023 #include <stdint.h>
00024 #include <assert.h>
00025 #include <stdlib.h>
00026 
00027 #define NELEMS(arr) (sizeof (arr) / sizeof (arr[0]))
00028 
00029 /* Definitions used in the body of the `gconv' function.  */
00030 #define CHARSET_NAME        "CP1258//"
00031 #define FROM_LOOP           from_cp1258
00032 #define TO_LOOP                    to_cp1258
00033 #define DEFINE_INIT         1
00034 #define DEFINE_FINI         1
00035 #define FROM_LOOP_MIN_NEEDED_FROM  1
00036 #define FROM_LOOP_MAX_NEEDED_FROM  1
00037 #define FROM_LOOP_MIN_NEEDED_TO           4
00038 #define FROM_LOOP_MAX_NEEDED_TO           4
00039 #define TO_LOOP_MIN_NEEDED_FROM           4
00040 #define TO_LOOP_MAX_NEEDED_FROM           4
00041 #define TO_LOOP_MIN_NEEDED_TO             1
00042 #define TO_LOOP_MAX_NEEDED_TO             2
00043 #define PREPARE_LOOP \
00044   int saved_state;                                                   \
00045   int *statep = &data->__statep->__count;
00046 #define EXTRA_LOOP_ARGS            , statep
00047 
00048 
00049 /* Since we might have to reset input pointer we must be able to save
00050    and restore the state.  */
00051 #define SAVE_RESET_STATE(Save) \
00052   if (Save)                                                          \
00053     saved_state = *statep;                                           \
00054   else                                                               \
00055     *statep = saved_state
00056 
00057 
00058 /* During CP1258 to UCS4 conversion, the COUNT element of the state
00059    contains the last UCS4 character, shifted by 3 bits.  */
00060 
00061 
00062 /* Since this is a stateful encoding we have to provide code which resets
00063    the output state to the initial state.  This has to be done during the
00064    flushing.  */
00065 #define EMIT_SHIFT_TO_INIT \
00066   if (data->__statep->__count != 0)                                         \
00067     {                                                                \
00068       if (FROM_DIRECTION)                                            \
00069        {                                                             \
00070          if (__builtin_expect (outbuf + 4 <= outend, 1))                    \
00071            {                                                         \
00072              /* Write out the last character.  */                           \
00073              *((uint32_t *) outbuf) = data->__statep->__count >> 3;         \
00074              outbuf += sizeof (uint32_t);                            \
00075              data->__statep->__count = 0;                            \
00076            }                                                         \
00077          else                                                        \
00078            /* We don't have enough room in the output buffer.  */           \
00079            status = __GCONV_FULL_OUTPUT;                             \
00080        }                                                             \
00081       else                                                           \
00082        /* We don't use shift states in the TO_DIRECTION.  */                \
00083        data->__statep->__count = 0;                                         \
00084     }
00085 
00086 
00087 /* First define the conversion function from CP1258 to UCS4.  */
00088 
00089 static const uint16_t to_ucs4[128] =
00090   {
00091     /* 0x80 */
00092     0x20AC,      0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
00093     0x02C6, 0x2030,      0, 0x2039, 0x0152,      0,      0,      0,
00094     /* 0x90 */
00095          0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
00096     0x02DC, 0x2122,      0, 0x203A, 0x0153,      0,      0, 0x0178,
00097     /* 0xA0 */
00098     0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
00099     0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
00100     /* 0xB0 */
00101     0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
00102     0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
00103     /* 0xC0 */
00104     0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
00105     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
00106     /* 0xD0 */
00107     0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
00108     0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
00109     /* 0xE0 */
00110     0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
00111     0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
00112     /* 0xF0 */
00113     0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
00114     0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF,
00115   };
00116 
00117 /* CP1258 contains five combining characters:
00118    0x0300, 0x0301, 0x0303, 0x0309, 0x0323.  */
00119 
00120 /* Composition tables for each of the relevant combining characters.  */
00121 static const struct
00122 {
00123   uint16_t base;
00124   uint16_t composed;
00125 } comp_table_data[] =
00126   {
00127 #define COMP_TABLE_IDX_0300 0
00128 #define COMP_TABLE_LEN_0300 31
00129     { 0x0041, 0x00C0 },
00130     { 0x0045, 0x00C8 },
00131     { 0x0049, 0x00CC },
00132     { 0x004E, 0x01F8 },
00133     { 0x004F, 0x00D2 },
00134     { 0x0055, 0x00D9 },
00135     { 0x0057, 0x1E80 },
00136     { 0x0059, 0x1EF2 },
00137     { 0x0061, 0x00E0 },
00138     { 0x0065, 0x00E8 },
00139     { 0x0069, 0x00EC },
00140     { 0x006E, 0x01F9 },
00141     { 0x006F, 0x00F2 },
00142     { 0x0075, 0x00F9 },
00143     { 0x0077, 0x1E81 },
00144     { 0x0079, 0x1EF3 },
00145     { 0x00A8, 0x1FED },
00146     { 0x00C2, 0x1EA6 },
00147     { 0x00CA, 0x1EC0 },
00148     { 0x00D4, 0x1ED2 },
00149     { 0x00DC, 0x01DB },
00150     { 0x00E2, 0x1EA7 },
00151     { 0x00EA, 0x1EC1 },
00152     { 0x00F4, 0x1ED3 },
00153     { 0x00FC, 0x01DC },
00154     { 0x0102, 0x1EB0 },
00155     { 0x0103, 0x1EB1 },
00156     /*{ 0x0112, 0x1E14 },*/
00157     /*{ 0x0113, 0x1E15 },*/
00158     /*{ 0x014C, 0x1E50 },*/
00159     /*{ 0x014D, 0x1E51 },*/
00160     { 0x01A0, 0x1EDC },
00161     { 0x01A1, 0x1EDD },
00162     { 0x01AF, 0x1EEA },
00163     { 0x01B0, 0x1EEB },
00164 #define COMP_TABLE_IDX_0301 (COMP_TABLE_IDX_0300 + COMP_TABLE_LEN_0300)
00165 #define COMP_TABLE_LEN_0301 60
00166     { 0x0041, 0x00C1 },
00167     { 0x0043, 0x0106 },
00168     { 0x0045, 0x00C9 },
00169     { 0x0047, 0x01F4 },
00170     { 0x0049, 0x00CD },
00171     { 0x004B, 0x1E30 },
00172     { 0x004C, 0x0139 },
00173     { 0x004D, 0x1E3E },
00174     { 0x004E, 0x0143 },
00175     { 0x004F, 0x00D3 },
00176     { 0x0050, 0x1E54 },
00177     { 0x0052, 0x0154 },
00178     { 0x0053, 0x015A },
00179     { 0x0055, 0x00DA },
00180     { 0x0057, 0x1E82 },
00181     { 0x0059, 0x00DD },
00182     { 0x005A, 0x0179 },
00183     { 0x0061, 0x00E1 },
00184     { 0x0063, 0x0107 },
00185     { 0x0065, 0x00E9 },
00186     { 0x0067, 0x01F5 },
00187     { 0x0069, 0x00ED },
00188     { 0x006B, 0x1E31 },
00189     { 0x006C, 0x013A },
00190     { 0x006D, 0x1E3F },
00191     { 0x006E, 0x0144 },
00192     { 0x006F, 0x00F3 },
00193     { 0x0070, 0x1E55 },
00194     { 0x0072, 0x0155 },
00195     { 0x0073, 0x015B },
00196     { 0x0075, 0x00FA },
00197     { 0x0077, 0x1E83 },
00198     { 0x0079, 0x00FD },
00199     { 0x007A, 0x017A },
00200     { 0x00A5, 0x0385 },
00201     { 0x00A8, 0x1FEE },
00202     { 0x00C2, 0x1EA4 },
00203     { 0x00C5, 0x01FA },
00204     { 0x00C6, 0x01FC },
00205     { 0x00C7, 0x1E08 },
00206     { 0x00CA, 0x1EBE },
00207     { 0x00CF, 0x1E2E },
00208     { 0x00D4, 0x1ED0 },
00209     /*{ 0x00D5, 0x1E4C },*/
00210     { 0x00D8, 0x01FE },
00211     { 0x00DC, 0x01D7 },
00212     { 0x00E2, 0x1EA5 },
00213     { 0x00E5, 0x01FB },
00214     { 0x00E6, 0x01FD },
00215     { 0x00E7, 0x1E09 },
00216     { 0x00EA, 0x1EBF },
00217     { 0x00EF, 0x1E2F },
00218     { 0x00F4, 0x1ED1 },
00219     /*{ 0x00F5, 0x1E4D },*/
00220     { 0x00F8, 0x01FF },
00221     { 0x00FC, 0x01D8 },
00222     { 0x0102, 0x1EAE },
00223     { 0x0103, 0x1EAF },
00224     /*{ 0x0112, 0x1E16 },*/
00225     /*{ 0x0113, 0x1E17 },*/
00226     /*{ 0x014C, 0x1E52 },*/
00227     /*{ 0x014D, 0x1E53 },*/
00228     /*{ 0x0168, 0x1E78 },*/
00229     /*{ 0x0169, 0x1E79 },*/
00230     { 0x01A0, 0x1EDA },
00231     { 0x01A1, 0x1EDB },
00232     { 0x01AF, 0x1EE8 },
00233     { 0x01B0, 0x1EE9 },
00234 #define COMP_TABLE_IDX_0303 (COMP_TABLE_IDX_0301 + COMP_TABLE_LEN_0301)
00235 #define COMP_TABLE_LEN_0303 34
00236     { 0x0041, 0x00C3 },
00237     { 0x0045, 0x1EBC },
00238     { 0x0049, 0x0128 },
00239     { 0x004E, 0x00D1 },
00240     { 0x004F, 0x00D5 },
00241     { 0x0055, 0x0168 },
00242     { 0x0056, 0x1E7C },
00243     { 0x0059, 0x1EF8 },
00244     { 0x0061, 0x00E3 },
00245     { 0x0065, 0x1EBD },
00246     { 0x0069, 0x0129 },
00247     { 0x006E, 0x00F1 },
00248     { 0x006F, 0x00F5 },
00249     { 0x0075, 0x0169 },
00250     { 0x0076, 0x1E7D },
00251     { 0x0079, 0x1EF9 },
00252     { 0x00C2, 0x1EAA },
00253     { 0x00CA, 0x1EC4 },
00254     { 0x00D3, 0x1E4C },
00255     { 0x00D4, 0x1ED6 },
00256     { 0x00D6, 0x1E4E },
00257     { 0x00DA, 0x1E78 },
00258     { 0x00E2, 0x1EAB },
00259     { 0x00EA, 0x1EC5 },
00260     { 0x00F3, 0x1E4D },
00261     { 0x00F4, 0x1ED7 },
00262     { 0x00F6, 0x1E4F },
00263     { 0x00FA, 0x1E79 },
00264     { 0x0102, 0x1EB4 },
00265     { 0x0103, 0x1EB5 },
00266     { 0x01A0, 0x1EE0 },
00267     { 0x01A1, 0x1EE1 },
00268     { 0x01AF, 0x1EEE },
00269     { 0x01B0, 0x1EEF },
00270 #define COMP_TABLE_IDX_0309 (COMP_TABLE_IDX_0303 + COMP_TABLE_LEN_0303)
00271 #define COMP_TABLE_LEN_0309 24
00272     { 0x0041, 0x1EA2 },
00273     { 0x0045, 0x1EBA },
00274     { 0x0049, 0x1EC8 },
00275     { 0x004F, 0x1ECE },
00276     { 0x0055, 0x1EE6 },
00277     { 0x0059, 0x1EF6 },
00278     { 0x0061, 0x1EA3 },
00279     { 0x0065, 0x1EBB },
00280     { 0x0069, 0x1EC9 },
00281     { 0x006F, 0x1ECF },
00282     { 0x0075, 0x1EE7 },
00283     { 0x0079, 0x1EF7 },
00284     { 0x00C2, 0x1EA8 },
00285     { 0x00CA, 0x1EC2 },
00286     { 0x00D4, 0x1ED4 },
00287     { 0x00E2, 0x1EA9 },
00288     { 0x00EA, 0x1EC3 },
00289     { 0x00F4, 0x1ED5 },
00290     { 0x0102, 0x1EB2 },
00291     { 0x0103, 0x1EB3 },
00292     { 0x01A0, 0x1EDE },
00293     { 0x01A1, 0x1EDF },
00294     { 0x01AF, 0x1EEC },
00295     { 0x01B0, 0x1EED },
00296 #define COMP_TABLE_IDX_0323 (COMP_TABLE_IDX_0309 + COMP_TABLE_LEN_0309)
00297 #define COMP_TABLE_LEN_0323 50
00298     { 0x0041, 0x1EA0 },
00299     { 0x0042, 0x1E04 },
00300     { 0x0044, 0x1E0C },
00301     { 0x0045, 0x1EB8 },
00302     { 0x0048, 0x1E24 },
00303     { 0x0049, 0x1ECA },
00304     { 0x004B, 0x1E32 },
00305     { 0x004C, 0x1E36 },
00306     { 0x004D, 0x1E42 },
00307     { 0x004E, 0x1E46 },
00308     { 0x004F, 0x1ECC },
00309     { 0x0052, 0x1E5A },
00310     { 0x0053, 0x1E62 },
00311     { 0x0054, 0x1E6C },
00312     { 0x0055, 0x1EE4 },
00313     { 0x0056, 0x1E7E },
00314     { 0x0057, 0x1E88 },
00315     { 0x0059, 0x1EF4 },
00316     { 0x005A, 0x1E92 },
00317     { 0x0061, 0x1EA1 },
00318     { 0x0062, 0x1E05 },
00319     { 0x0064, 0x1E0D },
00320     { 0x0065, 0x1EB9 },
00321     { 0x0068, 0x1E25 },
00322     { 0x0069, 0x1ECB },
00323     { 0x006B, 0x1E33 },
00324     { 0x006C, 0x1E37 },
00325     { 0x006D, 0x1E43 },
00326     { 0x006E, 0x1E47 },
00327     { 0x006F, 0x1ECD },
00328     { 0x0072, 0x1E5B },
00329     { 0x0073, 0x1E63 },
00330     { 0x0074, 0x1E6D },
00331     { 0x0075, 0x1EE5 },
00332     { 0x0076, 0x1E7F },
00333     { 0x0077, 0x1E89 },
00334     { 0x0079, 0x1EF5 },
00335     { 0x007A, 0x1E93 },
00336     { 0x00C2, 0x1EAC },
00337     { 0x00CA, 0x1EC6 },
00338     { 0x00D4, 0x1ED8 },
00339     { 0x00E2, 0x1EAD },
00340     { 0x00EA, 0x1EC7 },
00341     { 0x00F4, 0x1ED9 },
00342     { 0x0102, 0x1EB6 },
00343     { 0x0103, 0x1EB7 },
00344     { 0x01A0, 0x1EE2 },
00345     { 0x01A1, 0x1EE3 },
00346     { 0x01AF, 0x1EF0 },
00347     { 0x01B0, 0x1EF1 },
00348 #define COMP_TABLE_IDX_END (COMP_TABLE_IDX_0323 + COMP_TABLE_LEN_0323)
00349   };
00350 /* Compile-time verification of table size.  */
00351 typedef int verify1[(NELEMS (comp_table_data) == COMP_TABLE_IDX_END) - 1];
00352 
00353 static const struct
00354 {
00355   unsigned int idx;
00356   unsigned int len;
00357 } comp_table[5] =
00358   {
00359     { COMP_TABLE_IDX_0300, COMP_TABLE_LEN_0300 },
00360     { COMP_TABLE_IDX_0301, COMP_TABLE_LEN_0301 },
00361     { COMP_TABLE_IDX_0303, COMP_TABLE_LEN_0303 },
00362     { COMP_TABLE_IDX_0309, COMP_TABLE_LEN_0309 },
00363     { COMP_TABLE_IDX_0323, COMP_TABLE_LEN_0323 }
00364   };
00365 
00366 #define MIN_NEEDED_INPUT    FROM_LOOP_MIN_NEEDED_FROM
00367 #define MAX_NEEDED_INPUT    FROM_LOOP_MAX_NEEDED_FROM
00368 #define MIN_NEEDED_OUTPUT   FROM_LOOP_MIN_NEEDED_TO
00369 #define MAX_NEEDED_OUTPUT   FROM_LOOP_MAX_NEEDED_TO
00370 #define LOOPFCT                    FROM_LOOP
00371 #define BODY \
00372   {                                                                  \
00373     uint32_t ch = *inptr;                                            \
00374     uint32_t last_ch;                                                       \
00375     int must_buffer_ch;                                                     \
00376                                                                      \
00377     if (ch >= 0x80)                                                  \
00378       {                                                                     \
00379        ch = to_ucs4[ch - 0x80];                                      \
00380        if (__builtin_expect (ch == L'\0', 0))                               \
00381          {                                                           \
00382            /* This is an illegal character.  */                      \
00383            STANDARD_FROM_LOOP_ERR_HANDLER (1);                              \
00384          }                                                           \
00385       }                                                                     \
00386                                                                      \
00387     /* Determine whether there is a buffered character pending.  */         \
00388     last_ch = *statep >> 3;                                          \
00389                                                                      \
00390     /* We have to buffer ch if it is a possible match in comp_table_data.  */ \
00391     must_buffer_ch = (ch >= 0x0041 && ch <= 0x01b0);                        \
00392                                                                      \
00393     if (last_ch)                                                     \
00394       {                                                                     \
00395        if (ch >= 0x0300 && ch < 0x0340)                              \
00396          {                                                           \
00397            /* See whether last_ch and ch can be combined.  */               \
00398            unsigned int i, i1, i2;                                   \
00399                                                                      \
00400            switch (ch)                                                      \
00401              {                                                              \
00402              case 0x0300:                                            \
00403               i = 0;                                                 \
00404               break;                                                 \
00405              case 0x0301:                                            \
00406               i = 1;                                                 \
00407               break;                                                 \
00408              case 0x0303:                                            \
00409               i = 2;                                                 \
00410               break;                                                 \
00411              case 0x0309:                                            \
00412               i = 3;                                                 \
00413               break;                                                 \
00414              case 0x0323:                                            \
00415               i = 4;                                                 \
00416               break;                                                 \
00417              default:                                                       \
00418               abort ();                                              \
00419              }                                                              \
00420                                                                      \
00421            i1 = comp_table[i].idx;                                   \
00422            i2 = i1 + comp_table[i].len - 1;                                 \
00423                                                                      \
00424            if (last_ch >= comp_table_data[i1].base                          \
00425               && last_ch <= comp_table_data[i2].base)                       \
00426              {                                                              \
00427               for (;;)                                               \
00428                 {                                                    \
00429                   i = (i1 + i2) >> 1;                                       \
00430                   if (last_ch == comp_table_data[i].base)                   \
00431                     break;                                           \
00432                   if (last_ch < comp_table_data[i].base)                    \
00433                     {                                                       \
00434                      if (i1 == i)                                    \
00435                        goto not_combining;                                  \
00436                      i2 = i;                                                \
00437                     }                                                       \
00438                   else                                               \
00439                     {                                                       \
00440                      if (i1 != i)                                    \
00441                        i1 = i;                                       \
00442                      else                                            \
00443                        {                                             \
00444                          i = i2;                                     \
00445                          if (last_ch == comp_table_data[i].base)            \
00446                            break;                                    \
00447                          goto not_combining;                                \
00448                        }                                             \
00449                     }                                                       \
00450                 }                                                    \
00451               last_ch = comp_table_data[i].composed;                        \
00452               /* Output the combined character.  */                         \
00453               put32 (outptr, last_ch);                               \
00454               outptr += 4;                                           \
00455               *statep = 0;                                           \
00456               ++inptr;                                               \
00457               continue;                                              \
00458              }                                                              \
00459          }                                                           \
00460                                                                      \
00461       not_combining:                                                 \
00462        /* Output the buffered character.  */                                \
00463        put32 (outptr, last_ch);                                      \
00464        outptr += 4;                                                  \
00465        *statep = 0;                                                  \
00466                                                                      \
00467        /* If we don't have enough room to output ch as well, then deal             \
00468           with it in another round.  */                              \
00469        if (!must_buffer_ch && __builtin_expect (outptr + 4 > outend, 0))     \
00470          continue;                                                   \
00471       }                                                                     \
00472                                                                      \
00473     if (must_buffer_ch)                                                     \
00474       *statep = ch << 3;                                             \
00475     else                                                             \
00476       {                                                                     \
00477        put32 (outptr, ch);                                           \
00478        outptr += 4;                                                  \
00479       }                                                                     \
00480     ++inptr;                                                         \
00481   }
00482 #define LOOP_NEED_FLAGS
00483 #define EXTRA_LOOP_DECLS    , int *statep
00484 #define ONEBYTE_BODY \
00485   {                                                                  \
00486     uint32_t ch;                                                     \
00487                                                                      \
00488     if (c < 0x80)                                                    \
00489       ch = c;                                                        \
00490     else                                                             \
00491       {                                                                     \
00492        ch = to_ucs4[c - 0x80];                                              \
00493        if (ch == L'\0')                                              \
00494          return WEOF;                                                       \
00495       }                                                                     \
00496     if (ch >= 0x0041 && ch <= 0x01b0)                                       \
00497       return WEOF;                                                   \
00498     return ch;                                                              \
00499   }
00500 #include <iconv/loop.c>
00501 
00502 
00503 /* Next, define the conversion function from UCS4 to CP1258.  */
00504 
00505 static const unsigned char from_ucs4[] =
00506   {
00507 #define FROM_IDX_00 0
00508                             0xc4, 0xc5, 0xc6, 0xc7, /* 0x00c4-0x00c7 */
00509     0xc8, 0xc9, 0xca, 0xcb, 0x00, 0xcd, 0xce, 0xcf, /* 0x00c8-0x00cf */
00510     0x00, 0xd1, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0x00d0-0x00d7 */
00511     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0x00d8-0x00df */
00512     0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x00e0-0x00e7 */
00513     0xe8, 0xe9, 0xea, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0x00e8-0x00ef */
00514     0x00, 0xf1, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0x00f0-0x00f7 */
00515     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0x00f8-0x00ff */
00516     0x00, 0x00, 0xc3, 0xe3, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x0107 */
00517     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0108-0x010f */
00518     0xd0, 0xf0,                                     /* 0x0110-0x0111 */
00519 #define FROM_IDX_01 (FROM_IDX_00 + 78)
00520                 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x0152-0x0157 */
00521     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0158-0x015f */
00522     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0160-0x0167 */
00523     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0168-0x016f */
00524     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0170-0x0177 */
00525     0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0178-0x017f */
00526     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0180-0x0187 */
00527     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0188-0x018f */
00528     0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0190-0x0197 */
00529     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0198-0x019f */
00530     0xd5, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01a0-0x01a7 */
00531     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, /* 0x01a8-0x01af */
00532     0xfd,                                           /* 0x01b0-0x01b0 */
00533 #define FROM_IDX_02 (FROM_IDX_01 + 95)
00534                                         0x88, 0x00, /* 0x02c6-0x02c7 */
00535     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02c8-0x02cf */
00536     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02d0-0x02d7 */
00537     0x00, 0x00, 0x00, 0x00, 0x98,                   /* 0x02d8-0x02dc */
00538 #define FROM_IDX_03 (FROM_IDX_02 + 23)
00539     0xcc, 0xec, 0x00, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x0300-0x0307 */
00540     0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0308-0x030f */
00541     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0310-0x0317 */
00542     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0318-0x031f */
00543     0x00, 0x00, 0x00, 0xf2,                         /* 0x0320-0x0323 */
00544 #define FROM_IDX_20 (FROM_IDX_03 + 36)
00545                       0x96, 0x97, 0x00, 0x00, 0x00, /* 0x2013-0x2017 */
00546     0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x2018-0x201f */
00547     0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x2020-0x2027 */
00548     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2028-0x202f */
00549     0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2030-0x2037 */
00550     0x00, 0x8b, 0x9b,                               /* 0x2038-0x203a */
00551 #define FROM_IDX_FF (FROM_IDX_20 + 40)
00552   };
00553 /* Compile-time verification of table size.  */
00554 typedef int verify2[(NELEMS (from_ucs4) == FROM_IDX_FF) - 1];
00555 
00556 /* Decomposition table for the relevant Unicode characters. */
00557 static const struct
00558 {
00559   uint16_t composed;
00560   uint32_t base:8;
00561   uint32_t comb1:8;
00562 } decomp_table[] =
00563   {
00564     { 0x00c0, 0x41, 0xcc },
00565     { 0x00c1, 0x41, 0xec },
00566     { 0x00c3, 0x41, 0xde },
00567     { 0x00c8, 0x45, 0xcc },
00568     { 0x00c9, 0x45, 0xec },
00569     { 0x00cc, 0x49, 0xcc },
00570     { 0x00cd, 0x49, 0xec },
00571     { 0x00d1, 0x4e, 0xde },
00572     { 0x00d2, 0x4f, 0xcc },
00573     { 0x00d3, 0x4f, 0xec },
00574     { 0x00d5, 0x4f, 0xde },
00575     { 0x00d9, 0x55, 0xcc },
00576     { 0x00da, 0x55, 0xec },
00577     { 0x00dd, 0x59, 0xec },
00578     { 0x00e0, 0x61, 0xcc },
00579     { 0x00e1, 0x61, 0xec },
00580     { 0x00e3, 0x61, 0xde },
00581     { 0x00e8, 0x65, 0xcc },
00582     { 0x00e9, 0x65, 0xec },
00583     { 0x00ec, 0x69, 0xcc },
00584     { 0x00ed, 0x69, 0xec },
00585     { 0x00f1, 0x6e, 0xde },
00586     { 0x00f2, 0x6f, 0xcc },
00587     { 0x00f3, 0x6f, 0xec },
00588     { 0x00f5, 0x6f, 0xde },
00589     { 0x00f9, 0x75, 0xcc },
00590     { 0x00fa, 0x75, 0xec },
00591     { 0x00fd, 0x79, 0xec },
00592     { 0x0106, 0x43, 0xec },
00593     { 0x0107, 0x63, 0xec },
00594     { 0x0128, 0x49, 0xde },
00595     { 0x0129, 0x69, 0xde },
00596     { 0x0139, 0x4c, 0xec },
00597     { 0x013a, 0x6c, 0xec },
00598     { 0x0143, 0x4e, 0xec },
00599     { 0x0144, 0x6e, 0xec },
00600     { 0x0154, 0x52, 0xec },
00601     { 0x0155, 0x72, 0xec },
00602     { 0x015a, 0x53, 0xec },
00603     { 0x015b, 0x73, 0xec },
00604     { 0x0168, 0x55, 0xde },
00605     { 0x0169, 0x75, 0xde },
00606     { 0x0179, 0x5a, 0xec },
00607     { 0x017a, 0x7a, 0xec },
00608     { 0x01d7, 0xdc, 0xec },
00609     { 0x01d8, 0xfc, 0xec },
00610     { 0x01db, 0xdc, 0xcc },
00611     { 0x01dc, 0xfc, 0xcc },
00612     { 0x01f4, 0x47, 0xec },
00613     { 0x01f5, 0x67, 0xec },
00614     { 0x01f8, 0x4e, 0xcc },
00615     { 0x01f9, 0x6e, 0xcc },
00616     { 0x01fa, 0xc5, 0xec },
00617     { 0x01fb, 0xe5, 0xec },
00618     { 0x01fc, 0xc6, 0xec },
00619     { 0x01fd, 0xe6, 0xec },
00620     { 0x01fe, 0xd8, 0xec },
00621     { 0x01ff, 0xf8, 0xec },
00622     { 0x0385, 0xa5, 0xec },
00623     { 0x1e04, 0x42, 0xf2 },
00624     { 0x1e05, 0x62, 0xf2 },
00625     { 0x1e08, 0xc7, 0xec },
00626     { 0x1e09, 0xe7, 0xec },
00627     { 0x1e0c, 0x44, 0xf2 },
00628     { 0x1e0d, 0x64, 0xf2 },
00629     { 0x1e24, 0x48, 0xf2 },
00630     { 0x1e25, 0x68, 0xf2 },
00631     { 0x1e2e, 0xcf, 0xec },
00632     { 0x1e2f, 0xef, 0xec },
00633     { 0x1e30, 0x4b, 0xec },
00634     { 0x1e31, 0x6b, 0xec },
00635     { 0x1e32, 0x4b, 0xf2 },
00636     { 0x1e33, 0x6b, 0xf2 },
00637     { 0x1e36, 0x4c, 0xf2 },
00638     { 0x1e37, 0x6c, 0xf2 },
00639     { 0x1e3e, 0x4d, 0xec },
00640     { 0x1e3f, 0x6d, 0xec },
00641     { 0x1e42, 0x4d, 0xf2 },
00642     { 0x1e43, 0x6d, 0xf2 },
00643     { 0x1e46, 0x4e, 0xf2 },
00644     { 0x1e47, 0x6e, 0xf2 },
00645     { 0x1e4c, 0xd3, 0xde }, /*{ 0x1e4c, 0x00d5, 0xec }, { 0x1e4c, 0x004f, 1, 0xde },*/
00646     { 0x1e4d, 0xf3, 0xde }, /*{ 0x1e4d, 0x00f5, 0xec }, { 0x1e4d, 0x006f, 1, 0xde },*/
00647     { 0x1e4e, 0xd6, 0xde },
00648     { 0x1e4f, 0xf6, 0xde },
00649     { 0x1e54, 0x50, 0xec },
00650     { 0x1e55, 0x70, 0xec },
00651     { 0x1e5a, 0x52, 0xf2 },
00652     { 0x1e5b, 0x72, 0xf2 },
00653     { 0x1e62, 0x53, 0xf2 },
00654     { 0x1e63, 0x73, 0xf2 },
00655     { 0x1e6c, 0x54, 0xf2 },
00656     { 0x1e6d, 0x74, 0xf2 },
00657     { 0x1e78, 0xda, 0xde }, /*{ 0x1e78, 0x0168, 0xec }, { 0x1e78, 0x0055, 1, 0xde },*/
00658     { 0x1e79, 0xfa, 0xde }, /*{ 0x1e79, 0x0169, 0xec }, { 0x1e79, 0x0075, 1, 0xde },*/
00659     { 0x1e7c, 0x56, 0xde },
00660     { 0x1e7d, 0x76, 0xde },
00661     { 0x1e7e, 0x56, 0xf2 },
00662     { 0x1e7f, 0x76, 0xf2 },
00663     { 0x1e80, 0x57, 0xcc },
00664     { 0x1e81, 0x77, 0xcc },
00665     { 0x1e82, 0x57, 0xec },
00666     { 0x1e83, 0x77, 0xec },
00667     { 0x1e88, 0x57, 0xf2 },
00668     { 0x1e89, 0x77, 0xf2 },
00669     { 0x1e92, 0x5a, 0xf2 },
00670     { 0x1e93, 0x7a, 0xf2 },
00671     { 0x1ea0, 0x41, 0xf2 },
00672     { 0x1ea1, 0x61, 0xf2 },
00673     { 0x1ea2, 0x41, 0xd2 },
00674     { 0x1ea3, 0x61, 0xd2 },
00675     { 0x1ea4, 0xc2, 0xec },
00676     { 0x1ea5, 0xe2, 0xec },
00677     { 0x1ea6, 0xc2, 0xcc },
00678     { 0x1ea7, 0xe2, 0xcc },
00679     { 0x1ea8, 0xc2, 0xd2 },
00680     { 0x1ea9, 0xe2, 0xd2 },
00681     { 0x1eaa, 0xc2, 0xde },
00682     { 0x1eab, 0xe2, 0xde },
00683     { 0x1eac, 0xc2, 0xf2 },
00684     { 0x1ead, 0xe2, 0xf2 },
00685     { 0x1eae, 0xc3, 0xec },
00686     { 0x1eaf, 0xe3, 0xec },
00687     { 0x1eb0, 0xc3, 0xcc },
00688     { 0x1eb1, 0xe3, 0xcc },
00689     { 0x1eb2, 0xc3, 0xd2 },
00690     { 0x1eb3, 0xe3, 0xd2 },
00691     { 0x1eb4, 0xc3, 0xde },
00692     { 0x1eb5, 0xe3, 0xde },
00693     { 0x1eb6, 0xc3, 0xf2 },
00694     { 0x1eb7, 0xe3, 0xf2 },
00695     { 0x1eb8, 0x45, 0xf2 },
00696     { 0x1eb9, 0x65, 0xf2 },
00697     { 0x1eba, 0x45, 0xd2 },
00698     { 0x1ebb, 0x65, 0xd2 },
00699     { 0x1ebc, 0x45, 0xde },
00700     { 0x1ebd, 0x65, 0xde },
00701     { 0x1ebe, 0xca, 0xec },
00702     { 0x1ebf, 0xea, 0xec },
00703     { 0x1ec0, 0xca, 0xcc },
00704     { 0x1ec1, 0xea, 0xcc },
00705     { 0x1ec2, 0xca, 0xd2 },
00706     { 0x1ec3, 0xea, 0xd2 },
00707     { 0x1ec4, 0xca, 0xde },
00708     { 0x1ec5, 0xea, 0xde },
00709     { 0x1ec6, 0xca, 0xf2 },
00710     { 0x1ec7, 0xea, 0xf2 },
00711     { 0x1ec8, 0x49, 0xd2 },
00712     { 0x1ec9, 0x69, 0xd2 },
00713     { 0x1eca, 0x49, 0xf2 },
00714     { 0x1ecb, 0x69, 0xf2 },
00715     { 0x1ecc, 0x4f, 0xf2 },
00716     { 0x1ecd, 0x6f, 0xf2 },
00717     { 0x1ece, 0x4f, 0xd2 },
00718     { 0x1ecf, 0x6f, 0xd2 },
00719     { 0x1ed0, 0xd4, 0xec },
00720     { 0x1ed1, 0xf4, 0xec },
00721     { 0x1ed2, 0xd4, 0xcc },
00722     { 0x1ed3, 0xf4, 0xcc },
00723     { 0x1ed4, 0xd4, 0xd2 },
00724     { 0x1ed5, 0xf4, 0xd2 },
00725     { 0x1ed6, 0xd4, 0xde },
00726     { 0x1ed7, 0xf4, 0xde },
00727     { 0x1ed8, 0xd4, 0xf2 },
00728     { 0x1ed9, 0xf4, 0xf2 },
00729     { 0x1eda, 0xd5, 0xec },
00730     { 0x1edb, 0xf5, 0xec },
00731     { 0x1edc, 0xd5, 0xcc },
00732     { 0x1edd, 0xf5, 0xcc },
00733     { 0x1ede, 0xd5, 0xd2 },
00734     { 0x1edf, 0xf5, 0xd2 },
00735     { 0x1ee0, 0xd5, 0xde },
00736     { 0x1ee1, 0xf5, 0xde },
00737     { 0x1ee2, 0xd5, 0xf2 },
00738     { 0x1ee3, 0xf5, 0xf2 },
00739     { 0x1ee4, 0x55, 0xf2 },
00740     { 0x1ee5, 0x75, 0xf2 },
00741     { 0x1ee6, 0x55, 0xd2 },
00742     { 0x1ee7, 0x75, 0xd2 },
00743     { 0x1ee8, 0xdd, 0xec },
00744     { 0x1ee9, 0xfd, 0xec },
00745     { 0x1eea, 0xdd, 0xcc },
00746     { 0x1eeb, 0xfd, 0xcc },
00747     { 0x1eec, 0xdd, 0xd2 },
00748     { 0x1eed, 0xfd, 0xd2 },
00749     { 0x1eee, 0xdd, 0xde },
00750     { 0x1eef, 0xfd, 0xde },
00751     { 0x1ef0, 0xdd, 0xf2 },
00752     { 0x1ef1, 0xfd, 0xf2 },
00753     { 0x1ef2, 0x59, 0xcc },
00754     { 0x1ef3, 0x79, 0xcc },
00755     { 0x1ef4, 0x59, 0xf2 },
00756     { 0x1ef5, 0x79, 0xf2 },
00757     { 0x1ef6, 0x59, 0xd2 },
00758     { 0x1ef7, 0x79, 0xd2 },
00759     { 0x1ef8, 0x59, 0xde },
00760     { 0x1ef9, 0x79, 0xde },
00761     { 0x1fed, 0xa8, 0xcc },
00762     { 0x1fee, 0xa8, 0xec },
00763   };
00764 
00765 #define MIN_NEEDED_INPUT    TO_LOOP_MIN_NEEDED_FROM
00766 #define MAX_NEEDED_INPUT    TO_LOOP_MAX_NEEDED_FROM
00767 #define MIN_NEEDED_OUTPUT   TO_LOOP_MIN_NEEDED_TO
00768 #define MAX_NEEDED_OUTPUT   TO_LOOP_MAX_NEEDED_TO
00769 #define LOOPFCT                    TO_LOOP
00770 #define BODY \
00771   {                                                                  \
00772     uint32_t ch = get32 (inptr);                                     \
00773                                                                      \
00774     if (ch < 0x0080 || (ch >= 0x00a0 && ch < 0x00c3))                       \
00775       {                                                                     \
00776        *outptr++ = ch;                                                      \
00777        inptr += 4;                                                   \
00778       }                                                                     \
00779     else                                                             \
00780       {                                                                     \
00781        unsigned char res;                                            \
00782                                                                      \
00783        if (ch >= 0x00c4 && ch < 0x0112)                              \
00784          res = from_ucs4[ch - 0x00c4 + FROM_IDX_00];                        \
00785        else if (ch >= 0x0152 && ch < 0x01b1)                                \
00786          res = from_ucs4[ch - 0x0152 + FROM_IDX_01];                        \
00787        else if (ch >= 0x02c6 && ch < 0x02dd)                                \
00788          res = from_ucs4[ch - 0x02c6 + FROM_IDX_02];                        \
00789        else if (ch >= 0x0300 && ch < 0x0324)                                \
00790          res = from_ucs4[ch - 0x0300 + FROM_IDX_03];                        \
00791        else if (ch >= 0x0340 && ch < 0x0342) /* Vietnamese tone marks */     \
00792          res = from_ucs4[ch - 0x0340 + FROM_IDX_03];                        \
00793        else if (ch >= 0x2013 && ch < 0x203b)                                \
00794          res = from_ucs4[ch - 0x2013 + FROM_IDX_20];                        \
00795        else if (ch == 0x20ab)                                               \
00796          res = 0xfe;                                                 \
00797        else if (ch == 0x20ac)                                               \
00798          res = 0x80;                                                 \
00799        else if (ch == 0x2122)                                               \
00800          res = 0x99;                                                 \
00801        else                                                          \
00802          {                                                           \
00803            UNICODE_TAG_HANDLER (ch, 4);                              \
00804            res = 0;                                                  \
00805          }                                                           \
00806                                                                      \
00807        if (__builtin_expect (res != 0, 1))                                  \
00808          {                                                           \
00809            *outptr++ = res;                                          \
00810            inptr += 4;                                                      \
00811          }                                                           \
00812        else                                                          \
00813          {                                                           \
00814            /* Try canonical decomposition.  */                              \
00815            unsigned int i1, i2;                                      \
00816                                                                      \
00817            i1 = 0;                                                   \
00818            i2 = sizeof (decomp_table) / sizeof (decomp_table[0]) - 1;       \
00819            if (ch >= decomp_table[i1].composed                              \
00820               && ch <= decomp_table[i2].composed)                           \
00821              {                                                              \
00822               unsigned int i;                                               \
00823                                                                      \
00824               for (;;)                                               \
00825                 {                                                    \
00826                   i = (i1 + i2) >> 1;                                       \
00827                   if (ch == decomp_table[i].composed)                       \
00828                     break;                                           \
00829                   if (ch < decomp_table[i].composed)                        \
00830                     {                                                       \
00831                      if (i1 == i)                                    \
00832                        goto failed;                                         \
00833                      i2 = i;                                                \
00834                     }                                                       \
00835                   else                                               \
00836                     {                                                       \
00837                      if (i1 != i)                                    \
00838                        i1 = i;                                       \
00839                      else                                            \
00840                        {                                             \
00841                          i = i2;                                     \
00842                          if (ch == decomp_table[i].composed)                \
00843                            break;                                    \
00844                          goto failed;                                \
00845                        }                                             \
00846                     }                                                       \
00847                 }                                                    \
00848                                                                      \
00849               /* See whether we have room for two bytes.  */                \
00850               if (__builtin_expect (outptr + 1 >= outend, 0))               \
00851                 {                                                    \
00852                   result = __GCONV_FULL_OUTPUT;                      \
00853                   break;                                             \
00854                 }                                                    \
00855                                                                      \
00856               /* Found a canonical decomposition.  */                       \
00857               *outptr++ = decomp_table[i].base;                      \
00858               *outptr++ = decomp_table[i].comb1;                     \
00859               inptr += 4;                                            \
00860               continue;                                              \
00861              }                                                              \
00862                                                                      \
00863          failed:                                                     \
00864            /* This is an illegal character.  */                      \
00865            STANDARD_TO_LOOP_ERR_HANDLER (4);                                \
00866          }                                                           \
00867       }                                                                     \
00868   }
00869 #define LOOP_NEED_FLAGS
00870 #define EXTRA_LOOP_DECLS    , int *statep
00871 #include <iconv/loop.c>
00872 
00873 
00874 /* Now define the toplevel functions.  */
00875 #include <iconv/skeleton.c>