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 *
_icv_open()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
traverse_table(Entry * entry,int num,ucs_t ucs,Type * type)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
ucs_to_iscii(ucs_t uiid,char ** outbuf,size_t * outbytesleft,int isc_type,int * halant_context)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
_icv_close(_iconv_st * st)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
_icv_iconv(_iconv_st * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)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