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 #include <stdio.h> 26*91e1e26aSAlexander Pyhalov #include <errno.h> 27*91e1e26aSAlexander Pyhalov #include <stdlib.h> 28*91e1e26aSAlexander Pyhalov #include <strings.h> 29*91e1e26aSAlexander Pyhalov #include <sys/types.h> 30*91e1e26aSAlexander Pyhalov #include "iscii.h" 31*91e1e26aSAlexander Pyhalov #include "common_defs.h" 32*91e1e26aSAlexander Pyhalov 33*91e1e26aSAlexander Pyhalov #define MSB 0x80 /* most significant bit */ 34*91e1e26aSAlexander Pyhalov #define ONEBYTE 0xff /* right most byte */ 35*91e1e26aSAlexander Pyhalov 36*91e1e26aSAlexander Pyhalov #define REPLACE_CHAR '?' 37*91e1e26aSAlexander Pyhalov 38*91e1e26aSAlexander Pyhalov #define utf8_len(Ch) (Ch < 0x80 ? 1 : (Ch < 0xe0 ? 2 : (Ch < 0xf0 ? 3 : (Ch < 0xf8 ? 4 : (Ch < 0xfc ? 5 : 6))))) 39*91e1e26aSAlexander Pyhalov 40*91e1e26aSAlexander Pyhalov #define analyze_utf8(Ch, Mask, nBytes) \ 41*91e1e26aSAlexander Pyhalov if (Ch < 128) { \ 42*91e1e26aSAlexander Pyhalov nBytes = 1; \ 43*91e1e26aSAlexander Pyhalov Mask = 0x7f; \ 44*91e1e26aSAlexander Pyhalov } else if ((Ch & 0xe0) == 0xc0) { \ 45*91e1e26aSAlexander Pyhalov nBytes = 2; \ 46*91e1e26aSAlexander Pyhalov Mask = 0x1f; \ 47*91e1e26aSAlexander Pyhalov } else if ((Ch & 0xf0) == 0xe0) { \ 48*91e1e26aSAlexander Pyhalov nBytes = 3; \ 49*91e1e26aSAlexander Pyhalov Mask = 0x0f; \ 50*91e1e26aSAlexander Pyhalov } else if ((Ch & 0xf8) == 0xf0) { \ 51*91e1e26aSAlexander Pyhalov nBytes = 4; \ 52*91e1e26aSAlexander Pyhalov Mask = 0x07; \ 53*91e1e26aSAlexander Pyhalov } else if ((Ch & 0xfc) == 0xf8) { \ 54*91e1e26aSAlexander Pyhalov nBytes = 5; \ 55*91e1e26aSAlexander Pyhalov Mask = 0x03; \ 56*91e1e26aSAlexander Pyhalov } else if ((Ch & 0xfe) == 0xfc) { \ 57*91e1e26aSAlexander Pyhalov nBytes = 6; \ 58*91e1e26aSAlexander Pyhalov Mask = 0x01; \ 59*91e1e26aSAlexander Pyhalov } else \ 60*91e1e26aSAlexander Pyhalov nBytes = -1; 61*91e1e26aSAlexander Pyhalov 62*91e1e26aSAlexander Pyhalov #define ucs2_from_utf8(mUCS, Ch, Ct, Mask, Len) \ 63*91e1e26aSAlexander Pyhalov (mUCS) = (Ch)[0] & (Mask); \ 64*91e1e26aSAlexander Pyhalov for ((Ct) = 1; (Ct) < (Len); ++(Ct)) { \ 65*91e1e26aSAlexander Pyhalov if ( ( (Ch)[(Ct)] & 0xc0) != 0x80) { \ 66*91e1e26aSAlexander Pyhalov (mUCS) = -1; \ 67*91e1e26aSAlexander Pyhalov break; \ 68*91e1e26aSAlexander Pyhalov } \ 69*91e1e26aSAlexander Pyhalov (mUCS) <<= 6; \ 70*91e1e26aSAlexander Pyhalov (mUCS) |= ((Ch)[(Ct)] & 0x3f); \ 71*91e1e26aSAlexander Pyhalov } \ 72*91e1e26aSAlexander Pyhalov 73*91e1e26aSAlexander Pyhalov 74*91e1e26aSAlexander Pyhalov typedef struct _icv_state { 75*91e1e26aSAlexander Pyhalov char aATR; 76*91e1e26aSAlexander Pyhalov uchar_t keepc[4]; 77*91e1e26aSAlexander Pyhalov int halant_context; /* preceded by the Halant character or not */ 78*91e1e26aSAlexander Pyhalov int _ustate; 79*91e1e26aSAlexander Pyhalov int _errno; 80*91e1e26aSAlexander Pyhalov } _iconv_st; 81*91e1e26aSAlexander Pyhalov 82*91e1e26aSAlexander Pyhalov enum _CSTATE { U0, U1, U2, U3, U4, U5, U6 }; 83*91e1e26aSAlexander Pyhalov 84*91e1e26aSAlexander Pyhalov /* 85*91e1e26aSAlexander Pyhalov * Open; called from iconv_open() 86*91e1e26aSAlexander Pyhalov */ 87*91e1e26aSAlexander Pyhalov void * 88*91e1e26aSAlexander Pyhalov _icv_open() 89*91e1e26aSAlexander Pyhalov { 90*91e1e26aSAlexander Pyhalov _iconv_st *st; 91*91e1e26aSAlexander Pyhalov 92*91e1e26aSAlexander Pyhalov if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) { 93*91e1e26aSAlexander Pyhalov errno = ENOMEM; 94*91e1e26aSAlexander Pyhalov return ((void*)-1); 95*91e1e26aSAlexander Pyhalov } 96*91e1e26aSAlexander Pyhalov 97*91e1e26aSAlexander Pyhalov bzero(st, sizeof(_iconv_st)); 98*91e1e26aSAlexander Pyhalov st->aATR = 0x42; /* Devanagiri */ 99*91e1e26aSAlexander Pyhalov 100*91e1e26aSAlexander Pyhalov return ((void*)st); 101*91e1e26aSAlexander Pyhalov } 102*91e1e26aSAlexander Pyhalov 103*91e1e26aSAlexander Pyhalov typedef enum { t_NONE, t_NUKTA, t_EXT, t_HALANT, t_DOUBLE_DANDA } Type; 104*91e1e26aSAlexander Pyhalov 105*91e1e26aSAlexander Pyhalov static int 106*91e1e26aSAlexander Pyhalov traverse_table(Entry *entry, int num, ucs_t ucs, Type *type) 107*91e1e26aSAlexander Pyhalov { 108*91e1e26aSAlexander Pyhalov int i=0; 109*91e1e26aSAlexander Pyhalov int retc=0; 110*91e1e26aSAlexander Pyhalov 111*91e1e26aSAlexander Pyhalov *type = t_NONE; 112*91e1e26aSAlexander Pyhalov 113*91e1e26aSAlexander Pyhalov for ( ; i < num; ++i ) { 114*91e1e26aSAlexander Pyhalov Entry en = entry[i]; 115*91e1e26aSAlexander Pyhalov 116*91e1e26aSAlexander Pyhalov if (en.count == NUKTA || en.count == EXT || en.count == HALANT || en.count == DOUBLE_DANDA) { 117*91e1e26aSAlexander Pyhalov if ( ucs < en.ucs ) break; 118*91e1e26aSAlexander Pyhalov if ( ucs == en.ucs ) { /* found */ 119*91e1e26aSAlexander Pyhalov if ( en.count == NUKTA ) *type = t_NUKTA; 120*91e1e26aSAlexander Pyhalov if ( en.count == EXT ) *type = t_EXT; 121*91e1e26aSAlexander Pyhalov if ( en.count == HALANT ) *type = t_HALANT; 122*91e1e26aSAlexander Pyhalov if ( en.count == DOUBLE_DANDA ) *type = t_DOUBLE_DANDA; 123*91e1e26aSAlexander Pyhalov retc = en.iscii; 124*91e1e26aSAlexander Pyhalov break; 125*91e1e26aSAlexander Pyhalov } 126*91e1e26aSAlexander Pyhalov } else { 127*91e1e26aSAlexander Pyhalov if ( ucs < en.ucs ) break; 128*91e1e26aSAlexander Pyhalov if ( ucs >= en.ucs && ucs < en.ucs + en.count ) { 129*91e1e26aSAlexander Pyhalov retc = en.iscii + ( ucs - en.ucs ); 130*91e1e26aSAlexander Pyhalov break; 131*91e1e26aSAlexander Pyhalov } 132*91e1e26aSAlexander Pyhalov } 133*91e1e26aSAlexander Pyhalov } 134*91e1e26aSAlexander Pyhalov 135*91e1e26aSAlexander Pyhalov return retc; 136*91e1e26aSAlexander Pyhalov } 137*91e1e26aSAlexander Pyhalov 138*91e1e26aSAlexander Pyhalov static int 139*91e1e26aSAlexander Pyhalov ucs_to_iscii(ucs_t uiid, char **outbuf, size_t *outbytesleft, int isc_type, int *halant_context) 140*91e1e26aSAlexander Pyhalov { 141*91e1e26aSAlexander Pyhalov int nBytesRet = 0 ; 142*91e1e26aSAlexander Pyhalov Type type = t_NONE; 143*91e1e26aSAlexander Pyhalov int iscii; 144*91e1e26aSAlexander Pyhalov Entries en = unicode_table[isc_type]; 145*91e1e26aSAlexander Pyhalov 146*91e1e26aSAlexander Pyhalov if ( *outbytesleft == 0 ) { 147*91e1e26aSAlexander Pyhalov errno = E2BIG; 148*91e1e26aSAlexander Pyhalov return 0; 149*91e1e26aSAlexander Pyhalov } 150*91e1e26aSAlexander Pyhalov 151*91e1e26aSAlexander Pyhalov iscii = traverse_table(en.entry, en.items, uiid, &type); 152*91e1e26aSAlexander Pyhalov if ( iscii == 0 ) { 153*91e1e26aSAlexander Pyhalov **outbuf = REPLACE_CHAR; 154*91e1e26aSAlexander Pyhalov nBytesRet ++; 155*91e1e26aSAlexander Pyhalov } else { 156*91e1e26aSAlexander Pyhalov if ( type != t_NONE ) { 157*91e1e26aSAlexander Pyhalov 158*91e1e26aSAlexander Pyhalov /* buggy code */ 159*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 2 ) { 160*91e1e26aSAlexander Pyhalov errno = E2BIG; 161*91e1e26aSAlexander Pyhalov return 0; 162*91e1e26aSAlexander Pyhalov } 163*91e1e26aSAlexander Pyhalov 164*91e1e26aSAlexander Pyhalov switch (type) 165*91e1e26aSAlexander Pyhalov { 166*91e1e26aSAlexander Pyhalov case t_NUKTA: 167*91e1e26aSAlexander Pyhalov **outbuf = (uchar_t) iscii; 168*91e1e26aSAlexander Pyhalov *(*outbuf+1) = ISC_nukta; 169*91e1e26aSAlexander Pyhalov nBytesRet = 2; 170*91e1e26aSAlexander Pyhalov 171*91e1e26aSAlexander Pyhalov break; 172*91e1e26aSAlexander Pyhalov case t_EXT: 173*91e1e26aSAlexander Pyhalov **outbuf = ISC_ext; 174*91e1e26aSAlexander Pyhalov *(*outbuf+1) = (uchar_t) iscii; 175*91e1e26aSAlexander Pyhalov nBytesRet = 2; 176*91e1e26aSAlexander Pyhalov 177*91e1e26aSAlexander Pyhalov break; 178*91e1e26aSAlexander Pyhalov case t_HALANT: 179*91e1e26aSAlexander Pyhalov if ( (uiid == UNI_ZWJ || uiid == UNI_ZWNJ) && *halant_context ) 180*91e1e26aSAlexander Pyhalov { 181*91e1e26aSAlexander Pyhalov if ( uiid == UNI_ZWJ ) **outbuf = ISC_nukta; /* soft halant */ 182*91e1e26aSAlexander Pyhalov else **outbuf = ISC_halant; /* explicit halant */ 183*91e1e26aSAlexander Pyhalov 184*91e1e26aSAlexander Pyhalov nBytesRet = 1; 185*91e1e26aSAlexander Pyhalov } /* consume the UNI_ZWNJ or UNI_ZWJ if *halant_context is 0 */ 186*91e1e26aSAlexander Pyhalov 187*91e1e26aSAlexander Pyhalov break; 188*91e1e26aSAlexander Pyhalov case t_DOUBLE_DANDA: 189*91e1e26aSAlexander Pyhalov **outbuf = ISC_danda; 190*91e1e26aSAlexander Pyhalov *(*outbuf+1) = (uchar_t) iscii; 191*91e1e26aSAlexander Pyhalov nBytesRet = 2; 192*91e1e26aSAlexander Pyhalov break; 193*91e1e26aSAlexander Pyhalov case t_NONE: 194*91e1e26aSAlexander Pyhalov /* Not reached */ 195*91e1e26aSAlexander Pyhalov break; 196*91e1e26aSAlexander Pyhalov } 197*91e1e26aSAlexander Pyhalov } else { 198*91e1e26aSAlexander Pyhalov **outbuf = (uchar_t) iscii; 199*91e1e26aSAlexander Pyhalov nBytesRet = 1; 200*91e1e26aSAlexander Pyhalov } 201*91e1e26aSAlexander Pyhalov } 202*91e1e26aSAlexander Pyhalov 203*91e1e26aSAlexander Pyhalov /* if iscii == ISC_halant but type == t_HALANT, set *halant_context to 0 */ 204*91e1e26aSAlexander Pyhalov if ( iscii == ISC_halant && type == t_NONE ) *halant_context = 1; 205*91e1e26aSAlexander Pyhalov else *halant_context = 0; 206*91e1e26aSAlexander Pyhalov 207*91e1e26aSAlexander Pyhalov return nBytesRet; 208*91e1e26aSAlexander Pyhalov } 209*91e1e26aSAlexander Pyhalov 210*91e1e26aSAlexander Pyhalov /* 211*91e1e26aSAlexander Pyhalov * Close; called from iconv_close() 212*91e1e26aSAlexander Pyhalov */ 213*91e1e26aSAlexander Pyhalov void 214*91e1e26aSAlexander Pyhalov _icv_close(_iconv_st *st) 215*91e1e26aSAlexander Pyhalov { 216*91e1e26aSAlexander Pyhalov if (!st) 217*91e1e26aSAlexander Pyhalov errno = EBADF; 218*91e1e26aSAlexander Pyhalov else 219*91e1e26aSAlexander Pyhalov free(st); 220*91e1e26aSAlexander Pyhalov } 221*91e1e26aSAlexander Pyhalov 222*91e1e26aSAlexander Pyhalov /* 223*91e1e26aSAlexander Pyhalov * Conversion routine; called from iconv() 224*91e1e26aSAlexander Pyhalov */ 225*91e1e26aSAlexander Pyhalov size_t 226*91e1e26aSAlexander Pyhalov _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, 227*91e1e26aSAlexander Pyhalov char **outbuf, size_t *outbytesleft) 228*91e1e26aSAlexander Pyhalov { 229*91e1e26aSAlexander Pyhalov int n=0; 230*91e1e26aSAlexander Pyhalov 231*91e1e26aSAlexander Pyhalov if (st == NULL) { 232*91e1e26aSAlexander Pyhalov errno = EBADF; 233*91e1e26aSAlexander Pyhalov return ((size_t) -1); 234*91e1e26aSAlexander Pyhalov } 235*91e1e26aSAlexander Pyhalov 236*91e1e26aSAlexander Pyhalov 237*91e1e26aSAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 238*91e1e26aSAlexander Pyhalov st->aATR = 0x42; /* Devangiri */ 239*91e1e26aSAlexander Pyhalov st->_ustate = U0; 240*91e1e26aSAlexander Pyhalov st->_errno = 0; 241*91e1e26aSAlexander Pyhalov return ((size_t) 0); 242*91e1e26aSAlexander Pyhalov } 243*91e1e26aSAlexander Pyhalov 244*91e1e26aSAlexander Pyhalov st->_errno = errno = 0; 245*91e1e26aSAlexander Pyhalov 246*91e1e26aSAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) { 247*91e1e26aSAlexander Pyhalov 248*91e1e26aSAlexander Pyhalov uchar_t first_byte; 249*91e1e26aSAlexander Pyhalov 250*91e1e26aSAlexander Pyhalov switch ( st->_ustate ) { 251*91e1e26aSAlexander Pyhalov case U0: 252*91e1e26aSAlexander Pyhalov if ((**inbuf & MSB) == 0) { /* ASCII */ 253*91e1e26aSAlexander Pyhalov **outbuf = **inbuf; 254*91e1e26aSAlexander Pyhalov (*outbuf)++; (*outbytesleft)--; 255*91e1e26aSAlexander Pyhalov } else if ((**inbuf & 0xe0) == 0xc0) { /* 0xc2..0xdf */ 256*91e1e26aSAlexander Pyhalov 257*91e1e26aSAlexander Pyhalov /* invalid sequence if the first byte is either 0xc0 or 0xc1 */ 258*91e1e26aSAlexander Pyhalov if ( number_of_bytes_in_utf8_char[((uchar_t) **inbuf)] == ICV_TYPE_ILLEGAL_CHAR ) 259*91e1e26aSAlexander Pyhalov errno = EILSEQ; 260*91e1e26aSAlexander Pyhalov else { 261*91e1e26aSAlexander Pyhalov st->_ustate = U1; 262*91e1e26aSAlexander Pyhalov st->keepc[0] = **inbuf; 263*91e1e26aSAlexander Pyhalov } 264*91e1e26aSAlexander Pyhalov } else if ((**inbuf & 0xf0) == 0xe0) { 265*91e1e26aSAlexander Pyhalov st->_ustate = U2; 266*91e1e26aSAlexander Pyhalov st->keepc[0] = **inbuf; 267*91e1e26aSAlexander Pyhalov } else { 268*91e1e26aSAlexander Pyhalov /* four bytes of UTF-8 sequences */ 269*91e1e26aSAlexander Pyhalov if ( number_of_bytes_in_utf8_char[((uchar_t) **inbuf)] == ICV_TYPE_ILLEGAL_CHAR ) 270*91e1e26aSAlexander Pyhalov errno = EILSEQ; 271*91e1e26aSAlexander Pyhalov else { 272*91e1e26aSAlexander Pyhalov st->_ustate = U4; 273*91e1e26aSAlexander Pyhalov st->keepc[0] = **inbuf; 274*91e1e26aSAlexander Pyhalov } 275*91e1e26aSAlexander Pyhalov } 276*91e1e26aSAlexander Pyhalov break; 277*91e1e26aSAlexander Pyhalov case U1: 278*91e1e26aSAlexander Pyhalov if ((**inbuf & 0xc0) == MSB) { /* U+0080 -- U+07FF */ 279*91e1e26aSAlexander Pyhalov **outbuf = REPLACE_CHAR; 280*91e1e26aSAlexander Pyhalov (*outbuf)++; 281*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 282*91e1e26aSAlexander Pyhalov st->_ustate = U0; 283*91e1e26aSAlexander Pyhalov } else { 284*91e1e26aSAlexander Pyhalov errno = EILSEQ; 285*91e1e26aSAlexander Pyhalov } 286*91e1e26aSAlexander Pyhalov break; 287*91e1e26aSAlexander Pyhalov case U2: 288*91e1e26aSAlexander Pyhalov 289*91e1e26aSAlexander Pyhalov first_byte = st->keepc[0]; 290*91e1e26aSAlexander Pyhalov 291*91e1e26aSAlexander Pyhalov /* if the first byte is 0xed, it is illegal sequence if the second 292*91e1e26aSAlexander Pyhalov * one is between 0xa0 and 0xbf because surrogate section is ill-formed 293*91e1e26aSAlexander Pyhalov */ 294*91e1e26aSAlexander Pyhalov if (((uchar_t) **inbuf) < valid_min_2nd_byte[first_byte] || 295*91e1e26aSAlexander Pyhalov ((uchar_t) **inbuf) > valid_max_2nd_byte[first_byte] ) 296*91e1e26aSAlexander Pyhalov errno = EILSEQ; 297*91e1e26aSAlexander Pyhalov else { 298*91e1e26aSAlexander Pyhalov st->_ustate = U3; 299*91e1e26aSAlexander Pyhalov st->keepc[1] = **inbuf; 300*91e1e26aSAlexander Pyhalov } 301*91e1e26aSAlexander Pyhalov break; 302*91e1e26aSAlexander Pyhalov case U3: 303*91e1e26aSAlexander Pyhalov if ((**inbuf & 0xc0) == MSB) { 304*91e1e26aSAlexander Pyhalov unsigned char mChar = st->keepc[0]; 305*91e1e26aSAlexander Pyhalov ucs_t ucsid = 0; 306*91e1e26aSAlexander Pyhalov int i=0, mask=0, len=0; 307*91e1e26aSAlexander Pyhalov ISCII isc_type; 308*91e1e26aSAlexander Pyhalov 309*91e1e26aSAlexander Pyhalov st->keepc[2] = **inbuf; 310*91e1e26aSAlexander Pyhalov 311*91e1e26aSAlexander Pyhalov analyze_utf8(mChar, mask, len); 312*91e1e26aSAlexander Pyhalov 313*91e1e26aSAlexander Pyhalov ucs2_from_utf8(ucsid, (char *)&st->keepc[0], i, mask, len); 314*91e1e26aSAlexander Pyhalov 315*91e1e26aSAlexander Pyhalov /* 0xfffe and 0xffff should not be allowed */ 316*91e1e26aSAlexander Pyhalov if ( ucsid == 0xFFFE || ucsid == 0xFFFF ) 317*91e1e26aSAlexander Pyhalov { 318*91e1e26aSAlexander Pyhalov errno = EILSEQ; 319*91e1e26aSAlexander Pyhalov break; 320*91e1e26aSAlexander Pyhalov } 321*91e1e26aSAlexander Pyhalov 322*91e1e26aSAlexander Pyhalov get_script_types(ucsid, isc_type); 323*91e1e26aSAlexander Pyhalov if ( isc_type != NUM_ISCII && st->aATR != aTRs[isc_type] ) { 324*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 2 ) { 325*91e1e26aSAlexander Pyhalov errno = E2BIG; 326*91e1e26aSAlexander Pyhalov return (size_t)-1; 327*91e1e26aSAlexander Pyhalov } 328*91e1e26aSAlexander Pyhalov 329*91e1e26aSAlexander Pyhalov **outbuf = (uchar_t)ISC_atr; 330*91e1e26aSAlexander Pyhalov (*outbuf)++; 331*91e1e26aSAlexander Pyhalov **outbuf = aTRs[isc_type]; 332*91e1e26aSAlexander Pyhalov (*outbuf)++; 333*91e1e26aSAlexander Pyhalov (*outbytesleft)-=2; 334*91e1e26aSAlexander Pyhalov st->aATR = aTRs[isc_type]; 335*91e1e26aSAlexander Pyhalov } 336*91e1e26aSAlexander Pyhalov 337*91e1e26aSAlexander Pyhalov /* UNI_INV, UNI_ZWJ, UNI_ZWNJ would occur within any India Script as 338*91e1e26aSAlexander Pyhalov Consonant invisible, explicit halant and soft halant */ 339*91e1e26aSAlexander Pyhalov if ( ucsid == UNI_INV || ucsid == UNI_ZWNJ || ucsid == UNI_ZWJ ) 340*91e1e26aSAlexander Pyhalov isc_type = isc_TYPE[ st->aATR - 0x42 ]; 341*91e1e26aSAlexander Pyhalov 342*91e1e26aSAlexander Pyhalov if ( isc_type == NUM_ISCII ) { 343*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 1 ) { 344*91e1e26aSAlexander Pyhalov errno = E2BIG; 345*91e1e26aSAlexander Pyhalov return (size_t)-1; 346*91e1e26aSAlexander Pyhalov } 347*91e1e26aSAlexander Pyhalov 348*91e1e26aSAlexander Pyhalov **outbuf = REPLACE_CHAR; 349*91e1e26aSAlexander Pyhalov (*outbuf)++; 350*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 351*91e1e26aSAlexander Pyhalov } else { 352*91e1e26aSAlexander Pyhalov n = ucs_to_iscii(ucsid, outbuf, outbytesleft, isc_type, &st->halant_context); 353*91e1e26aSAlexander Pyhalov if ( n > 0 ) { 354*91e1e26aSAlexander Pyhalov (*outbuf) += n; 355*91e1e26aSAlexander Pyhalov (*outbytesleft) -= n; 356*91e1e26aSAlexander Pyhalov } else if ( errno == E2BIG ) { 357*91e1e26aSAlexander Pyhalov /* n == 0 if the ZWJ or ZWNJ has been consumed without error */ 358*91e1e26aSAlexander Pyhalov st->_errno = errno; 359*91e1e26aSAlexander Pyhalov errno = E2BIG; 360*91e1e26aSAlexander Pyhalov return (size_t)-1; 361*91e1e26aSAlexander Pyhalov } 362*91e1e26aSAlexander Pyhalov } 363*91e1e26aSAlexander Pyhalov } else { 364*91e1e26aSAlexander Pyhalov errno = EILSEQ; 365*91e1e26aSAlexander Pyhalov return (size_t)-1; 366*91e1e26aSAlexander Pyhalov } 367*91e1e26aSAlexander Pyhalov st->_ustate = U0; 368*91e1e26aSAlexander Pyhalov break; 369*91e1e26aSAlexander Pyhalov case U4: 370*91e1e26aSAlexander Pyhalov 371*91e1e26aSAlexander Pyhalov first_byte = st->keepc[0]; 372*91e1e26aSAlexander Pyhalov 373*91e1e26aSAlexander Pyhalov /* if the first byte is 0xf0, it is illegal sequence if 374*91e1e26aSAlexander Pyhalov * the second one is between 0x80 and 0x8f 375*91e1e26aSAlexander Pyhalov * for Four-Byte UTF: U+10000..U+10FFFF 376*91e1e26aSAlexander Pyhalov */ 377*91e1e26aSAlexander Pyhalov if (((uchar_t) **inbuf) < valid_min_2nd_byte[first_byte] || 378*91e1e26aSAlexander Pyhalov ((uchar_t) **inbuf) > valid_max_2nd_byte[first_byte] ) 379*91e1e26aSAlexander Pyhalov errno = EILSEQ; 380*91e1e26aSAlexander Pyhalov else { 381*91e1e26aSAlexander Pyhalov st->_ustate = U5; 382*91e1e26aSAlexander Pyhalov st->keepc[1] = **inbuf; 383*91e1e26aSAlexander Pyhalov } 384*91e1e26aSAlexander Pyhalov break; 385*91e1e26aSAlexander Pyhalov case U5: 386*91e1e26aSAlexander Pyhalov if ((**inbuf & 0xc0) == MSB) /* 0x80..0xbf */ 387*91e1e26aSAlexander Pyhalov { 388*91e1e26aSAlexander Pyhalov st->_ustate = U6; 389*91e1e26aSAlexander Pyhalov st->keepc[2] = **inbuf; 390*91e1e26aSAlexander Pyhalov } 391*91e1e26aSAlexander Pyhalov else 392*91e1e26aSAlexander Pyhalov errno = EILSEQ; 393*91e1e26aSAlexander Pyhalov break; 394*91e1e26aSAlexander Pyhalov case U6: 395*91e1e26aSAlexander Pyhalov if ((**inbuf & 0xc0) == MSB) /* 0x80..0xbf */ 396*91e1e26aSAlexander Pyhalov { 397*91e1e26aSAlexander Pyhalov st->keepc[3] = **inbuf; 398*91e1e26aSAlexander Pyhalov st->_ustate = U0; 399*91e1e26aSAlexander Pyhalov 400*91e1e26aSAlexander Pyhalov /* replace with REPLACE_CHAR */ 401*91e1e26aSAlexander Pyhalov **outbuf = REPLACE_CHAR; 402*91e1e26aSAlexander Pyhalov (*outbuf)++; 403*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 404*91e1e26aSAlexander Pyhalov } 405*91e1e26aSAlexander Pyhalov else 406*91e1e26aSAlexander Pyhalov errno = EILSEQ; 407*91e1e26aSAlexander Pyhalov break; 408*91e1e26aSAlexander Pyhalov } 409*91e1e26aSAlexander Pyhalov 410*91e1e26aSAlexander Pyhalov if (errno) 411*91e1e26aSAlexander Pyhalov break; 412*91e1e26aSAlexander Pyhalov 413*91e1e26aSAlexander Pyhalov (*inbuf)++; 414*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 415*91e1e26aSAlexander Pyhalov } /* end of while loop */ 416*91e1e26aSAlexander Pyhalov 417*91e1e26aSAlexander Pyhalov if (errno) return (size_t) -1; 418*91e1e26aSAlexander Pyhalov 419*91e1e26aSAlexander Pyhalov if (*inbytesleft == 0 && st->_ustate != U0) { 420*91e1e26aSAlexander Pyhalov errno = EINVAL; 421*91e1e26aSAlexander Pyhalov return (size_t)-1; 422*91e1e26aSAlexander Pyhalov } 423*91e1e26aSAlexander Pyhalov 424*91e1e26aSAlexander Pyhalov if (*inbytesleft > 0 && *outbytesleft == 0) { 425*91e1e26aSAlexander Pyhalov errno = E2BIG; 426*91e1e26aSAlexander Pyhalov return((size_t)-1); 427*91e1e26aSAlexander Pyhalov } 428*91e1e26aSAlexander Pyhalov 429*91e1e26aSAlexander Pyhalov return (size_t)(*inbytesleft); 430*91e1e26aSAlexander Pyhalov } 431