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