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 * 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 54 _icv_close(struct _icv_state *st) 55 { 56 free(st); 57 } 58 59 size_t 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