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 (c) 1995 by Sun Microsystems, Inc. 23 * All Rights Reserved. 24 */ 25 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <ctype.h> 30 #include <string.h> 31 #include "kctype.h" 32 #include "kdefs.h" 33 #include <errno.h> 34 #include "ktable.h" 35 #include "hangulcode.h" 36 37 38 KCHAR c2p(); 39 40 KCHAR packtocomp(KCHAR comb2); 41 42 43 struct _cv_state { 44 char **my_outbuf; 45 size_t *my_outbytesleft; 46 int invalid; 47 int flush_obuf; 48 char temp_obuf[5]; 49 int start_cnt; 50 int end_cnt; 51 char temp_ibuf[1]; 52 int ibuf_left; 53 }; 54 55 static unsigned short _johap_to_wansung(unsigned short code); 56 57 void AddChar (char Char, struct _cv_state *st); 58 59 /**** _ I C V _ O P E N ****/ 60 61 void* _icv_open() 62 { 63 return((void*)MAGIC_NUMBER); 64 } /* end of void* _icv_open(). */ 65 66 67 /**** _ I C V _ C L O S E ****/ 68 69 void _icv_close(int* cd) 70 { 71 if (!cd || cd != (int*)MAGIC_NUMBER) 72 errno = EBADF; 73 } /* end of void _icv_close(int*). */ 74 75 76 /**** _ I C V _ I C O N V ****/ 77 78 size_t _icv_iconv(int* cd, char** inbuf, size_t* inbufleft, 79 char** outbuf, size_t* outbufleft) 80 { 81 size_t ret_val = 0; 82 unsigned char* ib; 83 unsigned char* ob; 84 unsigned char* ibtail; 85 unsigned char* obtail; 86 87 if (!cd || cd != (int*)MAGIC_NUMBER) 88 { 89 errno = EBADF; 90 return((size_t)-1); 91 } 92 93 if (!inbuf || !(*inbuf)) 94 return((size_t)0); 95 96 ib = (unsigned char*)*inbuf; 97 ob = (unsigned char*)*outbuf; 98 ibtail = ib + *inbufleft; 99 obtail = ob + *outbufleft; 100 101 while (ib < ibtail) 102 { 103 if (!(*ib & 0x80)) 104 { 105 if (ob >= obtail) 106 { 107 errno = E2BIG; 108 ret_val = (size_t)-1; 109 break; 110 } 111 *ob++ = *ib++; 112 } 113 else 114 { 115 unsigned short result; 116 117 if ((ibtail - ib) < 2) 118 { 119 errno = EINVAL; 120 ret_val = (size_t)-1; 121 break; 122 } 123 124 result = _johap_to_wansung((unsigned short)(*ib)<<8 | 125 (unsigned short)(*(ib + 1))); 126 if (result != FAILED && result != ILLEGAL_SEQ) 127 { 128 if ((obtail - ob) < 2) 129 { 130 errno = E2BIG; 131 ret_val = (size_t)-1; 132 break; 133 } 134 *ob++ = (unsigned char)(result >> 8); 135 *ob++ = (unsigned char)(result & 0xFF); 136 } 137 else 138 { 139 errno = EILSEQ; 140 ret_val = (size_t)-1; 141 break; 142 } 143 ib += 2; 144 145 } 146 } 147 148 *inbuf = (char*)ib; 149 *inbufleft = ibtail - ib; 150 *outbuf = (char*)ob; 151 *outbufleft = obtail - ob; 152 153 return(ret_val); 154 } /* end of size_t _icv_iconv(int*, char**, size_t*, char**, size_t*). */ 155 156 157 /**** _ J O H A P _ T O _ W A N S U N G ****/ 158 159 static unsigned short _johap_to_wansung(unsigned short code) 160 { 161 short ci, v, cf; 162 short mask; 163 int disp, i; 164 long cfbit; 165 166 ci = CHOSUNG(code) - 0x0a; 167 v = JOONGSUNG(code) - (unsigned short)JOONGSUNG(code) / 4 - 2; 168 cf = JONGSUNG(code); 169 170 if (v < 0) 171 return(0xA4A0 + Y19_32[CHOSUNG(code) - 9]); 172 if (ci < 0) 173 { 174 if (cf <= 1) 175 return(0xA4BF + v); 176 return(ILLEGAL_SEQ); 177 } 178 179 for (cfbit = cmp_bitmap[ci][v], disp = 0, i = 0; i < cf; i++) 180 { 181 if (cfbit & BIT_MASK) 182 disp++; 183 cfbit >>= 1; 184 } 185 186 if (!(cfbit & BIT_MASK)) 187 return(ILLEGAL_SEQ); 188 189 code = cmp_srchtbl[ci][v] + disp; 190 mask = cmp_srchtbl[ci][v] & 0xff; 191 if ((mask + disp) > 0xfe) 192 code += SKIP; 193 194 return(code); 195 } /* end og static unsigned short _johap_to_wansung(unsigned short). */ 196 197 struct _cv_state * 198 _cv_open() 199 { 200 struct _cv_state *st; 201 202 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL) 203 return ((void *)-1); 204 205 st->invalid = 0; 206 st->flush_obuf = 0; 207 st->ibuf_left = 0; 208 st->start_cnt = 0; 209 st->end_cnt = 0; 210 211 return (st); 212 } 213 214 void 215 _cv_close(st) 216 struct _cv_state *st; 217 { 218 free(st); 219 } 220 221 222 size_t 223 _cv_enconv(st, inbuf, inbytesleft, outbuf, outbytesleft) 224 struct _cv_state *st; 225 char **inbuf; 226 size_t*inbytesleft; 227 char **outbuf; 228 size_t*outbytesleft; 229 { 230 int c, d; 231 KCHAR code; 232 233 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 234 st->invalid = 0; 235 st->flush_obuf = 0; 236 st->ibuf_left = 0; 237 st->start_cnt = 0; 238 st->end_cnt = 0; 239 return (0); 240 } 241 242 if (st->flush_obuf) { 243 while ((*outbytesleft > 0) && (st->start_cnt < st->end_cnt)) { 244 **outbuf = st->temp_obuf[st->start_cnt]; 245 (*outbuf)++; 246 (*outbytesleft)--; 247 (st->start_cnt)++; 248 } 249 250 if (st->start_cnt < st->end_cnt) { 251 return(*inbytesleft); 252 } else { 253 st->flush_obuf = 0; 254 st->start_cnt = 0; 255 st->end_cnt = 0; 256 } 257 } 258 259 st->my_outbuf = outbuf; 260 st->my_outbytesleft = outbytesleft; 261 262 while (*inbytesleft > 0 && *(st->my_outbytesleft) > 0) { 263 264 if (st->ibuf_left) { 265 c = st->temp_ibuf[0]; 266 st->ibuf_left = 0; 267 } else { 268 c = (**inbuf)&BYTE_MASK; 269 (*inbuf)++, (*inbytesleft)--; 270 } 271 272 if (iskorea1(c)) { 273 if ( *inbytesleft <= 0) { 274 st->ibuf_left = 1; 275 st->temp_ibuf[0] = c; 276 return(*inbytesleft); 277 } 278 279 d = (**inbuf)&BYTE_MASK; 280 (*inbuf)++, (*inbytesleft)--; 281 code = c<<8|d; 282 283 if ((code = packtocomp(code)) == K_ILLEGAL) { 284 AddChar ('?', st); 285 AddChar ('?', st); 286 } else { 287 AddChar (code>>8, st); 288 AddChar (code&BYTE_MASK, st); 289 } 290 if (st->invalid) { 291 st->invalid = 0; 292 return(*inbytesleft); 293 } 294 295 } else { /* output normal Ascii code */ 296 AddChar (c, st); 297 if (st->invalid) { 298 st->invalid = 0; 299 return(*inbytesleft); 300 } 301 } 302 } 303 return (*inbytesleft); 304 } 305 306 void 307 AddChar (Char, st) 308 char Char; 309 struct _cv_state *st; 310 { 311 /* no more outbuf space */ 312 if (*(st->my_outbytesleft) <= 0) { 313 st->invalid = 1; 314 st->temp_obuf[st->end_cnt] = Char; 315 st->end_cnt++; 316 st->flush_obuf = 1; 317 } else { 318 **(st->my_outbuf) = Char; 319 (*(st->my_outbuf))++, (*(st->my_outbytesleft))--; 320 } 321 } 322 323 #ifdef TEST 324 325 /* test case 1 */ 326 char ibuf1[] = {0xa8, 0x41, 0xa8, 0x42, 0x41, 0xa8 , 0x45}; 327 char obuf1[20]; 328 329 /* test case 2 */ 330 char ibuf2[] = {0xa8, 0x41, 0xa8, 0x42, 0xa8}; 331 char ibuf21[] = {0x45 , 0x41}; 332 char obuf2[20]; 333 334 /* test case 3 */ 335 char ibuf3[] = {0xa8, 0x41, 0xa8, 0x42, 0xa8, 0x45 , 0x41}; 336 char obuf3[5]; 337 338 339 main() 340 { 341 int i; 342 struct _cv_state *st; 343 size_t oleft, ileft; 344 char *ip1 = &ibuf1[0], *op1 = &obuf1[0], 345 *ip2 = &ibuf2[0], *ip21 = &ibuf21[0], *op2 = &obuf2[0], 346 *ip3 = &ibuf3[0], *op3 = &obuf3[0]; 347 348 /****************************** test case 1 *************************/ 349 ileft = sizeof(ibuf1); 350 oleft = sizeof(obuf1); 351 352 st = _cv_open(); 353 354 printf("TEST 1\n INPUT BUFFER: "); 355 for (i = 0; i < ileft ; i++) { 356 printf("%x ", 0xff&ibuf1[i]); 357 } 358 printf("\n"); 359 printf("OUTPUT: return value %d ", 360 _cv_enconv(st, &ip1, &ileft, &op1, &oleft)); 361 printf("ileft %d oleft %d\n", ileft, oleft); 362 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 363 st->ibuf_left); 364 printf("OUTPUT BUFFER: "); 365 for (i = 0; i < (sizeof(obuf1) - oleft) ; i++) { 366 printf("%x ", obuf1[i]); 367 } 368 printf("\n\n\n"); 369 _cv_close(st); 370 371 /************************ test case 2 ******************************/ 372 ileft = sizeof(ibuf2); 373 oleft = sizeof(obuf2); 374 375 st = _cv_open(); 376 377 printf("TEST 2\nINPUT BUFFER: "); 378 for (i = 0; i < ileft ; i++) { 379 printf("%x ", 0xff&ibuf2[i]); 380 } 381 printf("\n"); 382 printf("OUTPUT: return value %d ", 383 _cv_enconv(st, &ip2, &ileft, &op2, &oleft)); 384 printf("ileft %d oleft %d\n", ileft, oleft); 385 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 386 st->ibuf_left); 387 printf("OUTPUT BUFFER: "); 388 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 389 printf("%x ", obuf2[i]); 390 } 391 printf("\n\n"); 392 393 ileft = sizeof(ibuf21); 394 oleft = sizeof(obuf2); 395 op2 = &obuf2[0]; 396 printf("INPUT BUFFER: "); 397 for (i = 0; i < ileft ; i++) { 398 printf("%x ", 0xff&ibuf21[i]); 399 } 400 printf("\n"); 401 printf("OUTPUT: return value %d ", 402 _cv_enconv(st, &ip21, &ileft, &op2, &oleft)); 403 printf("ileft %d oleft %d\n", ileft, oleft); 404 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 405 st->ibuf_left); 406 printf("OUTPUT BUFFER: "); 407 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 408 printf("%x ", obuf2[i]); 409 } 410 printf("\n\n\n"); 411 _cv_close(st); 412 413 /************************ test case 3 ******************************/ 414 ileft = sizeof(ibuf3); 415 oleft = sizeof(obuf3); 416 417 st = _cv_open(); 418 419 printf("TEST 3\nINPUT BUFFER: "); 420 for (i = 0; i < ileft ; i++) { 421 printf("%x ", 0xff&ibuf3[i]); 422 } 423 printf("\n"); 424 printf("OUTPUT: return value %d ", 425 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 426 printf("ileft %d oleft %d\n", ileft, oleft); 427 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 428 st->ibuf_left); 429 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 430 st->end_cnt); 431 printf("OUTPUT BUFFER: "); 432 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 433 printf("%x ", obuf3[i]); 434 } 435 printf("\n\n"); 436 437 op3 = &obuf3[0]; 438 oleft = sizeof(obuf3); 439 printf("OUTPUT: return value %d ", 440 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 441 printf("ileft %d oleft %d\n", ileft, oleft); 442 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 443 st->ibuf_left); 444 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 445 st->end_cnt); 446 printf("OUTPUT BUFFER: "); 447 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 448 printf("%x ", obuf3[i]); 449 } 450 printf("\n\n"); 451 452 op3 = &obuf3[0]; 453 oleft = sizeof(obuf3); 454 printf("OUTPUT: return value %d ", 455 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 456 printf("ileft %d oleft %d\n", ileft, oleft); 457 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 458 st->ibuf_left); 459 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 460 st->end_cnt); 461 printf("OUTPUT BUFFER: "); 462 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 463 printf("%x ", obuf3[i]); 464 } 465 printf("\n\n\n"); 466 _cv_close(st); 467 } 468 469 /* expected output 470 471 TEST 1 472 INPUT BUFFER: a8 41 a8 42 41 a8 45 473 OUTPUT: return value 0 ileft 0 oleft 13 474 flush_obuf 0 ibuf_left 0 475 OUTPUT BUFFER: ffffffb0 ffffffa1 ffffffb0 ffffffa2 41 ffffffb0 ffffffa3 476 477 478 TEST 2 479 INPUT BUFFER: a8 41 a8 42 a8 480 OUTPUT: return value 0 ileft 0 oleft 16 481 flush_obuf 0 ibuf_left 1 482 OUTPUT BUFFER: ffffffb0 ffffffa1 ffffffb0 ffffffa2 483 484 INPUT BUFFER: 45 41 485 OUTPUT: return value 0 ileft 0 oleft 17 486 flush_obuf 0 ibuf_left 0 487 OUTPUT BUFFER: ffffffb0 ffffffa3 41 488 489 490 TEST 3 491 INPUT BUFFER: a8 41 a8 42 a8 45 41 492 OUTPUT: return value 1 ileft 1 oleft 0 493 flush_obuf 1 ibuf_left 0 494 strat_cnt 0 end_cnt 1 495 OUTPUT BUFFER: ffffffb0 ffffffa1 ffffffb0 ffffffa2 ffffffb0 496 497 OUTPUT: return value 0 ileft 0 oleft 3 498 flush_obuf 0 ibuf_left 0 499 strat_cnt 0 end_cnt 0 500 OUTPUT BUFFER: ffffffa3 41 501 502 OUTPUT: return value 0 ileft 0 oleft 5 503 flush_obuf 0 ibuf_left 0 504 strat_cnt 0 end_cnt 0 505 OUTPUT BUFFER: 506 */ 507 508 #endif /* TEST */ 509