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 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include <euc.h> 31 #include "japanese.h" 32 33 34 /* 35 * struct _cv_state; to keep status 36 */ 37 struct _icv_state { 38 int _st_cset; 39 int _st_cset_sav; 40 }; 41 42 void * 43 _icv_open() 44 { 45 struct _icv_state *st; 46 47 if ((st = (struct _icv_state *)malloc(sizeof (struct _icv_state))) 48 == NULL) 49 return ((void *)ERR_RETURN); 50 51 st->_st_cset = st->_st_cset_sav = CS_0; 52 53 return (st); 54 } 55 56 void 57 _icv_close(struct _icv_state *st) 58 { 59 free(st); 60 } 61 62 size_t 63 _icv_iconv(struct _icv_state *st, char **inbuf, size_t *inbytesleft, 64 char **outbuf, size_t *outbytesleft) 65 { 66 int cset; 67 int stat = ST_INIT; 68 unsigned char *op; 69 char *ip, ic; 70 size_t ileft, oleft; 71 size_t retval; 72 73 /* 74 * If inbuf and/or *inbuf are NULL, reset conversion descriptor 75 * and put escape sequence if needed. 76 */ 77 if ((inbuf == NULL) || (*inbuf == NULL)) { 78 st->_st_cset_sav = st->_st_cset = CS_0; 79 return ((size_t)0); 80 } 81 82 cset = st->_st_cset; 83 84 ip = *inbuf; 85 op = (unsigned char *)*outbuf; 86 ileft = *inbytesleft; 87 oleft = *outbytesleft; 88 89 /* 90 * Main loop; basically 1 loop per 1 input byte 91 */ 92 93 while ((int)ileft > 0) { 94 GET(ic); 95 if (stat == ST_INIT) { 96 goto text; 97 } 98 99 /* 100 * Half way of Kanji or ESC sequence 101 */ 102 if ((stat == ST_INCS1) || (stat == ST_INCS3)) { 103 stat = ST_INIT; 104 PUT(ic | CMSB); 105 continue; 106 } else if (stat == ST_ESC) { 107 if (ic == MBTOG0_1) { 108 if ((int)ileft > 0) { 109 stat = ST_MBTOG0_1; 110 continue; 111 } else { 112 UNGET(); 113 UNGET(); 114 errno = EINVAL; 115 retval = (size_t)ERR_RETURN; 116 goto ret; 117 } 118 } else if (ic == SBTOG0_1) { 119 if ((int)ileft > 0) { 120 stat = ST_SBTOG0; 121 continue; 122 } else { 123 UNGET(); 124 UNGET(); 125 errno = EINVAL; 126 retval = (size_t)ERR_RETURN; 127 goto ret; 128 } 129 } else if (ic == X208REV_1) { 130 if ((int)ileft > 0) { 131 stat = ST_208REV_1; 132 continue; 133 } else { 134 UNGET(); 135 UNGET(); 136 errno = EINVAL; 137 retval = (size_t)ERR_RETURN; 138 goto ret; 139 } 140 } else { 141 UNGET(); 142 UNGET(); 143 errno = EILSEQ; 144 retval = (size_t)ERR_RETURN; 145 goto ret; 146 } 147 } else if (stat == ST_MBTOG0_1) { 148 if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) { 149 stat = ST_INIT; 150 st->_st_cset_sav = cset = CS_1; 151 continue; 152 } else if (ic == F_X0212_90) { 153 stat = ST_INIT; 154 st->_st_cset_sav = cset = CS_3; 155 continue; 156 } else if (ic == MBTOG0_2) { 157 if ((int)ileft > 0) { 158 stat = ST_MBTOG0_2; 159 continue; 160 } else { 161 UNGET(); 162 UNGET(); 163 UNGET(); 164 errno = EINVAL; 165 retval = (size_t)ERR_RETURN; 166 goto ret; 167 } 168 } else { 169 UNGET(); 170 UNGET(); 171 UNGET(); 172 errno = EILSEQ; 173 retval = (size_t)ERR_RETURN; 174 goto ret; 175 } 176 } else if (stat == ST_MBTOG0_2) { 177 if ((ic == F_X0208_83_90) || (ic == F_X0208_78)) { 178 stat = ST_INIT; 179 st->_st_cset_sav = cset = CS_1; 180 continue; 181 } else if (ic == F_X0212_90) { 182 stat = ST_INIT; 183 st->_st_cset_sav = cset = CS_3; 184 continue; 185 } else { 186 UNGET(); 187 UNGET(); 188 UNGET(); 189 UNGET(); 190 errno = EILSEQ; 191 retval = (size_t)ERR_RETURN; 192 goto ret; 193 } 194 } else if (stat == ST_SBTOG0) { 195 if ((ic == F_ASCII) || 196 (ic == F_X0201_RM) || 197 (ic == F_ISO646)) { 198 stat = ST_INIT; 199 st->_st_cset_sav = cset = CS_0; 200 continue; 201 } else if (ic == F_X0201_KN) { 202 cset = CS_2; 203 stat = ST_INIT; 204 continue; 205 } else { 206 UNGET(); 207 UNGET(); 208 UNGET(); 209 errno = EILSEQ; 210 retval = (size_t)ERR_RETURN; 211 goto ret; 212 } 213 } else if (stat == ST_208REV_1) { 214 if (ic == X208REV_2) { 215 if ((int)ileft > 0) { 216 stat = ST_208REV_2; 217 continue; 218 } else { 219 UNGET(); 220 UNGET(); 221 UNGET(); 222 errno = EINVAL; 223 retval = (size_t)ERR_RETURN; 224 goto ret; 225 } 226 } else { 227 UNGET(); 228 UNGET(); 229 UNGET(); 230 errno = EILSEQ; 231 retval = (size_t)ERR_RETURN; 232 goto ret; 233 } 234 } else if (stat == ST_208REV_2) { 235 if (ic == ESC) { 236 if ((int)ileft > 0) { 237 stat = ST_REV_AFT_ESC; 238 continue; 239 } else { 240 UNGET(); 241 UNGET(); 242 UNGET(); 243 UNGET(); 244 errno = EINVAL; 245 retval = (size_t)ERR_RETURN; 246 goto ret; 247 } 248 } else { 249 UNGET(); 250 UNGET(); 251 UNGET(); 252 UNGET(); 253 errno = EILSEQ; 254 retval = (size_t)ERR_RETURN; 255 goto ret; 256 } 257 } else if (stat == ST_REV_AFT_ESC) { 258 if (ic == MBTOG0_1) { 259 if ((int)ileft > 0) { 260 stat = ST_REV_AFT_MBTOG0_1; 261 continue; 262 } else { 263 UNGET(); 264 UNGET(); 265 UNGET(); 266 UNGET(); 267 UNGET(); 268 errno = EINVAL; 269 retval = (size_t)ERR_RETURN; 270 goto ret; 271 } 272 } else { 273 UNGET(); 274 UNGET(); 275 UNGET(); 276 UNGET(); 277 UNGET(); 278 errno = EILSEQ; 279 retval = (size_t)ERR_RETURN; 280 goto ret; 281 } 282 } else if (stat == ST_REV_AFT_MBTOG0_1) { 283 if (ic == F_X0208_83_90) { 284 stat = ST_INIT; 285 st->_st_cset_sav = cset = CS_1; 286 continue; 287 } else if (ic == MBTOG0_2) { 288 if ((int)ileft > 0) { 289 stat = ST_REV_AFT_MBTOG0_2; 290 continue; 291 } else { 292 UNGET(); 293 UNGET(); 294 UNGET(); 295 UNGET(); 296 UNGET(); 297 UNGET(); 298 errno = EINVAL; 299 retval = (size_t)ERR_RETURN; 300 goto ret; 301 } 302 } else { 303 UNGET(); 304 UNGET(); 305 UNGET(); 306 UNGET(); 307 UNGET(); 308 UNGET(); 309 errno = EILSEQ; 310 retval = (size_t)ERR_RETURN; 311 goto ret; 312 } 313 } else if (stat == ST_REV_AFT_MBTOG0_2) { 314 if (ic == F_X0208_83_90) { 315 stat = ST_INIT; 316 st->_st_cset_sav = cset = CS_1; 317 continue; 318 } else { 319 UNGET(); 320 UNGET(); 321 UNGET(); 322 UNGET(); 323 UNGET(); 324 UNGET(); 325 UNGET(); 326 errno = EILSEQ; 327 retval = (size_t)ERR_RETURN; 328 goto ret; 329 } 330 } 331 text: 332 /* 333 * Break through chars or ESC sequence 334 */ 335 if (ic == ESC) { 336 if ((int)ileft > 0) { 337 stat = ST_ESC; 338 continue; 339 } else { 340 UNGET(); 341 errno = EINVAL; 342 retval = (size_t)ERR_RETURN; 343 goto ret; 344 } 345 } else if (ic == SO) { 346 cset = CS_2; 347 stat = ST_INIT; 348 continue; 349 } else if (ic == SI) { 350 cset = st->_st_cset_sav; 351 stat = ST_INIT; 352 continue; 353 } 354 if (!(ic & CMSB)) { 355 if (cset == CS_0) { 356 if (oleft < EUCW0) { 357 UNGET(); 358 errno = E2BIG; 359 retval = (size_t)ERR_RETURN; 360 goto ret; 361 } 362 PUT(ic); 363 continue; 364 } else if (cset == CS_2) { 365 if (oleft < (EUCW2 + SEQ_SS)) { 366 UNGET(); 367 errno = E2BIG; 368 retval = (size_t)ERR_RETURN; 369 goto ret; 370 } 371 PUT(SS2); 372 PUT(ic | CMSB); 373 continue; 374 } else if (cset == CS_3) { 375 if ((int)ileft > 0) { 376 if (oleft < (EUCW3 + SEQ_SS)) { 377 UNGET(); 378 errno = E2BIG; 379 retval = (size_t)ERR_RETURN; 380 goto ret; 381 } 382 stat = ST_INCS3; 383 PUT(SS3); 384 PUT(ic | CMSB); 385 continue; 386 } else { 387 UNGET(); 388 errno = EINVAL; 389 retval = (size_t)ERR_RETURN; 390 goto ret; 391 } 392 } else { 393 if ((int)ileft > 0) { 394 if (oleft < EUCW1) { 395 UNGET(); 396 errno = E2BIG; 397 retval = (size_t)ERR_RETURN; 398 goto ret; 399 } 400 stat = ST_INCS1; 401 PUT(ic | CMSB); 402 continue; 403 } else { 404 UNGET(); 405 errno = EINVAL; 406 retval = (size_t)ERR_RETURN; 407 goto ret; 408 } 409 } 410 } else { 411 if (oleft < UNKNOWNW) { 412 UNGET(); 413 errno = E2BIG; 414 retval = (size_t)ERR_RETURN; 415 goto ret; 416 } 417 PUT(ic); 418 continue; 419 } 420 } 421 retval = ileft; 422 ret: 423 *inbuf = ip; 424 *inbytesleft = ileft; 425 *outbuf = (char *)op; 426 *outbytesleft = oleft; 427 st->_st_cset = cset; 428 429 return (retval); 430 } 431