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) 2001 Sun Microsystems, Inc. 23*91e1e26aSAlexander Pyhalov * All rights reserved. 24*91e1e26aSAlexander Pyhalov */ 25*91e1e26aSAlexander Pyhalov 26*91e1e26aSAlexander Pyhalov #include <stdio.h> 27*91e1e26aSAlexander Pyhalov #include <errno.h> 28*91e1e26aSAlexander Pyhalov #include <stdlib.h> 29*91e1e26aSAlexander Pyhalov #include <strings.h> 30*91e1e26aSAlexander Pyhalov #include "iscii.h" 31*91e1e26aSAlexander Pyhalov 32*91e1e26aSAlexander Pyhalov #define MSB 0x80 /* most significant bit */ 33*91e1e26aSAlexander Pyhalov #define ONEBYTE 0xff /* right most byte */ 34*91e1e26aSAlexander Pyhalov 35*91e1e26aSAlexander Pyhalov #define REPLACE_CHAR1 0xEF /* invalid conversion character */ 36*91e1e26aSAlexander Pyhalov #define REPLACE_CHAR2 0xBF 37*91e1e26aSAlexander Pyhalov #define REPLACE_CHAR3 0xBD 38*91e1e26aSAlexander Pyhalov 39*91e1e26aSAlexander Pyhalov #define UTF8_SET1B(b,v) \ 40*91e1e26aSAlexander Pyhalov (b[0]=(v&0x7f)) 41*91e1e26aSAlexander Pyhalov 42*91e1e26aSAlexander Pyhalov #define UTF8_SET2B(b,v) \ 43*91e1e26aSAlexander Pyhalov (b[0]=(0xc0|((v>>6)&0x1f))); \ 44*91e1e26aSAlexander Pyhalov (b[1]=(0x80|((v&0x3f)))) 45*91e1e26aSAlexander Pyhalov 46*91e1e26aSAlexander Pyhalov #define UTF8_SET3B(b,v) \ 47*91e1e26aSAlexander Pyhalov (b[0]=(0xe0|((v>>12)&0xf))); \ 48*91e1e26aSAlexander Pyhalov (b[1]=(0x80|((v>>6)&0x3f))); \ 49*91e1e26aSAlexander Pyhalov (b[2]=(0x80|((v&0x3f)))) 50*91e1e26aSAlexander Pyhalov 51*91e1e26aSAlexander Pyhalov typedef struct _icv_state { 52*91e1e26aSAlexander Pyhalov char keepc[3]; /* keepc[0] is attr, keepc[1] and keepc[2] are lookup-ed */ 53*91e1e26aSAlexander Pyhalov short pState; /* Previous State */ 54*91e1e26aSAlexander Pyhalov int _errno; 55*91e1e26aSAlexander Pyhalov } _iconv_st; 56*91e1e26aSAlexander Pyhalov 57*91e1e26aSAlexander Pyhalov enum _CSTATE { S_BASIC, S_ATR, S_EXT, S_NONE }; 58*91e1e26aSAlexander Pyhalov 59*91e1e26aSAlexander Pyhalov #define have_nukta(isc_type) ( nukta_type[isc_type] != NULL ) 60*91e1e26aSAlexander Pyhalov #define have_EXT(isc_type) ( EXT_type[isc_type] != NULL ) 61*91e1e26aSAlexander Pyhalov #define FIRST_CHAR 0xA0 62*91e1e26aSAlexander Pyhalov 63*91e1e26aSAlexander Pyhalov static int copy_to_outbuf(ucs_t uniid, char *buf, size_t buflen); 64*91e1e26aSAlexander Pyhalov 65*91e1e26aSAlexander Pyhalov static ucs_t 66*91e1e26aSAlexander Pyhalov get_nukta(uchar iscii, int type) 67*91e1e26aSAlexander Pyhalov { 68*91e1e26aSAlexander Pyhalov int indx = iscii - FIRST_CHAR; 69*91e1e26aSAlexander Pyhalov int *iscii_nukta = nukta_type[type]; 70*91e1e26aSAlexander Pyhalov 71*91e1e26aSAlexander Pyhalov return ((indx >= 0) ? iscii_nukta[indx] : 0 ); 72*91e1e26aSAlexander Pyhalov } 73*91e1e26aSAlexander Pyhalov 74*91e1e26aSAlexander Pyhalov static ucs_t 75*91e1e26aSAlexander Pyhalov get_EXT(uchar iscii, int type) 76*91e1e26aSAlexander Pyhalov { 77*91e1e26aSAlexander Pyhalov int indx = iscii - FIRST_CHAR; 78*91e1e26aSAlexander Pyhalov int *iscii_EXT = EXT_type[type]; 79*91e1e26aSAlexander Pyhalov 80*91e1e26aSAlexander Pyhalov return ((indx >= 0) ? iscii_EXT[indx] : 0 ); 81*91e1e26aSAlexander Pyhalov } 82*91e1e26aSAlexander Pyhalov 83*91e1e26aSAlexander Pyhalov static ucs_t 84*91e1e26aSAlexander Pyhalov traverse_table(Entry *entry, int num, uchar iscii) 85*91e1e26aSAlexander Pyhalov { 86*91e1e26aSAlexander Pyhalov int i=0; 87*91e1e26aSAlexander Pyhalov ucs_t retucs=0; 88*91e1e26aSAlexander Pyhalov 89*91e1e26aSAlexander Pyhalov for ( ; i < num; ++i ) { 90*91e1e26aSAlexander Pyhalov Entry en = entry[i]; 91*91e1e26aSAlexander Pyhalov 92*91e1e26aSAlexander Pyhalov if ( iscii < en.iscii ) break; 93*91e1e26aSAlexander Pyhalov if ( iscii >= en.iscii && iscii < en.iscii + en.count ) { 94*91e1e26aSAlexander Pyhalov retucs = en.ucs + ( iscii - en.iscii ); 95*91e1e26aSAlexander Pyhalov break; 96*91e1e26aSAlexander Pyhalov } 97*91e1e26aSAlexander Pyhalov } 98*91e1e26aSAlexander Pyhalov 99*91e1e26aSAlexander Pyhalov return retucs; 100*91e1e26aSAlexander Pyhalov } 101*91e1e26aSAlexander Pyhalov 102*91e1e26aSAlexander Pyhalov /* 103*91e1e26aSAlexander Pyhalov * the copy_to_outbuf has to be called before the st->keepc needs to changed. 104*91e1e26aSAlexander Pyhalov * if E2BIG error, keep st->keepc. Will flush it at the beginning of next 105*91e1e26aSAlexander Pyhalov * _icv_iconv() invocation 106*91e1e26aSAlexander Pyhalov */ 107*91e1e26aSAlexander Pyhalov int 108*91e1e26aSAlexander Pyhalov iscii_to_utf8(_iconv_st *st, char *buf, size_t buflen) 109*91e1e26aSAlexander Pyhalov { 110*91e1e26aSAlexander Pyhalov #define DEV_ATR 0x42 111*91e1e26aSAlexander Pyhalov ucs_t uniid; 112*91e1e26aSAlexander Pyhalov int nBytes=0; 113*91e1e26aSAlexander Pyhalov ISCII isc_type = isc_TYPE[st->keepc[0] - DEV_ATR]; 114*91e1e26aSAlexander Pyhalov Entries en = iscii_table[isc_type]; 115*91e1e26aSAlexander Pyhalov /* unsigned int keepc0 = (unsigned int) (st->keepc[0] & ONEBYTE); */ 116*91e1e26aSAlexander Pyhalov unsigned int keepc1 = (unsigned int) (st->keepc[1] & ONEBYTE); 117*91e1e26aSAlexander Pyhalov unsigned int keepc2 = (unsigned int) (st->keepc[2] & ONEBYTE); 118*91e1e26aSAlexander Pyhalov 119*91e1e26aSAlexander Pyhalov if (keepc1 == 0xFF) { /* FFFD */ 120*91e1e26aSAlexander Pyhalov if ( buflen < 3 ) { 121*91e1e26aSAlexander Pyhalov errno = E2BIG; 122*91e1e26aSAlexander Pyhalov return 0; 123*91e1e26aSAlexander Pyhalov } 124*91e1e26aSAlexander Pyhalov 125*91e1e26aSAlexander Pyhalov *buf = (char)REPLACE_CHAR1; 126*91e1e26aSAlexander Pyhalov *(buf+1) = (char)REPLACE_CHAR2; 127*91e1e26aSAlexander Pyhalov *(buf+2) = (char)REPLACE_CHAR3; 128*91e1e26aSAlexander Pyhalov return (3); 129*91e1e26aSAlexander Pyhalov } 130*91e1e26aSAlexander Pyhalov 131*91e1e26aSAlexander Pyhalov if (keepc2 == 0) { /* Flush Single Character */ 132*91e1e26aSAlexander Pyhalov 133*91e1e26aSAlexander Pyhalov if (keepc1 & MSB) { /* ISCII - Non-Ascii Codepoints */ 134*91e1e26aSAlexander Pyhalov uniid = traverse_table(en.entry, en.items, keepc1); 135*91e1e26aSAlexander Pyhalov } else /* ASCII */ 136*91e1e26aSAlexander Pyhalov uniid = keepc1; 137*91e1e26aSAlexander Pyhalov 138*91e1e26aSAlexander Pyhalov if ( (nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 139*91e1e26aSAlexander Pyhalov st->keepc[1] = 0; 140*91e1e26aSAlexander Pyhalov 141*91e1e26aSAlexander Pyhalov } else { 142*91e1e26aSAlexander Pyhalov /* keepc[1] and keepc[2] != 0 */ 143*91e1e26aSAlexander Pyhalov if (keepc1 & MSB) { 144*91e1e26aSAlexander Pyhalov 145*91e1e26aSAlexander Pyhalov switch (keepc1) 146*91e1e26aSAlexander Pyhalov { 147*91e1e26aSAlexander Pyhalov case ISC_ext: 148*91e1e26aSAlexander Pyhalov 149*91e1e26aSAlexander Pyhalov if ( have_EXT(isc_type) && is_valid_ext_code(keepc2) ) 150*91e1e26aSAlexander Pyhalov { /* EXT only supported in Devanagari script */ 151*91e1e26aSAlexander Pyhalov 152*91e1e26aSAlexander Pyhalov uniid = get_EXT(keepc2, isc_type); 153*91e1e26aSAlexander Pyhalov if ((nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 154*91e1e26aSAlexander Pyhalov } 155*91e1e26aSAlexander Pyhalov else 156*91e1e26aSAlexander Pyhalov errno = EILSEQ; 157*91e1e26aSAlexander Pyhalov 158*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2] = 0; 159*91e1e26aSAlexander Pyhalov break; 160*91e1e26aSAlexander Pyhalov case ISC_halant: 161*91e1e26aSAlexander Pyhalov /* test whether there has enough space to hold the converted bytes */ 162*91e1e26aSAlexander Pyhalov if ((keepc2 == ISC_halant || keepc2 == ISC_nukta) && buflen < 6 ) 163*91e1e26aSAlexander Pyhalov goto E2big; 164*91e1e26aSAlexander Pyhalov 165*91e1e26aSAlexander Pyhalov uniid = traverse_table(en.entry, en.items, keepc1); 166*91e1e26aSAlexander Pyhalov if ((nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 167*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2]; 168*91e1e26aSAlexander Pyhalov 169*91e1e26aSAlexander Pyhalov if ( keepc2 == ISC_halant || keepc2 == ISC_nukta ) 170*91e1e26aSAlexander Pyhalov { 171*91e1e26aSAlexander Pyhalov int nbytes_2 = 0; 172*91e1e26aSAlexander Pyhalov if (keepc2 == ISC_halant) uniid = UNI_ZWNJ; /* explicit Halant */ 173*91e1e26aSAlexander Pyhalov if (keepc2 == ISC_nukta) uniid = UNI_ZWJ; /* soft Halant */ 174*91e1e26aSAlexander Pyhalov 175*91e1e26aSAlexander Pyhalov if ((nbytes_2 = copy_to_outbuf(uniid, buf+nBytes, buflen)) == 0) goto E2big; 176*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2] = 0; 177*91e1e26aSAlexander Pyhalov 178*91e1e26aSAlexander Pyhalov nBytes += nbytes_2; 179*91e1e26aSAlexander Pyhalov } 180*91e1e26aSAlexander Pyhalov 181*91e1e26aSAlexander Pyhalov break; 182*91e1e26aSAlexander Pyhalov case ISC_danda: 183*91e1e26aSAlexander Pyhalov if ( isc_type == DEV && keepc2 == ISC_danda ) 184*91e1e26aSAlexander Pyhalov { /* only in Devanagari script, it works */ 185*91e1e26aSAlexander Pyhalov uniid = UNI_DOUBLE_DANDA; 186*91e1e26aSAlexander Pyhalov if ((nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 187*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2] = 0; 188*91e1e26aSAlexander Pyhalov 189*91e1e26aSAlexander Pyhalov break; 190*91e1e26aSAlexander Pyhalov } 191*91e1e26aSAlexander Pyhalov 192*91e1e26aSAlexander Pyhalov /* fall into default case, convert the DANDA if it isn't DOUBLE_DANDA */ 193*91e1e26aSAlexander Pyhalov /* FALLTHRU */ 194*91e1e26aSAlexander Pyhalov default: 195*91e1e26aSAlexander Pyhalov 196*91e1e26aSAlexander Pyhalov uniid = traverse_table(en.entry, en.items, keepc1); 197*91e1e26aSAlexander Pyhalov 198*91e1e26aSAlexander Pyhalov if ( have_nukta(isc_type) && keepc2 == ISC_nukta) { 199*91e1e26aSAlexander Pyhalov /* then try to test whether it is Nukta Cases */ 200*91e1e26aSAlexander Pyhalov int ucs; 201*91e1e26aSAlexander Pyhalov 202*91e1e26aSAlexander Pyhalov if (( ucs = get_nukta(keepc1, isc_type)) != 0 ) { 203*91e1e26aSAlexander Pyhalov 204*91e1e26aSAlexander Pyhalov uniid = ucs; 205*91e1e26aSAlexander Pyhalov 206*91e1e26aSAlexander Pyhalov if ( (nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 207*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2] = 0; 208*91e1e26aSAlexander Pyhalov } else { 209*91e1e26aSAlexander Pyhalov if ( (nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 210*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2]; 211*91e1e26aSAlexander Pyhalov } 212*91e1e26aSAlexander Pyhalov } else { 213*91e1e26aSAlexander Pyhalov if ( (nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 214*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2]; 215*91e1e26aSAlexander Pyhalov } 216*91e1e26aSAlexander Pyhalov break; 217*91e1e26aSAlexander Pyhalov } /* end of switch */ 218*91e1e26aSAlexander Pyhalov } else { /* ASCII */ 219*91e1e26aSAlexander Pyhalov uniid = keepc1; 220*91e1e26aSAlexander Pyhalov if ( (nBytes = copy_to_outbuf(uniid, buf, buflen)) == 0) goto E2big; 221*91e1e26aSAlexander Pyhalov st->keepc[1] = st->keepc[2]; 222*91e1e26aSAlexander Pyhalov } 223*91e1e26aSAlexander Pyhalov st->keepc[2] = 0; 224*91e1e26aSAlexander Pyhalov } 225*91e1e26aSAlexander Pyhalov 226*91e1e26aSAlexander Pyhalov E2big: 227*91e1e26aSAlexander Pyhalov return nBytes; 228*91e1e26aSAlexander Pyhalov } 229*91e1e26aSAlexander Pyhalov 230*91e1e26aSAlexander Pyhalov static int 231*91e1e26aSAlexander Pyhalov copy_to_outbuf(ucs_t uniid, char *buf, size_t buflen) 232*91e1e26aSAlexander Pyhalov { 233*91e1e26aSAlexander Pyhalov if (uniid > 0) { 234*91e1e26aSAlexander Pyhalov if (uniid <= 0x7f) { 235*91e1e26aSAlexander Pyhalov if (buflen < 1) { 236*91e1e26aSAlexander Pyhalov errno = E2BIG; 237*91e1e26aSAlexander Pyhalov return(0); 238*91e1e26aSAlexander Pyhalov } 239*91e1e26aSAlexander Pyhalov UTF8_SET1B(buf, uniid); 240*91e1e26aSAlexander Pyhalov return (1); 241*91e1e26aSAlexander Pyhalov } 242*91e1e26aSAlexander Pyhalov 243*91e1e26aSAlexander Pyhalov if (uniid >= 0x80 && uniid <= 0x7ff) { 244*91e1e26aSAlexander Pyhalov if (buflen < 2) { 245*91e1e26aSAlexander Pyhalov errno = E2BIG; 246*91e1e26aSAlexander Pyhalov return(0); 247*91e1e26aSAlexander Pyhalov } 248*91e1e26aSAlexander Pyhalov UTF8_SET2B(buf, uniid); 249*91e1e26aSAlexander Pyhalov return (2); 250*91e1e26aSAlexander Pyhalov } 251*91e1e26aSAlexander Pyhalov 252*91e1e26aSAlexander Pyhalov if (uniid >= 0x800 && uniid <= 0xffff) { 253*91e1e26aSAlexander Pyhalov if (buflen < 3) { 254*91e1e26aSAlexander Pyhalov errno = E2BIG; 255*91e1e26aSAlexander Pyhalov return(0); 256*91e1e26aSAlexander Pyhalov } 257*91e1e26aSAlexander Pyhalov UTF8_SET3B(buf, uniid); 258*91e1e26aSAlexander Pyhalov return (3); 259*91e1e26aSAlexander Pyhalov } 260*91e1e26aSAlexander Pyhalov } else { /* Replacement Character */ 261*91e1e26aSAlexander Pyhalov if ( buflen < 3 ) { 262*91e1e26aSAlexander Pyhalov errno = E2BIG; 263*91e1e26aSAlexander Pyhalov return 0; 264*91e1e26aSAlexander Pyhalov } 265*91e1e26aSAlexander Pyhalov 266*91e1e26aSAlexander Pyhalov *buf = (char)REPLACE_CHAR1; 267*91e1e26aSAlexander Pyhalov *(buf+1) = (char)REPLACE_CHAR2; 268*91e1e26aSAlexander Pyhalov *(buf+2) = (char)REPLACE_CHAR3; 269*91e1e26aSAlexander Pyhalov return (3); 270*91e1e26aSAlexander Pyhalov } 271*91e1e26aSAlexander Pyhalov 272*91e1e26aSAlexander Pyhalov /* This code shouldn't be reached */ 273*91e1e26aSAlexander Pyhalov return (0); 274*91e1e26aSAlexander Pyhalov } 275*91e1e26aSAlexander Pyhalov 276*91e1e26aSAlexander Pyhalov /* 277*91e1e26aSAlexander Pyhalov * Open; called from iconv_open() 278*91e1e26aSAlexander Pyhalov */ 279*91e1e26aSAlexander Pyhalov void * 280*91e1e26aSAlexander Pyhalov _icv_open() 281*91e1e26aSAlexander Pyhalov { 282*91e1e26aSAlexander Pyhalov _iconv_st *st; 283*91e1e26aSAlexander Pyhalov 284*91e1e26aSAlexander Pyhalov if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) { 285*91e1e26aSAlexander Pyhalov errno = ENOMEM; 286*91e1e26aSAlexander Pyhalov return ((void*)-1); 287*91e1e26aSAlexander Pyhalov } 288*91e1e26aSAlexander Pyhalov 289*91e1e26aSAlexander Pyhalov bzero(st, sizeof(_iconv_st)); 290*91e1e26aSAlexander Pyhalov st->keepc[0] = DEV_ATR; 291*91e1e26aSAlexander Pyhalov st->pState = S_BASIC; 292*91e1e26aSAlexander Pyhalov 293*91e1e26aSAlexander Pyhalov return ((void*)st); 294*91e1e26aSAlexander Pyhalov } 295*91e1e26aSAlexander Pyhalov 296*91e1e26aSAlexander Pyhalov /* 297*91e1e26aSAlexander Pyhalov * Close; called from iconv_close() 298*91e1e26aSAlexander Pyhalov */ 299*91e1e26aSAlexander Pyhalov void 300*91e1e26aSAlexander Pyhalov _icv_close(_iconv_st *st) 301*91e1e26aSAlexander Pyhalov { 302*91e1e26aSAlexander Pyhalov if (!st) 303*91e1e26aSAlexander Pyhalov errno = EBADF; 304*91e1e26aSAlexander Pyhalov else 305*91e1e26aSAlexander Pyhalov free(st); 306*91e1e26aSAlexander Pyhalov } 307*91e1e26aSAlexander Pyhalov 308*91e1e26aSAlexander Pyhalov /* 309*91e1e26aSAlexander Pyhalov * Conversion routine; called from iconv() 310*91e1e26aSAlexander Pyhalov */ 311*91e1e26aSAlexander Pyhalov size_t 312*91e1e26aSAlexander Pyhalov _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, 313*91e1e26aSAlexander Pyhalov char **outbuf, size_t *outbytesleft) 314*91e1e26aSAlexander Pyhalov { 315*91e1e26aSAlexander Pyhalov int n; 316*91e1e26aSAlexander Pyhalov short curState; 317*91e1e26aSAlexander Pyhalov 318*91e1e26aSAlexander Pyhalov if (st == NULL) { 319*91e1e26aSAlexander Pyhalov errno = EBADF; 320*91e1e26aSAlexander Pyhalov return ((size_t) -1); 321*91e1e26aSAlexander Pyhalov } 322*91e1e26aSAlexander Pyhalov 323*91e1e26aSAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request */ 324*91e1e26aSAlexander Pyhalov st->keepc[0] = DEV_ATR; 325*91e1e26aSAlexander Pyhalov st->pState = S_BASIC; 326*91e1e26aSAlexander Pyhalov st->_errno = 0; 327*91e1e26aSAlexander Pyhalov return ((size_t)0); 328*91e1e26aSAlexander Pyhalov } 329*91e1e26aSAlexander Pyhalov 330*91e1e26aSAlexander Pyhalov /* flush if possible */ 331*91e1e26aSAlexander Pyhalov if ( st->_errno == E2BIG ) { 332*91e1e26aSAlexander Pyhalov n = iscii_to_utf8(st, *outbuf, *outbytesleft); 333*91e1e26aSAlexander Pyhalov (*outbuf) += n; 334*91e1e26aSAlexander Pyhalov (*outbytesleft) -= n; 335*91e1e26aSAlexander Pyhalov } 336*91e1e26aSAlexander Pyhalov 337*91e1e26aSAlexander Pyhalov st->_errno = errno = 0; /* reset internal and external errno */ 338*91e1e26aSAlexander Pyhalov 339*91e1e26aSAlexander Pyhalov /* a state machine for interpreting ISCII code */ 340*91e1e26aSAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) { 341*91e1e26aSAlexander Pyhalov unsigned int curChar = (unsigned int)(**inbuf & ONEBYTE); 342*91e1e26aSAlexander Pyhalov unsigned int prevChar = (unsigned int)(st->keepc[1] & ONEBYTE); 343*91e1e26aSAlexander Pyhalov 344*91e1e26aSAlexander Pyhalov if (curChar == ISC_ext) 345*91e1e26aSAlexander Pyhalov curState = S_EXT; 346*91e1e26aSAlexander Pyhalov else if (curChar == ISC_atr) 347*91e1e26aSAlexander Pyhalov curState = S_ATR; 348*91e1e26aSAlexander Pyhalov else 349*91e1e26aSAlexander Pyhalov curState = S_BASIC; 350*91e1e26aSAlexander Pyhalov 351*91e1e26aSAlexander Pyhalov switch (curState) { 352*91e1e26aSAlexander Pyhalov case S_BASIC: 353*91e1e26aSAlexander Pyhalov if (prevChar == 0) 354*91e1e26aSAlexander Pyhalov st->keepc[1] = curChar; 355*91e1e26aSAlexander Pyhalov else 356*91e1e26aSAlexander Pyhalov st->keepc[2] = curChar; 357*91e1e26aSAlexander Pyhalov 358*91e1e26aSAlexander Pyhalov if (st->pState == S_ATR) { 359*91e1e26aSAlexander Pyhalov /* clear the keepc[1], which is part of attribute */ 360*91e1e26aSAlexander Pyhalov st->keepc[1] = 0; 361*91e1e26aSAlexander Pyhalov /* change the attribute for Indian Script Fonts */ 362*91e1e26aSAlexander Pyhalov if ((curChar >= 0x42) && (curChar <= 0x4b) && curChar != 0x46) { 363*91e1e26aSAlexander Pyhalov st->keepc[0] = curChar; 364*91e1e26aSAlexander Pyhalov } 365*91e1e26aSAlexander Pyhalov /* other attributes such as display attributes would be ignored */ 366*91e1e26aSAlexander Pyhalov } else { /* Handle Cases and Flush */ 367*91e1e26aSAlexander Pyhalov 368*91e1e26aSAlexander Pyhalov if ((curChar > 0 && curChar <= 0x7f) || prevChar != 0) { 369*91e1e26aSAlexander Pyhalov n=iscii_to_utf8(st, *outbuf, *outbytesleft); 370*91e1e26aSAlexander Pyhalov if (n > 0) { 371*91e1e26aSAlexander Pyhalov (*outbuf) += n; 372*91e1e26aSAlexander Pyhalov (*outbytesleft) -= n; 373*91e1e26aSAlexander Pyhalov } else /* don't return immediately, need advance the *inbuf */ 374*91e1e26aSAlexander Pyhalov st->_errno = errno; 375*91e1e26aSAlexander Pyhalov } 376*91e1e26aSAlexander Pyhalov } 377*91e1e26aSAlexander Pyhalov break; 378*91e1e26aSAlexander Pyhalov case S_ATR: 379*91e1e26aSAlexander Pyhalov case S_EXT: /* Do nothing */ 380*91e1e26aSAlexander Pyhalov if (st->pState == S_BASIC) { /* Flush */ 381*91e1e26aSAlexander Pyhalov if ( st->keepc[1] == 0 ) 382*91e1e26aSAlexander Pyhalov { 383*91e1e26aSAlexander Pyhalov if (curState == S_EXT) st->keepc[1] = ISC_ext; 384*91e1e26aSAlexander Pyhalov break; 385*91e1e26aSAlexander Pyhalov } 386*91e1e26aSAlexander Pyhalov n = iscii_to_utf8(st, *outbuf, *outbytesleft); 387*91e1e26aSAlexander Pyhalov if (n > 0) { 388*91e1e26aSAlexander Pyhalov (*outbuf) += n; 389*91e1e26aSAlexander Pyhalov (*outbytesleft) -= n; 390*91e1e26aSAlexander Pyhalov } else /* don't return immediately */ 391*91e1e26aSAlexander Pyhalov st->_errno = errno; 392*91e1e26aSAlexander Pyhalov 393*91e1e26aSAlexander Pyhalov if (curState == S_EXT) st->keepc[1] = ISC_ext; 394*91e1e26aSAlexander Pyhalov } else { 395*91e1e26aSAlexander Pyhalov errno = EILSEQ; 396*91e1e26aSAlexander Pyhalov return (size_t)-1; 397*91e1e26aSAlexander Pyhalov } 398*91e1e26aSAlexander Pyhalov 399*91e1e26aSAlexander Pyhalov break; 400*91e1e26aSAlexander Pyhalov default: /* should never come here */ 401*91e1e26aSAlexander Pyhalov st->_errno = errno = EILSEQ; 402*91e1e26aSAlexander Pyhalov st->pState = S_BASIC; /* reset state */ 403*91e1e26aSAlexander Pyhalov break; 404*91e1e26aSAlexander Pyhalov } 405*91e1e26aSAlexander Pyhalov 406*91e1e26aSAlexander Pyhalov st->pState = curState; 407*91e1e26aSAlexander Pyhalov 408*91e1e26aSAlexander Pyhalov (*inbuf)++; 409*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 410*91e1e26aSAlexander Pyhalov 411*91e1e26aSAlexander Pyhalov if (errno) 412*91e1e26aSAlexander Pyhalov return(size_t)-1; 413*91e1e26aSAlexander Pyhalov } 414*91e1e26aSAlexander Pyhalov 415*91e1e26aSAlexander Pyhalov if (*inbytesleft > 0 && *outbytesleft == 0) { 416*91e1e26aSAlexander Pyhalov /* in this case, the st->_errno is zero */ 417*91e1e26aSAlexander Pyhalov errno = E2BIG; 418*91e1e26aSAlexander Pyhalov return(size_t)-1; 419*91e1e26aSAlexander Pyhalov } 420*91e1e26aSAlexander Pyhalov 421*91e1e26aSAlexander Pyhalov return (size_t)(*inbytesleft); 422*91e1e26aSAlexander Pyhalov } 423