* manual/arith.texi: Document MTASC-safety properties.
[jlayton/glibc.git] / iconvdata / euc-tw.c
1 /* Mapping tables for EUC-TW handling.
2    Copyright (C) 1998-2014 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 Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the 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    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <dlfcn.h>
21 #include <stdint.h>
22 #include <cns11643l1.h>
23 #include <cns11643.h>
24
25 /* Definitions used in the body of the `gconv' function.  */
26 #define CHARSET_NAME            "EUC-TW//"
27 #define FROM_LOOP               from_euc_tw
28 #define TO_LOOP                 to_euc_tw
29 #define DEFINE_INIT             1
30 #define DEFINE_FINI             1
31 #define MIN_NEEDED_FROM         1
32 #define MAX_NEEDED_FROM         4
33 #define MIN_NEEDED_TO           4
34
35
36 /* First define the conversion function from EUC-TW 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       /* Plain ASCII.  */                                                     \
47       ++inptr;                                                                \
48     else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e)                         \
49       {                                                                       \
50         /* This is illegal.  */                                               \
51         STANDARD_FROM_LOOP_ERR_HANDLER (1);                                   \
52       }                                                                       \
53     else                                                                      \
54       {                                                                       \
55         /* Two or more byte character.  First test whether the next byte      \
56            is also available.  */                                             \
57         uint32_t ch2;                                                         \
58                                                                               \
59         if (inptr + 1 >= inend)                                               \
60           {                                                                   \
61             /* The second byte is not available.  Store the intermediate      \
62                result.  */                                                    \
63             result = __GCONV_INCOMPLETE_INPUT;                                \
64             break;                                                            \
65           }                                                                   \
66                                                                               \
67         ch2 = *(inptr + 1);                                                   \
68                                                                               \
69         /* All second bytes of a multibyte character must be >= 0xa1. */      \
70         if (ch2 < 0xa1 || ch2 == 0xff)                                        \
71           STANDARD_FROM_LOOP_ERR_HANDLER (1);                                 \
72                                                                               \
73         if (ch == 0x8e)                                                       \
74           {                                                                   \
75             /* This is code set 2: CNS 11643, planes 1 to 16.  */             \
76             const unsigned char *endp = inptr + 1;                            \
77                                                                               \
78             ch = cns11643_to_ucs4 (&endp, inend - inptr - 1, 0x80);           \
79                                                                               \
80             if (ch == 0)                                                      \
81               {                                                               \
82                 /* The third or fourth byte is not available.  Store          \
83                    the intermediate result.  */                               \
84                 result = __GCONV_INCOMPLETE_INPUT;                            \
85                 break;                                                        \
86               }                                                               \
87                                                                               \
88             if (ch == __UNKNOWN_10646_CHAR)                                   \
89               /* Illegal input.  */                                           \
90               STANDARD_FROM_LOOP_ERR_HANDLER (1);                             \
91                                                                               \
92             inptr += 4;                                                       \
93           }                                                                   \
94         else                                                                  \
95           {                                                                   \
96             /* This is code set 1: CNS 11643, plane 1.  */                    \
97             const unsigned char *endp = inptr;                                \
98                                                                               \
99             ch = cns11643l1_to_ucs4 (&endp, inend - inptr, 0x80);             \
100             /* Please note that we need not test for the missing input        \
101                characters here anymore.  */                                   \
102             if (ch == __UNKNOWN_10646_CHAR)                                   \
103               /* Illegal input.  */                                           \
104               STANDARD_FROM_LOOP_ERR_HANDLER (2);                             \
105                                                                               \
106             inptr += 2;                                                       \
107           }                                                                   \
108       }                                                                       \
109                                                                               \
110     put32 (outptr, ch);                                                       \
111     outptr += 4;                                                              \
112   }
113 #define LOOP_NEED_FLAGS
114 #define ONEBYTE_BODY \
115   {                                                                           \
116     if (c < 0x80)                                                             \
117       return c;                                                               \
118     else                                                                      \
119       return WEOF;                                                            \
120   }
121 #include <iconv/loop.c>
122
123
124 /* Next, define the other direction.  */
125 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
126 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
127 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_FROM
128 #define LOOPFCT                 TO_LOOP
129 #define BODY \
130   {                                                                           \
131     uint32_t ch = get32 (inptr);                                              \
132                                                                               \
133     if (ch <= 0x7f)                                                           \
134       /* It's plain ASCII.  */                                                \
135       *outptr++ = ch;                                                         \
136     else                                                                      \
137       {                                                                       \
138         /* Try the CNS 11643 planes.  */                                      \
139         size_t found;                                                         \
140                                                                               \
141         found = ucs4_to_cns11643l1 (ch, outptr, outend - outptr);             \
142         if (__builtin_expect (found, 1) == 0)                                 \
143           {                                                                   \
144             /* We ran out of space.  */                                       \
145             result = __GCONV_FULL_OUTPUT;                                     \
146             break;                                                            \
147           }                                                                   \
148         if (__builtin_expect (found, 1) != __UNKNOWN_10646_CHAR)              \
149           {                                                                   \
150             /* It's a CNS 11643, plane 1 character, adjust it for EUC-TW.  */ \
151             *outptr++ += 0x80;                                                \
152             *outptr++ += 0x80;                                                \
153           }                                                                   \
154         else                                                                  \
155           {                                                                   \
156             /* No CNS 11643, plane 1 character.  */                           \
157                                                                               \
158             found = ucs4_to_cns11643 (ch, outptr + 1, outend - outptr - 1);   \
159             if (__builtin_expect (found, 1) == 0)                             \
160               {                                                               \
161                 /* We ran out of space.  */                                   \
162                 result = __GCONV_FULL_OUTPUT;                                 \
163                 break;                                                        \
164               }                                                               \
165             if (__builtin_expect (found, 0) == __UNKNOWN_10646_CHAR)          \
166               {                                                               \
167                 UNICODE_TAG_HANDLER (ch, 4);                                  \
168                                                                               \
169                 /* Illegal character.  */                                     \
170                 STANDARD_TO_LOOP_ERR_HANDLER (4);                             \
171               }                                                               \
172                                                                               \
173             /* It's a CNS 11643 character, adjust it for EUC-TW.  */          \
174             *outptr++ = '\x8e';                                               \
175             *outptr++ += 0xa0;                                                \
176             *outptr++ += 0x80;                                                \
177             *outptr++ += 0x80;                                                \
178           }                                                                   \
179       }                                                                       \
180                                                                               \
181     inptr += 4;                                                               \
182   }
183 #define LOOP_NEED_FLAGS
184 #include <iconv/loop.c>
185
186
187 /* Now define the toplevel functions.  */
188 #include <iconv/skeleton.c>