Back to index

glibc  2.9
iso-2022-jp-3.c
Go to the documentation of this file.
00001 /* Conversion module for ISO-2022-JP-3.
00002    Copyright (C) 1998-1999, 2000-2002, 2004, 2008
00003    Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
00006    and Bruno Haible <bruno@clisp.org>, 2002.
00007 
00008    The GNU C Library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    The GNU C Library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with the GNU C Library; if not, write to the Free
00020    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00021    02111-1307 USA.  */
00022 
00023 #include <assert.h>
00024 #include <dlfcn.h>
00025 #include <gconv.h>
00026 #include <stdint.h>
00027 #include <string.h>
00028 
00029 #include "jis0201.h"
00030 #include "jis0208.h"
00031 #include "jisx0213.h"
00032 
00033 /* This makes obvious what everybody knows: 0x1b is the Esc character.  */
00034 #define ESC 0x1b
00035 
00036 /* Definitions used in the body of the `gconv' function.  */
00037 #define CHARSET_NAME        "ISO-2022-JP-3//"
00038 #define FROM_LOOP           from_iso2022jp3_loop
00039 #define TO_LOOP                    to_iso2022jp3_loop
00040 #define DEFINE_INIT         1
00041 #define DEFINE_FINI         1
00042 #define FROM_LOOP_MIN_NEEDED_FROM  1
00043 #define FROM_LOOP_MAX_NEEDED_FROM  4
00044 #define FROM_LOOP_MIN_NEEDED_TO           4
00045 #define FROM_LOOP_MAX_NEEDED_TO           8
00046 #define TO_LOOP_MIN_NEEDED_FROM           4
00047 #define TO_LOOP_MAX_NEEDED_FROM           4
00048 #define TO_LOOP_MIN_NEEDED_TO             1
00049 #define TO_LOOP_MAX_NEEDED_TO             6
00050 #define PREPARE_LOOP \
00051   int saved_state;                                                   \
00052   int *statep = &data->__statep->__count;
00053 #define EXTRA_LOOP_ARGS            , statep
00054 
00055 
00056 /* The COUNT element of the state keeps track of the currently selected
00057    character set.  The possible values are:  */
00058 enum
00059 {
00060   ASCII_set = 0,            /* Esc ( B */
00061   JISX0208_1978_set = 1 << 3,      /* Esc $ @ */
00062   JISX0208_1983_set = 2 << 3,      /* Esc $ B */
00063   JISX0201_Roman_set = 3 << 3,     /* Esc ( J */
00064   JISX0201_Kana_set = 4 << 3,      /* Esc ( I */
00065   JISX0213_1_2000_set = 5 << 3,    /* Esc $ ( O */
00066   JISX0213_2_set = 6 << 3,  /* Esc $ ( P */
00067   JISX0213_1_2004_set = 7 << 3,    /* Esc $ ( Q */
00068   CURRENT_SEL_MASK = 7 << 3
00069 };
00070 
00071 /* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the state
00072    also contains the last two bytes to be output, shifted by 6 bits, and a
00073    one-bit indicator whether they must be preceded by the shift sequence,
00074    in bit 22.  */
00075 
00076 /* Since this is a stateful encoding we have to provide code which resets
00077    the output state to the initial state.  This has to be done during the
00078    flushing.  */
00079 #define EMIT_SHIFT_TO_INIT \
00080   if ((data->__statep->__count & ~7) != ASCII_set)                          \
00081     {                                                                \
00082       if (FROM_DIRECTION)                                            \
00083        {                                                             \
00084          /* It's easy, we don't have to emit anything, we just reset the     \
00085             state for the input.  */                                        \
00086          data->__statep->__count &= 7;                                      \
00087          data->__statep->__count |= ASCII_set;                              \
00088        }                                                             \
00089       else                                                           \
00090        {                                                             \
00091          /* We are not in the initial state.  To switch back we have        \
00092             to write out the buffered character and/or emit the sequence     \
00093             `Esc ( B'.  */                                           \
00094          size_t need =                                                      \
00095            (data->__statep->__count >> 6                             \
00096             ? (data->__statep->__count >> 22 ? 3 : 0) + 2                   \
00097             : 0)                                                     \
00098            + ((data->__statep->__count & CURRENT_SEL_MASK) != ASCII_set      \
00099               ? 3 : 0);                                              \
00100                                                                      \
00101          if (__builtin_expect (outbuf + need > outend, 0))                  \
00102            /* We don't have enough room in the output buffer.  */           \
00103            status = __GCONV_FULL_OUTPUT;                             \
00104          else                                                        \
00105            {                                                         \
00106              if (data->__statep->__count >> 6)                              \
00107               {                                                      \
00108                 uint32_t lasttwo = data->__statep->__count >> 6;            \
00109                                                                      \
00110                 if (lasttwo >> 16)                                   \
00111                   {                                                  \
00112                     /* Write out the shift sequence before the last         \
00113                       character.  */                                        \
00114                     assert ((data->__statep->__count & CURRENT_SEL_MASK)    \
00115                            == JISX0208_1983_set);                           \
00116                     *outbuf++ = ESC;                                        \
00117                     *outbuf++ = '$';                                        \
00118                     *outbuf++ = 'B';                                        \
00119                   }                                                  \
00120                 /* Write out the last character.  */                        \
00121                 *outbuf++ = (lasttwo >> 8) & 0xff;                          \
00122                 *outbuf++ = lasttwo & 0xff;                                 \
00123               }                                                      \
00124              if ((data->__statep->__count & CURRENT_SEL_MASK) != ASCII_set)  \
00125               {                                                      \
00126                 /* Write out the shift sequence.  */                        \
00127                 *outbuf++ = ESC;                                     \
00128                 *outbuf++ = '(';                                     \
00129                 *outbuf++ = 'B';                                     \
00130               }                                                      \
00131              data->__statep->__count &= 7;                                  \
00132              data->__statep->__count |= ASCII_set;                          \
00133            }                                                         \
00134        }                                                             \
00135     }
00136 
00137 
00138 /* Since we might have to reset input pointer we must be able to save
00139    and retore the state.  */
00140 #define SAVE_RESET_STATE(Save) \
00141   if (Save)                                                          \
00142     saved_state = *statep;                                           \
00143   else                                                               \
00144     *statep = saved_state
00145 
00146 
00147 /* First define the conversion function from ISO-2022-JP-3 to UCS-4.  */
00148 #define MIN_NEEDED_INPUT    FROM_LOOP_MIN_NEEDED_FROM
00149 #define MAX_NEEDED_INPUT    FROM_LOOP_MAX_NEEDED_FROM
00150 #define MIN_NEEDED_OUTPUT   FROM_LOOP_MIN_NEEDED_TO
00151 #define MAX_NEEDED_OUTPUT   FROM_LOOP_MAX_NEEDED_TO
00152 #define LOOPFCT                    FROM_LOOP
00153 #define BODY \
00154   {                                                                  \
00155     uint32_t ch = *inptr;                                            \
00156                                                                      \
00157     /* Recognize escape sequences.  */                                      \
00158     if (__builtin_expect (ch == ESC, 0))                             \
00159       {                                                                     \
00160        /* We now must be prepared to read two to three more bytes.          \
00161           If we have a match in the first byte but then the input buffer     \
00162           ends we terminate with an error since we must not risk missing     \
00163           an escape sequence just because it is not entirely in the         \
00164           current input buffer.  */                                         \
00165        if (__builtin_expect (inptr + 2 >= inend, 0)                         \
00166            || (inptr[1] == '$' && inptr[2] == '('                           \
00167               && __builtin_expect (inptr + 3 >= inend, 0)))                 \
00168          {                                                           \
00169            /* Not enough input available.  */                               \
00170            result = __GCONV_INCOMPLETE_INPUT;                               \
00171            break;                                                    \
00172          }                                                           \
00173                                                                      \
00174        if (inptr[1] == '(')                                          \
00175          {                                                           \
00176            if (inptr[2] == 'B')                                      \
00177              {                                                              \
00178               /* ASCII selected.  */                                        \
00179               set = ASCII_set;                                       \
00180               inptr += 3;                                            \
00181               continue;                                              \
00182              }                                                              \
00183            else if (inptr[2] == 'J')                                        \
00184              {                                                              \
00185               /* JIS X 0201 selected.  */                            \
00186               set = JISX0201_Roman_set;                              \
00187               inptr += 3;                                            \
00188               continue;                                              \
00189              }                                                              \
00190            else if (inptr[2] == 'I')                                        \
00191              {                                                              \
00192               /* JIS X 0201 selected.  */                            \
00193               set = JISX0201_Kana_set;                               \
00194               inptr += 3;                                            \
00195               continue;                                              \
00196              }                                                              \
00197          }                                                           \
00198        else if (inptr[1] == '$')                                     \
00199          {                                                           \
00200            if (inptr[2] == '@')                                      \
00201              {                                                              \
00202               /* JIS X 0208-1978 selected.  */                       \
00203               set = JISX0208_1978_set;                               \
00204               inptr += 3;                                            \
00205               continue;                                              \
00206              }                                                              \
00207            else if (inptr[2] == 'B')                                        \
00208              {                                                              \
00209               /* JIS X 0208-1983 selected.  */                       \
00210               set = JISX0208_1983_set;                               \
00211               inptr += 3;                                            \
00212               continue;                                              \
00213              }                                                              \
00214            else if (inptr[2] == '(')                                        \
00215              {                                                              \
00216               if (inptr[3] == 'O' || inptr[3] == 'Q')                       \
00217                 {                                                    \
00218                   /* JIS X 0213 plane 1 selected.  */                       \
00219                   /* In this direction we don't need to distinguish the     \
00220                      versions from 2000 and 2004. */                        \
00221                   set = JISX0213_1_2004_set;                                \
00222                   inptr += 4;                                               \
00223                   continue;                                          \
00224                 }                                                    \
00225               else if (inptr[3] == 'P')                              \
00226                 {                                                    \
00227                   /* JIS X 0213 plane 2 selected.  */                       \
00228                   set = JISX0213_2_set;                              \
00229                   inptr += 4;                                               \
00230                   continue;                                          \
00231                 }                                                    \
00232              }                                                              \
00233          }                                                           \
00234       }                                                                     \
00235                                                                      \
00236     if (ch >= 0x80)                                                  \
00237       {                                                                     \
00238        STANDARD_FROM_LOOP_ERR_HANDLER (1);                                  \
00239       }                                                                     \
00240     else if (set == ASCII_set || (ch < 0x21 || ch == 0x7f))                 \
00241       /* Almost done, just advance the input pointer.  */                   \
00242       ++inptr;                                                              \
00243     else if (set == JISX0201_Roman_set)                                     \
00244       {                                                                     \
00245        /* Use the JIS X 0201 table.  */                              \
00246        ch = jisx0201_to_ucs4 (ch);                                   \
00247        if (__builtin_expect (ch == __UNKNOWN_10646_CHAR, 0))                \
00248          {                                                           \
00249            STANDARD_FROM_LOOP_ERR_HANDLER (1);                              \
00250          }                                                           \
00251        ++inptr;                                                      \
00252       }                                                                     \
00253     else if (set == JISX0201_Kana_set)                                      \
00254       {                                                                     \
00255        /* Use the JIS X 0201 table.  */                              \
00256        ch = jisx0201_to_ucs4 (ch + 0x80);                            \
00257        if (__builtin_expect (ch == __UNKNOWN_10646_CHAR, 0))                \
00258          {                                                           \
00259            STANDARD_FROM_LOOP_ERR_HANDLER (1);                              \
00260          }                                                           \
00261        ++inptr;                                                      \
00262       }                                                                     \
00263     else if (set == JISX0208_1978_set || set == JISX0208_1983_set)          \
00264       {                                                                     \
00265        /* XXX I don't have the tables for these two old variants of         \
00266           JIS X 0208.  Therefore I'm using the tables for JIS X             \
00267           0208-1990.  If somebody has problems with this please             \
00268           provide the appropriate tables.  */                               \
00269        ch = jisx0208_to_ucs4 (&inptr, inend - inptr, 0);                    \
00270                                                                      \
00271        if (__builtin_expect (ch == 0, 0))                            \
00272          {                                                           \
00273            result = __GCONV_INCOMPLETE_INPUT;                               \
00274            break;                                                    \
00275          }                                                           \
00276        else if (__builtin_expect (ch == __UNKNOWN_10646_CHAR, 0))           \
00277          {                                                           \
00278            STANDARD_FROM_LOOP_ERR_HANDLER (1);                              \
00279          }                                                           \
00280       }                                                                     \
00281     else /* (set == JISX0213_1_2004_set || set == JISX0213_2_set) */        \
00282       {                                                                     \
00283        if (__builtin_expect (inptr + 1 >= inend, 0))                        \
00284          {                                                           \
00285            result = __GCONV_INCOMPLETE_INPUT;                               \
00286            break;                                                    \
00287          }                                                           \
00288                                                                      \
00289        ch = jisx0213_to_ucs4 (                                              \
00290               ((JISX0213_1_2004_set - set + (1 << 3)) << 5) + ch,           \
00291               inptr[1]);                                             \
00292        if (ch == 0)                                                  \
00293          STANDARD_FROM_LOOP_ERR_HANDLER (1);                                \
00294                                                                      \
00295        if (ch < 0x80)                                                       \
00296          {                                                           \
00297            /* It's a combining character.  */                               \
00298            uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0];            \
00299            uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1];            \
00300                                                                      \
00301            /* See whether we have room for two characters.  */              \
00302            if (outptr + 8 <= outend)                                        \
00303              {                                                              \
00304               inptr += 2;                                            \
00305               put32 (outptr, u1);                                    \
00306               outptr += 4;                                           \
00307               put32 (outptr, u2);                                    \
00308               outptr += 4;                                           \
00309               continue;                                              \
00310              }                                                              \
00311            else                                                      \
00312              {                                                              \
00313               result = __GCONV_FULL_OUTPUT;                                 \
00314               break;                                                 \
00315              }                                                              \
00316          }                                                           \
00317                                                                      \
00318        inptr += 2;                                                   \
00319       }                                                                     \
00320                                                                      \
00321     put32 (outptr, ch);                                                     \
00322     outptr += 4;                                                     \
00323   }
00324 #define LOOP_NEED_FLAGS
00325 #define EXTRA_LOOP_DECLS    , int *statep
00326 #define INIT_PARAMS         int set = *statep
00327 #define UPDATE_PARAMS              *statep = set
00328 #include <iconv/loop.c>
00329 
00330 
00331 /* Next, define the other direction, from UCS-4 to ISO-2022-JP-3.  */
00332 
00333 /* Composition tables for each of the relevant combining characters.  */
00334 static const struct
00335 {
00336   uint16_t base;
00337   uint16_t composed;
00338 } comp_table_data[] =
00339 {
00340 #define COMP_TABLE_IDX_02E5 0
00341 #define COMP_TABLE_LEN_02E5 1
00342   { 0x2b64, 0x2b65 }, /* 0x12B65 = 0x12B64 U+02E5 */
00343 #define COMP_TABLE_IDX_02E9 (COMP_TABLE_IDX_02E5 + COMP_TABLE_LEN_02E5)
00344 #define COMP_TABLE_LEN_02E9 1
00345   { 0x2b60, 0x2b66 }, /* 0x12B66 = 0x12B60 U+02E9 */
00346 #define COMP_TABLE_IDX_0300 (COMP_TABLE_IDX_02E9 + COMP_TABLE_LEN_02E9)
00347 #define COMP_TABLE_LEN_0300 5
00348   { 0x295c, 0x2b44 }, /* 0x12B44 = 0x1295C U+0300 */
00349   { 0x2b38, 0x2b48 }, /* 0x12B48 = 0x12B38 U+0300 */
00350   { 0x2b37, 0x2b4a }, /* 0x12B4A = 0x12B37 U+0300 */
00351   { 0x2b30, 0x2b4c }, /* 0x12B4C = 0x12B30 U+0300 */
00352   { 0x2b43, 0x2b4e }, /* 0x12B4E = 0x12B43 U+0300 */
00353 #define COMP_TABLE_IDX_0301 (COMP_TABLE_IDX_0300 + COMP_TABLE_LEN_0300)
00354 #define COMP_TABLE_LEN_0301 4
00355   { 0x2b38, 0x2b49 }, /* 0x12B49 = 0x12B38 U+0301 */
00356   { 0x2b37, 0x2b4b }, /* 0x12B4B = 0x12B37 U+0301 */
00357   { 0x2b30, 0x2b4d }, /* 0x12B4D = 0x12B30 U+0301 */
00358   { 0x2b43, 0x2b4f }, /* 0x12B4F = 0x12B43 U+0301 */
00359 #define COMP_TABLE_IDX_309A (COMP_TABLE_IDX_0301 + COMP_TABLE_LEN_0301)
00360 #define COMP_TABLE_LEN_309A 14
00361   { 0x242b, 0x2477 }, /* 0x12477 = 0x1242B U+309A */
00362   { 0x242d, 0x2478 }, /* 0x12478 = 0x1242D U+309A */
00363   { 0x242f, 0x2479 }, /* 0x12479 = 0x1242F U+309A */
00364   { 0x2431, 0x247a }, /* 0x1247A = 0x12431 U+309A */
00365   { 0x2433, 0x247b }, /* 0x1247B = 0x12433 U+309A */
00366   { 0x252b, 0x2577 }, /* 0x12577 = 0x1252B U+309A */
00367   { 0x252d, 0x2578 }, /* 0x12578 = 0x1252D U+309A */
00368   { 0x252f, 0x2579 }, /* 0x12579 = 0x1252F U+309A */
00369   { 0x2531, 0x257a }, /* 0x1257A = 0x12531 U+309A */
00370   { 0x2533, 0x257b }, /* 0x1257B = 0x12533 U+309A */
00371   { 0x253b, 0x257c }, /* 0x1257C = 0x1253B U+309A */
00372   { 0x2544, 0x257d }, /* 0x1257D = 0x12544 U+309A */
00373   { 0x2548, 0x257e }, /* 0x1257E = 0x12548 U+309A */
00374   { 0x2675, 0x2678 }, /* 0x12678 = 0x12675 U+309A */
00375 };
00376 
00377 #define MIN_NEEDED_INPUT    TO_LOOP_MIN_NEEDED_FROM
00378 #define MAX_NEEDED_INPUT    TO_LOOP_MAX_NEEDED_FROM
00379 #define MIN_NEEDED_OUTPUT   TO_LOOP_MIN_NEEDED_TO
00380 #define MAX_NEEDED_OUTPUT   TO_LOOP_MAX_NEEDED_TO
00381 #define LOOPFCT                    TO_LOOP
00382 #define BODY \
00383   {                                                                  \
00384     uint32_t ch = get32 (inptr);                                     \
00385                                                                      \
00386     if (lasttwo != 0)                                                       \
00387       {                                                                     \
00388        /* Attempt to combine the last character with this one.  */          \
00389        unsigned int idx;                                             \
00390        unsigned int len;                                             \
00391                                                                      \
00392        if (ch == 0x02e5)                                             \
00393          idx = COMP_TABLE_IDX_02E5, len = COMP_TABLE_LEN_02E5;              \
00394        else if (ch == 0x02e9)                                               \
00395          idx = COMP_TABLE_IDX_02E9, len = COMP_TABLE_LEN_02E9;              \
00396        else if (ch == 0x0300)                                               \
00397          idx = COMP_TABLE_IDX_0300, len = COMP_TABLE_LEN_0300;              \
00398        else if (ch == 0x0301)                                               \
00399          idx = COMP_TABLE_IDX_0301, len = COMP_TABLE_LEN_0301;              \
00400        else if (ch == 0x309a)                                               \
00401          idx = COMP_TABLE_IDX_309A, len = COMP_TABLE_LEN_309A;              \
00402        else                                                          \
00403          goto not_combining;                                                \
00404                                                                      \
00405        do                                                            \
00406          if (comp_table_data[idx].base == (uint16_t) lasttwo)               \
00407            break;                                                    \
00408        while (++idx, --len > 0);                                     \
00409                                                                      \
00410        if (len > 0)                                                  \
00411          {                                                           \
00412            /* Output the combined character.  */                     \
00413            /* We know the combined character is in JISX0213 plane 1,        \
00414               but the buffered character may have been in JISX0208 or in     \
00415               JISX0213 plane 1.  */                                         \
00416            size_t need =                                             \
00417              (lasttwo >> 16                                          \
00418               || (set != JISX0213_1_2000_set && set != JISX0213_1_2004_set)  \
00419               ? 4 : 0);                                              \
00420                                                                      \
00421            if (__builtin_expect (outptr + need + 2 > outend, 0))            \
00422              {                                                              \
00423               result = __GCONV_FULL_OUTPUT;                                 \
00424               break;                                                 \
00425              }                                                              \
00426            if (need)                                                 \
00427              {                                                              \
00428               /* But first, output the escape sequence.  */                 \
00429               *outptr++ = ESC;                                       \
00430               *outptr++ = '$';                                       \
00431               *outptr++ = '(';                                       \
00432               *outptr++ = 'O';                                       \
00433               set = JISX0213_1_2000_set;                             \
00434              }                                                              \
00435            lasttwo = comp_table_data[idx].composed;                         \
00436            *outptr++ = (lasttwo >> 8) & 0xff;                               \
00437            *outptr++ = lasttwo & 0xff;                                      \
00438            lasttwo = 0;                                              \
00439            inptr += 4;                                                      \
00440            continue;                                                 \
00441          }                                                           \
00442                                                                      \
00443       not_combining:                                                 \
00444        /* Output the buffered character.  */                                \
00445        /* We know it is in JISX0208 or in JISX0213 plane 1.  */             \
00446        {                                                             \
00447          size_t need = (lasttwo >> 16 ? 3 : 0);                      \
00448                                                                      \
00449          if (__builtin_expect (outptr + need + 2 > outend, 0))              \
00450            {                                                         \
00451              result = __GCONV_FULL_OUTPUT;                                  \
00452              break;                                                  \
00453            }                                                         \
00454          if (need)                                                   \
00455            {                                                         \
00456              /* But first, output the escape sequence.  */                  \
00457              assert (set == JISX0208_1983_set);                      \
00458              *outptr++ = ESC;                                               \
00459              *outptr++ = '$';                                               \
00460              *outptr++ = 'B';                                               \
00461            }                                                         \
00462          *outptr++ = (lasttwo >> 8) & 0xff;                                 \
00463          *outptr++ = lasttwo & 0xff;                                        \
00464          lasttwo = 0;                                                       \
00465          continue;                                                   \
00466        }                                                             \
00467       }                                                                     \
00468                                                                      \
00469     /* First see whether we can write the character using the currently            \
00470        selected character set.  */                                   \
00471     if (set == ASCII_set)                                            \
00472       {                                                                     \
00473        /* Please note that the NUL byte is *not* matched if we are not             \
00474           currently using the ASCII charset.  This is because we must       \
00475           switch to the initial state whenever a NUL byte is written.  */    \
00476        if (ch <= 0x7f)                                                      \
00477          {                                                           \
00478            *outptr++ = ch;                                           \
00479            inptr += 4;                                                      \
00480            continue;                                                 \
00481          }                                                           \
00482       }                                                                     \
00483     /* ISO-2022-JP recommends to encode the newline character always in            \
00484        ASCII since this allows a context-free interpretation of the         \
00485        characters at the beginning of the next line.  Otherwise it would      \
00486        have to be known whether the last line ended using ASCII or          \
00487        JIS X 0201.  */                                                      \
00488     else if (set == JISX0201_Roman_set)                                     \
00489       {                                                                     \
00490        unsigned char buf[1];                                                \
00491        if (ucs4_to_jisx0201 (ch, buf) != __UNKNOWN_10646_CHAR               \
00492            && buf[0] > 0x20 && buf[0] < 0x80)                               \
00493          {                                                           \
00494            *outptr++ = buf[0];                                              \
00495            inptr += 4;                                                      \
00496            continue;                                                 \
00497          }                                                           \
00498       }                                                                     \
00499     else if (set == JISX0201_Kana_set)                                      \
00500       {                                                                     \
00501        unsigned char buf[1];                                                \
00502        if (ucs4_to_jisx0201 (ch, buf) != __UNKNOWN_10646_CHAR               \
00503            && buf[0] >= 0x80)                                               \
00504          {                                                           \
00505            *outptr++ = buf[0] - 0x80;                                       \
00506            inptr += 4;                                                      \
00507            continue;                                                 \
00508          }                                                           \
00509       }                                                                     \
00510     else if (/*set == JISX0208_1978_set || */ set == JISX0208_1983_set)            \
00511       {                                                                     \
00512        size_t written = ucs4_to_jisx0208 (ch, outptr, outend - outptr);      \
00513                                                                      \
00514        if (written != __UNKNOWN_10646_CHAR)                                 \
00515          {                                                           \
00516            uint32_t jch = ucs4_to_jisx0213 (ch);                     \
00517                                                                      \
00518            if (jch & 0x0080)                                                \
00519              {                                                              \
00520               /* A possible match in comp_table_data.  Buffer it.  */       \
00521               lasttwo = jch & 0x7f7f;                                       \
00522               inptr += 4;                                            \
00523               continue;                                              \
00524              }                                                              \
00525            if (__builtin_expect (written == 0, 0))                          \
00526              {                                                              \
00527               result = __GCONV_FULL_OUTPUT;                                 \
00528               break;                                                 \
00529              }                                                              \
00530            else                                                      \
00531              {                                                              \
00532               outptr += written;                                     \
00533               inptr += 4;                                            \
00534               continue;                                              \
00535             }                                                        \
00536          }                                                           \
00537       }                                                                     \
00538     else                                                             \
00539       {                                                                     \
00540        /* (set == JISX0213_1_2000_set || set == JISX0213_1_2004_set         \
00541            || set == JISX0213_2_set) */                              \
00542        uint32_t jch = ucs4_to_jisx0213 (ch);                                \
00543                                                                      \
00544        if (jch != 0                                                  \
00545            && (jch & 0x8000                                          \
00546               ? set == JISX0213_2_set                                       \
00547               : (set == JISX0213_1_2004_set                                 \
00548                  || (set == JISX0213_1_2000_set                      \
00549                      && !jisx0213_added_in_2004_p (jch)))))                 \
00550          {                                                           \
00551            if (jch & 0x0080)                                                \
00552              {                                                              \
00553               /* A possible match in comp_table_data.  Buffer it.  */       \
00554                                                                      \
00555               /* We know it's a JISX 0213 plane 1 character.  */            \
00556               assert ((jch & 0x8000) == 0);                                 \
00557                                                                      \
00558               lasttwo = jch & 0x7f7f;                                       \
00559               inptr += 4;                                            \
00560               continue;                                              \
00561              }                                                              \
00562                                                                      \
00563            if (__builtin_expect (outptr + 1 >= outend, 0))                  \
00564              {                                                              \
00565               result = __GCONV_FULL_OUTPUT;                                 \
00566               break;                                                 \
00567              }                                                              \
00568            *outptr++ = (jch >> 8) & 0x7f;                            \
00569            *outptr++ = jch & 0x7f;                                   \
00570            inptr += 4;                                                      \
00571            continue;                                                 \
00572          }                                                           \
00573       }                                                                     \
00574                                                                      \
00575     /* The attempts to use the currently selected character set failed,            \
00576        either because the character requires a different character set,            \
00577        or because the character is unknown.  */                             \
00578                                                                      \
00579     if (ch <= 0x7f)                                                  \
00580       {                                                                     \
00581        /* We must encode using ASCII.  First write out the escape           \
00582           sequence.  */                                              \
00583        if (__builtin_expect (outptr + 3 > outend, 0))                       \
00584          {                                                           \
00585            result = __GCONV_FULL_OUTPUT;                             \
00586            break;                                                    \
00587          }                                                           \
00588                                                                      \
00589        *outptr++ = ESC;                                              \
00590        *outptr++ = '(';                                              \
00591        *outptr++ = 'B';                                              \
00592        set = ASCII_set;                                              \
00593                                                                      \
00594        if (__builtin_expect (outptr >= outend, 0))                          \
00595          {                                                           \
00596            result = __GCONV_FULL_OUTPUT;                             \
00597            break;                                                    \
00598          }                                                           \
00599        *outptr++ = ch;                                                      \
00600       }                                                                     \
00601     else                                                             \
00602       {                                                                     \
00603        unsigned char buf[2];                                                \
00604                                                                      \
00605        /* Try JIS X 0201 Roman.  */                                         \
00606        if (ucs4_to_jisx0201 (ch, buf) != __UNKNOWN_10646_CHAR               \
00607            && buf[0] > 0x20 && buf[0] < 0x80)                               \
00608          {                                                           \
00609            if (set != JISX0201_Roman_set)                            \
00610              {                                                              \
00611               if (__builtin_expect (outptr + 3 > outend, 0))                \
00612                 {                                                    \
00613                   result = __GCONV_FULL_OUTPUT;                      \
00614                   break;                                             \
00615                 }                                                    \
00616               *outptr++ = ESC;                                       \
00617               *outptr++ = '(';                                       \
00618               *outptr++ = 'J';                                       \
00619               set = JISX0201_Roman_set;                              \
00620              }                                                              \
00621                                                                      \
00622            if (__builtin_expect (outptr >= outend, 0))                      \
00623              {                                                              \
00624               result = __GCONV_FULL_OUTPUT;                                 \
00625               break;                                                 \
00626              }                                                              \
00627            *outptr++ = buf[0];                                              \
00628          }                                                           \
00629        else                                                          \
00630          {                                                           \
00631            uint32_t jch = ucs4_to_jisx0213 (ch);                     \
00632                                                                      \
00633            /* Try JIS X 0208.  */                                    \
00634            size_t written = ucs4_to_jisx0208 (ch, buf, 2);                  \
00635            if (written != __UNKNOWN_10646_CHAR)                      \
00636              {                                                              \
00637               if (jch & 0x0080)                                      \
00638                 {                                                    \
00639                   /* A possible match in comp_table_data.  Buffer it.  */   \
00640                   lasttwo = ((set != JISX0208_1983_set ? 1 : 0) << 16)      \
00641                            | (jch & 0x7f7f);                                \
00642                   set = JISX0208_1983_set;                                  \
00643                   inptr += 4;                                               \
00644                   continue;                                          \
00645                 }                                                    \
00646                                                                      \
00647               if (set != JISX0208_1983_set)                                 \
00648                 {                                                    \
00649                   if (__builtin_expect (outptr + 3 > outend, 0))            \
00650                     {                                                       \
00651                      result = __GCONV_FULL_OUTPUT;                          \
00652                      break;                                          \
00653                     }                                                       \
00654                   *outptr++ = ESC;                                   \
00655                   *outptr++ = '$';                                   \
00656                   *outptr++ = 'B';                                   \
00657                   set = JISX0208_1983_set;                                  \
00658                 }                                                    \
00659                                                                      \
00660               if (__builtin_expect (outptr + 2 > outend, 0))                \
00661                 {                                                    \
00662                   result = __GCONV_FULL_OUTPUT;                      \
00663                   break;                                             \
00664                 }                                                    \
00665               *outptr++ = buf[0];                                    \
00666               *outptr++ = buf[1];                                    \
00667              }                                                              \
00668            else                                                      \
00669              {                                                              \
00670               /* Try JIS X 0213.  */                                        \
00671               if (jch != 0)                                          \
00672                 {                                                    \
00673                   int new_set =                                      \
00674                     (jch & 0x8000                                    \
00675                      ? JISX0213_2_set                                       \
00676                      : jisx0213_added_in_2004_p (jch)                       \
00677                       ? JISX0213_1_2004_set                                 \
00678                       : JISX0213_1_2000_set);                        \
00679                                                                      \
00680                   if (set != new_set)                                       \
00681                     {                                                       \
00682                      if (__builtin_expect (outptr + 4 > outend, 0))         \
00683                        {                                             \
00684                          result = __GCONV_FULL_OUTPUT;               \
00685                          break;                                      \
00686                        }                                             \
00687                      *outptr++ = ESC;                                \
00688                      *outptr++ = '$';                                \
00689                      *outptr++ = '(';                                \
00690                      *outptr++ =                                     \
00691                        ((new_set - JISX0213_1_2000_set) >> 3) + 'O';        \
00692                      set = new_set;                                         \
00693                     }                                                       \
00694                                                                      \
00695                   if (jch & 0x0080)                                         \
00696                     {                                                       \
00697                      /* A possible match in comp_table_data.                \
00698                         Buffer it.  */                               \
00699                                                                      \
00700                      /* We know it's a JIS X 0213 plane 1 character.  */   \
00701                      assert ((jch & 0x8000) == 0);                          \
00702                                                                      \
00703                      lasttwo = jch & 0x7f7f;                                \
00704                      inptr += 4;                                     \
00705                      continue;                                       \
00706                     }                                                       \
00707                                                                      \
00708                   if (__builtin_expect (outptr + 1 >= outend, 0))           \
00709                     {                                                       \
00710                      result = __GCONV_FULL_OUTPUT;                          \
00711                      break;                                          \
00712                     }                                                       \
00713                   *outptr++ = (jch >> 8) & 0x7f;                     \
00714                   *outptr++ = jch & 0x7f;                            \
00715                 }                                                    \
00716               else                                                   \
00717                 {                                                    \
00718                   /* Try JIS X 0201 Katakana.  This is officially not part  \
00719                      of ISO-2022-JP-3.  Therefore we try it after all other \
00720                      attempts.  */                                   \
00721                   if (ucs4_to_jisx0201 (ch, buf) != __UNKNOWN_10646_CHAR    \
00722                      && buf[0] >= 0x80)                              \
00723                     {                                                       \
00724                      if (set != JISX0201_Kana_set)                          \
00725                        {                                             \
00726                          if (__builtin_expect (outptr + 3 > outend, 0))    \
00727                            {                                                \
00728                             result = __GCONV_FULL_OUTPUT;                   \
00729                             break;                                   \
00730                            }                                                \
00731                          *outptr++ = ESC;                            \
00732                          *outptr++ = '(';                            \
00733                          *outptr++ = 'I';                            \
00734                          set = JISX0201_Kana_set;                           \
00735                        }                                             \
00736                                                                      \
00737                      if (__builtin_expect (outptr >= outend, 0))            \
00738                        {                                             \
00739                          result = __GCONV_FULL_OUTPUT;               \
00740                          break;                                      \
00741                        }                                             \
00742                      *outptr++ = buf[0] - 0x80;                      \
00743                     }                                                       \
00744                   else                                               \
00745                     {                                                       \
00746                      UNICODE_TAG_HANDLER (ch, 4);                           \
00747                                                                      \
00748                      /* Illegal character.  */                       \
00749                      STANDARD_TO_LOOP_ERR_HANDLER (4);               \
00750                     }                                                       \
00751                 }                                                    \
00752              }                                                              \
00753          }                                                           \
00754       }                                                                     \
00755                                                                      \
00756     /* Now that we wrote the output increment the input pointer.  */        \
00757     inptr += 4;                                                             \
00758   }
00759 #define LOOP_NEED_FLAGS
00760 #define EXTRA_LOOP_DECLS    , int *statep
00761 #define INIT_PARAMS         int set = *statep & CURRENT_SEL_MASK;           \
00762                             uint32_t lasttwo = *statep >> 6
00763 #define REINIT_PARAMS              do                                       \
00764                               {                                      \
00765                                 set = *statep & CURRENT_SEL_MASK;           \
00766                                 lasttwo = *statep >> 6;              \
00767                               }                                      \
00768                             while (0)
00769 #define UPDATE_PARAMS              *statep = set | (lasttwo << 6)
00770 #include <iconv/loop.c>
00771 
00772 
00773 /* Now define the toplevel functions.  */
00774 #include <iconv/skeleton.c>