1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 1994-2003 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <euc.h>
30 #define JFP_ICONV_STATELESS
31 #include "japanese.h"
32
33
34 void *
_icv_open(void)35 _icv_open(void)
36 {
37 return (_icv_open_stateless());
38 }
39
40 void
_icv_close(void * cd)41 _icv_close(void *cd)
42 {
43 _icv_close_stateless(cd);
44 return;
45 }
46
47 size_t
_icv_iconv(void * cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)48 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft,
49 char **outbuf, size_t *outbytesleft)
50 {
51 int stat;
52 unsigned char *ip, ic, *op;
53 size_t ileft, oleft;
54 size_t retval;
55
56 /*
57 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
58 * and put escape sequence if needed.
59 */
60 if ((inbuf == NULL) || (*inbuf == NULL)) {
61 /* nothing to do here for this module */
62 return ((size_t)0);
63 }
64
65 stat = ST_INIT;
66
67 ip = (unsigned char *)*inbuf;
68 op = (unsigned char *)*outbuf;
69 ileft = *inbytesleft;
70 oleft = *outbytesleft;
71
72 /*
73 * Main loop; basically 1 loop per 1 input byte
74 */
75
76 while ((int)ileft > 0) {
77 GET(ic);
78 if ((stat == ST_INCS1) || (stat == ST_INCS3)) {
79 ic = sjtojis2[ic];
80 PUT(ic | CMSB);
81 stat = ST_INIT;
82 continue;
83 } else if (ISASC((int)ic)) { /* ASCII */
84 CHECK2BIG(EUCW0,1);
85 PUT(ic);
86 continue;
87 } else if (ISSJKANA(ic)) { /* kana start */
88 CHECK2BIG((SS2W + EUCW2),1);
89 PUT(SS2);
90 PUT(ic);
91 continue;
92 } else if (ISSJKANJI1(ic)) { /* CS_1 kanji starts */
93 if ((int)ileft > 0) {
94 if (ISSJKANJI2(*ip)) {
95 CHECK2BIG(EUCW1,1);
96 stat = ST_INCS1;
97 ic = sjtojis1[(ic - 0x80)];
98 if (*ip >= 0x9f) {
99 ic++;
100 }
101 PUT(ic | CMSB);
102 continue;
103 } else { /* 2nd byte is illegal */
104 UNGET();
105 errno = EILSEQ;
106 retval = (size_t)ERR_RETURN;
107 goto ret;
108 }
109 } else { /* input fragment of Kanji */
110 UNGET();
111 errno = EINVAL;
112 retval = (size_t)ERR_RETURN;
113 goto ret;
114 }
115 } else if (ISSJSUPKANJI1(ic)) { /* CS_3 kanji starts */
116 if ((int)ileft > 0) {
117 if (ISSJKANJI2(*ip)) {
118 CHECK2BIG((SS3W + EUCW3),1);
119 stat = ST_INCS3;
120 ic = sjtojis1[(ic - 0x80)];
121 if (*ip >= 0x9f) {
122 ic++;
123 }
124 PUT(SS3);
125 PUT(ic | CMSB);
126 continue;
127 } else { /* 2nd byte is illegal */
128 UNGET();
129 errno = EILSEQ;
130 retval = (size_t)ERR_RETURN;
131 goto ret;
132 }
133 } else { /* input fragment of Kanji */
134 UNGET();
135 errno = EINVAL;
136 retval = (size_t)ERR_RETURN;
137 goto ret;
138 }
139 } else if (ISSJIBM(ic) || /* Extended IBM char. area */
140 ISSJNECIBM(ic)) { /* NEC/IBM char. area */
141 /*
142 * We need a special treatment for each codes.
143 * By adding some offset number for them, we
144 * can process them as the same way of that of
145 * extended IBM chars.
146 */
147 if ((int)ileft > 0) {
148 if (ISSJKANJI2(*ip)) {
149 unsigned short dest;
150 dest = (ic << 8);
151 GET(ic);
152 dest += ic;
153 if ((0xed40 <= dest) &&
154 (dest <= 0xeffc)) {
155 REMAP_NEC(dest);
156 if (dest == 0xffff) {
157 goto ill_ibm;
158 }
159 }
160 if ((dest == 0xfa54) ||
161 (dest == 0xfa5b)) {
162 CHECK2BIG(EUCW1,2);
163 if (dest == 0xfa54) {
164 PUT(0xa2);
165 PUT(0xcc);
166 } else {
167 PUT(0xa2);
168 PUT(0xe8);
169 }
170 continue;
171 }
172 CHECK2BIG((SS3W + EUCW3),2);
173 dest = dest - 0xfa40 -
174 (((dest>>8) - 0xfa) * 0x40);
175 dest = sjtoibmext[dest];
176 if (dest == 0xffff) {
177 /*
178 * Illegal code points
179 * in IBM-EXT area.
180 */
181 ill_ibm:
182 UNGET();
183 UNGET();
184 errno = EILSEQ;
185 retval = (size_t)ERR_RETURN;
186 goto ret;
187 }
188 PUT(SS3);
189 PUT((dest>>8) & 0xff);
190 PUT(dest & 0xff);
191 continue;
192 } else { /* 2nd byte is illegal */
193 UNGET();
194 errno = EILSEQ;
195 retval = (size_t)ERR_RETURN;
196 goto ret;
197 }
198 } else { /* input fragment of Kanji */
199 UNGET();
200 errno = EINVAL;
201 retval = (size_t)ERR_RETURN;
202 goto ret;
203 }
204 } else if ((0xeb <= ic) && (ic <= 0xec)) {
205 /*
206 * Based on the draft convention of OSF-JVC CDEWG,
207 * characters in this area will be mapped to
208 * "CHIKAN-MOJI." (convertible character)
209 * So far, we'll use (0x222e) for it.
210 */
211 if ((int)ileft > 0) {
212 if (ISSJKANJI2(*ip)) {
213 CHECK2BIG(EUCW1,1);
214 GET(ic); /* Dummy */
215 PUT((EGETA>>8) & 0xff);
216 PUT(EGETA & 0xff);
217 continue;
218 } else { /* 2nd byte is illegal */
219 UNGET();
220 errno = EILSEQ;
221 retval = (size_t)ERR_RETURN;
222 goto ret;
223 }
224 } else { /* input fragment of Kanji */
225 UNGET();
226 errno = EINVAL;
227 retval = (size_t)ERR_RETURN;
228 goto ret;
229 }
230 } else { /* 1st byte is illegal */
231 UNGET();
232 errno = EILSEQ;
233 retval = (size_t)ERR_RETURN;
234 goto ret;
235 }
236 }
237 retval = ileft;
238 ret:
239 *inbuf = (char *)ip;
240 *inbytesleft = ileft;
241 *outbuf = (char *)op;
242 *outbytesleft = oleft;
243
244 return (retval);
245 }
246