1*91e1e26aSAlexander Pyhalov /* 2*91e1e26aSAlexander Pyhalov * CDDL HEADER START 3*91e1e26aSAlexander Pyhalov * 4*91e1e26aSAlexander Pyhalov * The contents of this file are subject to the terms of the 5*91e1e26aSAlexander Pyhalov * Common Development and Distribution License (the "License"). 6*91e1e26aSAlexander Pyhalov * You may not use this file except in compliance with the License. 7*91e1e26aSAlexander Pyhalov * 8*91e1e26aSAlexander Pyhalov * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE 9*91e1e26aSAlexander Pyhalov * or http://www.opensolaris.org/os/licensing. 10*91e1e26aSAlexander Pyhalov * See the License for the specific language governing permissions 11*91e1e26aSAlexander Pyhalov * and limitations under the License. 12*91e1e26aSAlexander Pyhalov * 13*91e1e26aSAlexander Pyhalov * When distributing Covered Code, include this CDDL HEADER in each 14*91e1e26aSAlexander Pyhalov * file and include the License file at src/OPENSOLARIS.LICENSE. 15*91e1e26aSAlexander Pyhalov * If applicable, add the following below this CDDL HEADER, with the 16*91e1e26aSAlexander Pyhalov * fields enclosed by brackets "[]" replaced with your own identifying 17*91e1e26aSAlexander Pyhalov * information: Portions Copyright [yyyy] [name of copyright owner] 18*91e1e26aSAlexander Pyhalov * 19*91e1e26aSAlexander Pyhalov * CDDL HEADER END 20*91e1e26aSAlexander Pyhalov */ 21*91e1e26aSAlexander Pyhalov /* 22*91e1e26aSAlexander Pyhalov * Copyright (c) 1994 by Sun Microsystems, Inc. 23*91e1e26aSAlexander Pyhalov */ 24*91e1e26aSAlexander Pyhalov 25*91e1e26aSAlexander Pyhalov #include <stdio.h> 26*91e1e26aSAlexander Pyhalov #include <stdlib.h> 27*91e1e26aSAlexander Pyhalov #include <errno.h> 28*91e1e26aSAlexander Pyhalov #include <gb2312_unicode.h> 29*91e1e26aSAlexander Pyhalov 30*91e1e26aSAlexander Pyhalov #define MSB 0x80 31*91e1e26aSAlexander Pyhalov 32*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR1 0xEF 33*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR2 0xBF 34*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR3 0xBD 35*91e1e26aSAlexander Pyhalov 36*91e1e26aSAlexander Pyhalov 37*91e1e26aSAlexander Pyhalov enum _GSTATE { G0, G1, G2, G3, G4, G5}; 38*91e1e26aSAlexander Pyhalov 39*91e1e26aSAlexander Pyhalov 40*91e1e26aSAlexander Pyhalov typedef struct _icv_state { 41*91e1e26aSAlexander Pyhalov char _lastc; 42*91e1e26aSAlexander Pyhalov short _gstate; 43*91e1e26aSAlexander Pyhalov } _iconv_st; 44*91e1e26aSAlexander Pyhalov 45*91e1e26aSAlexander Pyhalov int 46*91e1e26aSAlexander Pyhalov hz2utf8(char in_byte1, char in_byte2, char *buf, int buflen); 47*91e1e26aSAlexander Pyhalov 48*91e1e26aSAlexander Pyhalov /* 49*91e1e26aSAlexander Pyhalov * Open; called from iconv_open() 50*91e1e26aSAlexander Pyhalov */ 51*91e1e26aSAlexander Pyhalov void * 52*91e1e26aSAlexander Pyhalov _icv_open() 53*91e1e26aSAlexander Pyhalov { 54*91e1e26aSAlexander Pyhalov _iconv_st *st; 55*91e1e26aSAlexander Pyhalov 56*91e1e26aSAlexander Pyhalov if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { 57*91e1e26aSAlexander Pyhalov errno = ENOMEM; 58*91e1e26aSAlexander Pyhalov return ((void *) -1); 59*91e1e26aSAlexander Pyhalov } 60*91e1e26aSAlexander Pyhalov 61*91e1e26aSAlexander Pyhalov st->_gstate = G0; 62*91e1e26aSAlexander Pyhalov return ((void *)st); 63*91e1e26aSAlexander Pyhalov } 64*91e1e26aSAlexander Pyhalov 65*91e1e26aSAlexander Pyhalov 66*91e1e26aSAlexander Pyhalov /* 67*91e1e26aSAlexander Pyhalov * Close; called from iconv_close() 68*91e1e26aSAlexander Pyhalov */ 69*91e1e26aSAlexander Pyhalov void 70*91e1e26aSAlexander Pyhalov _icv_close(_iconv_st *st) 71*91e1e26aSAlexander Pyhalov { 72*91e1e26aSAlexander Pyhalov if (st == NULL) 73*91e1e26aSAlexander Pyhalov errno = EBADF; 74*91e1e26aSAlexander Pyhalov else 75*91e1e26aSAlexander Pyhalov free(st); 76*91e1e26aSAlexander Pyhalov } 77*91e1e26aSAlexander Pyhalov 78*91e1e26aSAlexander Pyhalov 79*91e1e26aSAlexander Pyhalov /* 80*91e1e26aSAlexander Pyhalov * Actual conversion; called from iconv() 81*91e1e26aSAlexander Pyhalov */ 82*91e1e26aSAlexander Pyhalov /*======================================================================= 83*91e1e26aSAlexander Pyhalov * 84*91e1e26aSAlexander Pyhalov * ~ { Chinese 85*91e1e26aSAlexander Pyhalov * +-> G0 -----> G1 ----> G2 ----> G3 86*91e1e26aSAlexander Pyhalov * | | ascii | ascii |~} | 87*91e1e26aSAlexander Pyhalov * +----------------------+--------+ 88*91e1e26aSAlexander Pyhalov *=======================================================================*/ 89*91e1e26aSAlexander Pyhalov size_t 90*91e1e26aSAlexander Pyhalov _icv_iconv(_iconv_st *st, char **inbuf, size_t*inbytesleft, 91*91e1e26aSAlexander Pyhalov char **outbuf, size_t*outbytesleft) 92*91e1e26aSAlexander Pyhalov { 93*91e1e26aSAlexander Pyhalov int n; 94*91e1e26aSAlexander Pyhalov 95*91e1e26aSAlexander Pyhalov if (st == NULL) { 96*91e1e26aSAlexander Pyhalov errno = EBADF; 97*91e1e26aSAlexander Pyhalov return -1; 98*91e1e26aSAlexander Pyhalov } 99*91e1e26aSAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 100*91e1e26aSAlexander Pyhalov st->_gstate = G0; 101*91e1e26aSAlexander Pyhalov return 0; 102*91e1e26aSAlexander Pyhalov } 103*91e1e26aSAlexander Pyhalov 104*91e1e26aSAlexander Pyhalov errno = 0; 105*91e1e26aSAlexander Pyhalov 106*91e1e26aSAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) { 107*91e1e26aSAlexander Pyhalov switch (st->_gstate) { 108*91e1e26aSAlexander Pyhalov case G0: 109*91e1e26aSAlexander Pyhalov if ( **inbuf == '~' ) { 110*91e1e26aSAlexander Pyhalov st->_gstate = G1; 111*91e1e26aSAlexander Pyhalov } else if (((**inbuf) & MSB) == 0) { /* ASCII */ 112*91e1e26aSAlexander Pyhalov **outbuf = **inbuf; 113*91e1e26aSAlexander Pyhalov (*outbuf)++, (*outbytesleft)--; 114*91e1e26aSAlexander Pyhalov } 115*91e1e26aSAlexander Pyhalov break; 116*91e1e26aSAlexander Pyhalov case G1: 117*91e1e26aSAlexander Pyhalov if ( **inbuf == '{' ) { 118*91e1e26aSAlexander Pyhalov st->_gstate = G2; 119*91e1e26aSAlexander Pyhalov } else if (**inbuf == '\n') { 120*91e1e26aSAlexander Pyhalov st->_gstate = G0; 121*91e1e26aSAlexander Pyhalov } else if (**inbuf == '~') { 122*91e1e26aSAlexander Pyhalov **outbuf = '~'; 123*91e1e26aSAlexander Pyhalov (*outbuf)++, (*outbytesleft)--; 124*91e1e26aSAlexander Pyhalov st->_gstate = G0; 125*91e1e26aSAlexander Pyhalov } else { 126*91e1e26aSAlexander Pyhalov errno = EINVAL; 127*91e1e26aSAlexander Pyhalov } 128*91e1e26aSAlexander Pyhalov break; 129*91e1e26aSAlexander Pyhalov case G2: 130*91e1e26aSAlexander Pyhalov if ( **inbuf == '~' ) { 131*91e1e26aSAlexander Pyhalov st->_gstate = G4; 132*91e1e26aSAlexander Pyhalov } else { 133*91e1e26aSAlexander Pyhalov st->_lastc = **inbuf; 134*91e1e26aSAlexander Pyhalov st->_gstate = G3; 135*91e1e26aSAlexander Pyhalov } 136*91e1e26aSAlexander Pyhalov break; 137*91e1e26aSAlexander Pyhalov case G3: 138*91e1e26aSAlexander Pyhalov n = hz2utf8(st->_lastc, **inbuf, *outbuf, *outbytesleft); 139*91e1e26aSAlexander Pyhalov if (n > 0) { 140*91e1e26aSAlexander Pyhalov (*outbuf) += n, (*outbytesleft) -= n; 141*91e1e26aSAlexander Pyhalov } else { 142*91e1e26aSAlexander Pyhalov errno = E2BIG; 143*91e1e26aSAlexander Pyhalov return (size_t)-1; 144*91e1e26aSAlexander Pyhalov } 145*91e1e26aSAlexander Pyhalov st->_gstate = G2; 146*91e1e26aSAlexander Pyhalov break; 147*91e1e26aSAlexander Pyhalov case G4: 148*91e1e26aSAlexander Pyhalov if ( **inbuf == '}' ) { 149*91e1e26aSAlexander Pyhalov st->_gstate = G0; 150*91e1e26aSAlexander Pyhalov } else if (**inbuf == '\n') { 151*91e1e26aSAlexander Pyhalov st->_gstate = G2; 152*91e1e26aSAlexander Pyhalov continue; 153*91e1e26aSAlexander Pyhalov } else { 154*91e1e26aSAlexander Pyhalov errno = EINVAL; 155*91e1e26aSAlexander Pyhalov } 156*91e1e26aSAlexander Pyhalov 157*91e1e26aSAlexander Pyhalov break; 158*91e1e26aSAlexander Pyhalov } 159*91e1e26aSAlexander Pyhalov 160*91e1e26aSAlexander Pyhalov (*inbuf)++, (*inbytesleft)--; 161*91e1e26aSAlexander Pyhalov if (errno) 162*91e1e26aSAlexander Pyhalov { 163*91e1e26aSAlexander Pyhalov return (size_t)-1; 164*91e1e26aSAlexander Pyhalov } 165*91e1e26aSAlexander Pyhalov } 166*91e1e26aSAlexander Pyhalov 167*91e1e26aSAlexander Pyhalov if (*inbytesleft > 0 && *outbytesleft == 0) { 168*91e1e26aSAlexander Pyhalov errno = E2BIG; 169*91e1e26aSAlexander Pyhalov return (size_t)-1; 170*91e1e26aSAlexander Pyhalov } 171*91e1e26aSAlexander Pyhalov return ((size_t)(*inbytesleft)); 172*91e1e26aSAlexander Pyhalov } 173*91e1e26aSAlexander Pyhalov 174*91e1e26aSAlexander Pyhalov 175*91e1e26aSAlexander Pyhalov int 176*91e1e26aSAlexander Pyhalov hz2utf8(in_byte1, in_byte2, buf, buflen) 177*91e1e26aSAlexander Pyhalov char in_byte1, in_byte2; 178*91e1e26aSAlexander Pyhalov char *buf; 179*91e1e26aSAlexander Pyhalov int buflen; 180*91e1e26aSAlexander Pyhalov { 181*91e1e26aSAlexander Pyhalov 182*91e1e26aSAlexander Pyhalov int idx; 183*91e1e26aSAlexander Pyhalov int unicode; 184*91e1e26aSAlexander Pyhalov 185*91e1e26aSAlexander Pyhalov if ( buflen < 2 ) 186*91e1e26aSAlexander Pyhalov return 0; 187*91e1e26aSAlexander Pyhalov in_byte1 |= MSB; 188*91e1e26aSAlexander Pyhalov in_byte2 |= MSB; 189*91e1e26aSAlexander Pyhalov 190*91e1e26aSAlexander Pyhalov 191*91e1e26aSAlexander Pyhalov idx = (((in_byte1 & 0xff) - 0xa1) * 94) + (in_byte2 & 0xff) - 0xa1; 192*91e1e26aSAlexander Pyhalov if (idx >= 0) { 193*91e1e26aSAlexander Pyhalov unicode = Unicode[idx]; 194*91e1e26aSAlexander Pyhalov if (unicode >= 0x0080 && unicode <= 0x07ff) { 195*91e1e26aSAlexander Pyhalov if ( buflen < 2 ) 196*91e1e26aSAlexander Pyhalov return 0; 197*91e1e26aSAlexander Pyhalov *buf = ((unicode >> 6) & 0x1f) | 0xc0; 198*91e1e26aSAlexander Pyhalov *(buf+1) = (unicode & 0x3f) | MSB; 199*91e1e26aSAlexander Pyhalov return 2; 200*91e1e26aSAlexander Pyhalov } 201*91e1e26aSAlexander Pyhalov if (unicode >= 0x0800 && unicode <= 0xffff) { 202*91e1e26aSAlexander Pyhalov if ( buflen < 3 ) 203*91e1e26aSAlexander Pyhalov return 0; 204*91e1e26aSAlexander Pyhalov *buf = ((unicode >> 12) & 0x0f) | 0xe0; 205*91e1e26aSAlexander Pyhalov *(buf+1) = ((unicode >> 6) & 0x3f) | MSB; 206*91e1e26aSAlexander Pyhalov *(buf+2) = (unicode & 0x3f) | MSB; 207*91e1e26aSAlexander Pyhalov return 3; 208*91e1e26aSAlexander Pyhalov } 209*91e1e26aSAlexander Pyhalov } 210*91e1e26aSAlexander Pyhalov if ( buflen < 3 ) 211*91e1e26aSAlexander Pyhalov return 0; 212*91e1e26aSAlexander Pyhalov 213*91e1e26aSAlexander Pyhalov *buf = UTF8_NON_ID_CHAR1; 214*91e1e26aSAlexander Pyhalov *(buf+1) = UTF8_NON_ID_CHAR2; 215*91e1e26aSAlexander Pyhalov *(buf+2) = UTF8_NON_ID_CHAR3; 216*91e1e26aSAlexander Pyhalov return 3; 217*91e1e26aSAlexander Pyhalov } 218