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 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 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 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 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 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