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 KCHAR c2p(); 38 39 struct _cv_state { 40 char **my_outbuf; 41 size_t *my_outbytesleft; 42 int invalid; 43 int flush_obuf; 44 char temp_obuf[5]; 45 int start_cnt; 46 int end_cnt; 47 char temp_ibuf[1]; 48 int ibuf_left; 49 }; 50 51 void AddChar (char Char, struct _cv_state *st); 52 int write_21(KCHAR code_2, struct _cv_state *st); 53 54 55 static void echo_vowel(char*, int*); 56 static void echo_consonant(char*, int*); 57 static int _wansung_to_cvc(unsigned short code, 58 unsigned char* ci_ret, unsigned char* v_ret, unsigned char* cf_ret); 59 60 typedef enum { ASCII, WANSUNG } _conv_desc; 61 62 63 /**** _ I C V _ O P E N ****/ 64 65 void* _icv_open() 66 { 67 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc)); 68 69 if (cd == (_conv_desc*)NULL) 70 { 71 errno = ENOMEM; 72 return((void*)-1); 73 } 74 75 *cd = ASCII; 76 77 return((void*)cd); 78 } /* end of int _icv_open(). */ 79 80 81 /**** _ I C V _ C L O S E ****/ 82 83 void _icv_close(_conv_desc* cd) 84 { 85 if (!cd) 86 errno = EBADF; 87 else 88 free((void*)cd); 89 } /* end of void _icv_close(_conv_desc*). */ 90 91 92 /**** _ I C V _ I C O N V ****/ 93 94 size_t _icv_iconv(_conv_desc* state, char** inbuf, size_t* inbufleft, 95 char** outbuf, size_t* outbufleft) 96 { 97 size_t ret_val = 0; 98 unsigned char* ib; 99 unsigned char* ob; 100 unsigned char* ibtail; 101 unsigned char* obtail; 102 103 if (!state) 104 { 105 errno = EBADF; 106 return((size_t)-1); 107 } 108 109 if (!inbuf || !(*inbuf)) 110 { 111 if (*state == WANSUNG) 112 { 113 if (outbufleft && *outbufleft >= 1 && outbuf && *outbuf) 114 { 115 **outbuf = SI; 116 (*outbuf)++; 117 (*outbufleft)--; 118 } 119 else 120 { 121 errno = E2BIG; 122 return((size_t)-1); 123 } 124 } 125 126 *state = ASCII; 127 return((size_t)0); 128 } 129 130 ib = (unsigned char*)*inbuf; 131 ob = (unsigned char*)*outbuf; 132 ibtail = ib + *inbufleft; 133 obtail = ob + *outbufleft; 134 135 while (ib < ibtail) 136 { 137 if (!(*ib & 0x80)) /* 7 bits */ 138 { 139 if ((obtail - ob) < (*state == WANSUNG ? 2 : 1)) 140 { 141 errno = E2BIG; 142 ret_val = (size_t)-1; 143 break; 144 } 145 if (*state == WANSUNG) 146 { 147 *ob++ = SI; 148 *state = ASCII; 149 } 150 *ob++ = *ib++; 151 } 152 else 153 { 154 unsigned char ci, v, cf; 155 register int ret, j; 156 int i; 157 char c[5]; 158 159 if ((ibtail - ib) < 2) 160 { 161 errno = EINVAL; 162 ret_val = (size_t)-1; 163 break; 164 } 165 166 ret = _wansung_to_cvc((unsigned short)(*ib) << 8 | 167 (unsigned short)(*(ib + 1)), &ci, &v, &cf); 168 i = 0; 169 if (ret != ILLEGAL_SEQ && ret != FAILED) 170 { 171 c[i] = (char)Y19_32[ci != CVC_FILL ? 172 ci + 1 : 0] + '@'; 173 if (c[i] > '@') 174 i++; 175 c[i] = (char)Y21_32[v != CVC_FILL ? v + 176 (short)(v + 1) / 3 + 2 : 1] + '`'; 177 if (c[i] > 'a') 178 echo_vowel(c, &i); 179 c[i] = (char)Y28_32[cf != CVC_FILL ? 180 cf - 1 : 0] + '@'; 181 if (c[i] > '@') 182 echo_consonant(c, &i); 183 184 if ((obtail - ob) < (i + (*state == ASCII ? 185 1 : 0))) 186 { 187 errno = E2BIG; 188 ret_val = (size_t)-1; 189 break; 190 } 191 if (*state == ASCII) 192 { 193 *ob++ = SO; 194 *state = WANSUNG; 195 } 196 for (j = 0; j < i; j++) 197 *ob++ = c[j]; 198 } 199 else 200 { 201 /* Let's assume the code is non-identical. */ 202 if (*state == WANSUNG) 203 { 204 if ((obtail - ob) < 3) 205 { 206 errno = E2BIG; 207 ret_val = (size_t)-1; 208 break; 209 } 210 *ob++ = SI; 211 *state = ASCII; 212 } 213 else if ((obtail - ob) < 2) 214 { 215 errno = E2BIG; 216 ret_val = (size_t)-1; 217 break; 218 } 219 *ob++ = NON_IDENTICAL; 220 *ob++ = NON_IDENTICAL; 221 ret_val += 2; 222 } 223 ib += 2; 224 } 225 } 226 227 *inbuf = (char*)ib; 228 *inbufleft = ibtail - ib; 229 *outbuf = (char*)ob; 230 *outbufleft = obtail - ob; 231 232 return(ret_val); 233 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/ 234 235 236 /**** E C H O _ V O W E L ****/ 237 238 static void echo_vowel(char* c, int* i) 239 { 240 if (c[*i] == 'm') /* _|_|- */ 241 { 242 c[(*i)++] = 'l'; /* _|_ */ 243 c[(*i)++] = 'b'; /* |- */ 244 } 245 else if (c[*i] == 'n') /* _|_H */ 246 { 247 c[(*i)++] = 'l'; /* _|_ */ 248 c[(*i)++] = 'c'; /* H */ 249 } 250 else if (c[*i] == 'o') /* _|_| */ 251 { 252 c[(*i)++] = 'l'; /* _|_ */ 253 c[(*i)++] = '|'; /* | */ 254 } 255 else if (c[*i] == 't') /* T-| */ 256 { 257 c[(*i)++] = 's'; /* T */ 258 c[(*i)++] = 'f'; /* -| */ 259 } 260 else if (c[*i] == 'u') /* T-|| */ 261 { 262 c[(*i)++] = 's'; /* T */ 263 c[(*i)++] = 'g'; /* -|| */ 264 } 265 else if (c[*i] == 'v') /* T| */ 266 { 267 c[(*i)++] = 's'; /* T */ 268 c[(*i)++] = '|'; /* | */ 269 } 270 else if (c[*i] == '{') /* _| */ 271 { 272 c[(*i)++] = 'z'; /* __ */ 273 c[(*i)++] = '|'; /* | */ 274 } 275 else 276 (*i)++; 277 } /* end of static void echo_vowel(char*, int*). */ 278 279 280 /**** E C H O _ C O N S O N A N T ****/ 281 282 static void echo_consonant(char* c, int* i) 283 { 284 if (c[*i] == 'C') /* gs */ 285 { 286 c[(*i)++] = 'A'; /* g */ 287 c[(*i)++] = 'U'; /* s */ 288 } 289 else if (c[*i] == 'E') /* nj */ 290 { 291 c[(*i)++] = 'D'; /* n */ 292 c[(*i)++] = 'X'; /* j */ 293 } 294 else if (c[*i] == 'F') /* nh */ 295 { 296 c[(*i)++] = 'D'; /* n */ 297 c[(*i)++] = '^'; /* h */ 298 } 299 else if (c[*i] == 'J') /* rg */ 300 { 301 c[(*i)++] = 'I'; /* r */ 302 c[(*i)++] = 'A'; /* g */ 303 } 304 else if (c[*i] == 'K') /* rm */ 305 { 306 c[(*i)++] = 'I'; /* r */ 307 c[(*i)++] = 'Q'; /* m */ 308 } 309 else if (c[*i] == 'L') /* rb */ 310 { 311 c[(*i)++] = 'I'; /* r */ 312 c[(*i)++] = 'R'; /* b */ 313 } 314 else if (c[*i] == 'M') /* rs */ 315 { 316 c[(*i)++] = 'I'; /* r */ 317 c[(*i)++] = 'U'; /* s */ 318 } 319 else if (c[*i] == 'N') /* rt */ 320 { 321 c[(*i)++] = 'I'; /* r */ 322 c[(*i)++] = '\\'; /* t */ 323 } 324 else if (c[*i] == 'O') /* rp */ 325 { 326 c[(*i)++] = 'I'; /* r */ 327 c[(*i)++] = ']'; /* p */ 328 } 329 else if (c[*i] == 'P') /* rh */ 330 { 331 c[(*i)++] = 'I'; /* r */ 332 c[(*i)++] = '^'; /* h */ 333 } 334 else if (c[*i] == 'T') /* bs */ 335 { 336 c[(*i)++] = 'R'; /* b */ 337 c[(*i)++] = 'U'; /* s */ 338 } 339 else 340 (*i)++; 341 } /* end of static void echo_consonant(char*, int*). */ 342 343 344 /**** _ W A N S U N G _ T O _ C V C ****/ 345 346 static int _wansung_to_cvc(unsigned short code, 347 unsigned char* ci_ret, unsigned char* v_ret, unsigned char* cf_ret) 348 { 349 register short h, i, l; 350 short ci, v, cf; 351 short disp; 352 long cfbit; 353 354 *ci_ret = *v_ret = *cf_ret = CVC_FILL; 355 356 if (code >= 0xB0A1 && code <= 0xC8FE) 357 { 358 if ((unsigned short)(code & 0xFF) < 0xA1) 359 return(ILLEGAL_SEQ); 360 361 for (h = CI_CNT, l = 0; ; ) 362 { 363 ci = (l + h) / 2; 364 if (l >= h) 365 break; 366 if (code < cmp_srchtbl[ci][0]) 367 h = ci - 1; 368 else if (code < cmp_srchtbl[ci + 1][0]) 369 break; 370 else 371 l = ci + 1; 372 } 373 374 for (v = 1; ; ) 375 { 376 if (code < cmp_srchtbl[ci][v]) 377 { 378 while (!cmp_srchtbl[ci][--v]) 379 ; 380 break; 381 } 382 else if (v == V_CNT) 383 break; 384 v++; 385 } 386 387 disp = code - cmp_srchtbl[ci][v]; 388 if (((short)(cmp_srchtbl[ci][v] & 0xFF) + disp) > 0xFE) 389 disp -= SKIP; 390 391 for (cfbit = cmp_bitmap[ci][v], i = -1, cf = -1; i < disp; cf++) 392 { 393 if (cfbit & 0x01) 394 i++; 395 cfbit >>= 1; 396 } 397 398 if (cf == -1) 399 return(FAILED); 400 401 *ci_ret = (unsigned char)ci; 402 *v_ret = (unsigned char)v; 403 if (cf >= 2) 404 *cf_ret = (unsigned char)cf; 405 return(HANGUL); 406 } 407 408 /* Chosung-only */ 409 if ((code >= 0xA4A1 && code <= 0xA4BE) && (X32_19[code - 0xA4A0] != -1)) 410 { 411 *ci_ret = (unsigned char)((X32_19[code - 0xA4A0] << 2) - 0xA0); 412 return(HANJA_OR_SYMBOL); 413 } 414 else if (code >= 0xA4BF && code <= 0xA4D3) /* Joongsung-only */ 415 { 416 *v_ret = (unsigned char)(code - 0xA4BE); 417 return(HANJA_OR_SYMBOL); 418 } 419 420 return(ILLEGAL_SEQ); 421 } /* end of static int _wansung_to_cvc(unsigned short, unsigned char*, 422 unsigned char*, unsigned char*). */ 423 424 struct _cv_state * 425 _cv_open() 426 { 427 struct _cv_state *st; 428 429 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL) 430 return ((void *)-1); 431 432 st->invalid = 0; 433 st->flush_obuf = 0; 434 st->ibuf_left = 0; 435 st->start_cnt = 0; 436 st->end_cnt = 0; 437 438 return (st); 439 } 440 441 void 442 _cv_close(st) 443 struct _cv_state *st; 444 { 445 free(st); 446 } 447 448 449 size_t 450 _cv_enconv(st, inbuf, inbytesleft, outbuf, outbytesleft) 451 struct _cv_state *st; 452 char **inbuf; 453 size_t*inbytesleft; 454 char **outbuf; 455 size_t*outbytesleft; 456 { 457 int c, d; 458 KCHAR code; 459 460 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 461 st->invalid = 0; 462 st->flush_obuf = 0; 463 st->ibuf_left = 0; 464 st->start_cnt = 0; 465 st->end_cnt = 0; 466 return (0); 467 } 468 469 if (st->flush_obuf) { 470 while ((*outbytesleft > 0) && (st->start_cnt < st->end_cnt)) { 471 **outbuf = st->temp_obuf[st->start_cnt]; 472 (*outbuf)++; 473 (*outbytesleft)--; 474 (st->start_cnt)++; 475 } 476 477 if (st->start_cnt < st->end_cnt) { 478 return(*inbytesleft); 479 } else { 480 st->flush_obuf = 0; 481 st->start_cnt = 0; 482 st->end_cnt = 0; 483 } 484 } 485 486 st->my_outbuf = outbuf; 487 st->my_outbytesleft = outbytesleft; 488 489 while (*inbytesleft > 0 && *(st->my_outbytesleft) > 0) { 490 491 if (st->ibuf_left) { 492 c = st->temp_ibuf[0]; 493 st->ibuf_left = 0; 494 } else { 495 c = (**inbuf)&BYTE_MASK; 496 (*inbuf)++, (*inbytesleft)--; 497 } 498 499 if (iskorea1(c)) {/* Completion Code */ 500 if ( *inbytesleft <= 0) { 501 st->ibuf_left = 1; 502 st->temp_ibuf[0] = c; 503 return(*inbytesleft); 504 } 505 506 d = (**inbuf)&BYTE_MASK; 507 (*inbuf)++, (*inbytesleft)--; 508 code = c<<8|d; 509 510 511 /* output hangul character */ 512 if (iskorea2(code&BYTE_MASK) && !ishanja(c)) { 513 514 if (ishangul(c)) { 515 code = c2p(code); 516 AddChar (0x0e, st); 517 write_21(code, st); 518 AddChar (0x0f, st); 519 520 } else if (ishaninit(code) || ishanmid(code)) { 521 AddChar (0x0e, st); 522 if (ishaninit(code)) { 523 AddChar(code - 0xa4a0 + 0x40, st); 524 } else { 525 code -= 0xa4bf; 526 code += (code/6) * 2 + 1; 527 AddChar(code + 0x61, st); 528 } 529 AddChar (0x0f, st); 530 531 /* other case */ 532 } else { 533 AddChar ('?', st); 534 AddChar ('?', st); 535 /*AddChar (c); 536 AddChar (code&BYTE_MASK);*/ 537 } 538 539 } else { 540 AddChar ('?', st); 541 AddChar ('?', st); 542 } 543 544 if (st->invalid) { /* ran out of outbuf space */ 545 st->invalid = 0; 546 return(*inbytesleft); 547 } 548 549 } else { /* output normal Ascii code */ 550 AddChar (c, st); 551 if (st->invalid) { 552 st->invalid = 0; 553 /*(*outbuf)--; 554 (*outbytesleft)++; 555 (*inbuf)--; 556 (*inbytesleft)++;*/ 557 return(*inbytesleft); 558 } 559 } 560 } 561 return (*inbytesleft); 562 } 563 564 void 565 AddChar (Char, st) 566 char Char; 567 struct _cv_state *st; 568 { 569 /* no more outbuf space */ 570 if (*(st->my_outbytesleft) <= 0) { 571 st->invalid = 1; 572 st->temp_obuf[st->end_cnt] = Char; 573 st->end_cnt++; 574 st->flush_obuf = 1; 575 } else { 576 **(st->my_outbuf) = Char; 577 (*(st->my_outbuf))++, (*(st->my_outbytesleft))--; 578 } 579 } 580 581 #ifdef TEST 582 583 /* test case 1 */ 584 char ibuf1[] = {0xbf, 0xc0, 0xbc, 0xbc, 0xc3, 0xa2 , 0x41}; 585 char obuf1[20]; 586 587 /* test case 2 */ 588 char ibuf2[] = {0xbf, 0xc0, 0xbc, 0xbc, 0xc3}; 589 char ibuf21[] = {0xa2 , 0x41}; 590 char obuf2[20]; 591 592 /* test case 3 */ 593 char ibuf3[] = {0xbf, 0xc0, 0xbc, 0xbc, 0xc3, 0xa2 , 0x41}; 594 char obuf3[5]; 595 596 main() 597 { 598 int i; 599 struct _cv_state *st; 600 size_t oleft, ileft; 601 char *ip1 = &ibuf1[0], *op1 = &obuf1[0], 602 *ip2 = &ibuf2[0], *ip21 = &ibuf21[0], *op2 = &obuf2[0], 603 *ip3 = &ibuf3[0], *op3 = &obuf3[0]; 604 605 /****************************** test case 1 *************************/ 606 ileft = sizeof(ibuf1); 607 oleft = sizeof(obuf1); 608 609 st = _cv_open(); 610 611 printf("TEST 1\n INPUT BUFFER: "); 612 for (i = 0; i < ileft ; i++) { 613 printf("%x ", 0xff&ibuf1[i]); 614 } 615 printf("\n"); 616 printf("OUTPUT: return value %d ", 617 _cv_enconv(st, &ip1, &ileft, &op1, &oleft)); 618 printf("ileft %d oleft %d\n", ileft, oleft); 619 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 620 st->ibuf_left); 621 printf("OUTPUT BUFFER: "); 622 for (i = 0; i < (sizeof(obuf1) - oleft) ; i++) { 623 printf("%x ", obuf1[i]); 624 } 625 printf("\n\n\n"); 626 _cv_close(st); 627 628 /************************ test case 2 ******************************/ 629 ileft = sizeof(ibuf2); 630 oleft = sizeof(obuf2); 631 632 st = _cv_open(); 633 634 printf("TEST 2\nINPUT BUFFER: "); 635 for (i = 0; i < ileft ; i++) { 636 printf("%x ", 0xff&ibuf2[i]); 637 } 638 printf("\n"); 639 printf("OUTPUT: return value %d ", 640 _cv_enconv(st, &ip2, &ileft, &op2, &oleft)); 641 printf("ileft %d oleft %d\n", ileft, oleft); 642 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 643 st->ibuf_left); 644 printf("OUTPUT BUFFER: "); 645 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 646 printf("%x ", obuf2[i]); 647 } 648 printf("\n\n"); 649 650 ileft = sizeof(ibuf21); 651 oleft = sizeof(obuf2); 652 op2 = &obuf2[0]; 653 printf("INPUT BUFFER: "); 654 for (i = 0; i < ileft ; i++) { 655 printf("%x ", 0xff&ibuf21[i]); 656 } 657 printf("\n"); 658 printf("OUTPUT: return value %d ", 659 _cv_enconv(st, &ip21, &ileft, &op2, &oleft)); 660 printf("ileft %d oleft %d\n", ileft, oleft); 661 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 662 st->ibuf_left); 663 printf("OUTPUT BUFFER: "); 664 for (i = 0; i < (sizeof(obuf2) - oleft) ; i++) { 665 printf("%x ", obuf2[i]); 666 } 667 printf("\n\n\n"); 668 _cv_close(st); 669 670 /************************ test case 3 ******************************/ 671 ileft = sizeof(ibuf3); 672 oleft = sizeof(obuf3); 673 674 st = _cv_open(); 675 676 printf("TEST 3\nINPUT BUFFER: "); 677 for (i = 0; i < ileft ; i++) { 678 printf("%x ", 0xff&ibuf3[i]); 679 } 680 printf("\n"); 681 printf("OUTPUT: return value %d ", 682 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 683 printf("ileft %d oleft %d\n", ileft, oleft); 684 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 685 st->ibuf_left); 686 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 687 st->end_cnt); 688 printf("OUTPUT BUFFER: "); 689 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 690 printf("%x ", obuf3[i]); 691 } 692 printf("\n\n"); 693 694 op3 = &obuf3[0]; 695 oleft = sizeof(obuf3); 696 printf("OUTPUT: return value %d ", 697 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 698 printf("ileft %d oleft %d\n", ileft, oleft); 699 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 700 st->ibuf_left); 701 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 702 st->end_cnt); 703 printf("OUTPUT BUFFER: "); 704 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 705 printf("%x ", obuf3[i]); 706 } 707 printf("\n\n"); 708 709 op3 = &obuf3[0]; 710 oleft = sizeof(obuf3); 711 printf("OUTPUT: return value %d ", 712 _cv_enconv(st, &ip3, &ileft, &op3, &oleft)); 713 printf("ileft %d oleft %d\n", ileft, oleft); 714 printf(" flush_obuf %d ibuf_left %d\n", st->flush_obuf, 715 st->ibuf_left); 716 printf(" strat_cnt %d end_cnt %d\n", st->start_cnt, 717 st->end_cnt); 718 printf("OUTPUT BUFFER: "); 719 for (i = 0; i < (sizeof(obuf3) - oleft) ; i++) { 720 printf("%x ", obuf3[i]); 721 } 722 printf("\n\n\n"); 723 _cv_close(st); 724 } 725 726 /* expected output 727 728 TEST 1 729 INPUT BUFFER: bf c0 bc bc c3 a2 41 730 OUTPUT: return value 0 ileft 0 oleft 6 731 flush_obuf 0 ibuf_left 0 732 OUTPUT BUFFER: e 57 6c f e 55 67 f e 5a 62 57 f 41 733 734 735 TEST 2 736 INPUT BUFFER: bf c0 bc bc c3 737 OUTPUT: return value 0 ileft 0 oleft 12 738 flush_obuf 0 ibuf_left 1 739 OUTPUT BUFFER: e 57 6c f e 55 67 f 740 741 INPUT BUFFER: a2 41 742 OUTPUT: return value 0 ileft 0 oleft 14 743 flush_obuf 0 ibuf_left 0 744 OUTPUT BUFFER: e 5a 62 57 f 41 745 746 747 TEST 3 748 INPUT BUFFER: bf c0 bc bc c3 a2 41 749 OUTPUT: return value 3 ileft 3 oleft 0 750 flush_obuf 1 ibuf_left 0 751 strat_cnt 0 end_cnt 3 752 OUTPUT BUFFER: e 57 6c f e 753 754 OUTPUT: return value 1 ileft 1 oleft 0 755 flush_obuf 1 ibuf_left 0 756 strat_cnt 0 end_cnt 3 757 OUTPUT BUFFER: 55 67 f e 5a 758 759 OUTPUT: return value 0 ileft 0 oleft 1 760 flush_obuf 0 ibuf_left 0 761 strat_cnt 0 end_cnt 0 762 OUTPUT BUFFER: 62 57 f 41 763 764 */ 765 #endif /* TEST */ 766