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 static unsigned short lookuptbl(unsigned short);
34 
35 void *
_icv_open(void)36 _icv_open(void)
37 {
38 	return (_icv_open_stateless());
39 }
40 
41 void
_icv_close(void * cd)42 _icv_close(void *cd)
43 {
44 	_icv_close_stateless(cd);
45 	return;
46 }
47 
48 size_t
_icv_iconv(void * cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)49 _icv_iconv(void *cd, char **inbuf, size_t *inbytesleft,
50 				char **outbuf, size_t *outbytesleft)
51 {
52 	int				stat;
53 	unsigned char	*ip, ic, *op;
54 	size_t			ileft, oleft;
55 	size_t			retval;
56 
57 	stat = ST_INIT;
58 
59 	/*
60 	 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
61 	 * and put escape sequence if needed.
62 	 */
63 	if ((inbuf == NULL) || (*inbuf == NULL)) {
64 		/* nothing to do here for this module */
65 		return ((size_t)0);
66 	}
67 
68 	ip = (unsigned char *)*inbuf;
69 	op = (unsigned char *)*outbuf;
70 	ileft = *inbytesleft;
71 	oleft = *outbytesleft;
72 
73 	/*
74 	 * Main loop; basically 1 loop per 1 input byte
75 	 */
76 
77 	while ((int)ileft > 0) {
78 		GET(ic);
79 		if (stat == ST_INCS2) {
80 			PUT(ic);
81 			stat = ST_INIT;
82 			continue;
83 		}
84 		if (ISASC((int)ic)) {		/* ASCII */
85 			if (oleft < SJISW0) {
86 				UNGET();
87 				errno = E2BIG;
88 				retval = (size_t)ERR_RETURN;
89 				goto ret;
90 			}
91 			PUT(ic);
92 			continue;
93 		}
94 		if (ISCS1(ic)) {			/* Kanji starts */
95 			if ((int)ileft > 0) {
96 				if (ISCS1(*ip)) {
97 					int even_ku;
98 					if (oleft < SJISW1) {
99 						UNGET();
100 						errno = E2BIG;
101 						retval = (size_t)ERR_RETURN;
102 						goto ret;
103 					}
104 					ic &= 0x7f;
105 					PUT(jis208tosj1[ic]);
106 					if ((ic % 2) == 0)
107 						even_ku = TRUE;
108 					else
109 						even_ku = FALSE;
110 					GET(ic);
111 					ic &= 0x7f;
112 					if (even_ku)
113 						ic += 0x80;
114 					PUT(jistosj2[ic]);
115 					continue;
116 				} else {	/* 2nd byte is illegal */
117 					UNGET();
118 					errno = EILSEQ;
119 					retval = (size_t)ERR_RETURN;
120 					goto ret;
121 				}
122 			} else {		/* input fragment of Kanji */
123 				UNGET();
124 				errno = EINVAL;
125 				retval = (size_t)ERR_RETURN;
126 				goto ret;
127 			}
128 		} else if (ic == SS2) {	/* Kana starts */
129 			if ((int)ileft > 0) {
130 				if (ISCS2(*ip)) {
131 					if (oleft < SJISW2) {
132 						UNGET();
133 						errno = E2BIG;
134 						retval = (size_t)ERR_RETURN;
135 						goto ret;
136 					}
137 					stat = ST_INCS2;
138 					continue;
139 				} else {	/* 2nd byte is illegal */
140 					UNGET();
141 					errno = EILSEQ;
142 					retval = (size_t)ERR_RETURN;
143 					goto ret;
144 				}
145 			} else {		/* input fragment of Kana */
146 				UNGET();
147 				errno = EINVAL;
148 				retval = (size_t)ERR_RETURN;
149 				goto ret;
150 			}
151 		} else if (ic == SS3) { /* CS_3 Kanji starts */
152 			unsigned short dest;
153 			if (ileft >= EUCW3) {
154 				if (ISCS3(*ip) && ISCS3(*(ip + 1))) {
155 					if (oleft < SJISW1) {
156 						UNGET();
157 						errno = E2BIG;
158 						retval = (size_t)ERR_RETURN;
159 						goto ret;
160 					}
161 					if (*ip < 0xf5) { /* check IBM area */
162 						GET(ic);
163 						dest = (ic << 8);
164 						GET(ic);
165 						dest += ic;
166 						dest = lookuptbl(dest);
167 						if (dest == 0xffff) {
168 							/*
169 							 * Illegal code points
170 							 * in G3 plane.
171 							 */
172 							UNGET();
173 							UNGET();
174 							errno = E2BIG;
175 							retval =
176 							(size_t)ERR_RETURN;
177 							goto ret;
178 						} else {
179 							PUT((dest >> 8) &
180 							0xff);
181 							PUT(dest & 0xff);
182 						}
183 						continue;
184 					} else {
185 						unsigned char c1, c2;
186 
187 						GET(c1);
188 						GET(c2);
189 						c1 &= 0x7f;
190 						c2 &= 0x7f;
191 						if ((c1 % 2) == 0)
192 							c2 += 0x80;
193 						c1 = jis212tosj1[c1];
194 						c2 = jistosj2[c2];
195 						if ((c1 != 0xff) &&
196 							(c2 != 0xff)) {
197 							PUT(c1);
198 							PUT(c2);
199 							continue;
200 						}
201 						PUT((PGETA >> 8) & 0xff);
202 						PUT(PGETA & 0xff);
203 						continue;
204 					}
205 				} else {
206 					errno = EILSEQ;
207 					retval = (size_t)ERR_RETURN;
208 					goto ret;
209 				}
210 			} else {	/* input fragment of JISX0212 */
211 				UNGET();
212 				errno = EINVAL;
213 				retval = (size_t)ERR_RETURN;
214 				goto ret;
215 			}
216 		} else {
217 			UNGET();
218 			errno = EILSEQ;
219 			retval = (size_t)ERR_RETURN;
220 			goto ret;
221 		}
222 	}
223 	retval = ileft;
224 ret:
225 	*inbuf = (char *)ip;
226 	*inbytesleft = ileft;
227 	*outbuf = (char *)op;
228 	*outbytesleft = oleft;
229 
230 	return (retval);
231 }
232 
233 /*
234  * lookuptbl()
235  * Return the index number if its index-ed number
236  * is the same as dest value.
237  */
238 static unsigned short
lookuptbl(unsigned short dest)239 lookuptbl(unsigned short dest)
240 {
241 	unsigned short tmp;
242 	int i;
243 	int sz = (sizeof (sjtoibmext) / sizeof (sjtoibmext[0]));
244 
245 	for (i = 0; i < sz; i++) {
246 		tmp = sjtoibmext[i];
247 		if (tmp == dest)
248 			return ((i + 0xfa40 + ((i / 0xc0) * 0x40)));
249 	}
250 	return (PGETA);
251 }
252