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
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <euc.h>
31 #include "japanese.h"
32
33
34 /*
35 * struct _cv_state; to keep status
36 */
37 struct _icv_state {
38 int _st_cset;
39 int _st_cset_sav;
40 };
41
42 void *
_icv_open()43 _icv_open()
44 {
45 struct _icv_state *st;
46
47 if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state)))
48 == NULL)
49 return ((void *)ERR_RETURN);
50
51 st->_st_cset = st->_st_cset_sav = CS_0;
52
53 return (st);
54 }
55
56 void
_icv_close(struct _icv_state * st)57 _icv_close(struct _icv_state *st)
58 {
59 free(st);
60 }
61
62 size_t
_icv_iconv(struct _icv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)63 _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft,
64 char **outbuf, size_t *outbytesleft)
65 {
66 int cset;
67 int stat = ST_INIT;
68 unsigned char *op;
69 char *ip, ic;
70 size_t ileft, oleft;
71 size_t retval;
72
73 /*
74 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
75 * and put escape sequence if needed.
76 */
77 if ((inbuf == NULL) || (*inbuf == NULL)) {
78 st->_st_cset_sav = st->_st_cset = CS_0;
79 return ((size_t)0);
80 }
81
82 cset = st->_st_cset;
83
84 ip = *inbuf;
85 op = (unsigned char *)*outbuf;
86 ileft = *inbytesleft;
87 oleft = *outbytesleft;
88
89 /*
90 * Main loop; basically 1 loop per 1 input byte
91 */
92
93 while ((int)ileft > 0) {
94 GET(ic);
95 if (stat == ST_INIT) {
96 goto text;
97 }
98
99 /*
100 * Half way of Kanji or ESC sequence
101 */
102 if ((stat == ST_INCS1) || (stat == ST_INCS3)) {
103 stat = ST_INIT;
104 PUT(ic | CMSB);
105 continue;
106 } else if (stat == ST_ESC) {
107 if (ic == MBTOG0_1) {
108 if ((int)ileft > 0) {
109 stat = ST_MBTOG0_1;
110 continue;
111 } else {
112 UNGET();
113 UNGET();
114 errno = EINVAL;
115 retval = (size_t)ERR_RETURN;
116 goto ret;
117 }
118 } else if (ic == SBTOG0_1) {
119 if ((int)ileft > 0) {
120 stat = ST_SBTOG0;
121 continue;
122 } else {
123 UNGET();
124 UNGET();
125 errno = EINVAL;
126 retval = (size_t)ERR_RETURN;
127 goto ret;
128 }
129 } else if (ic == X208REV_1) {
130 if ((int)ileft > 0) {
131 stat = ST_208REV_1;
132 continue;
133 } else {
134 UNGET();
135 UNGET();
136 errno = EINVAL;
137 retval = (size_t)ERR_RETURN;
138 goto ret;
139 }
140 } else {
141 UNGET();
142 UNGET();
143 errno = EILSEQ;
144 retval = (size_t)ERR_RETURN;
145 goto ret;
146 }
147 } else if (stat == ST_MBTOG0_1) {
148 if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) {
149 stat = ST_INIT;
150 st->_st_cset_sav = cset = CS_1;
151 continue;
152 } else if (ic == F_X0212_90) {
153 stat = ST_INIT;
154 st->_st_cset_sav = cset = CS_3;
155 continue;
156 } else if (ic == MBTOG0_2) {
157 if ((int)ileft > 0) {
158 stat = ST_MBTOG0_2;
159 continue;
160 } else {
161 UNGET();
162 UNGET();
163 UNGET();
164 errno = EINVAL;
165 retval = (size_t)ERR_RETURN;
166 goto ret;
167 }
168 } else {
169 UNGET();
170 UNGET();
171 UNGET();
172 errno = EILSEQ;
173 retval = (size_t)ERR_RETURN;
174 goto ret;
175 }
176 } else if (stat == ST_MBTOG0_2) {
177 if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) {
178 stat = ST_INIT;
179 st->_st_cset_sav = cset = CS_1;
180 continue;
181 } else if (ic == F_X0212_90) {
182 stat = ST_INIT;
183 st->_st_cset_sav = cset = CS_3;
184 continue;
185 } else {
186 UNGET();
187 UNGET();
188 UNGET();
189 UNGET();
190 errno = EILSEQ;
191 retval = (size_t)ERR_RETURN;
192 goto ret;
193 }
194 } else if (stat == ST_SBTOG0) {
195 if ((ic == F_ASCII) ||
196 (ic == F_X0201_RM) ||
197 (ic == F_ISO646)) {
198 stat = ST_INIT;
199 st->_st_cset_sav = cset = CS_0;
200 continue;
201 } else if (ic == F_X0201_KN) {
202 cset = CS_2;
203 stat = ST_INIT;
204 continue;
205 } else {
206 UNGET();
207 UNGET();
208 UNGET();
209 errno = EILSEQ;
210 retval = (size_t)ERR_RETURN;
211 goto ret;
212 }
213 } else if (stat == ST_208REV_1) {
214 if (ic == X208REV_2) {
215 if ((int)ileft > 0) {
216 stat = ST_208REV_2;
217 continue;
218 } else {
219 UNGET();
220 UNGET();
221 UNGET();
222 errno = EINVAL;
223 retval = (size_t)ERR_RETURN;
224 goto ret;
225 }
226 } else {
227 UNGET();
228 UNGET();
229 UNGET();
230 errno = EILSEQ;
231 retval = (size_t)ERR_RETURN;
232 goto ret;
233 }
234 } else if (stat == ST_208REV_2) {
235 if (ic == ESC) {
236 if ((int)ileft > 0) {
237 stat = ST_REV_AFT_ESC;
238 continue;
239 } else {
240 UNGET();
241 UNGET();
242 UNGET();
243 UNGET();
244 errno = EINVAL;
245 retval = (size_t)ERR_RETURN;
246 goto ret;
247 }
248 } else {
249 UNGET();
250 UNGET();
251 UNGET();
252 UNGET();
253 errno = EILSEQ;
254 retval = (size_t)ERR_RETURN;
255 goto ret;
256 }
257 } else if (stat == ST_REV_AFT_ESC) {
258 if (ic == MBTOG0_1) {
259 if ((int)ileft > 0) {
260 stat = ST_REV_AFT_MBTOG0_1;
261 continue;
262 } else {
263 UNGET();
264 UNGET();
265 UNGET();
266 UNGET();
267 UNGET();
268 errno = EINVAL;
269 retval = (size_t)ERR_RETURN;
270 goto ret;
271 }
272 } else {
273 UNGET();
274 UNGET();
275 UNGET();
276 UNGET();
277 UNGET();
278 errno = EILSEQ;
279 retval = (size_t)ERR_RETURN;
280 goto ret;
281 }
282 } else if (stat == ST_REV_AFT_MBTOG0_1) {
283 if (ic == F_X0208_83_90) {
284 stat = ST_INIT;
285 st->_st_cset_sav = cset = CS_1;
286 continue;
287 } else if (ic == MBTOG0_2) {
288 if ((int)ileft > 0) {
289 stat = ST_REV_AFT_MBTOG0_2;
290 continue;
291 } else {
292 UNGET();
293 UNGET();
294 UNGET();
295 UNGET();
296 UNGET();
297 UNGET();
298 errno = EINVAL;
299 retval = (size_t)ERR_RETURN;
300 goto ret;
301 }
302 } else {
303 UNGET();
304 UNGET();
305 UNGET();
306 UNGET();
307 UNGET();
308 UNGET();
309 errno = EILSEQ;
310 retval = (size_t)ERR_RETURN;
311 goto ret;
312 }
313 } else if (stat == ST_REV_AFT_MBTOG0_2) {
314 if (ic == F_X0208_83_90) {
315 stat = ST_INIT;
316 st->_st_cset_sav = cset = CS_1;
317 continue;
318 } else {
319 UNGET();
320 UNGET();
321 UNGET();
322 UNGET();
323 UNGET();
324 UNGET();
325 UNGET();
326 errno = EILSEQ;
327 retval = (size_t)ERR_RETURN;
328 goto ret;
329 }
330 }
331 text:
332 /*
333 * Break through chars or ESC sequence
334 */
335 if (ic == ESC) {
336 if ((int)ileft > 0) {
337 stat = ST_ESC;
338 continue;
339 } else {
340 UNGET();
341 errno = EINVAL;
342 retval = (size_t)ERR_RETURN;
343 goto ret;
344 }
345 } else if (ic == SO) {
346 cset = CS_2;
347 stat = ST_INIT;
348 continue;
349 } else if (ic == SI) {
350 cset = st->_st_cset_sav;
351 stat = ST_INIT;
352 continue;
353 }
354 if (!(ic & CMSB)) {
355 if (cset == CS_0) {
356 if (oleft < EUCW0) {
357 UNGET();
358 errno = E2BIG;
359 retval = (size_t)ERR_RETURN;
360 goto ret;
361 }
362 PUT(ic);
363 continue;
364 } else if (cset == CS_2) {
365 if (oleft < (EUCW2 + SEQ_SS)) {
366 UNGET();
367 errno = E2BIG;
368 retval = (size_t)ERR_RETURN;
369 goto ret;
370 }
371 PUT(SS2);
372 PUT(ic | CMSB);
373 continue;
374 } else if (cset == CS_3) {
375 if ((int)ileft > 0) {
376 if (oleft < (EUCW3 + SEQ_SS)) {
377 UNGET();
378 errno = E2BIG;
379 retval = (size_t)ERR_RETURN;
380 goto ret;
381 }
382 stat = ST_INCS3;
383 PUT(SS3);
384 PUT(ic | CMSB);
385 continue;
386 } else {
387 UNGET();
388 errno = EINVAL;
389 retval = (size_t)ERR_RETURN;
390 goto ret;
391 }
392 } else {
393 if ((int)ileft > 0) {
394 if (oleft < EUCW1) {
395 UNGET();
396 errno = E2BIG;
397 retval = (size_t)ERR_RETURN;
398 goto ret;
399 }
400 stat = ST_INCS1;
401 PUT(ic | CMSB);
402 continue;
403 } else {
404 UNGET();
405 errno = EINVAL;
406 retval = (size_t)ERR_RETURN;
407 goto ret;
408 }
409 }
410 } else {
411 if (oleft < UNKNOWNW) {
412 UNGET();
413 errno = E2BIG;
414 retval = (size_t)ERR_RETURN;
415 goto ret;
416 }
417 PUT(ic);
418 continue;
419 }
420 }
421 retval = ileft;
422 ret:
423 *inbuf = ip;
424 *inbytesleft = ileft;
425 *outbuf = (char *)op;
426 *outbytesleft = oleft;
427 st->_st_cset = cset;
428
429 return (retval);
430 }
431