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