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