xref: /titanic_52/usr/src/lib/iconv_modules/hi_IN/ea-iscii%iscii91.c (revision 91e1e26ac6a73ce959289cf7d3d96c4baedbe0b8)
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 <ctype.h>
27*91e1e26aSAlexander Pyhalov #include <errno.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 #define EA_START     0x40
35*91e1e26aSAlexander Pyhalov 
36*91e1e26aSAlexander Pyhalov #define get_vowel(a)  EAISCII_vowel_type[(a) - EA_START]
37*91e1e26aSAlexander Pyhalov #define get_nukta_value(a)  EAISCII_nukta_type[(a) - EA_START]
38*91e1e26aSAlexander Pyhalov #define is_first_vowel(a) ((a) == FIRST_VOWEL)
39*91e1e26aSAlexander Pyhalov #define is_nukta(a) ((a) == NUKTA_VALUE)
40*91e1e26aSAlexander Pyhalov 
41*91e1e26aSAlexander Pyhalov typedef enum { SPACE, ASCII, POSSIBLE_ISCII, ISCII } CONTEXT;
42*91e1e26aSAlexander Pyhalov typedef struct _icv_state {
43*91e1e26aSAlexander Pyhalov     uchar   keepc;    /* if is_vowel is true, store the char following the FIRST_VOWEL */
44*91e1e26aSAlexander Pyhalov     CONTEXT context;
45*91e1e26aSAlexander Pyhalov     int     is_vowel;
46*91e1e26aSAlexander Pyhalov } _iconv_st;
47*91e1e26aSAlexander Pyhalov 
48*91e1e26aSAlexander Pyhalov static uchar
49*91e1e26aSAlexander Pyhalov traverse_table(Entry *entry , int num, uchar ea_iscii)
50*91e1e26aSAlexander Pyhalov {
51*91e1e26aSAlexander Pyhalov     int   i=0;
52*91e1e26aSAlexander Pyhalov     uchar iscii=0;
53*91e1e26aSAlexander Pyhalov 
54*91e1e26aSAlexander Pyhalov     for ( ; i < num; ++i) {
55*91e1e26aSAlexander Pyhalov         Entry en = entry[i];
56*91e1e26aSAlexander Pyhalov 
57*91e1e26aSAlexander Pyhalov         if ( ea_iscii < en.ea_iscii ) break;
58*91e1e26aSAlexander Pyhalov         if ( ea_iscii >= en.ea_iscii && ea_iscii < en.ea_iscii + en.count ) {
59*91e1e26aSAlexander Pyhalov             iscii = (ea_iscii - en.ea_iscii) + en.iscii;
60*91e1e26aSAlexander Pyhalov             break;
61*91e1e26aSAlexander Pyhalov         }
62*91e1e26aSAlexander Pyhalov     }
63*91e1e26aSAlexander Pyhalov 
64*91e1e26aSAlexander Pyhalov     return iscii;
65*91e1e26aSAlexander Pyhalov }
66*91e1e26aSAlexander Pyhalov 
67*91e1e26aSAlexander Pyhalov /*
68*91e1e26aSAlexander Pyhalov  * run in ISCII context.
69*91e1e26aSAlexander Pyhalov  * ea_iscii being 0: flush the keepc
70*91e1e26aSAlexander Pyhalov  * flag return 0: don't decide iscii yet, need to advance the next char in outbuf
71*91e1e26aSAlexander Pyhalov  */
72*91e1e26aSAlexander Pyhalov static uchar
73*91e1e26aSAlexander Pyhalov get_iscii(_iconv_st *st, uchar ea_iscii, int *flag)
74*91e1e26aSAlexander Pyhalov {
75*91e1e26aSAlexander Pyhalov     uchar iscii = 0;
76*91e1e26aSAlexander Pyhalov 
77*91e1e26aSAlexander Pyhalov     if ( st->keepc == 0 ) {
78*91e1e26aSAlexander Pyhalov         if ( ea_iscii == 0 ) { *flag = 0; return 0; }
79*91e1e26aSAlexander Pyhalov         if ( ea_iscii < EA_START ) return 0; /* invalid iscii */
80*91e1e26aSAlexander Pyhalov 
81*91e1e26aSAlexander Pyhalov         if ( get_nukta_value(ea_iscii) || is_first_vowel(ea_iscii) ) {
82*91e1e26aSAlexander Pyhalov             /* do nothing except store ea_iscii into st->keepc */
83*91e1e26aSAlexander Pyhalov             *flag = 0;
84*91e1e26aSAlexander Pyhalov             st->keepc = ea_iscii;
85*91e1e26aSAlexander Pyhalov         } else {
86*91e1e26aSAlexander Pyhalov             iscii = traverse_table( eaiscii_isc_tbl,
87*91e1e26aSAlexander Pyhalov                        sizeof(eaiscii_isc_tbl)/sizeof(Entry), ea_iscii);
88*91e1e26aSAlexander Pyhalov         }
89*91e1e26aSAlexander Pyhalov     } else {
90*91e1e26aSAlexander Pyhalov        uchar vowel, nukta_value;
91*91e1e26aSAlexander Pyhalov 
92*91e1e26aSAlexander Pyhalov        if ( st->is_vowel ) {
93*91e1e26aSAlexander Pyhalov            /* need decide whether it is 0xAE or 0xB2 case */
94*91e1e26aSAlexander Pyhalov            if ( ea_iscii >= EA_START && is_nukta(ea_iscii) ) {
95*91e1e26aSAlexander Pyhalov                if ( st->keepc == 0x73 ) iscii = 0xAE;
96*91e1e26aSAlexander Pyhalov                if ( st->keepc == 0x76 ) iscii = 0xB2;
97*91e1e26aSAlexander Pyhalov                st->keepc = 0;
98*91e1e26aSAlexander Pyhalov            } else {
99*91e1e26aSAlexander Pyhalov                iscii = get_vowel(st->keepc);
100*91e1e26aSAlexander Pyhalov                st->keepc = ea_iscii;
101*91e1e26aSAlexander Pyhalov            }
102*91e1e26aSAlexander Pyhalov            st->is_vowel = 0;
103*91e1e26aSAlexander Pyhalov            goto end;
104*91e1e26aSAlexander Pyhalov        }
105*91e1e26aSAlexander Pyhalov 
106*91e1e26aSAlexander Pyhalov        if ( is_first_vowel(st->keepc) ) {
107*91e1e26aSAlexander Pyhalov            if ( (ea_iscii >= EA_START) && (vowel = get_vowel(ea_iscii)) ) {
108*91e1e26aSAlexander Pyhalov                 if ( ea_iscii == 0x73 || ea_iscii == 0x76 ) {
109*91e1e26aSAlexander Pyhalov                     st->keepc = ea_iscii;
110*91e1e26aSAlexander Pyhalov                     *flag = 0;
111*91e1e26aSAlexander Pyhalov                     st->is_vowel = 1;
112*91e1e26aSAlexander Pyhalov                 } else {
113*91e1e26aSAlexander Pyhalov                     st->keepc = 0;
114*91e1e26aSAlexander Pyhalov                     iscii = vowel;
115*91e1e26aSAlexander Pyhalov                 }
116*91e1e26aSAlexander Pyhalov            } else {
117*91e1e26aSAlexander Pyhalov                 iscii = traverse_table( eaiscii_isc_tbl,
118*91e1e26aSAlexander Pyhalov                        sizeof(eaiscii_isc_tbl)/sizeof(Entry), st->keepc);
119*91e1e26aSAlexander Pyhalov                 st->keepc = ea_iscii;
120*91e1e26aSAlexander Pyhalov            }
121*91e1e26aSAlexander Pyhalov        } else if ( (st->keepc >= EA_START) && (nukta_value = get_nukta_value(st->keepc))) {
122*91e1e26aSAlexander Pyhalov            if ( ea_iscii >= EA_START && is_nukta(ea_iscii) ) {
123*91e1e26aSAlexander Pyhalov                 st->keepc = 0;
124*91e1e26aSAlexander Pyhalov                 iscii = nukta_value;
125*91e1e26aSAlexander Pyhalov            } else {
126*91e1e26aSAlexander Pyhalov                 iscii = traverse_table( eaiscii_isc_tbl,
127*91e1e26aSAlexander Pyhalov                        sizeof(eaiscii_isc_tbl)/sizeof(Entry), st->keepc);
128*91e1e26aSAlexander Pyhalov                 st->keepc = ea_iscii;
129*91e1e26aSAlexander Pyhalov            }
130*91e1e26aSAlexander Pyhalov        } else {
131*91e1e26aSAlexander Pyhalov            iscii = traverse_table( eaiscii_isc_tbl,
132*91e1e26aSAlexander Pyhalov                   sizeof(eaiscii_isc_tbl)/sizeof(Entry), st->keepc);
133*91e1e26aSAlexander Pyhalov            st->keepc = ea_iscii;
134*91e1e26aSAlexander Pyhalov        }
135*91e1e26aSAlexander Pyhalov     }
136*91e1e26aSAlexander Pyhalov 
137*91e1e26aSAlexander Pyhalov end:
138*91e1e26aSAlexander Pyhalov     return iscii;
139*91e1e26aSAlexander Pyhalov }
140*91e1e26aSAlexander Pyhalov 
141*91e1e26aSAlexander Pyhalov void *
142*91e1e26aSAlexander Pyhalov _icv_open()
143*91e1e26aSAlexander Pyhalov {
144*91e1e26aSAlexander Pyhalov     _iconv_st *st;
145*91e1e26aSAlexander Pyhalov 
146*91e1e26aSAlexander Pyhalov     if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) {
147*91e1e26aSAlexander Pyhalov         errno = ENOMEM;
148*91e1e26aSAlexander Pyhalov         return ((void*)-1);
149*91e1e26aSAlexander Pyhalov     }
150*91e1e26aSAlexander Pyhalov 
151*91e1e26aSAlexander Pyhalov     bzero(st, sizeof(_iconv_st));
152*91e1e26aSAlexander Pyhalov 
153*91e1e26aSAlexander Pyhalov     return ((void*)st);
154*91e1e26aSAlexander Pyhalov }
155*91e1e26aSAlexander Pyhalov 
156*91e1e26aSAlexander Pyhalov /*
157*91e1e26aSAlexander Pyhalov  * Close; called from iconv_close()
158*91e1e26aSAlexander Pyhalov  */
159*91e1e26aSAlexander Pyhalov void
160*91e1e26aSAlexander Pyhalov _icv_close(_iconv_st *st)
161*91e1e26aSAlexander Pyhalov {
162*91e1e26aSAlexander Pyhalov     if (!st)
163*91e1e26aSAlexander Pyhalov         errno = EBADF;
164*91e1e26aSAlexander Pyhalov     else
165*91e1e26aSAlexander Pyhalov         free(st);
166*91e1e26aSAlexander Pyhalov }
167*91e1e26aSAlexander Pyhalov 
168*91e1e26aSAlexander Pyhalov size_t
169*91e1e26aSAlexander Pyhalov _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft,
170*91e1e26aSAlexander Pyhalov        char **outbuf, size_t *outbytesleft)
171*91e1e26aSAlexander Pyhalov {
172*91e1e26aSAlexander Pyhalov     if (st == NULL) {
173*91e1e26aSAlexander Pyhalov         errno = EBADF;
174*91e1e26aSAlexander Pyhalov         return ((size_t) -1);
175*91e1e26aSAlexander Pyhalov     }
176*91e1e26aSAlexander Pyhalov 
177*91e1e26aSAlexander Pyhalov     if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
178*91e1e26aSAlexander Pyhalov         return ((size_t)0);
179*91e1e26aSAlexander Pyhalov     }
180*91e1e26aSAlexander Pyhalov 
181*91e1e26aSAlexander Pyhalov     /* a state machine for interpreting ISCII code */
182*91e1e26aSAlexander Pyhalov     while (*inbytesleft > 0 && *outbytesleft > 0) {
183*91e1e26aSAlexander Pyhalov         uchar c = (uchar)**inbuf;
184*91e1e26aSAlexander Pyhalov 
185*91e1e26aSAlexander Pyhalov         if ( c & MSB ) { errno = EILSEQ; return (size_t)-1; }
186*91e1e26aSAlexander Pyhalov 
187*91e1e26aSAlexander Pyhalov         switch (st->context) {
188*91e1e26aSAlexander Pyhalov         case SPACE:
189*91e1e26aSAlexander Pyhalov             if ( c == LEADING_BYTE ) st->context = POSSIBLE_ISCII;
190*91e1e26aSAlexander Pyhalov             else {
191*91e1e26aSAlexander Pyhalov                 if ( !isspace(c) ) st->context = ASCII;
192*91e1e26aSAlexander Pyhalov                 **outbuf = c;
193*91e1e26aSAlexander Pyhalov                 (*outbuf)++;
194*91e1e26aSAlexander Pyhalov                 (*outbytesleft)--;
195*91e1e26aSAlexander Pyhalov             }
196*91e1e26aSAlexander Pyhalov             break;
197*91e1e26aSAlexander Pyhalov         case ASCII:
198*91e1e26aSAlexander Pyhalov             if ( isspace(c) ) st->context = SPACE;
199*91e1e26aSAlexander Pyhalov             **outbuf = c;
200*91e1e26aSAlexander Pyhalov             (*outbuf)++;
201*91e1e26aSAlexander Pyhalov             (*outbytesleft)--;
202*91e1e26aSAlexander Pyhalov             break;
203*91e1e26aSAlexander Pyhalov         case POSSIBLE_ISCII:
204*91e1e26aSAlexander Pyhalov             /* it is impossible to represent with 'xx' one ASCII word that starts with 'x' */
205*91e1e26aSAlexander Pyhalov             if ( !isspace(c) ) { st->context = ISCII; continue; } /* don't advance */
206*91e1e26aSAlexander Pyhalov 
207*91e1e26aSAlexander Pyhalov             **outbuf = LEADING_BYTE;  /* the previous 'x' */
208*91e1e26aSAlexander Pyhalov             (*outbuf)++;
209*91e1e26aSAlexander Pyhalov             (*outbytesleft)--;
210*91e1e26aSAlexander Pyhalov             st->context = ASCII;
211*91e1e26aSAlexander Pyhalov 
212*91e1e26aSAlexander Pyhalov             if (*outbytesleft < 1) {
213*91e1e26aSAlexander Pyhalov                 errno = E2BIG;
214*91e1e26aSAlexander Pyhalov                 return (size_t)-1;
215*91e1e26aSAlexander Pyhalov             }
216*91e1e26aSAlexander Pyhalov 
217*91e1e26aSAlexander Pyhalov             **outbuf = c;
218*91e1e26aSAlexander Pyhalov             (*outbuf)++;
219*91e1e26aSAlexander Pyhalov             (*outbytesleft)--;
220*91e1e26aSAlexander Pyhalov             st->context = SPACE;
221*91e1e26aSAlexander Pyhalov 
222*91e1e26aSAlexander Pyhalov             break;
223*91e1e26aSAlexander Pyhalov         case ISCII:
224*91e1e26aSAlexander Pyhalov             if ( isspace(c) ) {
225*91e1e26aSAlexander Pyhalov                 uchar iscii;
226*91e1e26aSAlexander Pyhalov                 int flag = 1;
227*91e1e26aSAlexander Pyhalov 
228*91e1e26aSAlexander Pyhalov                 /* flush keepc */
229*91e1e26aSAlexander Pyhalov                 iscii = get_iscii(st, 0, &flag);
230*91e1e26aSAlexander Pyhalov                 if (flag) {
231*91e1e26aSAlexander Pyhalov                     if ( iscii ) **outbuf = iscii;
232*91e1e26aSAlexander Pyhalov                     else **outbuf = REPLACE_CHAR;
233*91e1e26aSAlexander Pyhalov 
234*91e1e26aSAlexander Pyhalov                     (*outbuf)++;
235*91e1e26aSAlexander Pyhalov                     (*outbytesleft)--;
236*91e1e26aSAlexander Pyhalov                 }
237*91e1e26aSAlexander Pyhalov 
238*91e1e26aSAlexander Pyhalov                 if ( *outbytesleft < 1 ) {
239*91e1e26aSAlexander Pyhalov                     errno = E2BIG;
240*91e1e26aSAlexander Pyhalov                     return (size_t)-1;
241*91e1e26aSAlexander Pyhalov                 }
242*91e1e26aSAlexander Pyhalov 
243*91e1e26aSAlexander Pyhalov                 **outbuf = c;
244*91e1e26aSAlexander Pyhalov                 (*outbuf)++;
245*91e1e26aSAlexander Pyhalov                 (*outbytesleft)--;
246*91e1e26aSAlexander Pyhalov                 st->context = SPACE;
247*91e1e26aSAlexander Pyhalov             } else {
248*91e1e26aSAlexander Pyhalov                uchar iscii;
249*91e1e26aSAlexander Pyhalov                int   flag = 1;
250*91e1e26aSAlexander Pyhalov 
251*91e1e26aSAlexander Pyhalov                iscii = get_iscii(st, c, &flag);
252*91e1e26aSAlexander Pyhalov                if (flag) {
253*91e1e26aSAlexander Pyhalov                    if ( iscii ) **outbuf = iscii;
254*91e1e26aSAlexander Pyhalov                    else **outbuf = REPLACE_CHAR;
255*91e1e26aSAlexander Pyhalov 
256*91e1e26aSAlexander Pyhalov                    (*outbuf)++;
257*91e1e26aSAlexander Pyhalov                    (*outbytesleft)--;
258*91e1e26aSAlexander Pyhalov                }
259*91e1e26aSAlexander Pyhalov             }
260*91e1e26aSAlexander Pyhalov             break;
261*91e1e26aSAlexander Pyhalov         }
262*91e1e26aSAlexander Pyhalov 
263*91e1e26aSAlexander Pyhalov         (*inbuf)++;
264*91e1e26aSAlexander Pyhalov         (*inbytesleft)--;
265*91e1e26aSAlexander Pyhalov     }
266*91e1e26aSAlexander Pyhalov 
267*91e1e26aSAlexander Pyhalov     if ( *inbytesleft > 0 && *outbytesleft == 0 ) {
268*91e1e26aSAlexander Pyhalov          errno = E2BIG;
269*91e1e26aSAlexander Pyhalov          return ((size_t)-1);
270*91e1e26aSAlexander Pyhalov     }
271*91e1e26aSAlexander Pyhalov 
272*91e1e26aSAlexander Pyhalov     return ((size_t)(*inbytesleft));
273*91e1e26aSAlexander Pyhalov }
274