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