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 /* Copyright 1995 by Sun Microsystems, Inc. 22 * All rights are reserved. 23 */ 24 25 #include <stdio.h> 26 #include <string.h> 27 #include "kdefs.h" 28 #include "ktable.h" 29 30 int input_typ(char c); 31 32 struct _cv_state { 33 char temp_ibuf[5]; 34 int ibuf_left; 35 int istart, iend; 36 char temp_obuf[1]; 37 int flush_obuf; 38 }; 39 40 KCHAR packtocomp(KCHAR comb2); 41 42 #ifndef SUNVIEW 43 char vowel_mix(char c1,char c2); 44 #endif 45 46 /* 47 * Hangul 7-bit(KS C 5601) to Standard 2-byte Combination code(87-3) 48 */ 49 50 51 static int cur_stat = 1; /* current state of automata */ 52 static int cur_act; /* current action of automata */ 53 54 static char han_buf[5] = {0,0,0,0,0 }; /* Hangul buffer */ 55 56 static int temp_flag; /* Hangul temporary flag */ 57 static int han_temp = 0; /* Hangul temporary while two 58 2-byte code are generated */ 59 60 static int next_stat[14][21]={ /* next state table[current state][input] */ 61 /* input 62 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ 63 /*state*/ 64 /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65 /* 1 */ { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1}, 66 /* 2 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2}, 67 /* 3 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2}, 68 /* 4 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}, 69 /* 5 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 8, 3, 8, 3, 3, 3, 2, 1, 2}, 70 /* 6 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 8, 8, 3, 3, 3, 2, 1, 2}, 71 /* 7 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 3, 8, 3, 3, 3, 2, 1, 2}, 72 /* 8 */ { 0, 4, 9,10,11,12,13,13,13,13,13, 3, 3, 3, 3, 3, 3, 3, 2, 1, 2}, 73 /* 9 */ { 0, 4, 4, 4, 4, 4, 4,13, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}, 74 /*10 */ { 0, 4, 4, 4, 4, 4, 4, 4,13,13, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}, 75 /*11 */ { 0, 4,13, 4, 4,13, 4,13, 4,13,13, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}, 76 /*12 */ { 0, 4, 4, 4, 4, 4, 4,13, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2}, 77 /*13 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 5, 6, 7, 2, 1, 2} 78 }; 79 80 static int next_act[14][21]={ /* next action table[current state][input] */ 81 /*input 82 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ 83 /*state*/ 84 /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85 /* 1 */ { 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 4},/*4-1*/ 86 /* 2 */ { 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,15,15,15,15,15,15,15, 1, 3, 4}, 87 /* 3 */ { 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,15,15,15,15,15,15,15, 1, 3, 4}, 88 /* 4 */ { 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 6, 6, 6, 6, 6, 6,16,12,13}, 89 /* 5 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,14,10,14,10,10,10,16,12,13}, 90 /* 6 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,14,14,10,10,10,16,12,13}, 91 /* 7 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,10,14,10,10,10,16,12,13}, 92 /* 8 */ { 0, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7,10,10,10,10,10,10,10,16,12,13}, 93 /* 9 */ { 0, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9,17,17,17,17,17,17,17,16,12,13}, 94 /*10 */ { 0, 9, 9, 9, 9, 9, 9, 9, 8, 8, 9,17,17,17,17,17,17,17,16,12,13}, 95 /*11 */ { 0, 9, 8, 9, 9, 8, 9, 8, 9, 8, 8,17,17,17,17,17,17,17,16,12,13}, 96 /*12 */ { 0, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9,17,17,17,17,17,17,17,16,12,13}, 97 /*13 */ { 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,17,17,17,17,17,17,17,16,12,13} 98 }; 99 100 KCHAR 101 getc_12(my_inbuf, my_inbytesleft, st) 102 char **my_inbuf; 103 size_t *my_inbytesleft; 104 struct _cv_state *st; 105 { 106 register char c; /* input character */ 107 register int cur_input; /* type of input character */ 108 register KCHAR code_2; /* 2-byte char converted */ 109 KCHAR make_2(); 110 111 if(temp_flag == 1){ 112 code_2 = han_temp; 113 temp_flag = 0; 114 return(code_2); 115 } 116 for(;;){ /* read 1 byte */ 117 if (st->ibuf_left) { 118 c = st->temp_ibuf[st->istart]; 119 st->istart++; 120 if (st->istart >= st->iend) { 121 st->ibuf_left = 0; 122 st->istart = 0; 123 st->iend = 0; 124 } 125 } else { 126 c = **my_inbuf; 127 (*my_inbuf)++, (*my_inbytesleft)--; 128 } 129 /* run Hangul automata */ 130 cur_input = input_typ(c); 131 cur_act = next_act[cur_stat][cur_input]; 132 cur_stat = next_stat[cur_stat][cur_input]; 133 switch (cur_act) { 134 case 1: 135 break; 136 case 2: 137 break; 138 case 3: 139 break; 140 case 4: 141 return(0x0000 | c); 142 case 5: 143 han_buf[1] = c; 144 break; 145 case 6: 146 han_buf[2] = c; 147 if((code_2=packtocomp(make_2(2))) == 0xFFFF){ 148 han_buf[2] = 0; 149 code_2 = make_2(0); 150 if (st->ibuf_left) { 151 st->istart--; 152 } else { 153 (*my_inbuf)--, (*my_inbytesleft)++; 154 } 155 cur_stat = 2; 156 return(code_2); 157 } 158 break; 159 case 7: 160 han_buf[3] = c; 161 if((code_2=packtocomp(make_2(2))) == 0xFFFF){ 162 han_buf[3] = 0; 163 code_2 = make_2(0); 164 if (st->ibuf_left) { 165 st->istart--; 166 } else { 167 (*my_inbuf)--, (*my_inbytesleft)++; 168 } 169 cur_stat = 2; 170 return(code_2); 171 } 172 break; 173 case 8: 174 han_buf[4] = c; 175 if((code_2=packtocomp(make_2(2))) == 0xFFFF){ 176 han_buf[4] = 0; 177 code_2 = make_2(0); 178 cur_stat = 2; 179 if (st->ibuf_left) { 180 st->istart--; 181 } else { 182 (*my_inbuf)--, (*my_inbytesleft)++; 183 } 184 return(code_2); 185 } 186 break; 187 case 9: 188 code_2 = make_2(0); 189 han_buf[1] = c; 190 return(code_2); 191 case 10: 192 code_2 = make_2(0); 193 han_buf[2] = c; 194 han_temp = make_2(0); 195 temp_flag = 1; 196 return(code_2); 197 case 11: /* Unused */ 198 return(make_2(0)); 199 case 12: 200 return(make_2(0)); 201 case 13: 202 code_2 = make_2(0); 203 han_temp = (0x0000 | c); 204 temp_flag = 1; 205 return(code_2); 206 case 14: 207 han_buf[0] = han_buf[2]; /* Save */ 208 han_buf[2] = vowel_mix(han_buf[2],c); 209 if((code_2=packtocomp(make_2(2))) == 0xFFFF){ 210 han_buf[2] = han_buf[0]; /* Recover */ 211 code_2 = make_2(0); 212 if (st->ibuf_left) { 213 st->istart--; 214 } else { 215 (*my_inbuf)--, (*my_inbytesleft)++; 216 } 217 cur_stat = 2; 218 return(code_2); 219 } 220 break; 221 case 15: 222 han_buf[2] = c; 223 return(make_2(0)); 224 case 16: 225 return(make_2(0)); 226 case 17: 227 code_2 = make_2(1); 228 han_buf[2] = c; 229 return(code_2); 230 default: 231 break; 232 } 233 } 234 } 235 236 int input_typ(char c) 237 { 238 switch(c) { 239 case D_DI_GUD: /* double di-gud 0x48 'H' */ 240 case D_BI_UB: /* double bi-ub 0x52 'S' */ 241 case D_JI_UD: /* double ji-ud 0x59 'Y' */ 242 return(1); 243 244 case GI_UG: /* gi-ug 0x41 'A' */ 245 return(2); 246 247 case NI_UN: /* ni-un 0x44 'D' */ 248 return(3); 249 250 case RI_UL: /* ri-ul 0x49 'I' */ 251 return(4); 252 253 case BI_UB: /* bi-ub 0x52 'R' */ 254 return(5); 255 256 case D_GI_UG: /* double gi-ug 0x42 'B' */ 257 case DI_GUD: /* di-gud 0x47 'G' */ 258 case D_SI_OD: /* double si-od 0x56 'V' */ 259 case YI_UNG: /* yi-ung 0x57 'W' */ 260 case CHI_UD: /* chi-ud 0x5a 'Z' */ 261 case KI_UK: /* ki-uk 0x5b '[' */ 262 return(6); 263 264 case SI_OD: /* si-od 0x55 'U' */ 265 return(7); 266 267 case JI_UD: /* ji_ud 0x58 'X' */ 268 return(8); 269 270 case HI_UD: /* hi-ud 0x5e '^' */ 271 return(9); 272 273 case MI_UM: /* mi-um 0x51 'Q' */ 274 case PI_UP: /* pi-up 0x5d ']' */ 275 case TI_GUT: /* ti-gut 0x51 '\' */ 276 return(10); 277 278 case YEA: /* yea 0x6b 'k' */ 279 case IA: /* ia 0x64 'd' */ 280 case IYAI: /* iyai 0x65 'e' */ 281 case IE: /* ie 0x6a 'j' */ 282 case YO: /* yo 0x72 'r' */ 283 case YU: /* yu 0x77 'g' */ 284 return(11); 285 286 case A: /* a 0x62 'b' */ 287 case AE: /* ae 0x63 'c' */ 288 return(12); 289 290 case E: /* e 0x66 'f' */ 291 case EA: /* ea 0x67 'g' */ 292 return(13); 293 294 case I: /* i 0x7c '|' */ 295 return(14); 296 297 case O: /* o 0x6c 'l' */ 298 return(15); 299 300 case U: /* u 0x73 's' */ 301 return(16); 302 303 case EU: /* eu 0x7a 'z' */ 304 return(17); 305 306 default: 307 if(c == '\016') /* Ctrl-N Hangul delimiter */ 308 return(18); 309 if(c == '\017' || c == '\024') /* Ctrl-O Ctrl-T English delimiter */ 310 return(19); 311 return(20); 312 } 313 } 314 315 /* This routine make 2-byte code from hangul buffer, if parameter (1) 316 is given, han_buf[4] or han_buf[3] is eliminated before making a 317 2-byte code and inserted han_buf[1] after 2-byte code is made */ 318 319 KCHAR make_2(n) 320 register int n; 321 { 322 register KCHAR code_2 = 0; 323 register char tmp = 0; 324 register int i; 325 326 /* if n = 1, save han_buf[3] or han_buf[4] */ 327 if (n == 1) { 328 if(han_buf[4]){ 329 tmp = han_buf[4]; 330 han_buf[4] = 0; 331 } else{ 332 tmp = han_buf[3]; 333 han_buf[3] = 0; 334 } 335 } 336 337 if(han_buf[1] > BEG_OF_CONSO){ 338 code_2 = code_2 | X32_19[han_buf[1] - BEG_OF_CONSO]; 339 } else { 340 code_2 = 0x9; 341 } 342 343 if(han_buf[2] > BEG_OF_VOW){ 344 code_2 = ((code_2 << 5) | X32_21[han_buf[2] - BEG_OF_VOW]); 345 } else{ 346 code_2 = (code_2 << 5) | 0x1; 347 } 348 349 if(han_buf[3] > BEG_OF_CONSO){ 350 code_2 = ((code_2 << 5) | X32_28[han_buf[3] - BEG_OF_CONSO]); 351 } else { 352 code_2 = code_2 << 5 | 0x01; 353 } 354 355 if(han_buf[4] > BEG_OF_CONSO){ 356 switch(han_buf[3]){ 357 /* process gi-ug si-od */ 358 case GI_UG: 359 if(han_buf[4] == SI_OD){ 360 code_2 += 2; 361 } 362 break; 363 364 /* process ni-un zi-ud, ni-un hi-ud */ 365 case NI_UN: 366 switch (han_buf[4]) { 367 case JI_UD: 368 code_2++; 369 break; 370 case HI_UD: 371 code_2 += 2; 372 break; 373 default: 374 break; 375 } 376 break; 377 378 /* process ri-ul gi-ug, ri-ul mi-um, 379 ri-ul bi-ub, ri-ul si-od, ri-ul ti-ut, 380 ri-ul pi-up, ri-ul hi-ud */ 381 case RI_UL: 382 switch (han_buf[4]) { 383 case GI_UG: 384 code_2++; 385 break; 386 387 case MI_UM: 388 code_2 += 2; 389 break; 390 391 case BI_UB: 392 code_2 += 3; 393 break; 394 395 case SI_OD: 396 code_2 += 4; 397 break; 398 399 case TI_GUT: 400 code_2 += 5; 401 break; 402 403 case PI_UP: 404 code_2 += 6; 405 break; 406 407 case HI_UD: 408 code_2 += 7; 409 break; 410 411 default: 412 break; 413 } 414 break; 415 416 /* process bi-ub si-od */ 417 case BI_UB: 418 if(han_buf[4] == SI_OD){ 419 code_2++; 420 } 421 break; 422 423 /* process si-od si-od */ 424 case SI_OD: 425 if(han_buf[4] == SI_OD){ 426 code_2++; 427 } 428 break; 429 } 430 } 431 432 /* set 1st 7-bit of code_2 */ 433 code_2 = code_2 | 0x8000; 434 435 /* initialize Hangul buffer */ 436 if(n != 2) 437 for(i = 0; i < 5; i++){ 438 han_buf[i] = 0; 439 } 440 441 if(n == 1){ /* restore Hangul temporary */ 442 han_buf[1] = tmp; 443 } 444 445 return(code_2); 446 } 447 448 /* This routine make double vowel from han_buf[2] and input character c */ 449 450 #ifndef SUNVIEW 451 char vowel_mix(char c1,char c2) 452 { 453 register char c = '\0'; /* result double vowel */ 454 455 switch(c1){ 456 /* process o-a, o-ae, o-i */ 457 case O: 458 switch (c2) { 459 case A: 460 c = c1 + 1; 461 break; 462 case AE: 463 c = c1 + 2; 464 break; 465 case I: 466 c = c1 + 3; 467 break; 468 } 469 break; 470 471 /* process u-oe, u-e, u-i */ 472 case U: 473 switch (c2) { 474 case E: 475 c = c1 + 1; 476 break; 477 case EA: 478 c = c1 + 2; 479 break; 480 case I: 481 c = c1 + 3; 482 break; 483 } 484 break; 485 486 /* process eu-i */ 487 case EU: 488 if(c2 == I){ 489 c = c1 + 1; 490 } 491 break; 492 } 493 return(c); 494 } 495 #endif 496