96e075628ca7fd665427df2b4a97f2b563164799
[kopensolaris-gnu/glibc.git] / iconvdata / eucjp.c
1 /* Mapping tables for EUC-JP handling.
2    Copyright (C) 1998 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 <stdint.h>
22 #include <gconv.h>
23 #include <jis0201.h>
24 #include <jis0208.h>
25 #include <jis0212.h>
26
27 /* Definitions used in the body of the `gconv' function.  */
28 #define CHARSET_NAME            "EUC-JP//"
29 #define FROM_LOOP               from_euc_jp
30 #define TO_LOOP                 to_euc_jp
31 #define DEFINE_INIT             1
32 #define DEFINE_FINI             1
33 #define MIN_NEEDED_FROM         1
34 #define MAX_NEEDED_FROM         3
35 #define MIN_NEEDED_TO           4
36
37
38 /* First define the conversion function from EUC-JP to UCS4.  */
39 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
40 #define MAX_NEEDED_INPUT        MAX_NEEDED_FROM
41 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
42 #define LOOPFCT                 FROM_LOOP
43 #define BODY \
44   {                                                                           \
45     uint32_t ch = *inptr;                                                     \
46                                                                               \
47     if (ch <= 0x7f)                                                           \
48       ++inptr;                                                                \
49     else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f)           \
50       {                                                                       \
51         /* This is illegal.  */                                               \
52         result = GCONV_ILLEGAL_INPUT;                                         \
53         break;                                                                \
54       }                                                                       \
55     else                                                                      \
56       {                                                                       \
57         /* Two or more byte character.  First test whether the next           \
58            character is also available.  */                                   \
59         int ch2;                                                              \
60                                                                               \
61         if (NEED_LENGTH_TEST && inptr + 1 >= inend)                           \
62           {                                                                   \
63             /* The second character is not available.  Store the              \
64                intermediate result.  */                                       \
65             result = GCONV_INCOMPLETE_INPUT;                                  \
66             break;                                                            \
67           }                                                                   \
68                                                                               \
69         ch2 = inptr[1];                                                       \
70                                                                               \
71         /* All second bytes of a multibyte character must be >= 0xa1. */      \
72         if (ch2 < 0xa1)                                                       \
73           {                                                                   \
74             /* This is an illegal character.  */                              \
75             result = GCONV_ILLEGAL_INPUT;                                     \
76             break;                                                            \
77           }                                                                   \
78                                                                               \
79         if (ch == 0x8e)                                                       \
80           {                                                                   \
81             /* This is code set 2: half-width katakana.  */                   \
82             ch = jisx0201_to_ucs4 (ch2);                                      \
83             inptr += 2;                                                       \
84           }                                                                   \
85         else                                                                  \
86           {                                                                   \
87             const unsigned char *endp;                                        \
88                                                                               \
89             if (ch == 0x8f)                                                   \
90               {                                                               \
91                 /* This is code set 3: JIS X 0212-1990.  */                   \
92                 endp = inptr + 1;                                             \
93                                                                               \
94                 ch = jisx0212_to_ucs4 (&endp,                                 \
95                                        NEED_LENGTH_TEST ? inend - endp : 2,   \
96                                        0x80);                                 \
97               }                                                               \
98             else                                                              \
99               {                                                               \
100                 /* This is code set 1: JIS X 0208.  */                        \
101                 endp = inptr;                                                 \
102                                                                               \
103                 ch = jisx0208_to_ucs4 (&endp,                                 \
104                                        NEED_LENGTH_TEST ? inend - inptr : 2,  \
105                                        0x80);                                 \
106               }                                                               \
107                                                                               \
108             if (NEED_LENGTH_TEST && ch == 0)                                  \
109               {                                                               \
110                 /* Not enough input available.  */                            \
111                 result = GCONV_INCOMPLETE_INPUT;                              \
112                 break;                                                        \
113               }                                                               \
114             if (ch == UNKNOWN_10646_CHAR)                                     \
115               {                                                               \
116                 /* Illegal character.  */                                     \
117                 result = GCONV_ILLEGAL_INPUT;                                 \
118                 break;                                                        \
119               }                                                               \
120             inptr = endp;                                                     \
121           }                                                                   \
122       }                                                                       \
123                                                                               \
124     *((uint32_t *) outptr)++ = ch;                                            \
125   }
126 #include <iconv/loop.c>
127
128
129 /* Next, define the other direction.  */
130 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
131 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
132 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_FROM
133 #define LOOPFCT                 TO_LOOP
134 #define BODY \
135   {                                                                           \
136     uint32_t ch = *((uint32_t *) inptr);                                      \
137                                                                               \
138     if (ch <= 0x7f)                                                           \
139       /* It's plain ASCII.  */                                                \
140       *outptr++ = ch;                                                         \
141     else                                                                      \
142       {                                                                       \
143         /* Try the JIS character sets.  */                                    \
144         size_t found;                                                         \
145                                                                               \
146         /* See whether we have room for at least two characters.  */          \
147         if (NEED_LENGTH_TEST && outptr + 1 >= outend)                         \
148           {                                                                   \
149             result = GCONV_FULL_OUTPUT;                                       \
150             break;                                                            \
151           }                                                                   \
152                                                                               \
153         found = ucs4_to_jisx0201 (ch, outptr + 1);                            \
154         if (found != UNKNOWN_10646_CHAR)                                      \
155           {                                                                   \
156             /* Yes, it's a JIS 0201 character.  Store the shift byte.  */     \
157             *outptr = 0x8e;                                                   \
158             outptr += 2;                                                      \
159           }                                                                   \
160         else                                                                  \
161           {                                                                   \
162             /* No JIS 0201 character.  */                                     \
163             found = ucs4_to_jisx0208 (ch, outptr, 2);                         \
164             /* Please note that we always have enough room for the output. */ \
165             if (found != UNKNOWN_10646_CHAR)                                  \
166               {                                                               \
167                 /* It's a JIS 0208 character, adjust it for EUC-JP.  */       \
168                 *outptr++ += 0x80;                                            \
169                 *outptr++ += 0x80;                                            \
170               }                                                               \
171             else                                                              \
172               {                                                               \
173                 /* No JIS 0208 character.  */                                 \
174                 found = ucs4_to_jisx0212 (ch, outptr + 1,                     \
175                                           (NEED_LENGTH_TEST                   \
176                                            ? outend - outptr - 1 : 2));       \
177                                                                               \
178                 if (found == 0)                                               \
179                   {                                                           \
180                     /* We ran out of space.  */                               \
181                     result = GCONV_FULL_OUTPUT;                               \
182                     break;                                                    \
183                   }                                                           \
184                 else if (found != UNKNOWN_10646_CHAR)                         \
185                   {                                                           \
186                     /* It's a JIS 0212 character, adjust it for EUC-JP.  */   \
187                     *outptr++ = 0x8f;                                         \
188                     *outptr++ += 0x80;                                        \
189                     *outptr++ += 0x80;                                        \
190                   }                                                           \
191                 else                                                          \
192                   {                                                           \
193                     /* Illegal character.  */                                 \
194                     result = GCONV_ILLEGAL_INPUT;                             \
195                     break;                                                    \
196                   }                                                           \
197               }                                                               \
198           }                                                                   \
199       }                                                                       \
200                                                                               \
201     inptr += 4;                                                               \
202   }
203 #include <iconv/loop.c>
204
205
206 /* Now define the toplevel functions.  */
207 #include <iconv/skeleton.c>