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 /* 23*91e1e26aSAlexander Pyhalov * Copyright (c) 1997, by Sun Microsystems, Inc. 24*91e1e26aSAlexander Pyhalov * All rights reserved. 25*91e1e26aSAlexander Pyhalov */ 26*91e1e26aSAlexander Pyhalov 27*91e1e26aSAlexander Pyhalov #include <stdio.h> 28*91e1e26aSAlexander Pyhalov #include <stdlib.h> 29*91e1e26aSAlexander Pyhalov #include <errno.h> 30*91e1e26aSAlexander Pyhalov #include <sys/types.h> 31*91e1e26aSAlexander Pyhalov 32*91e1e26aSAlexander Pyhalov #include "tab_lookup.h" /* table lookup data types */ 33*91e1e26aSAlexander Pyhalov 34*91e1e26aSAlexander Pyhalov int bisearch(unsigned long val, _icv_state *st, int n); 35*91e1e26aSAlexander Pyhalov 36*91e1e26aSAlexander Pyhalov #define MSB 0x80 /* most significant bit */ 37*91e1e26aSAlexander Pyhalov #define MBYTE 0x8e /* multi-byte (4 byte character) */ 38*91e1e26aSAlexander Pyhalov #define PMASK 0xa0 /* plane number mask */ 39*91e1e26aSAlexander Pyhalov #define ONEBYTE 0xff /* right most byte */ 40*91e1e26aSAlexander Pyhalov 41*91e1e26aSAlexander Pyhalov /* non-identified character */ 42*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR1 0xEF 43*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR2 0xBF 44*91e1e26aSAlexander Pyhalov #define UTF8_NON_ID_CHAR3 0xBD 45*91e1e26aSAlexander Pyhalov 46*91e1e26aSAlexander Pyhalov enum _USTATE { C0, C1, C2 }; 47*91e1e26aSAlexander Pyhalov 48*91e1e26aSAlexander Pyhalov 49*91e1e26aSAlexander Pyhalov int ibm_to_utf8(_icv_state *st, char *buf, size_t buflen); 50*91e1e26aSAlexander Pyhalov 51*91e1e26aSAlexander Pyhalov 52*91e1e26aSAlexander Pyhalov /* 53*91e1e26aSAlexander Pyhalov * Actual conversion; called from iconv() 54*91e1e26aSAlexander Pyhalov * Input is UTF-8 data. 55*91e1e26aSAlexander Pyhalov * first convert to UCS2 56*91e1e26aSAlexander Pyhalov */ 57*91e1e26aSAlexander Pyhalov size_t 58*91e1e26aSAlexander Pyhalov _icv_iconv(_icv_state *st, char **inbuf, size_t *inbytesleft, 59*91e1e26aSAlexander Pyhalov char **outbuf, size_t *outbytesleft) 60*91e1e26aSAlexander Pyhalov { 61*91e1e26aSAlexander Pyhalov /* 62*91e1e26aSAlexander Pyhalov * Actual conversion; called from iconv() 63*91e1e26aSAlexander Pyhalov */ 64*91e1e26aSAlexander Pyhalov 65*91e1e26aSAlexander Pyhalov int n; 66*91e1e26aSAlexander Pyhalov 67*91e1e26aSAlexander Pyhalov #ifdef DEBUG 68*91e1e26aSAlexander Pyhalov fprintf(stderr, "========== iconv(): IBM --> UTF8 ==========\n"); 69*91e1e26aSAlexander Pyhalov #endif 70*91e1e26aSAlexander Pyhalov 71*91e1e26aSAlexander Pyhalov if (st == NULL) { 72*91e1e26aSAlexander Pyhalov errno = EBADF; 73*91e1e26aSAlexander Pyhalov return ((size_t) -1); 74*91e1e26aSAlexander Pyhalov } 75*91e1e26aSAlexander Pyhalov 76*91e1e26aSAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 77*91e1e26aSAlexander Pyhalov st->ustate = C0; 78*91e1e26aSAlexander Pyhalov st->_errno = 0; 79*91e1e26aSAlexander Pyhalov st->shift = SHIFT_IN; 80*91e1e26aSAlexander Pyhalov return ((size_t) 0); 81*91e1e26aSAlexander Pyhalov } 82*91e1e26aSAlexander Pyhalov 83*91e1e26aSAlexander Pyhalov st->_errno = 0; /* reset internal errno */ 84*91e1e26aSAlexander Pyhalov errno = 0; /* reset external errno */ 85*91e1e26aSAlexander Pyhalov 86*91e1e26aSAlexander Pyhalov /* a state machine for interpreting UTF8 code */ 87*91e1e26aSAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) { 88*91e1e26aSAlexander Pyhalov switch (**inbuf) { 89*91e1e26aSAlexander Pyhalov case SHIFT_OUT : 90*91e1e26aSAlexander Pyhalov if (st->shift == SHIFT_IN) { 91*91e1e26aSAlexander Pyhalov st->shift = SHIFT_OUT; 92*91e1e26aSAlexander Pyhalov (*inbuf)++; 93*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 94*91e1e26aSAlexander Pyhalov continue; 95*91e1e26aSAlexander Pyhalov } 96*91e1e26aSAlexander Pyhalov break; 97*91e1e26aSAlexander Pyhalov case SHIFT_IN : 98*91e1e26aSAlexander Pyhalov if (st->shift == SHIFT_OUT) { 99*91e1e26aSAlexander Pyhalov st->shift = SHIFT_IN; 100*91e1e26aSAlexander Pyhalov (*inbuf)++; 101*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 102*91e1e26aSAlexander Pyhalov continue; 103*91e1e26aSAlexander Pyhalov } 104*91e1e26aSAlexander Pyhalov break; 105*91e1e26aSAlexander Pyhalov } 106*91e1e26aSAlexander Pyhalov 107*91e1e26aSAlexander Pyhalov switch (st->ustate) { 108*91e1e26aSAlexander Pyhalov case C0 : 109*91e1e26aSAlexander Pyhalov /* the input is ascii, single byte, convert it */ 110*91e1e26aSAlexander Pyhalov if (st->shift == SHIFT_IN) { 111*91e1e26aSAlexander Pyhalov st->keepc[0] = 0x0; 112*91e1e26aSAlexander Pyhalov st->keepc[1] = **inbuf; 113*91e1e26aSAlexander Pyhalov st->ustate = C2; 114*91e1e26aSAlexander Pyhalov continue; 115*91e1e26aSAlexander Pyhalov } 116*91e1e26aSAlexander Pyhalov 117*91e1e26aSAlexander Pyhalov /* two bytes character */ 118*91e1e26aSAlexander Pyhalov st->keepc[0] = (**inbuf); 119*91e1e26aSAlexander Pyhalov st->ustate = C1; 120*91e1e26aSAlexander Pyhalov break; 121*91e1e26aSAlexander Pyhalov case C1 : 122*91e1e26aSAlexander Pyhalov st->keepc[1] = (**inbuf); 123*91e1e26aSAlexander Pyhalov st->ustate = C2; 124*91e1e26aSAlexander Pyhalov continue; 125*91e1e26aSAlexander Pyhalov case C2 : 126*91e1e26aSAlexander Pyhalov n = ibm_to_utf8(st, *outbuf, *outbytesleft); 127*91e1e26aSAlexander Pyhalov if (n > 0) { 128*91e1e26aSAlexander Pyhalov (*outbuf) += n; 129*91e1e26aSAlexander Pyhalov (*outbytesleft) -= n; 130*91e1e26aSAlexander Pyhalov } else { 131*91e1e26aSAlexander Pyhalov st->_errno = errno; 132*91e1e26aSAlexander Pyhalov return((size_t)-1); 133*91e1e26aSAlexander Pyhalov } 134*91e1e26aSAlexander Pyhalov st->ustate = C0; 135*91e1e26aSAlexander Pyhalov st->_errno = 0; 136*91e1e26aSAlexander Pyhalov break; 137*91e1e26aSAlexander Pyhalov 138*91e1e26aSAlexander Pyhalov default: /* should never come here */ 139*91e1e26aSAlexander Pyhalov st->_errno = errno = EILSEQ; 140*91e1e26aSAlexander Pyhalov st->ustate = C0; /* reset state */ 141*91e1e26aSAlexander Pyhalov break; 142*91e1e26aSAlexander Pyhalov } 143*91e1e26aSAlexander Pyhalov 144*91e1e26aSAlexander Pyhalov 145*91e1e26aSAlexander Pyhalov (*inbuf)++; 146*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 147*91e1e26aSAlexander Pyhalov 148*91e1e26aSAlexander Pyhalov if (st->_errno) { 149*91e1e26aSAlexander Pyhalov #ifdef DEBUG 150*91e1e26aSAlexander Pyhalov fprintf(stderr, "!!!!!\tst->_errno = %d\tst->ustate = %d\n", 151*91e1e26aSAlexander Pyhalov st->_errno, st->ustate); 152*91e1e26aSAlexander Pyhalov #endif 153*91e1e26aSAlexander Pyhalov break; 154*91e1e26aSAlexander Pyhalov } 155*91e1e26aSAlexander Pyhalov 156*91e1e26aSAlexander Pyhalov if (errno) 157*91e1e26aSAlexander Pyhalov return((size_t)-1); 158*91e1e26aSAlexander Pyhalov } 159*91e1e26aSAlexander Pyhalov 160*91e1e26aSAlexander Pyhalov if (*outbytesleft == 0) { 161*91e1e26aSAlexander Pyhalov errno = E2BIG; 162*91e1e26aSAlexander Pyhalov return((size_t)-1); 163*91e1e26aSAlexander Pyhalov } 164*91e1e26aSAlexander Pyhalov return (*inbytesleft); 165*91e1e26aSAlexander Pyhalov } 166*91e1e26aSAlexander Pyhalov 167*91e1e26aSAlexander Pyhalov /* 168*91e1e26aSAlexander Pyhalov * IBM code --> (Unicode) 169*91e1e26aSAlexander Pyhalov * Unicode --> UTF8 (FSS-UTF) 170*91e1e26aSAlexander Pyhalov * (File System Safe Universal Character Set Transformation Format) 171*91e1e26aSAlexander Pyhalov * Return: > 0 - converted with enough space in output buffer 172*91e1e26aSAlexander Pyhalov * = 0 - no space in outbuf 173*91e1e26aSAlexander Pyhalov */ 174*91e1e26aSAlexander Pyhalov int ibm_to_utf8(st, buf, buflen) 175*91e1e26aSAlexander Pyhalov _icv_state *st; 176*91e1e26aSAlexander Pyhalov char *buf; 177*91e1e26aSAlexander Pyhalov size_t buflen; 178*91e1e26aSAlexander Pyhalov { 179*91e1e26aSAlexander Pyhalov unsigned long ibm_val; /* Big-5 value */ 180*91e1e26aSAlexander Pyhalov int unidx; /* Unicode index */ 181*91e1e26aSAlexander Pyhalov unsigned long uni_val; /* Unicode */ 182*91e1e26aSAlexander Pyhalov 183*91e1e26aSAlexander Pyhalov ibm_val = ((st->keepc[0]&ONEBYTE) << 8) + (st->keepc[1]&ONEBYTE); 184*91e1e26aSAlexander Pyhalov #ifdef DEBUG 185*91e1e26aSAlexander Pyhalov fprintf(stderr, "%x\t", ibm_val); 186*91e1e26aSAlexander Pyhalov #endif 187*91e1e26aSAlexander Pyhalov 188*91e1e26aSAlexander Pyhalov 189*91e1e26aSAlexander Pyhalov unidx = bisearch(ibm_val, st, st->table_size); 190*91e1e26aSAlexander Pyhalov 191*91e1e26aSAlexander Pyhalov if (unidx >= 0) 192*91e1e26aSAlexander Pyhalov { 193*91e1e26aSAlexander Pyhalov if ( st->left_to_right ) 194*91e1e26aSAlexander Pyhalov uni_val = st->table[unidx].right_code; 195*91e1e26aSAlexander Pyhalov else 196*91e1e26aSAlexander Pyhalov uni_val = st->table[unidx].left_code; 197*91e1e26aSAlexander Pyhalov } 198*91e1e26aSAlexander Pyhalov 199*91e1e26aSAlexander Pyhalov #ifdef DEBUG 200*91e1e26aSAlexander Pyhalov fprintf(stderr, "unidx = %d, unicode = %x\t", unidx, uni_val); 201*91e1e26aSAlexander Pyhalov #endif 202*91e1e26aSAlexander Pyhalov 203*91e1e26aSAlexander Pyhalov if (unidx >= 0) { /* do Unicode to UTF8 conversion */ 204*91e1e26aSAlexander Pyhalov if (uni_val <= 0x07f) { 205*91e1e26aSAlexander Pyhalov if (buflen < 1) { 206*91e1e26aSAlexander Pyhalov errno = E2BIG; 207*91e1e26aSAlexander Pyhalov return 0; 208*91e1e26aSAlexander Pyhalov } 209*91e1e26aSAlexander Pyhalov *buf = uni_val; 210*91e1e26aSAlexander Pyhalov return 1; 211*91e1e26aSAlexander Pyhalov } 212*91e1e26aSAlexander Pyhalov if (uni_val >= 0x0080 && uni_val <= 0x07ff) { 213*91e1e26aSAlexander Pyhalov if (buflen < 2) { 214*91e1e26aSAlexander Pyhalov #ifdef DEBUG 215*91e1e26aSAlexander Pyhalov fprintf(stderr, "outbuf overflow in ibm_to_utf8()!!\n"); 216*91e1e26aSAlexander Pyhalov #endif 217*91e1e26aSAlexander Pyhalov errno = E2BIG; 218*91e1e26aSAlexander Pyhalov return(0); 219*91e1e26aSAlexander Pyhalov } 220*91e1e26aSAlexander Pyhalov *buf = (char)((uni_val >> 6) & 0x1f) | 0xc0; 221*91e1e26aSAlexander Pyhalov *(buf+1) = (char)(uni_val & 0x3f) | 0x80; 222*91e1e26aSAlexander Pyhalov #ifdef DEBUG 223*91e1e26aSAlexander Pyhalov fprintf(stderr, "%x %x\n", *buf&ONEBYTE, *(buf+1)&ONEBYTE); 224*91e1e26aSAlexander Pyhalov #endif 225*91e1e26aSAlexander Pyhalov return(2); 226*91e1e26aSAlexander Pyhalov } 227*91e1e26aSAlexander Pyhalov if (uni_val >= 0x0800 && uni_val <= 0xffff) { 228*91e1e26aSAlexander Pyhalov if (buflen < 3) { 229*91e1e26aSAlexander Pyhalov #ifdef DEBUG 230*91e1e26aSAlexander Pyhalov fprintf(stderr, "outbuf overflow in ibm_to_utf8()!!\n"); 231*91e1e26aSAlexander Pyhalov #endif 232*91e1e26aSAlexander Pyhalov errno = E2BIG; 233*91e1e26aSAlexander Pyhalov return(0); 234*91e1e26aSAlexander Pyhalov } 235*91e1e26aSAlexander Pyhalov *buf = (char)((uni_val >> 12) & 0xf) | 0xe0; 236*91e1e26aSAlexander Pyhalov *(buf+1) = (char)((uni_val >>6) & 0x3f) | 0x80; 237*91e1e26aSAlexander Pyhalov *(buf+2) = (char)(uni_val & 0x3f) | 0x80; 238*91e1e26aSAlexander Pyhalov #ifdef DEBUG 239*91e1e26aSAlexander Pyhalov fprintf(stderr, "%x %x %x\n", *buf&ONEBYTE, *(buf+1)&ONEBYTE, *(buf+2)&ONEBYTE); 240*91e1e26aSAlexander Pyhalov #endif 241*91e1e26aSAlexander Pyhalov return(3); 242*91e1e26aSAlexander Pyhalov } 243*91e1e26aSAlexander Pyhalov } 244*91e1e26aSAlexander Pyhalov 245*91e1e26aSAlexander Pyhalov /* can't find a match in IBM --> UTF8 table or illegal UTF8 code */ 246*91e1e26aSAlexander Pyhalov if (buflen < 3) { 247*91e1e26aSAlexander Pyhalov #ifdef DEBUG 248*91e1e26aSAlexander Pyhalov fprintf(stderr, "outbuf overflow in ibm_to_utf8()!!\n"); 249*91e1e26aSAlexander Pyhalov #endif 250*91e1e26aSAlexander Pyhalov errno = E2BIG; 251*91e1e26aSAlexander Pyhalov return(0); 252*91e1e26aSAlexander Pyhalov } 253*91e1e26aSAlexander Pyhalov 254*91e1e26aSAlexander Pyhalov *buf = (char)UTF8_NON_ID_CHAR1; 255*91e1e26aSAlexander Pyhalov *(buf+1) = (char)UTF8_NON_ID_CHAR2; 256*91e1e26aSAlexander Pyhalov *(buf+2) = (char)UTF8_NON_ID_CHAR3; 257*91e1e26aSAlexander Pyhalov 258*91e1e26aSAlexander Pyhalov #ifdef DEBUG 259*91e1e26aSAlexander Pyhalov fprintf(stderr, "%c %c %c\n", *buf, *(buf+1), *(buf+2)); 260*91e1e26aSAlexander Pyhalov #endif 261*91e1e26aSAlexander Pyhalov return(3); 262*91e1e26aSAlexander Pyhalov } 263