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) 1997, by Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25
26
27 /*
28 Converts From: ISO2022-CN-EXT encoding.
29 Converts To: Taiwanese EUC encoding ( CNS11643 )
30 */
31
32 #include "iso2022-cn.h"
33 #include "gb2312_cns11643.h"
34
35
36 /* Forward reference the functions constrained to the scope of this file */
37 static int chinese_to_euc( _iconv_st*, unsigned char**, size_t*, int);
38 static int gb_to_euc( _iconv_st *st, unsigned char **outbuf, size_t *outbytesleft);
39
40
41 extern int errno;
42
43
44 size_t
_icv_iconv(_iconv_st * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)45 _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft,
46 char **outbuf, size_t *outbytesleft)
47 {
48 return iso2022_icv_iconv(st, inbuf, inbytesleft, (unsigned char**) outbuf, outbytesleft,
49 chinese_to_euc);
50 }
51
52
53 static int
chinese_to_euc(_iconv_st * st,unsigned char ** outbuf,size_t * outbytesleft,int plane_no)54 chinese_to_euc( _iconv_st *st, unsigned char **outbuf, size_t *outbytesleft, int plane_no )
55 {
56
57 if ( st->SSfunc == NULL && st->SOcharset == 'A') { /* GB2312 */
58 return gb_to_euc(st, outbuf, outbytesleft);
59 }
60
61 if ( plane_no < 0 )/* Not a CNS character */
62 return (1);
63
64 if ( plane_no >= 2) {
65 if ( *outbytesleft < 4 ){
66 st->_errno = errno = E2BIG;
67 return (-1);
68 }
69 /* Output the multi-byte code and plane number */
70 *(*outbuf)++ = (unsigned char) MBYTE;
71 *(*outbuf)++ = (unsigned char) (PMASK + plane_no);
72 (*outbytesleft) -= 2;
73 }
74
75 if ( *outbytesleft < 2 ){ /* Redundant test if SS2 or SS3 character */
76 st->_errno = errno = E2BIG;
77 return (-1);
78 }
79
80 *(*outbuf)++ = (unsigned char) (st->keepc[0] | MSB);
81 *(*outbuf)++ = (unsigned char) (st->keepc[1] | MSB);
82 (*outbytesleft) -= 2;
83
84 return (0);
85 }
86
make_cns(_iconv_st * st,unsigned long cnscode,unsigned char ** outbuf,size_t * outbytesleft)87 static int make_cns(_iconv_st *st, unsigned long cnscode, unsigned char **outbuf, size_t *outbytesleft)
88 {
89 int plane_no, ret; /* return buffer size */
90
91 ret = (int) (cnscode >> 16);
92 switch (ret) {
93 case 0x21: /* 0x8EA1 - G */
94 case 0x22: /* 0x8EA2 - H */
95 case 0x23: /* 0x8EA3 - I */
96 case 0x24: /* 0x8EA4 - J */
97 case 0x25: /* 0x8EA5 - K */
98 case 0x26: /* 0x8EA6 - L */
99 case 0x27: /* 0x8EA7 - M */
100 case 0x28: /* 0x8EA8 - N */
101 case 0x29: /* 0x8EA9 - O */
102 case 0x2a: /* 0x8EAA - P */
103 case 0x2b: /* 0x8EAB - Q */
104 case 0x2c: /* 0x8EAC - R */
105 case 0x2d: /* 0x8EAD - S */
106 case 0x2f: /* 0x8EAF - U */
107 case 0x30: /* 0x8EB0 - V */
108 plane_no = ret - 0x20;
109 break;
110 case 0x2e: /* 0x8EAE - T */
111 plane_no = 3; /* CNS 11643-1992 */
112 break;
113 default:
114 st->_errno = errno = EILSEQ;
115 return (0);
116 }
117
118 if ( plane_no >= 2) {
119 if ( *outbytesleft < 4 ){
120 st->_errno = errno = E2BIG;
121 return (-1);
122 }
123 /* Output the multi-byte code and plane number */
124 *(*outbuf)++ = (unsigned char) MBYTE;
125 *(*outbuf)++ = (unsigned char) (PMASK + plane_no);
126 (*outbytesleft) -= 2;
127 }
128
129 if ( *outbytesleft < 2 ){ /* Redundant test if SS2 or SS3 character */
130 st->_errno = errno = E2BIG;
131 return (-1);
132 }
133
134 *(*outbuf)++ = (unsigned char) (((cnscode >> 8) & 0xff) | MSB);
135 *(*outbuf)++ = (unsigned char) ((cnscode & 0xff) | MSB);
136 (*outbytesleft) -= 2;
137
138 return (0);
139 }
140
141 static int
gb_cns_comp(const void * p1,const void * p2)142 gb_cns_comp(const void *p1, const void *p2)
143 {
144 gb_cns *ptr1 = (gb_cns*) p1, *ptr2 = (gb_cns*) p2;
145 long result = ptr1->gbcode - ptr2->gbcode;
146 return result == 0 ? 0 : result > 0 ? 1 : -1;
147 }
148
149 static int
gb_to_euc(_iconv_st * st,unsigned char ** outbuf,size_t * outbytesleft)150 gb_to_euc( _iconv_st *st, unsigned char **outbuf, size_t *outbytesleft )
151 {
152 gb_cns *ptr, key;
153
154 key.gbcode = (unsigned long) ((st->keepc[0] | MSB) << 8) + (st->keepc[1] | MSB);
155 ptr = (gb_cns*) bsearch(&key, gb_cns_tab, BIG5MAX, sizeof(gb_cns), gb_cns_comp);
156
157 if ( ptr && ptr->cnscode > 0 )
158 return make_cns(st, ptr->cnscode, outbuf, outbytesleft);
159 else
160 return (1);
161 }
162