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
_icv_open()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
_icv_close(_conv_desc * cd)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
_icv_iconv(_conv_desc * state,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)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
echo_vowel(char * c,int * i)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
echo_consonant(char * c,int * i)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
_wansung_to_cvc(unsigned short code,unsigned char * ci_ret,unsigned char * v_ret,unsigned char * cf_ret)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 *
_cv_open()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
_cv_close(st)442 _cv_close(st)
443 struct _cv_state *st;
444 {
445 free(st);
446 }
447
448
449 size_t
_cv_enconv(st,inbuf,inbytesleft,outbuf,outbytesleft)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
AddChar(Char,st)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
main()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