Update.
[platform/upstream/glibc.git] / iconvdata / euc-cn.c
1 /* Mapping tables for EUC-CN handling.
2    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <dlfcn.h>
22 #include <gb2312.h>
23 #include <stdint.h>
24
25 /* Definitions used in the body of the `gconv' function.  */
26 #define CHARSET_NAME            "EUC-CN//"
27 #define FROM_LOOP               from_euc_cn
28 #define TO_LOOP                 to_euc_cn
29 #define DEFINE_INIT             1
30 #define DEFINE_FINI             1
31 #define MIN_NEEDED_FROM         1
32 #define MAX_NEEDED_FROM         2
33 #define MIN_NEEDED_TO           4
34
35
36 /* First define the conversion function from EUC-CN to UCS4.  */
37 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
38 #define MAX_NEEDED_INPUT        MAX_NEEDED_FROM
39 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
40 #define LOOPFCT                 FROM_LOOP
41 #define BODY \
42   {                                                                           \
43     uint32_t ch = *inptr;                                                     \
44                                                                               \
45     if (ch <= 0x7f)                                                           \
46       ++inptr;                                                                \
47     else                                                                      \
48       if ((__builtin_expect (ch, 0xa1) <= 0xa0 && ch != 0x8e && ch != 0x8f)   \
49           || __builtin_expect (ch, 0xfe) > 0xfe)                              \
50         {                                                                     \
51           /* This is illegal.  */                                             \
52           if (! ignore_errors_p ())                                           \
53             {                                                                 \
54               result = __GCONV_ILLEGAL_INPUT;                                 \
55               break;                                                          \
56             }                                                                 \
57                                                                               \
58           ++inptr;                                                            \
59           ++*irreversible;                                                    \
60           continue;                                                           \
61         }                                                                     \
62       else                                                                    \
63         {                                                                     \
64           /* Two or more byte character.  First test whether the              \
65              next character is also available.  */                            \
66           const unsigned char *endp;                                          \
67                                                                               \
68           if (__builtin_expect (inptr + 1 >= inend, 0))                       \
69             {                                                                 \
70               /* The second character is not available.  Store                \
71                  the intermediate result.  */                                 \
72               result = __GCONV_INCOMPLETE_INPUT;                              \
73               break;                                                          \
74             }                                                                 \
75                                                                               \
76           ch = inptr[1];                                                      \
77                                                                               \
78           /* All second bytes of a multibyte character must be >= 0xa1. */    \
79           if (__builtin_expect (ch, 0xa1) < 0xa1)                             \
80             {                                                                 \
81               if (! ignore_errors_p ())                                       \
82                 {                                                             \
83                   /* This is an illegal character.  */                        \
84                   result = __GCONV_ILLEGAL_INPUT;                             \
85                   break;                                                      \
86                 }                                                             \
87                                                                               \
88               ++inptr;                                                        \
89               ++*irreversible;                                                \
90               continue;                                                       \
91             }                                                                 \
92                                                                               \
93           /* This is code set 1: GB 2312-80.  */                              \
94           endp = inptr;                                                       \
95                                                                               \
96           ch = gb2312_to_ucs4 (&endp, 2, 0x80);                               \
97           if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR)               \
98             {                                                                 \
99               /* This is an illegal character.  */                            \
100               if (! ignore_errors_p ())                                       \
101                 {                                                             \
102                   /* This is an illegal character.  */                        \
103                   result = __GCONV_ILLEGAL_INPUT;                             \
104                   break;                                                      \
105                 }                                                             \
106                                                                               \
107               inptr += 2;                                                     \
108               ++*irreversible;                                                \
109               continue;                                                       \
110             }                                                                 \
111                                                                               \
112           inptr += 2;                                                         \
113         }                                                                     \
114                                                                               \
115     put32 (outptr, ch);                                                       \
116     outptr += 4;                                                              \
117   }
118 #define LOOP_NEED_FLAGS
119 #include <iconv/loop.c>
120
121
122 /* Next, define the other direction.  */
123 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
124 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
125 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_FROM
126 #define LOOPFCT                 TO_LOOP
127 #define BODY \
128   {                                                                           \
129     uint32_t ch = get32 (inptr);                                              \
130                                                                               \
131     if (ch <= L'\x7f')                                                        \
132       /* It's plain ASCII.  */                                                \
133       *outptr++ = (unsigned char) ch;                                         \
134     else                                                                      \
135       {                                                                       \
136         size_t found;                                                         \
137                                                                               \
138         found = ucs4_to_gb2312 (ch, outptr, outend - outptr);                 \
139         if (__builtin_expect (found, 1) != 0)                                 \
140           {                                                                   \
141             if (__builtin_expect (found, 0) == __UNKNOWN_10646_CHAR)          \
142               {                                                               \
143                 /* Illegal character.  */                                     \
144                 if (step_data->__trans.__trans_fct != NULL)                   \
145                   {                                                           \
146                     result = DL_CALL_FCT (step_data->__trans.__trans_fct,     \
147                                           (step, step_data, *inptrp, &inptr,  \
148                                            inend, *outptrp, &outptr, outend,  \
149                                            irreversible));                    \
150                     if (result != __GCONV_OK)                                 \
151                       break;                                                  \
152                   }                                                           \
153                 else if (! ignore_errors_p ())                                \
154                   {                                                           \
155                     result = __GCONV_ILLEGAL_INPUT;                           \
156                     break;                                                    \
157                   }                                                           \
158                 else                                                          \
159                   {                                                           \
160                     inptr += 4;                                               \
161                     ++*irreversible;                                          \
162                   }                                                           \
163                 continue;                                                     \
164               }                                                               \
165                                                                               \
166             /* It's a GB 2312 character, adjust it for EUC-CN.  */            \
167             *outptr++ += 0x80;                                                \
168             *outptr++ += 0x80;                                                \
169           }                                                                   \
170         else                                                                  \
171           {                                                                   \
172             /* We ran out of space.  */                                       \
173             result = __GCONV_FULL_OUTPUT;                                     \
174             break;                                                            \
175           }                                                                   \
176       }                                                                       \
177     inptr += 4;                                                               \
178   }
179 #define LOOP_NEED_FLAGS
180 #include <iconv/loop.c>
181
182
183 /* Now define the toplevel functions.  */
184 #include <iconv/skeleton.c>