1*16d86563SAlexander Pyhalov /*
2*16d86563SAlexander Pyhalov  * CDDL HEADER START
3*16d86563SAlexander Pyhalov  *
4*16d86563SAlexander Pyhalov  * The contents of this file are subject to the terms of the
5*16d86563SAlexander Pyhalov  * Common Development and Distribution License (the "License").
6*16d86563SAlexander Pyhalov  * You may not use this file except in compliance with the License.
7*16d86563SAlexander Pyhalov  *
8*16d86563SAlexander Pyhalov  * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9*16d86563SAlexander Pyhalov  * or http://www.opensolaris.org/os/licensing.
10*16d86563SAlexander Pyhalov  * See the License for the specific language governing permissions
11*16d86563SAlexander Pyhalov  * and limitations under the License.
12*16d86563SAlexander Pyhalov  *
13*16d86563SAlexander Pyhalov  * When distributing Covered Code, include this CDDL HEADER in each
14*16d86563SAlexander Pyhalov  * file and include the License file at src/OPENSOLARIS.LICENSE.
15*16d86563SAlexander Pyhalov  * If applicable, add the following below this CDDL HEADER, with the
16*16d86563SAlexander Pyhalov  * fields enclosed by brackets "[]" replaced with your own identifying
17*16d86563SAlexander Pyhalov  * information: Portions Copyright [yyyy] [name of copyright owner]
18*16d86563SAlexander Pyhalov  *
19*16d86563SAlexander Pyhalov  * CDDL HEADER END
20*16d86563SAlexander Pyhalov  */
21*16d86563SAlexander Pyhalov /*
22*16d86563SAlexander Pyhalov  * Copyright 1994-2003 Sun Microsystems, Inc.  All rights reserved.
23*16d86563SAlexander Pyhalov  * Use is subject to license terms.
24*16d86563SAlexander Pyhalov  */
25*16d86563SAlexander Pyhalov 
26*16d86563SAlexander Pyhalov #include <stdio.h>
27*16d86563SAlexander Pyhalov #include <stdlib.h>
28*16d86563SAlexander Pyhalov #include <errno.h>
29*16d86563SAlexander Pyhalov #include <euc.h>
30*16d86563SAlexander Pyhalov #include "japanese.h"
31*16d86563SAlexander Pyhalov 
32*16d86563SAlexander Pyhalov /*
33*16d86563SAlexander Pyhalov  * struct _icv_state; to keep stat
34*16d86563SAlexander Pyhalov  */
35*16d86563SAlexander Pyhalov struct _icv_state {
36*16d86563SAlexander Pyhalov 	int	_st_cset;
37*16d86563SAlexander Pyhalov };
38*16d86563SAlexander Pyhalov 
39*16d86563SAlexander Pyhalov void *
_icv_open()40*16d86563SAlexander Pyhalov _icv_open()
41*16d86563SAlexander Pyhalov {
42*16d86563SAlexander Pyhalov 	struct _icv_state *st;
43*16d86563SAlexander Pyhalov 
44*16d86563SAlexander Pyhalov 	if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state)))
45*16d86563SAlexander Pyhalov 									== NULL)
46*16d86563SAlexander Pyhalov 		return ((void *)ERR_RETURN);
47*16d86563SAlexander Pyhalov 
48*16d86563SAlexander Pyhalov 	st->_st_cset = CS_0;
49*16d86563SAlexander Pyhalov 	return (st);
50*16d86563SAlexander Pyhalov }
51*16d86563SAlexander Pyhalov 
52*16d86563SAlexander Pyhalov void
_icv_close(struct _icv_state * st)53*16d86563SAlexander Pyhalov _icv_close(struct _icv_state *st)
54*16d86563SAlexander Pyhalov {
55*16d86563SAlexander Pyhalov 	free(st);
56*16d86563SAlexander Pyhalov }
57*16d86563SAlexander Pyhalov 
58*16d86563SAlexander Pyhalov size_t
_icv_iconv(struct _icv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)59*16d86563SAlexander Pyhalov _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft,
60*16d86563SAlexander Pyhalov 				char **outbuf, size_t *outbytesleft)
61*16d86563SAlexander Pyhalov {
62*16d86563SAlexander Pyhalov 	int cset, stat;
63*16d86563SAlexander Pyhalov 	unsigned char *ip, ic;
64*16d86563SAlexander Pyhalov 	char *op;
65*16d86563SAlexander Pyhalov 	size_t ileft, oleft;
66*16d86563SAlexander Pyhalov 	size_t retval;
67*16d86563SAlexander Pyhalov 
68*16d86563SAlexander Pyhalov 	stat = ST_INIT;
69*16d86563SAlexander Pyhalov 
70*16d86563SAlexander Pyhalov 	/*
71*16d86563SAlexander Pyhalov 	 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
72*16d86563SAlexander Pyhalov 	 * and put escape sequence if needed.
73*16d86563SAlexander Pyhalov 	 */
74*16d86563SAlexander Pyhalov 	if ((inbuf == NULL) || (*inbuf == NULL)) {
75*16d86563SAlexander Pyhalov 		if ((st->_st_cset == CS_1) || (st->_st_cset == CS_3)) {
76*16d86563SAlexander Pyhalov 			if ((outbuf != NULL) && (*outbuf != NULL)
77*16d86563SAlexander Pyhalov 					&& (outbytesleft != NULL)) {
78*16d86563SAlexander Pyhalov 				op = (char *)*outbuf;
79*16d86563SAlexander Pyhalov 				oleft = *outbytesleft;
80*16d86563SAlexander Pyhalov 				if (oleft < SEQ_SBTOG0) {
81*16d86563SAlexander Pyhalov 					errno = E2BIG;
82*16d86563SAlexander Pyhalov 					return ((size_t)-1);
83*16d86563SAlexander Pyhalov 				}
84*16d86563SAlexander Pyhalov 				PUT(ESC);
85*16d86563SAlexander Pyhalov 				PUT(SBTOG0_1);
86*16d86563SAlexander Pyhalov 				PUT(F_X0201_RM);
87*16d86563SAlexander Pyhalov 				*outbuf = (char *)op;
88*16d86563SAlexander Pyhalov 				*outbytesleft = oleft;
89*16d86563SAlexander Pyhalov 			}
90*16d86563SAlexander Pyhalov 			st->_st_cset = CS_0;
91*16d86563SAlexander Pyhalov 		} else if (st->_st_cset == CS_2) {
92*16d86563SAlexander Pyhalov 			if ((outbuf != NULL) && (*outbuf != NULL)
93*16d86563SAlexander Pyhalov 					&& (outbytesleft != NULL)) {
94*16d86563SAlexander Pyhalov 				op = (char *)*outbuf;
95*16d86563SAlexander Pyhalov 				oleft = *outbytesleft;
96*16d86563SAlexander Pyhalov 				if (oleft < SEQ_SOSI) {
97*16d86563SAlexander Pyhalov 					errno = E2BIG;
98*16d86563SAlexander Pyhalov 					return ((size_t)-1);
99*16d86563SAlexander Pyhalov 				}
100*16d86563SAlexander Pyhalov 				PUT(SI);
101*16d86563SAlexander Pyhalov 				*outbuf = (char *)op;
102*16d86563SAlexander Pyhalov 				*outbytesleft = oleft;
103*16d86563SAlexander Pyhalov 			}
104*16d86563SAlexander Pyhalov 			st->_st_cset = CS_0;
105*16d86563SAlexander Pyhalov 		}
106*16d86563SAlexander Pyhalov 		return ((size_t)0);
107*16d86563SAlexander Pyhalov 	}
108*16d86563SAlexander Pyhalov 
109*16d86563SAlexander Pyhalov 	cset = st->_st_cset;
110*16d86563SAlexander Pyhalov 
111*16d86563SAlexander Pyhalov 	ip = (unsigned char *)*inbuf;
112*16d86563SAlexander Pyhalov 	op = *outbuf;
113*16d86563SAlexander Pyhalov 	ileft = *inbytesleft;
114*16d86563SAlexander Pyhalov 	oleft = *outbytesleft;
115*16d86563SAlexander Pyhalov 
116*16d86563SAlexander Pyhalov 	/*
117*16d86563SAlexander Pyhalov 	 * Main loop; basically 1 loop per 1 input byte
118*16d86563SAlexander Pyhalov 	 */
119*16d86563SAlexander Pyhalov 
120*16d86563SAlexander Pyhalov 	while ((int)ileft > 0) {
121*16d86563SAlexander Pyhalov 		GET(ic);
122*16d86563SAlexander Pyhalov 		if (stat == ST_INCS2) {
123*16d86563SAlexander Pyhalov 			PUT(ic & CMASK);
124*16d86563SAlexander Pyhalov 			stat = ST_INIT;
125*16d86563SAlexander Pyhalov 			continue;
126*16d86563SAlexander Pyhalov 		} else if (stat == ST_INCS1) {
127*16d86563SAlexander Pyhalov 			PUT(ic & CMASK);
128*16d86563SAlexander Pyhalov 			stat = ST_INIT;
129*16d86563SAlexander Pyhalov 			continue;
130*16d86563SAlexander Pyhalov 		} else if (stat == ST_INCS3) {
131*16d86563SAlexander Pyhalov 			PUT(ic & CMASK);
132*16d86563SAlexander Pyhalov 			GET(ic);
133*16d86563SAlexander Pyhalov 			PUT(ic & CMASK);
134*16d86563SAlexander Pyhalov 			stat = ST_INIT;
135*16d86563SAlexander Pyhalov 			continue;
136*16d86563SAlexander Pyhalov 		}
137*16d86563SAlexander Pyhalov 		if (ISASC((int)ic)) { /* ASCII */
138*16d86563SAlexander Pyhalov 			if ((cset == CS_1) || (cset == CS_3)) {
139*16d86563SAlexander Pyhalov 				if (oleft < SEQ_SBTOG0) {
140*16d86563SAlexander Pyhalov 					UNGET();
141*16d86563SAlexander Pyhalov 					errno = E2BIG;
142*16d86563SAlexander Pyhalov 					retval = (size_t)ERR_RETURN;
143*16d86563SAlexander Pyhalov 					goto ret;
144*16d86563SAlexander Pyhalov 				}
145*16d86563SAlexander Pyhalov 				PUT(ESC);	/* Kanji Out */
146*16d86563SAlexander Pyhalov 				PUT(SBTOG0_1);
147*16d86563SAlexander Pyhalov 				PUT(F_X0201_RM);
148*16d86563SAlexander Pyhalov 			} else if (cset == CS_2) {
149*16d86563SAlexander Pyhalov 				if (oleft < SEQ_SOSI) {
150*16d86563SAlexander Pyhalov 					UNGET();
151*16d86563SAlexander Pyhalov 					errno = E2BIG;
152*16d86563SAlexander Pyhalov 					retval = (size_t)ERR_RETURN;
153*16d86563SAlexander Pyhalov 					goto ret;
154*16d86563SAlexander Pyhalov 				}
155*16d86563SAlexander Pyhalov 				PUT(SI);	/* Shift In */
156*16d86563SAlexander Pyhalov 			}
157*16d86563SAlexander Pyhalov 			cset = CS_0;
158*16d86563SAlexander Pyhalov 			if (oleft < JISW0) {
159*16d86563SAlexander Pyhalov 				UNGET();
160*16d86563SAlexander Pyhalov 				errno = E2BIG;
161*16d86563SAlexander Pyhalov 				retval = (size_t)ERR_RETURN;
162*16d86563SAlexander Pyhalov 				goto ret;
163*16d86563SAlexander Pyhalov 			}
164*16d86563SAlexander Pyhalov 			PUT(ic);
165*16d86563SAlexander Pyhalov 			continue;
166*16d86563SAlexander Pyhalov 		} else if (ISCS1(ic)) {
167*16d86563SAlexander Pyhalov 			if ((int)ileft > 0) {	/* Kanj starts */
168*16d86563SAlexander Pyhalov 				if (ISCS1(*ip)) {
169*16d86563SAlexander Pyhalov 					if (cset == CS_2) {
170*16d86563SAlexander Pyhalov 						if (oleft < SEQ_SOSI) {
171*16d86563SAlexander Pyhalov 							UNGET();
172*16d86563SAlexander Pyhalov 							errno = E2BIG;
173*16d86563SAlexander Pyhalov 							retval =
174*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
175*16d86563SAlexander Pyhalov 							goto ret;
176*16d86563SAlexander Pyhalov 						}
177*16d86563SAlexander Pyhalov 						cset = CS_0;
178*16d86563SAlexander Pyhalov 						PUT(SI);
179*16d86563SAlexander Pyhalov 					}
180*16d86563SAlexander Pyhalov 					if (cset != CS_1) {
181*16d86563SAlexander Pyhalov 						if (oleft < SEQ_MBTOG0_O) {
182*16d86563SAlexander Pyhalov 							UNGET();
183*16d86563SAlexander Pyhalov 							errno = E2BIG;
184*16d86563SAlexander Pyhalov 							retval =
185*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
186*16d86563SAlexander Pyhalov 							goto ret;
187*16d86563SAlexander Pyhalov 						}
188*16d86563SAlexander Pyhalov 						cset = CS_1;
189*16d86563SAlexander Pyhalov 						PUT(ESC);
190*16d86563SAlexander Pyhalov 						PUT(MBTOG0_1);
191*16d86563SAlexander Pyhalov 						PUT(F_X0208_83_90);
192*16d86563SAlexander Pyhalov 					}
193*16d86563SAlexander Pyhalov 					if (oleft < JISW1) {
194*16d86563SAlexander Pyhalov 						UNGET();
195*16d86563SAlexander Pyhalov 						errno = E2BIG;
196*16d86563SAlexander Pyhalov 						retval = (size_t)ERR_RETURN;
197*16d86563SAlexander Pyhalov 						goto ret;
198*16d86563SAlexander Pyhalov 					}
199*16d86563SAlexander Pyhalov 					stat = ST_INCS1;
200*16d86563SAlexander Pyhalov 					PUT(ic & CMASK);
201*16d86563SAlexander Pyhalov 					continue;
202*16d86563SAlexander Pyhalov 				} else {	/* 2nd byte is illegal */
203*16d86563SAlexander Pyhalov 					errno = EILSEQ;
204*16d86563SAlexander Pyhalov 					retval = (size_t)ERR_RETURN;
205*16d86563SAlexander Pyhalov 					goto ret;
206*16d86563SAlexander Pyhalov 				}
207*16d86563SAlexander Pyhalov 			} else {		/* input fragment of Kanji */
208*16d86563SAlexander Pyhalov 				UNGET();
209*16d86563SAlexander Pyhalov 				errno = EINVAL;
210*16d86563SAlexander Pyhalov 				retval = (size_t)ERR_RETURN;
211*16d86563SAlexander Pyhalov 				goto ret;
212*16d86563SAlexander Pyhalov 			}
213*16d86563SAlexander Pyhalov 		} else if (ic == SS2) {	/* Kana starts */
214*16d86563SAlexander Pyhalov 			if ((int)ileft > 0) {
215*16d86563SAlexander Pyhalov 				if (ISCS2(*ip)) {
216*16d86563SAlexander Pyhalov 					if ((cset == CS_1) || (cset == CS_3)) {
217*16d86563SAlexander Pyhalov 						if (oleft < SEQ_SBTOG0) {
218*16d86563SAlexander Pyhalov 							UNGET();
219*16d86563SAlexander Pyhalov 							errno = E2BIG;
220*16d86563SAlexander Pyhalov 							retval =
221*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
222*16d86563SAlexander Pyhalov 							goto ret;
223*16d86563SAlexander Pyhalov 						}
224*16d86563SAlexander Pyhalov 						cset = CS_0;
225*16d86563SAlexander Pyhalov 						PUT(ESC);
226*16d86563SAlexander Pyhalov 						PUT(SBTOG0_1);
227*16d86563SAlexander Pyhalov 						PUT(F_X0201_RM);
228*16d86563SAlexander Pyhalov 					}
229*16d86563SAlexander Pyhalov 					if (cset != CS_2) {
230*16d86563SAlexander Pyhalov 						if (oleft < SEQ_SOSI) {
231*16d86563SAlexander Pyhalov 							UNGET();
232*16d86563SAlexander Pyhalov 							errno = E2BIG;
233*16d86563SAlexander Pyhalov 							retval =
234*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
235*16d86563SAlexander Pyhalov 							goto ret;
236*16d86563SAlexander Pyhalov 						}
237*16d86563SAlexander Pyhalov 						cset = CS_2;
238*16d86563SAlexander Pyhalov 						PUT(SO);
239*16d86563SAlexander Pyhalov 					}
240*16d86563SAlexander Pyhalov 					if (oleft < JISW2) {
241*16d86563SAlexander Pyhalov 						UNGET();
242*16d86563SAlexander Pyhalov 						errno = E2BIG;
243*16d86563SAlexander Pyhalov 						retval = (size_t)ERR_RETURN;
244*16d86563SAlexander Pyhalov 						goto ret;
245*16d86563SAlexander Pyhalov 					}
246*16d86563SAlexander Pyhalov 					stat = ST_INCS2;
247*16d86563SAlexander Pyhalov 					continue;
248*16d86563SAlexander Pyhalov 				} else {	/* 2nd byte is illegal */
249*16d86563SAlexander Pyhalov 					errno = EILSEQ;
250*16d86563SAlexander Pyhalov 					retval = (size_t)ERR_RETURN;
251*16d86563SAlexander Pyhalov 					goto ret;
252*16d86563SAlexander Pyhalov 				}
253*16d86563SAlexander Pyhalov 			} else {		/* input fragment of Kana */
254*16d86563SAlexander Pyhalov 				UNGET();
255*16d86563SAlexander Pyhalov 				errno = EINVAL;
256*16d86563SAlexander Pyhalov 				retval = (size_t)ERR_RETURN;
257*16d86563SAlexander Pyhalov 				goto ret;
258*16d86563SAlexander Pyhalov 			}
259*16d86563SAlexander Pyhalov 		} else if (ic == SS3) {	/* JISX0212 starts */
260*16d86563SAlexander Pyhalov 			if (ileft >= EUCW3) {
261*16d86563SAlexander Pyhalov 				if (ISCS3(*ip) && ISCS3(*(ip + 1))) {
262*16d86563SAlexander Pyhalov 					if (cset == CS_2) {
263*16d86563SAlexander Pyhalov 						if (oleft < SEQ_SOSI) {
264*16d86563SAlexander Pyhalov 							UNGET();
265*16d86563SAlexander Pyhalov 							errno = E2BIG;
266*16d86563SAlexander Pyhalov 							retval =
267*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
268*16d86563SAlexander Pyhalov 							goto ret;
269*16d86563SAlexander Pyhalov 						}
270*16d86563SAlexander Pyhalov 						cset = CS_0;
271*16d86563SAlexander Pyhalov 						PUT(SI);
272*16d86563SAlexander Pyhalov 					}
273*16d86563SAlexander Pyhalov 					if (cset != CS_3) {
274*16d86563SAlexander Pyhalov 						if (oleft < SEQ_MBTOG0) {
275*16d86563SAlexander Pyhalov 							UNGET();
276*16d86563SAlexander Pyhalov 							errno = E2BIG;
277*16d86563SAlexander Pyhalov 							retval =
278*16d86563SAlexander Pyhalov 							(size_t)ERR_RETURN;
279*16d86563SAlexander Pyhalov 							goto ret;
280*16d86563SAlexander Pyhalov 						}
281*16d86563SAlexander Pyhalov 						cset = CS_3;
282*16d86563SAlexander Pyhalov 						PUT(ESC);
283*16d86563SAlexander Pyhalov 						PUT(MBTOG0_1);
284*16d86563SAlexander Pyhalov 						PUT(MBTOG0_2);
285*16d86563SAlexander Pyhalov 						PUT(F_X0212_90);
286*16d86563SAlexander Pyhalov 					}
287*16d86563SAlexander Pyhalov 					if (oleft < JISW3) {
288*16d86563SAlexander Pyhalov 						UNGET();
289*16d86563SAlexander Pyhalov 						errno = E2BIG;
290*16d86563SAlexander Pyhalov 						retval = (size_t)ERR_RETURN;
291*16d86563SAlexander Pyhalov 						goto ret;
292*16d86563SAlexander Pyhalov 					}
293*16d86563SAlexander Pyhalov 					stat = ST_INCS3;
294*16d86563SAlexander Pyhalov 					continue;
295*16d86563SAlexander Pyhalov 				} else {
296*16d86563SAlexander Pyhalov 					errno = EILSEQ;
297*16d86563SAlexander Pyhalov 					retval = (size_t)ERR_RETURN;
298*16d86563SAlexander Pyhalov 					goto ret;
299*16d86563SAlexander Pyhalov 				}
300*16d86563SAlexander Pyhalov 			} else {	/* input fragment of JISX0212 */
301*16d86563SAlexander Pyhalov 				UNGET();
302*16d86563SAlexander Pyhalov 				errno = EINVAL;
303*16d86563SAlexander Pyhalov 				retval = (size_t)ERR_RETURN;
304*16d86563SAlexander Pyhalov 				goto ret;
305*16d86563SAlexander Pyhalov 			}
306*16d86563SAlexander Pyhalov 		} else {
307*16d86563SAlexander Pyhalov 			UNGET();
308*16d86563SAlexander Pyhalov 			errno = EILSEQ;
309*16d86563SAlexander Pyhalov 			retval = (size_t)ERR_RETURN;
310*16d86563SAlexander Pyhalov 			goto ret;
311*16d86563SAlexander Pyhalov 		}
312*16d86563SAlexander Pyhalov 	}
313*16d86563SAlexander Pyhalov 	retval = ileft;
314*16d86563SAlexander Pyhalov ret:
315*16d86563SAlexander Pyhalov 	*inbuf = (char *)ip;
316*16d86563SAlexander Pyhalov 	*inbytesleft = ileft;
317*16d86563SAlexander Pyhalov 	*outbuf = op;
318*16d86563SAlexander Pyhalov 	*outbytesleft = oleft;
319*16d86563SAlexander Pyhalov 	st->_st_cset = cset;
320*16d86563SAlexander Pyhalov 
321*16d86563SAlexander Pyhalov 	return (retval);
322*16d86563SAlexander Pyhalov }
323