1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright(c) 2001 Sun Microsystems, Inc. 23 * All rights reserved. 24 */ 25 #include <stdio.h> 26 #include <errno.h> 27 #include <ctype.h> 28 #include <strings.h> 29 #include <stdlib.h> 30 #include "ea-iscii.h" 31 32 #define MSB 0x80 33 #define REPLACE_CHAR '?' 34 35 typedef enum { SPACE, ASCII, ISCII } CONTEXT; 36 37 typedef struct _icv_state { 38 CONTEXT context; 39 } _iconv_st; 40 41 static uchar 42 traverse_table(Entry *entry , int num, uchar iscii, uchar *type) 43 { 44 int i = 0; 45 uchar ea_iscii=0; 46 47 *type = 0; 48 49 for ( ; i < num; ++i) { 50 Entry en = entry[i]; 51 52 if ( iscii < en.iscii ) break; 53 54 if ( en.count == NUKTA || en.count == MATRA || en.count == 55 COMBINED_MATRA_NUKTA ) { 56 if ( iscii == en.iscii ) { 57 *type = en.count; 58 ea_iscii = en.ea_iscii; 59 break; 60 } 61 } else { 62 if ( iscii >= en.iscii && iscii < en.iscii + en.count ) { 63 ea_iscii = (iscii - en.iscii) + en.ea_iscii; 64 break; 65 } 66 } 67 } 68 69 return ea_iscii; 70 } 71 72 void * 73 _icv_open() 74 { 75 _iconv_st *st; 76 77 if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) { 78 errno = ENOMEM; 79 return ((void*)-1); 80 } 81 82 bzero(st, sizeof(_iconv_st)); 83 84 return ((void*)st); 85 } 86 87 /* 88 * Close; called from iconv_close() 89 */ 90 void 91 _icv_close(_iconv_st *st) 92 { 93 if (!st) 94 errno = EBADF; 95 else 96 free(st); 97 } 98 99 size_t 100 _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, 101 char **outbuf, size_t *outbytesleft) 102 { 103 if (st == NULL) { 104 errno = EBADF; 105 return ((size_t) -1); 106 } 107 108 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ 109 return ((size_t)0); 110 } 111 112 /* a state machine for interpreting ISCII code */ 113 while (*inbytesleft > 0 && *outbytesleft > 0) { 114 uchar c = (uchar)**inbuf; 115 116 if ( c & MSB ) { 117 118 uchar type, ea_iscii; 119 120 if ( st->context != ISCII ) { 121 122 if ( st->context != SPACE ) { 123 /* force to insert ' ' between ASCII and ISCII */ 124 **outbuf = 0x20; 125 (*outbuf)++; 126 (*outbytesleft)--; 127 st->context = SPACE; 128 } 129 130 if ( *outbytesleft < 1 ) { 131 errno = E2BIG; 132 /* don't advance */ 133 return (size_t)-1; 134 } 135 136 st->context = ISCII; 137 **outbuf = LEADING_BYTE; 138 (*outbuf)++; 139 (*outbytesleft)--; 140 } 141 142 if ((ea_iscii = traverse_table(isc_eaiscii_tbl, 143 sizeof(isc_eaiscii_tbl)/sizeof(Entry), c, &type ))) { 144 switch ( type ) { 145 case MATRA: 146 if ( *outbytesleft < 2 ) { 147 errno = E2BIG; 148 return (size_t)-1; 149 } 150 151 **outbuf = FIRST_VOWEL; 152 *(*outbuf+1) = ea_iscii; 153 (*outbuf) += 2; 154 (*outbytesleft) -= 2; 155 break; 156 case NUKTA: 157 if ( *outbytesleft < 2 ) { 158 errno = E2BIG; 159 return (size_t)-1; 160 } 161 162 **outbuf = ea_iscii; 163 *(*outbuf+1) = NUKTA_VALUE; 164 (*outbuf) += 2; 165 (*outbytesleft) -= 2; 166 break; 167 case COMBINED_MATRA_NUKTA: 168 if ( *outbytesleft < 3 ) { 169 errno = E2BIG; 170 return (size_t)-1; 171 } 172 173 **outbuf = FIRST_VOWEL; 174 *(*outbuf+1) = ea_iscii; 175 *(*outbuf+2) = NUKTA_VALUE; 176 (*outbuf) += 3; 177 (*outbytesleft) -= 3; 178 break; 179 case 0: 180 if ( *outbytesleft < 1 ) { 181 errno = E2BIG; 182 return (size_t)-1; 183 } 184 185 **outbuf = ea_iscii; 186 (*outbuf)++; 187 (*outbytesleft)--; 188 break; 189 } 190 } else { /* REPLACE_CHAR */ 191 if ( *outbytesleft < 1 ) { 192 errno = E2BIG; 193 return (size_t)-1; 194 } 195 196 **outbuf = REPLACE_CHAR; 197 (*outbuf)++; 198 (*outbytesleft)--; 199 } 200 } else { /* ASCII */ 201 if ( st->context == ISCII && !isspace(c) ) { 202 /* force to insert ' ' between ASCII and ISCII */ 203 **outbuf = 0x20; 204 (*outbuf)++; 205 (*outbytesleft)--; 206 st->context = SPACE; 207 } 208 209 if ( *outbytesleft < 1 ) { 210 errno = E2BIG; 211 return (size_t)-1; 212 } 213 214 **outbuf = c; 215 (*outbuf)++; 216 (*outbytesleft)--; 217 218 st->context = ASCII; 219 if ( isspace(c) ) 220 st->context = SPACE; 221 } 222 223 (*inbuf)++; 224 (*inbytesleft)--; 225 } 226 227 if ( *inbytesleft > 0 && *outbytesleft == 0 ) { 228 errno = E2BIG; 229 return ((size_t)-1); 230 } 231 232 return ((size_t)(*inbytesleft)); 233 } 234