b4c1725eeab2c4705ad29e1cfa1d5aa2a00d5713
[kopensolaris-gnu/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 <gb2312.h>
22 #include <stdint.h>
23
24 /* Definitions used in the body of the `gconv' function.  */
25 #define CHARSET_NAME            "EUC-CN//"
26 #define FROM_LOOP               from_euc_cn
27 #define TO_LOOP                 to_euc_cn
28 #define DEFINE_INIT             1
29 #define DEFINE_FINI             1
30 #define MIN_NEEDED_FROM         1
31 #define MAX_NEEDED_FROM         2
32 #define MIN_NEEDED_TO           4
33
34
35 /* First define the conversion function from EUC-CN to UCS4.  */
36 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
37 #define MAX_NEEDED_INPUT        MAX_NEEDED_FROM
38 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
39 #define LOOPFCT                 FROM_LOOP
40 #define BODY \
41   {                                                                           \
42     uint32_t ch = *inptr;                                                     \
43                                                                               \
44     if (ch <= 0x7f)                                                           \
45       ++inptr;                                                                \
46     else                                                                      \
47       if ((__builtin_expect (ch, 0xa1) <= 0xa0 && ch != 0x8e && ch != 0x8f)   \
48           || __builtin_expect (ch, 0xfe) > 0xfe)                              \
49         {                                                                     \
50           /* This is illegal.  */                                             \
51           if (! ignore_errors_p ())                                           \
52             {                                                                 \
53               result = __GCONV_ILLEGAL_INPUT;                                 \
54               break;                                                          \
55             }                                                                 \
56                                                                               \
57           ++inptr;                                                            \
58           ++*converted;                                                       \
59           continue;                                                           \
60         }                                                                     \
61       else                                                                    \
62         {                                                                     \
63           /* Two or more byte character.  First test whether the              \
64              next character is also available.  */                            \
65           const unsigned char *endp;                                          \
66                                                                               \
67           if (NEED_LENGTH_TEST && __builtin_expect (inptr + 1 >= inend, 0))   \
68             {                                                                 \
69               /* The second character is not available.  Store                \
70                  the intermediate result.  */                                 \
71               result = __GCONV_INCOMPLETE_INPUT;                              \
72               break;                                                          \
73             }                                                                 \
74                                                                               \
75           ch = inptr[1];                                                      \
76                                                                               \
77           /* All second bytes of a multibyte character must be >= 0xa1. */    \
78           if (__builtin_expect (ch, 0xa1) < 0xa1)                             \
79             {                                                                 \
80               if (! ignore_errors_p ())                                       \
81                 {                                                             \
82                   /* This is an illegal character.  */                        \
83                   result = __GCONV_ILLEGAL_INPUT;                             \
84                   break;                                                      \
85                 }                                                             \
86                                                                               \
87               ++inptr;                                                        \
88               ++*converted;                                                   \
89               continue;                                                       \
90             }                                                                 \
91                                                                               \
92           /* This is code set 1: GB 2312-80.  */                              \
93           endp = inptr;                                                       \
94                                                                               \
95           ch = gb2312_to_ucs4 (&endp, 2, 0x80);                               \
96           if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR)               \
97             {                                                                 \
98               /* This is an illegal character.  */                            \
99               if (! ignore_errors_p ())                                       \
100                 {                                                             \
101                   /* This is an illegal character.  */                        \
102                   result = __GCONV_ILLEGAL_INPUT;                             \
103                   break;                                                      \
104                 }                                                             \
105                                                                               \
106               inptr += 2;                                                     \
107               ++*converted;                                                   \
108               continue;                                                       \
109             }                                                                 \
110                                                                               \
111           inptr += 2;                                                         \
112         }                                                                     \
113                                                                               \
114     put32 (outptr, ch);                                                       \
115     outptr += 4;                                                              \
116   }
117 #include <iconv/loop.c>
118
119
120 /* Next, define the other direction.  */
121 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
122 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
123 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_FROM
124 #define LOOPFCT                 TO_LOOP
125 #define BODY \
126   {                                                                           \
127     uint32_t ch = get32 (inptr);                                              \
128                                                                               \
129     if (ch <= L'\x7f')                                                        \
130       /* It's plain ASCII.  */                                                \
131       *outptr++ = (unsigned char) ch;                                         \
132     else                                                                      \
133       {                                                                       \
134         size_t found;                                                         \
135                                                                               \
136         found = ucs4_to_gb2312 (ch, outptr,                                   \
137                                 (NEED_LENGTH_TEST                             \
138                                  ? outend - outptr : MAX_NEEDED_OUTPUT));     \
139         if (!NEED_LENGTH_TEST || __builtin_expect (found, 1) != 0)            \
140           {                                                                   \
141             if (__builtin_expect (found, 0) == __UNKNOWN_10646_CHAR)          \
142               {                                                               \
143                 /* Illegal character.  */                                     \
144                 if (! ignore_errors_p ())                                     \
145                   {                                                           \
146                     result = __GCONV_ILLEGAL_INPUT;                           \
147                     break;                                                    \
148                   }                                                           \
149                                                                               \
150                 inptr += 4;                                                   \
151                 ++*converted;                                                 \
152                 continue;                                                     \
153               }                                                               \
154                                                                               \
155             /* It's a GB 2312 character, adjust it for EUC-CN.  */            \
156             *outptr++ += 0x80;                                                \
157             *outptr++ += 0x80;                                                \
158           }                                                                   \
159         else                                                                  \
160           {                                                                   \
161             /* We ran out of space.  */                                       \
162             result = __GCONV_FULL_OUTPUT;                                     \
163             break;                                                            \
164           }                                                                   \
165       }                                                                       \
166     inptr += 4;                                                               \
167   }
168 #include <iconv/loop.c>
169
170
171 /* Now define the toplevel functions.  */
172 #include <iconv/skeleton.c>