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 #include "japanese.h"
31 
32 
33 /*
34  * struct _icv_state; to keep stat
35  */
36 struct _icv_state {
37 	int	_st_cset;
38 };
39 
40 void *
_icv_open()41 _icv_open()
42 {
43 	struct _icv_state *st;
44 
45 	if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state)))
46 									== NULL)
47 		return ((void *)ERR_RETURN);
48 
49 	st->_st_cset = CS_0;
50 	return (st);
51 }
52 
53 void
_icv_close(struct _icv_state * st)54 _icv_close(struct _icv_state *st)
55 {
56 	free(st);
57 }
58 
59 size_t
_icv_iconv(struct _icv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)60 _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft,
61 				char **outbuf, size_t *outbytesleft)
62 {
63 	int cset;
64 	unsigned char *ip, ic;
65 	char *op;
66 	size_t ileft, oleft;
67 	size_t retval;
68 
69 	/*
70 	 * If inbuf and/or *inbuf are NULL, reset conversion descriptor
71 	 * and put escape sequence if needed.
72 	 */
73 	if ((inbuf == NULL) || (*inbuf == NULL)) {
74 		if (st->_st_cset != CS_0) {
75 			if ((outbuf != NULL) && (*outbuf != NULL)
76 					&& (outbytesleft != NULL)) {
77 				op = (char *)*outbuf;
78 				oleft = *outbytesleft;
79 				if (oleft < SEQ_SBTOG0) {
80 					errno = E2BIG;
81 					return ((size_t)-1);
82 				}
83 				PUT(ESC);
84 				PUT(SBTOG0_1);
85 				PUT(F_X0201_RM);
86 				*outbuf = (char *)op;
87 				*outbytesleft = oleft;
88 			}
89 			st->_st_cset = CS_0;
90 		}
91 		return ((size_t)0);
92 	}
93 
94 	cset = st->_st_cset;
95 
96 	ip = (unsigned char *)*inbuf;
97 	op = *outbuf;
98 	ileft = *inbytesleft;
99 	oleft = *outbytesleft;
100 
101 	/*
102 	 * Main loop; basically 1 loop per 1 output char
103 	 */
104 	while ((int)ileft > 0) {
105 		GET(ic);
106 		if (ISASC((int)ic)) { /* ASCII */
107 			if (cset != CS_0) {
108 				if (oleft < SEQ_SBTOG0) {
109 					UNGET();
110 					errno = E2BIG;
111 					retval = (size_t)ERR_RETURN;
112 					goto ret;
113 				}
114 				PUT(ESC);	/* Kanji Out */
115 				PUT(SBTOG0_1);
116 				PUT(F_X0201_RM);
117 			}
118 			cset = CS_0;
119 			if (oleft < JISW0) {
120 				UNGET();
121 				errno = E2BIG;
122 				retval = (size_t)ERR_RETURN;
123 				goto ret;
124 			}
125 			/* Put ASCII character */
126 			PUT(ic);
127 			continue;
128 		} else if (ISCS1((int)ic)) { /* CS_1 starts */
129 			if ((int)ileft > 0) {
130 				if (ISCS1(ic) && ISCS1(*ip)) {
131 					if (cset != CS_1) {
132 						if (oleft < SEQ_MBTOG0_O) {
133 							UNGET();
134 							errno = E2BIG;
135 							retval =
136 							(size_t)ERR_RETURN;
137 							goto ret;
138 						}
139 						cset = CS_1;
140 						PUT(ESC);
141 						PUT(MBTOG0_1);
142 						PUT(F_X0208_83_90);
143 					}
144 					if (oleft < JISW1) {
145 						UNGET();
146 						errno = E2BIG;
147 						retval = (size_t)ERR_RETURN;
148 						goto ret;
149 					}
150 #ifdef  RFC1468_MODE /* Convert VDC and UDC to GETA */
151 					if ((ic == 0xad) || (0xf5 <= ic )){
152 						PUT((JGETA >> 8) & CMASK);
153 						GET(ic); /* Get dummy */
154 						PUT(JGETA & CMASK);
155 						continue;
156 					}
157 #endif  /* RFC1468_MODE */
158 					/* Put JIS X 0208 character */
159 					PUT(ic & CMASK);
160 					GET(ic);
161 					PUT(ic & CMASK);
162 					continue;
163 				} else {
164 					errno = EILSEQ;
165 					retval = (size_t)ERR_RETURN;
166 					goto ret;
167 				}
168 			} else {		/* input fragment of Kanji */
169 				UNGET();
170 				errno = EINVAL;
171 				retval = (size_t)ERR_RETURN;
172 				goto ret;
173 			}
174 		} else if (ic == SS2) {	/* Kana starts */
175 			if ((int)ileft > 0) {
176 				if (ISCS2(*ip)) {
177 
178 #ifdef  RFC1468_MODE	/* Substitute JIS X 0208 for JIS X 0201 Katakana */
179 				unsigned short  zenkaku;
180 					if (cset != CS_1) {
181 						if (oleft < SEQ_MBTOG0_O) {
182 							UNGET();
183 							errno = E2BIG;
184 							retval =
185 							(size_t)ERR_RETURN;
186 							goto ret;
187 						}
188 						PUT(ESC);
189 						PUT(MBTOG0_1);
190 						PUT(F_X0208_83_90);
191 						cset = CS_1;
192 					}
193 					if (oleft < JISW1) {
194 						UNGET();
195 						errno = E2BIG;
196 						retval = (size_t)ERR_RETURN;
197 						goto ret;
198 					}
199 					GET(ic);
200 					zenkaku = halfkana2zenkakuj[ic - 0xA1];
201 					ic = (unsigned char)((zenkaku >> 8) &
202 					CMASK);
203 					PUT(ic);
204 					ic = (unsigned char)(zenkaku & CMASK);
205 					PUT(ic);
206 #else   /* ISO-2022-JP.UIOSF */
207 					if (cset != CS_2) {
208 						if (oleft < SEQ_SBTOG0) {
209 							UNGET();
210 							errno = E2BIG;
211 							retval =
212 							(size_t)ERR_RETURN;
213 							goto ret;
214 						}
215 						PUT(ESC);
216 						PUT(SBTOG0_1);
217 						PUT(F_X0201_KN);
218 						cset = CS_2;
219 					}
220 					if (oleft < JISW2) {
221 						UNGET();
222 						errno = E2BIG;
223 						retval = (size_t)ERR_RETURN;
224 						goto ret;
225 					}
226 					/* Put Kana character */
227 					GET(ic);
228 					PUT(ic & CMASK);
229 #endif  /* RFC1468_MODE */
230 					continue;
231 				} else {	/* 2nd byte is illegal */
232 					errno = EILSEQ;
233 					retval = (size_t)ERR_RETURN;
234 					goto ret;
235 				}
236 			} else {		/* input fragment of Kana */
237 				UNGET();
238 				errno = EINVAL;
239 				retval = (size_t)ERR_RETURN;
240 				goto ret;
241 			}
242 		} else if (ic == SS3) {	/* JISX0212 starts */
243 			if (ileft >= EUCW3) {
244 				if (ISCS3(*ip) && ISCS3(*(ip + 1))) {
245 
246 /* ISO-2022-JP.RFC1468 or ISO-2022-JP.UIOSF */
247 #ifdef  RFC1468_MODE	/* Substitute JIS X 0208 "Geta" for JIS X 0212 */
248 					if (cset != CS_1) {
249 						if (oleft < SEQ_MBTOG0_O) {
250 							UNGET();
251 							errno = E2BIG;
252 							retval =
253 							(size_t)ERR_RETURN;
254 							goto ret;
255 						}
256 						cset = CS_1;
257 						PUT(ESC);
258 						PUT(MBTOG0_1);
259 						PUT(F_X0208_83_90);
260 					}
261 					if (oleft < JISW1) {
262 						UNGET();
263 						errno = E2BIG;
264 						retval = (size_t)ERR_RETURN;
265 						goto ret;
266 					}
267 					/* Put GETA (0x222e) */
268 					ic = (unsigned char)((JGETA >> 8) &
269 					CMASK);
270 					PUT(ic);
271 					ic = (unsigned char)(JGETA & CMASK);
272 					PUT(ic);
273 					GET(ic); /* dummy GET */
274 					GET(ic); /* dummy GET */
275 #else   /* ISO-2022-JP.UIOSF */
276 					if (cset != CS_3) {
277 						if (oleft < SEQ_MBTOG0) {
278 							UNGET();
279 							errno = E2BIG;
280 							retval =
281 							(size_t)ERR_RETURN;
282 							goto ret;
283 						}
284 						cset = CS_3;
285 						PUT(ESC);
286 						PUT(MBTOG0_1);
287 						PUT(MBTOG0_2);
288 						PUT(F_X0212_90);
289 					}
290 					if (oleft < JISW3) {
291 						UNGET();
292 						errno = E2BIG;
293 						retval = (size_t)ERR_RETURN;
294 						goto ret;
295 					}
296 					/* Put JIS X 0212 character */
297 					GET(ic);
298 					PUT(ic & CMASK);
299 					GET(ic);
300 					PUT(ic & CMASK);
301 #endif  /* RFC1468_MODE */
302 					continue;
303 				} else {
304 					errno = EILSEQ;
305 					retval = (size_t)ERR_RETURN;
306 					goto ret;
307 				}
308 			} else {	/* input fragment of JISX0212 */
309 				UNGET();
310 				errno = EINVAL;
311 				retval = (size_t)ERR_RETURN;
312 				goto ret;
313 			}
314 		} else {
315 			UNGET();
316 			errno = EILSEQ;
317 			retval = (size_t)ERR_RETURN;
318 			goto ret;
319 		}
320 	}
321 	retval = ileft;
322 ret:
323 	*inbuf = (char *)ip;
324 	*inbytesleft = ileft;
325 	*outbuf = op;
326 	*outbytesleft = oleft;
327 	st->_st_cset = cset;
328 
329 	return (retval);
330 }
331