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