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