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 #include "japanese.h"
31
32
33 /*
34 * struct _icv_state; to keep stat
35 */
36 struct _icv_state {
37 int _st_cset;
38 };
39
40 void *
_icv_open()41 _icv_open()
42 {
43 struct _icv_state *st;
44
45 if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state)))
46 == NULL)
47 return ((void *)ERR_RETURN);
48
49 st->_st_cset = CS_0;
50 return (st);
51 }
52
53 void
_icv_close(struct _icv_state * st)54 _icv_close(struct _icv_state *st)
55 {
56 free(st);
57 }
58
59 size_t
_icv_iconv(struct _icv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)60 _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft,
61 char **outbuf, size_t *outbytesleft)
62 {
63 int cset;
64 unsigned char *ip, ic;
65 char *op;
66 size_t ileft, oleft;
67 size_t retval;
68
69 /*
70 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
71 * and put escape sequence if needed.
72 */
73 if ((inbuf == NULL) || (*inbuf == NULL)) {
74 if (st->_st_cset != CS_0) {
75 if ((outbuf != NULL) && (*outbuf != NULL)
76 && (outbytesleft != NULL)) {
77 op = (char *)*outbuf;
78 oleft = *outbytesleft;
79 if (oleft < SEQ_SBTOG0) {
80 errno = E2BIG;
81 return ((size_t)-1);
82 }
83 PUT(ESC);
84 PUT(SBTOG0_1);
85 PUT(F_X0201_RM);
86 *outbuf = (char *)op;
87 *outbytesleft = oleft;
88 }
89 st->_st_cset = CS_0;
90 }
91 return ((size_t)0);
92 }
93
94 cset = st->_st_cset;
95
96 ip = (unsigned char *)*inbuf;
97 op = *outbuf;
98 ileft = *inbytesleft;
99 oleft = *outbytesleft;
100
101 /*
102 * Main loop; basically 1 loop per 1 output char
103 */
104 while ((int)ileft > 0) {
105 GET(ic);
106 if (ISASC((int)ic)) { /* ASCII */
107 if (cset != CS_0) {
108 if (oleft < SEQ_SBTOG0) {
109 UNGET();
110 errno = E2BIG;
111 retval = (size_t)ERR_RETURN;
112 goto ret;
113 }
114 PUT(ESC); /* Kanji Out */
115 PUT(SBTOG0_1);
116 PUT(F_X0201_RM);
117 }
118 cset = CS_0;
119 if (oleft < JISW0) {
120 UNGET();
121 errno = E2BIG;
122 retval = (size_t)ERR_RETURN;
123 goto ret;
124 }
125 /* Put ASCII character */
126 PUT(ic);
127 continue;
128 } else if (ISCS1((int)ic)) { /* CS_1 starts */
129 if ((int)ileft > 0) {
130 if (ISCS1(ic) && ISCS1(*ip)) {
131 if (cset != CS_1) {
132 if (oleft < SEQ_MBTOG0_O) {
133 UNGET();
134 errno = E2BIG;
135 retval =
136 (size_t)ERR_RETURN;
137 goto ret;
138 }
139 cset = CS_1;
140 PUT(ESC);
141 PUT(MBTOG0_1);
142 PUT(F_X0208_83_90);
143 }
144 if (oleft < JISW1) {
145 UNGET();
146 errno = E2BIG;
147 retval = (size_t)ERR_RETURN;
148 goto ret;
149 }
150 #ifdef RFC1468_MODE /* Convert VDC and UDC to GETA */
151 if ((ic == 0xad) || (0xf5 <= ic )){
152 PUT((JGETA >> 8) & CMASK);
153 GET(ic); /* Get dummy */
154 PUT(JGETA & CMASK);
155 continue;
156 }
157 #endif /* RFC1468_MODE */
158 /* Put JIS X 0208 character */
159 PUT(ic & CMASK);
160 GET(ic);
161 PUT(ic & CMASK);
162 continue;
163 } else {
164 errno = EILSEQ;
165 retval = (size_t)ERR_RETURN;
166 goto ret;
167 }
168 } else { /* input fragment of Kanji */
169 UNGET();
170 errno = EINVAL;
171 retval = (size_t)ERR_RETURN;
172 goto ret;
173 }
174 } else if (ic == SS2) { /* Kana starts */
175 if ((int)ileft > 0) {
176 if (ISCS2(*ip)) {
177
178 #ifdef RFC1468_MODE /* Substitute JIS X 0208 for JIS X 0201 Katakana */
179 unsigned short zenkaku;
180 if (cset != CS_1) {
181 if (oleft < SEQ_MBTOG0_O) {
182 UNGET();
183 errno = E2BIG;
184 retval =
185 (size_t)ERR_RETURN;
186 goto ret;
187 }
188 PUT(ESC);
189 PUT(MBTOG0_1);
190 PUT(F_X0208_83_90);
191 cset = CS_1;
192 }
193 if (oleft < JISW1) {
194 UNGET();
195 errno = E2BIG;
196 retval = (size_t)ERR_RETURN;
197 goto ret;
198 }
199 GET(ic);
200 zenkaku = halfkana2zenkakuj[ic - 0xA1];
201 ic = (unsigned char)((zenkaku >> 8) &
202 CMASK);
203 PUT(ic);
204 ic = (unsigned char)(zenkaku & CMASK);
205 PUT(ic);
206 #else /* ISO-2022-JP.UIOSF */
207 if (cset != CS_2) {
208 if (oleft < SEQ_SBTOG0) {
209 UNGET();
210 errno = E2BIG;
211 retval =
212 (size_t)ERR_RETURN;
213 goto ret;
214 }
215 PUT(ESC);
216 PUT(SBTOG0_1);
217 PUT(F_X0201_KN);
218 cset = CS_2;
219 }
220 if (oleft < JISW2) {
221 UNGET();
222 errno = E2BIG;
223 retval = (size_t)ERR_RETURN;
224 goto ret;
225 }
226 /* Put Kana character */
227 GET(ic);
228 PUT(ic & CMASK);
229 #endif /* RFC1468_MODE */
230 continue;
231 } else { /* 2nd byte is illegal */
232 errno = EILSEQ;
233 retval = (size_t)ERR_RETURN;
234 goto ret;
235 }
236 } else { /* input fragment of Kana */
237 UNGET();
238 errno = EINVAL;
239 retval = (size_t)ERR_RETURN;
240 goto ret;
241 }
242 } else if (ic == SS3) { /* JISX0212 starts */
243 if (ileft >= EUCW3) {
244 if (ISCS3(*ip) && ISCS3(*(ip + 1))) {
245
246 /* ISO-2022-JP.RFC1468 or ISO-2022-JP.UIOSF */
247 #ifdef RFC1468_MODE /* Substitute JIS X 0208 "Geta" for JIS X 0212 */
248 if (cset != CS_1) {
249 if (oleft < SEQ_MBTOG0_O) {
250 UNGET();
251 errno = E2BIG;
252 retval =
253 (size_t)ERR_RETURN;
254 goto ret;
255 }
256 cset = CS_1;
257 PUT(ESC);
258 PUT(MBTOG0_1);
259 PUT(F_X0208_83_90);
260 }
261 if (oleft < JISW1) {
262 UNGET();
263 errno = E2BIG;
264 retval = (size_t)ERR_RETURN;
265 goto ret;
266 }
267 /* Put GETA (0x222e) */
268 ic = (unsigned char)((JGETA >> 8) &
269 CMASK);
270 PUT(ic);
271 ic = (unsigned char)(JGETA & CMASK);
272 PUT(ic);
273 GET(ic); /* dummy GET */
274 GET(ic); /* dummy GET */
275 #else /* ISO-2022-JP.UIOSF */
276 if (cset != CS_3) {
277 if (oleft < SEQ_MBTOG0) {
278 UNGET();
279 errno = E2BIG;
280 retval =
281 (size_t)ERR_RETURN;
282 goto ret;
283 }
284 cset = CS_3;
285 PUT(ESC);
286 PUT(MBTOG0_1);
287 PUT(MBTOG0_2);
288 PUT(F_X0212_90);
289 }
290 if (oleft < JISW3) {
291 UNGET();
292 errno = E2BIG;
293 retval = (size_t)ERR_RETURN;
294 goto ret;
295 }
296 /* Put JIS X 0212 character */
297 GET(ic);
298 PUT(ic & CMASK);
299 GET(ic);
300 PUT(ic & CMASK);
301 #endif /* RFC1468_MODE */
302 continue;
303 } else {
304 errno = EILSEQ;
305 retval = (size_t)ERR_RETURN;
306 goto ret;
307 }
308 } else { /* input fragment of JISX0212 */
309 UNGET();
310 errno = EINVAL;
311 retval = (size_t)ERR_RETURN;
312 goto ret;
313 }
314 } else {
315 UNGET();
316 errno = EILSEQ;
317 retval = (size_t)ERR_RETURN;
318 goto ret;
319 }
320 }
321 retval = ileft;
322 ret:
323 *inbuf = (char *)ip;
324 *inbytesleft = ileft;
325 *outbuf = op;
326 *outbytesleft = oleft;
327 st->_st_cset = cset;
328
329 return (retval);
330 }
331