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 <ctype.h> 28*91e1e26aSAlexander Pyhalov #include <strings.h> 29*91e1e26aSAlexander Pyhalov #include <stdlib.h> 30*91e1e26aSAlexander Pyhalov #include "ea-iscii.h" 31*91e1e26aSAlexander Pyhalov 32*91e1e26aSAlexander Pyhalov #define MSB 0x80 33*91e1e26aSAlexander Pyhalov #define REPLACE_CHAR '?' 34*91e1e26aSAlexander Pyhalov 35*91e1e26aSAlexander Pyhalov typedef enum { SPACE, ASCII, ISCII } CONTEXT; 36*91e1e26aSAlexander Pyhalov 37*91e1e26aSAlexander Pyhalov typedef struct _icv_state { 38*91e1e26aSAlexander Pyhalov CONTEXT context; 39*91e1e26aSAlexander Pyhalov } _iconv_st; 40*91e1e26aSAlexander Pyhalov 41*91e1e26aSAlexander Pyhalov static uchar 42*91e1e26aSAlexander Pyhalov traverse_table(Entry *entry , int num, uchar iscii, uchar *type) 43*91e1e26aSAlexander Pyhalov { 44*91e1e26aSAlexander Pyhalov int i = 0; 45*91e1e26aSAlexander Pyhalov uchar ea_iscii=0; 46*91e1e26aSAlexander Pyhalov 47*91e1e26aSAlexander Pyhalov *type = 0; 48*91e1e26aSAlexander Pyhalov 49*91e1e26aSAlexander Pyhalov for ( ; i < num; ++i) { 50*91e1e26aSAlexander Pyhalov Entry en = entry[i]; 51*91e1e26aSAlexander Pyhalov 52*91e1e26aSAlexander Pyhalov if ( iscii < en.iscii ) break; 53*91e1e26aSAlexander Pyhalov 54*91e1e26aSAlexander Pyhalov if ( en.count == NUKTA || en.count == MATRA || en.count == 55*91e1e26aSAlexander Pyhalov COMBINED_MATRA_NUKTA ) { 56*91e1e26aSAlexander Pyhalov if ( iscii == en.iscii ) { 57*91e1e26aSAlexander Pyhalov *type = en.count; 58*91e1e26aSAlexander Pyhalov ea_iscii = en.ea_iscii; 59*91e1e26aSAlexander Pyhalov break; 60*91e1e26aSAlexander Pyhalov } 61*91e1e26aSAlexander Pyhalov } else { 62*91e1e26aSAlexander Pyhalov if ( iscii >= en.iscii && iscii < en.iscii + en.count ) { 63*91e1e26aSAlexander Pyhalov ea_iscii = (iscii - en.iscii) + en.ea_iscii; 64*91e1e26aSAlexander Pyhalov break; 65*91e1e26aSAlexander Pyhalov } 66*91e1e26aSAlexander Pyhalov } 67*91e1e26aSAlexander Pyhalov } 68*91e1e26aSAlexander Pyhalov 69*91e1e26aSAlexander Pyhalov return ea_iscii; 70*91e1e26aSAlexander Pyhalov } 71*91e1e26aSAlexander Pyhalov 72*91e1e26aSAlexander Pyhalov void * 73*91e1e26aSAlexander Pyhalov _icv_open() 74*91e1e26aSAlexander Pyhalov { 75*91e1e26aSAlexander Pyhalov _iconv_st *st; 76*91e1e26aSAlexander Pyhalov 77*91e1e26aSAlexander Pyhalov if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) { 78*91e1e26aSAlexander Pyhalov errno = ENOMEM; 79*91e1e26aSAlexander Pyhalov return ((void*)-1); 80*91e1e26aSAlexander Pyhalov } 81*91e1e26aSAlexander Pyhalov 82*91e1e26aSAlexander Pyhalov bzero(st, sizeof(_iconv_st)); 83*91e1e26aSAlexander Pyhalov 84*91e1e26aSAlexander Pyhalov return ((void*)st); 85*91e1e26aSAlexander Pyhalov } 86*91e1e26aSAlexander Pyhalov 87*91e1e26aSAlexander Pyhalov /* 88*91e1e26aSAlexander Pyhalov * Close; called from iconv_close() 89*91e1e26aSAlexander Pyhalov */ 90*91e1e26aSAlexander Pyhalov void 91*91e1e26aSAlexander Pyhalov _icv_close(_iconv_st *st) 92*91e1e26aSAlexander Pyhalov { 93*91e1e26aSAlexander Pyhalov if (!st) 94*91e1e26aSAlexander Pyhalov errno = EBADF; 95*91e1e26aSAlexander Pyhalov else 96*91e1e26aSAlexander Pyhalov free(st); 97*91e1e26aSAlexander Pyhalov } 98*91e1e26aSAlexander Pyhalov 99*91e1e26aSAlexander Pyhalov size_t 100*91e1e26aSAlexander Pyhalov _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, 101*91e1e26aSAlexander Pyhalov char **outbuf, size_t *outbytesleft) 102*91e1e26aSAlexander Pyhalov { 103*91e1e26aSAlexander Pyhalov if (st == NULL) { 104*91e1e26aSAlexander Pyhalov errno = EBADF; 105*91e1e26aSAlexander Pyhalov return ((size_t) -1); 106*91e1e26aSAlexander Pyhalov } 107*91e1e26aSAlexander Pyhalov 108*91e1e26aSAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 109*91e1e26aSAlexander Pyhalov return ((size_t)0); 110*91e1e26aSAlexander Pyhalov } 111*91e1e26aSAlexander Pyhalov 112*91e1e26aSAlexander Pyhalov /* a state machine for interpreting ISCII code */ 113*91e1e26aSAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) { 114*91e1e26aSAlexander Pyhalov uchar c = (uchar)**inbuf; 115*91e1e26aSAlexander Pyhalov 116*91e1e26aSAlexander Pyhalov if ( c & MSB ) { 117*91e1e26aSAlexander Pyhalov 118*91e1e26aSAlexander Pyhalov uchar type, ea_iscii; 119*91e1e26aSAlexander Pyhalov 120*91e1e26aSAlexander Pyhalov if ( st->context != ISCII ) { 121*91e1e26aSAlexander Pyhalov 122*91e1e26aSAlexander Pyhalov if ( st->context != SPACE ) { 123*91e1e26aSAlexander Pyhalov /* force to insert ' ' between ASCII and ISCII */ 124*91e1e26aSAlexander Pyhalov **outbuf = 0x20; 125*91e1e26aSAlexander Pyhalov (*outbuf)++; 126*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 127*91e1e26aSAlexander Pyhalov st->context = SPACE; 128*91e1e26aSAlexander Pyhalov } 129*91e1e26aSAlexander Pyhalov 130*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 1 ) { 131*91e1e26aSAlexander Pyhalov errno = E2BIG; 132*91e1e26aSAlexander Pyhalov /* don't advance */ 133*91e1e26aSAlexander Pyhalov return (size_t)-1; 134*91e1e26aSAlexander Pyhalov } 135*91e1e26aSAlexander Pyhalov 136*91e1e26aSAlexander Pyhalov st->context = ISCII; 137*91e1e26aSAlexander Pyhalov **outbuf = LEADING_BYTE; 138*91e1e26aSAlexander Pyhalov (*outbuf)++; 139*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 140*91e1e26aSAlexander Pyhalov } 141*91e1e26aSAlexander Pyhalov 142*91e1e26aSAlexander Pyhalov if ((ea_iscii = traverse_table(isc_eaiscii_tbl, 143*91e1e26aSAlexander Pyhalov sizeof(isc_eaiscii_tbl)/sizeof(Entry), c, &type ))) { 144*91e1e26aSAlexander Pyhalov switch ( type ) { 145*91e1e26aSAlexander Pyhalov case MATRA: 146*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 2 ) { 147*91e1e26aSAlexander Pyhalov errno = E2BIG; 148*91e1e26aSAlexander Pyhalov return (size_t)-1; 149*91e1e26aSAlexander Pyhalov } 150*91e1e26aSAlexander Pyhalov 151*91e1e26aSAlexander Pyhalov **outbuf = FIRST_VOWEL; 152*91e1e26aSAlexander Pyhalov *(*outbuf+1) = ea_iscii; 153*91e1e26aSAlexander Pyhalov (*outbuf) += 2; 154*91e1e26aSAlexander Pyhalov (*outbytesleft) -= 2; 155*91e1e26aSAlexander Pyhalov break; 156*91e1e26aSAlexander Pyhalov case NUKTA: 157*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 2 ) { 158*91e1e26aSAlexander Pyhalov errno = E2BIG; 159*91e1e26aSAlexander Pyhalov return (size_t)-1; 160*91e1e26aSAlexander Pyhalov } 161*91e1e26aSAlexander Pyhalov 162*91e1e26aSAlexander Pyhalov **outbuf = ea_iscii; 163*91e1e26aSAlexander Pyhalov *(*outbuf+1) = NUKTA_VALUE; 164*91e1e26aSAlexander Pyhalov (*outbuf) += 2; 165*91e1e26aSAlexander Pyhalov (*outbytesleft) -= 2; 166*91e1e26aSAlexander Pyhalov break; 167*91e1e26aSAlexander Pyhalov case COMBINED_MATRA_NUKTA: 168*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 3 ) { 169*91e1e26aSAlexander Pyhalov errno = E2BIG; 170*91e1e26aSAlexander Pyhalov return (size_t)-1; 171*91e1e26aSAlexander Pyhalov } 172*91e1e26aSAlexander Pyhalov 173*91e1e26aSAlexander Pyhalov **outbuf = FIRST_VOWEL; 174*91e1e26aSAlexander Pyhalov *(*outbuf+1) = ea_iscii; 175*91e1e26aSAlexander Pyhalov *(*outbuf+2) = NUKTA_VALUE; 176*91e1e26aSAlexander Pyhalov (*outbuf) += 3; 177*91e1e26aSAlexander Pyhalov (*outbytesleft) -= 3; 178*91e1e26aSAlexander Pyhalov break; 179*91e1e26aSAlexander Pyhalov case 0: 180*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 1 ) { 181*91e1e26aSAlexander Pyhalov errno = E2BIG; 182*91e1e26aSAlexander Pyhalov return (size_t)-1; 183*91e1e26aSAlexander Pyhalov } 184*91e1e26aSAlexander Pyhalov 185*91e1e26aSAlexander Pyhalov **outbuf = ea_iscii; 186*91e1e26aSAlexander Pyhalov (*outbuf)++; 187*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 188*91e1e26aSAlexander Pyhalov break; 189*91e1e26aSAlexander Pyhalov } 190*91e1e26aSAlexander Pyhalov } else { /* REPLACE_CHAR */ 191*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 1 ) { 192*91e1e26aSAlexander Pyhalov errno = E2BIG; 193*91e1e26aSAlexander Pyhalov return (size_t)-1; 194*91e1e26aSAlexander Pyhalov } 195*91e1e26aSAlexander Pyhalov 196*91e1e26aSAlexander Pyhalov **outbuf = REPLACE_CHAR; 197*91e1e26aSAlexander Pyhalov (*outbuf)++; 198*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 199*91e1e26aSAlexander Pyhalov } 200*91e1e26aSAlexander Pyhalov } else { /* ASCII */ 201*91e1e26aSAlexander Pyhalov if ( st->context == ISCII && !isspace(c) ) { 202*91e1e26aSAlexander Pyhalov /* force to insert ' ' between ASCII and ISCII */ 203*91e1e26aSAlexander Pyhalov **outbuf = 0x20; 204*91e1e26aSAlexander Pyhalov (*outbuf)++; 205*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 206*91e1e26aSAlexander Pyhalov st->context = SPACE; 207*91e1e26aSAlexander Pyhalov } 208*91e1e26aSAlexander Pyhalov 209*91e1e26aSAlexander Pyhalov if ( *outbytesleft < 1 ) { 210*91e1e26aSAlexander Pyhalov errno = E2BIG; 211*91e1e26aSAlexander Pyhalov return (size_t)-1; 212*91e1e26aSAlexander Pyhalov } 213*91e1e26aSAlexander Pyhalov 214*91e1e26aSAlexander Pyhalov **outbuf = c; 215*91e1e26aSAlexander Pyhalov (*outbuf)++; 216*91e1e26aSAlexander Pyhalov (*outbytesleft)--; 217*91e1e26aSAlexander Pyhalov 218*91e1e26aSAlexander Pyhalov st->context = ASCII; 219*91e1e26aSAlexander Pyhalov if ( isspace(c) ) 220*91e1e26aSAlexander Pyhalov st->context = SPACE; 221*91e1e26aSAlexander Pyhalov } 222*91e1e26aSAlexander Pyhalov 223*91e1e26aSAlexander Pyhalov (*inbuf)++; 224*91e1e26aSAlexander Pyhalov (*inbytesleft)--; 225*91e1e26aSAlexander Pyhalov } 226*91e1e26aSAlexander Pyhalov 227*91e1e26aSAlexander Pyhalov if ( *inbytesleft > 0 && *outbytesleft == 0 ) { 228*91e1e26aSAlexander Pyhalov errno = E2BIG; 229*91e1e26aSAlexander Pyhalov return ((size_t)-1); 230*91e1e26aSAlexander Pyhalov } 231*91e1e26aSAlexander Pyhalov 232*91e1e26aSAlexander Pyhalov return ((size_t)(*inbytesleft)); 233*91e1e26aSAlexander Pyhalov } 234