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
_icv_open()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
_icv_close(int * cd)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
_icv_iconv(int * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)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
_johap_to_wansung(unsigned short code)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 *
_cv_open()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
_cv_close(st)215 _cv_close(st)
216 struct _cv_state *st;
217 {
218 free(st);
219 }
220
221
222 size_t
_cv_enconv(st,inbuf,inbytesleft,outbuf,outbytesleft)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
AddChar(Char,st)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
main()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