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