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) 1995, by 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 <stdlib.h>
28*16d86563SAlexander Pyhalov #include <strings.h>
29*16d86563SAlexander Pyhalov #include <errno.h>
30*16d86563SAlexander Pyhalov #ifdef DEBUG
31*16d86563SAlexander Pyhalov #include <sys/fcntl.h>
32*16d86563SAlexander Pyhalov #include <sys/stat.h>
33*16d86563SAlexander Pyhalov #endif
34*16d86563SAlexander Pyhalov #include <gb2312_unicode.h>
35*16d86563SAlexander Pyhalov #include <cns11643_unicode_CN.h> /* CNS 11643 to Unicode mapping table */
36*16d86563SAlexander Pyhalov
37*16d86563SAlexander Pyhalov #define UTF8_NON_ID_CHAR1 0xEF
38*16d86563SAlexander Pyhalov #define UTF8_NON_ID_CHAR2 0xBF
39*16d86563SAlexander Pyhalov #define UTF8_NON_ID_CHAR3 0xBD
40*16d86563SAlexander Pyhalov
41*16d86563SAlexander Pyhalov #define MSB 0x80 /* most significant bit */
42*16d86563SAlexander Pyhalov #define MBYTE 0x8e /* multi-byte (4 byte character) */
43*16d86563SAlexander Pyhalov #define PMASK 0xa0 /* plane number mask */
44*16d86563SAlexander Pyhalov #define ONEBYTE 0xff /* right most byte */
45*16d86563SAlexander Pyhalov #define MSB_OFF 0x7f /* mask off MBS */
46*16d86563SAlexander Pyhalov
47*16d86563SAlexander Pyhalov #define SI 0x0f /* shift in */
48*16d86563SAlexander Pyhalov #define SO 0x0e /* shift out */
49*16d86563SAlexander Pyhalov #define ESC 0x1b /* escape */
50*16d86563SAlexander Pyhalov #define SS2 0x4e /* SS2 shift out */
51*16d86563SAlexander Pyhalov #define SS3 0x4f /* SS3 shift out */
52*16d86563SAlexander Pyhalov #define NON_ID_CHAR_BYTE1 0xA1 /* non-identified character */
53*16d86563SAlexander Pyhalov #define NON_ID_CHAR_BYTE2 0xF5 /* non-identified character */
54*16d86563SAlexander Pyhalov
55*16d86563SAlexander Pyhalov typedef struct _icv_state {
56*16d86563SAlexander Pyhalov char _buf[10];
57*16d86563SAlexander Pyhalov size_t _bufcont;
58*16d86563SAlexander Pyhalov char _keepc[4]; /* maximum # byte of CNS11643 code */
59*16d86563SAlexander Pyhalov short _gstate; /* state machine id */
60*16d86563SAlexander Pyhalov short _istate; /* state for shift in/out */
61*16d86563SAlexander Pyhalov int _plane; /* plane number for Chinese character */
62*16d86563SAlexander Pyhalov int _last_plane; /* last charactor's plane # */
63*16d86563SAlexander Pyhalov int _errno; /* internal errno */
64*16d86563SAlexander Pyhalov } _iconv_st;
65*16d86563SAlexander Pyhalov
66*16d86563SAlexander Pyhalov enum _GSTATE { G0, G1, G2, G3, G4, G5, G6, G7, G8, G9, \
67*16d86563SAlexander Pyhalov G10,G11,G12,G13,G14,G15,G16,G17,G18,G19, \
68*16d86563SAlexander Pyhalov G20,G21,G22,G23,G24,G25,G26,G27,G28,G29 };
69*16d86563SAlexander Pyhalov
70*16d86563SAlexander Pyhalov enum _ISTATE { IN, OUT };
71*16d86563SAlexander Pyhalov
72*16d86563SAlexander Pyhalov
73*16d86563SAlexander Pyhalov int iso_gb_to_utf(_iconv_st * st, char* buf, size_t buflen);
74*16d86563SAlexander Pyhalov int iso_cns_to_utf(_iconv_st * st, char* buf, size_t buflen);
75*16d86563SAlexander Pyhalov int iso_cns_to_utf(_iconv_st * st, char* buf, size_t buflen);
76*16d86563SAlexander Pyhalov int binsearch(unsigned long x, table_t v[], int n);
77*16d86563SAlexander Pyhalov int flush_buf(_iconv_st * st, char ** outbuf, size_t * outbytesleft);
78*16d86563SAlexander Pyhalov
flush_buf(_iconv_st * st,char ** outbuf,size_t * outbytesleft)79*16d86563SAlexander Pyhalov int flush_buf(_iconv_st * st, char ** outbuf, size_t * outbytesleft) {
80*16d86563SAlexander Pyhalov if (!st->_bufcont)
81*16d86563SAlexander Pyhalov return 0;
82*16d86563SAlexander Pyhalov if (st->_bufcont > *outbytesleft) {
83*16d86563SAlexander Pyhalov st->_errno = E2BIG;
84*16d86563SAlexander Pyhalov return -1;
85*16d86563SAlexander Pyhalov }
86*16d86563SAlexander Pyhalov if (st->_istate != IN) {
87*16d86563SAlexander Pyhalov st->_errno = EILSEQ;
88*16d86563SAlexander Pyhalov return -1;
89*16d86563SAlexander Pyhalov }
90*16d86563SAlexander Pyhalov strncpy(st->_buf, *outbuf, st->_bufcont);
91*16d86563SAlexander Pyhalov (*outbuf)+=(st->_bufcont);
92*16d86563SAlexander Pyhalov (*outbytesleft)-=(st->_bufcont);
93*16d86563SAlexander Pyhalov st->_bufcont = 0;
94*16d86563SAlexander Pyhalov return st->_bufcont;
95*16d86563SAlexander Pyhalov }
96*16d86563SAlexander Pyhalov
97*16d86563SAlexander Pyhalov /*
98*16d86563SAlexander Pyhalov * Open; called from iconv_open()
99*16d86563SAlexander Pyhalov */
100*16d86563SAlexander Pyhalov void *
_icv_open()101*16d86563SAlexander Pyhalov _icv_open()
102*16d86563SAlexander Pyhalov {
103*16d86563SAlexander Pyhalov _iconv_st *st;
104*16d86563SAlexander Pyhalov
105*16d86563SAlexander Pyhalov if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) {
106*16d86563SAlexander Pyhalov errno = ENOMEM;
107*16d86563SAlexander Pyhalov return ((void *) -1);
108*16d86563SAlexander Pyhalov }
109*16d86563SAlexander Pyhalov
110*16d86563SAlexander Pyhalov st->_gstate = G0;
111*16d86563SAlexander Pyhalov st->_istate = IN;
112*16d86563SAlexander Pyhalov st->_last_plane = st->_plane = -1;
113*16d86563SAlexander Pyhalov st->_errno = 0;
114*16d86563SAlexander Pyhalov st->_bufcont = 0;
115*16d86563SAlexander Pyhalov
116*16d86563SAlexander Pyhalov return ((void *) st);
117*16d86563SAlexander Pyhalov }
118*16d86563SAlexander Pyhalov
119*16d86563SAlexander Pyhalov /*
120*16d86563SAlexander Pyhalov * Close; called from iconv_close()
121*16d86563SAlexander Pyhalov */
122*16d86563SAlexander Pyhalov void
_icv_close(_iconv_st * st)123*16d86563SAlexander Pyhalov _icv_close(_iconv_st *st)
124*16d86563SAlexander Pyhalov {
125*16d86563SAlexander Pyhalov if (st == NULL)
126*16d86563SAlexander Pyhalov errno = EBADF;
127*16d86563SAlexander Pyhalov else
128*16d86563SAlexander Pyhalov free(st);
129*16d86563SAlexander Pyhalov }
130*16d86563SAlexander Pyhalov
131*16d86563SAlexander Pyhalov /*
132*16d86563SAlexander Pyhalov * Actual conversion; called from iconv()
133*16d86563SAlexander Pyhalov */
134*16d86563SAlexander Pyhalov /*=========================================================================
135*16d86563SAlexander Pyhalov *
136*16d86563SAlexander Pyhalov * State Machine for interpreting ISO 2022-7 code
137*16d86563SAlexander Pyhalov *
138*16d86563SAlexander Pyhalov *=========================================================================
139*16d86563SAlexander Pyhalov *
140*16d86563SAlexander Pyhalov * plane 2 - 16
141*16d86563SAlexander Pyhalov * +---------->-------+
142*16d86563SAlexander Pyhalov * plane ^ |
143*16d86563SAlexander Pyhalov * ESC $ ) number SO | plane 1 v
144*16d86563SAlexander Pyhalov * +-> G0 ----> G1 ---> G2 ---> G3 ------> G4 --> G5 -------> G6 G7
145*16d86563SAlexander Pyhalov * | | ascii | ascii | ascii | ascii | SI | | | |
146*16d86563SAlexander Pyhalov * +----------------------------+ <-----+------+ +------<---+------+
147*16d86563SAlexander Pyhalov * ^ |
148*16d86563SAlexander Pyhalov * | ascii v
149*16d86563SAlexander Pyhalov * +---------<-------------<---------+
150*16d86563SAlexander Pyhalov *
151*16d86563SAlexander Pyhalov *=========================================================================*/
_icv_iconv(_iconv_st * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)152*16d86563SAlexander Pyhalov size_t _icv_iconv(_iconv_st *st, \
153*16d86563SAlexander Pyhalov char **inbuf, size_t *inbytesleft, \
154*16d86563SAlexander Pyhalov char **outbuf, size_t *outbytesleft) {
155*16d86563SAlexander Pyhalov int n;
156*16d86563SAlexander Pyhalov char c;
157*16d86563SAlexander Pyhalov
158*16d86563SAlexander Pyhalov if (st == NULL) {
159*16d86563SAlexander Pyhalov errno = EBADF;
160*16d86563SAlexander Pyhalov return ((size_t) -1);
161*16d86563SAlexander Pyhalov }
162*16d86563SAlexander Pyhalov
163*16d86563SAlexander Pyhalov if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
164*16d86563SAlexander Pyhalov st->_gstate = G0;
165*16d86563SAlexander Pyhalov st->_istate = IN;
166*16d86563SAlexander Pyhalov st->_errno = 0;
167*16d86563SAlexander Pyhalov st->_plane = st->_last_plane = -1;
168*16d86563SAlexander Pyhalov return ((size_t) 0);
169*16d86563SAlexander Pyhalov }
170*16d86563SAlexander Pyhalov
171*16d86563SAlexander Pyhalov errno = st->_errno = 0; /* reset internal and external errno */
172*16d86563SAlexander Pyhalov
173*16d86563SAlexander Pyhalov /* a state machine for interpreting ISO 2022-7 code */
174*16d86563SAlexander Pyhalov while (*inbytesleft > 0 && *outbytesleft > 0) {
175*16d86563SAlexander Pyhalov switch (st->_gstate) {
176*16d86563SAlexander Pyhalov case G0: /* assuming ASCII in the beginning */
177*16d86563SAlexander Pyhalov if (**inbuf == ESC) {
178*16d86563SAlexander Pyhalov st->_gstate = G1;
179*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = ESC;
180*16d86563SAlexander Pyhalov } else { /* real ASCII */
181*16d86563SAlexander Pyhalov **outbuf = **inbuf;
182*16d86563SAlexander Pyhalov (*outbuf)++;
183*16d86563SAlexander Pyhalov (*outbytesleft)--;
184*16d86563SAlexander Pyhalov }
185*16d86563SAlexander Pyhalov break;
186*16d86563SAlexander Pyhalov case G1: /* got ESC, expecting $ */
187*16d86563SAlexander Pyhalov if (**inbuf == '$') {
188*16d86563SAlexander Pyhalov st->_gstate = G2;
189*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = '$';
190*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
191*16d86563SAlexander Pyhalov errno = st->_errno;
192*16d86563SAlexander Pyhalov return (size_t)-1;
193*16d86563SAlexander Pyhalov } else {
194*16d86563SAlexander Pyhalov st->_gstate = G0;
195*16d86563SAlexander Pyhalov st->_errno = 0;
196*16d86563SAlexander Pyhalov st->_istate = IN;
197*16d86563SAlexander Pyhalov continue; /* don't advance inbuf */
198*16d86563SAlexander Pyhalov }
199*16d86563SAlexander Pyhalov break;
200*16d86563SAlexander Pyhalov case G2: /* got $, expecting ) * or + */
201*16d86563SAlexander Pyhalov if (**inbuf == ')') {
202*16d86563SAlexander Pyhalov st->_gstate = G3;
203*16d86563SAlexander Pyhalov } else if (**inbuf == '*') {
204*16d86563SAlexander Pyhalov st->_gstate = G12;
205*16d86563SAlexander Pyhalov st->_plane = 2;
206*16d86563SAlexander Pyhalov } else if (**inbuf == '+') {
207*16d86563SAlexander Pyhalov st->_gstate = G19;
208*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
209*16d86563SAlexander Pyhalov errno = st->_errno;
210*16d86563SAlexander Pyhalov return (size_t)-1;
211*16d86563SAlexander Pyhalov } else {
212*16d86563SAlexander Pyhalov st->_gstate = G0;
213*16d86563SAlexander Pyhalov st->_errno = 0;
214*16d86563SAlexander Pyhalov st->_istate = IN;
215*16d86563SAlexander Pyhalov continue; /* don't advance inbuf */
216*16d86563SAlexander Pyhalov }
217*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = **inbuf;
218*16d86563SAlexander Pyhalov break;
219*16d86563SAlexander Pyhalov case G3: /* got ) expecting A,G,H */
220*16d86563SAlexander Pyhalov /* H is for the bug of and zh_TW.BIG5 */
221*16d86563SAlexander Pyhalov if (**inbuf == 'A') {
222*16d86563SAlexander Pyhalov st->_plane = 0;
223*16d86563SAlexander Pyhalov st->_gstate = G4;
224*16d86563SAlexander Pyhalov } else if (**inbuf == 'G') {
225*16d86563SAlexander Pyhalov st->_plane = 1;
226*16d86563SAlexander Pyhalov st->_gstate = G8;
227*16d86563SAlexander Pyhalov } else if (**inbuf == 'H') {
228*16d86563SAlexander Pyhalov st->_plane = 2;
229*16d86563SAlexander Pyhalov st->_gstate = G8;
230*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
231*16d86563SAlexander Pyhalov errno = st->_errno;
232*16d86563SAlexander Pyhalov return (size_t)-1;
233*16d86563SAlexander Pyhalov } else {
234*16d86563SAlexander Pyhalov st->_gstate = G0;
235*16d86563SAlexander Pyhalov st->_errno = 0;
236*16d86563SAlexander Pyhalov st->_istate = IN;
237*16d86563SAlexander Pyhalov continue;
238*16d86563SAlexander Pyhalov }
239*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = **inbuf;
240*16d86563SAlexander Pyhalov break;
241*16d86563SAlexander Pyhalov case G4: /* ESC $ ) A got, and SO is expected */
242*16d86563SAlexander Pyhalov if (**inbuf == SO) {
243*16d86563SAlexander Pyhalov st->_gstate = G5;
244*16d86563SAlexander Pyhalov st->_istate = OUT;
245*16d86563SAlexander Pyhalov st->_bufcont = 0;
246*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
247*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
248*16d86563SAlexander Pyhalov errno = st->_errno;
249*16d86563SAlexander Pyhalov return (size_t)-1;
250*16d86563SAlexander Pyhalov } else {
251*16d86563SAlexander Pyhalov st->_gstate = G0;
252*16d86563SAlexander Pyhalov st->_errno = 0;
253*16d86563SAlexander Pyhalov st->_istate = IN;
254*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
255*16d86563SAlexander Pyhalov continue;
256*16d86563SAlexander Pyhalov }
257*16d86563SAlexander Pyhalov break;
258*16d86563SAlexander Pyhalov case G5: /* SO (Shift Out) */
259*16d86563SAlexander Pyhalov if (**inbuf == SI) {
260*16d86563SAlexander Pyhalov st->_istate = IN;
261*16d86563SAlexander Pyhalov st->_gstate = G7;
262*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
263*16d86563SAlexander Pyhalov } else if (**inbuf == ESC) {
264*16d86563SAlexander Pyhalov /*
265*16d86563SAlexander Pyhalov && *((*inbuf) + 1) == '$') {
266*16d86563SAlexander Pyhalov if (flush_buf(st, outbuf, outbytesleft) == -1) {
267*16d86563SAlexander Pyhalov errno = st->_errno;
268*16d86563SAlexander Pyhalov return (size_t)-1;
269*16d86563SAlexander Pyhalov }
270*16d86563SAlexander Pyhalov */
271*16d86563SAlexander Pyhalov st->_bufcont = 0;
272*16d86563SAlexander Pyhalov st->_gstate = G0;
273*16d86563SAlexander Pyhalov continue;
274*16d86563SAlexander Pyhalov } else { /* Chinese Charactors */
275*16d86563SAlexander Pyhalov st->_keepc[0] = **inbuf;
276*16d86563SAlexander Pyhalov st->_gstate = G6;
277*16d86563SAlexander Pyhalov }
278*16d86563SAlexander Pyhalov break;
279*16d86563SAlexander Pyhalov case G6: /* GB2312: 2nd Chinese character */
280*16d86563SAlexander Pyhalov st->_keepc[1] = **inbuf;
281*16d86563SAlexander Pyhalov n = iso_gb_to_utf(st, *outbuf, *outbytesleft);
282*16d86563SAlexander Pyhalov if (n > 0) {
283*16d86563SAlexander Pyhalov (*outbuf) += n;
284*16d86563SAlexander Pyhalov (*outbytesleft) -= n;
285*16d86563SAlexander Pyhalov } else {
286*16d86563SAlexander Pyhalov errno = st->_errno;
287*16d86563SAlexander Pyhalov return (size_t)-1;
288*16d86563SAlexander Pyhalov }
289*16d86563SAlexander Pyhalov st->_gstate = G5;
290*16d86563SAlexander Pyhalov break;
291*16d86563SAlexander Pyhalov case G7: /* Shift in */
292*16d86563SAlexander Pyhalov if (**inbuf == SO) {
293*16d86563SAlexander Pyhalov st->_gstate = G5;
294*16d86563SAlexander Pyhalov st->_istate = OUT;
295*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
296*16d86563SAlexander Pyhalov st->_bufcont = 0;
297*16d86563SAlexander Pyhalov } else if (**inbuf == ESC) {
298*16d86563SAlexander Pyhalov /*
299*16d86563SAlexander Pyhalov && *((*inbuf) + 1) == '$') {
300*16d86563SAlexander Pyhalov */
301*16d86563SAlexander Pyhalov st->_gstate = G0;
302*16d86563SAlexander Pyhalov continue;
303*16d86563SAlexander Pyhalov } else {
304*16d86563SAlexander Pyhalov **outbuf = **inbuf;
305*16d86563SAlexander Pyhalov (*outbuf)++;
306*16d86563SAlexander Pyhalov (*outbytesleft) --;
307*16d86563SAlexander Pyhalov }
308*16d86563SAlexander Pyhalov break;
309*16d86563SAlexander Pyhalov case G8: /* CNS: Chinese character */
310*16d86563SAlexander Pyhalov if (**inbuf == SO) {
311*16d86563SAlexander Pyhalov st->_istate = OUT;
312*16d86563SAlexander Pyhalov st->_gstate = G9;
313*16d86563SAlexander Pyhalov st->_bufcont = 0;
314*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
315*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
316*16d86563SAlexander Pyhalov errno = st->_errno;
317*16d86563SAlexander Pyhalov return (size_t)-1;
318*16d86563SAlexander Pyhalov } else {
319*16d86563SAlexander Pyhalov st->_gstate = G0;
320*16d86563SAlexander Pyhalov st->_errno = 0;
321*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
322*16d86563SAlexander Pyhalov st->_istate = IN;
323*16d86563SAlexander Pyhalov continue;
324*16d86563SAlexander Pyhalov }
325*16d86563SAlexander Pyhalov break;
326*16d86563SAlexander Pyhalov case G9:
327*16d86563SAlexander Pyhalov if (**inbuf == SI) {
328*16d86563SAlexander Pyhalov st->_istate = IN;
329*16d86563SAlexander Pyhalov st->_gstate = G11;
330*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
331*16d86563SAlexander Pyhalov } else if (**inbuf == ESC) {
332*16d86563SAlexander Pyhalov /*
333*16d86563SAlexander Pyhalov && *((*inbuf) + 1) == '$') {
334*16d86563SAlexander Pyhalov */
335*16d86563SAlexander Pyhalov if (flush_buf(st, outbuf, outbytesleft) == -1) {
336*16d86563SAlexander Pyhalov errno = st->_errno;
337*16d86563SAlexander Pyhalov return (size_t)-1;
338*16d86563SAlexander Pyhalov }
339*16d86563SAlexander Pyhalov st->_gstate = G0;
340*16d86563SAlexander Pyhalov continue;
341*16d86563SAlexander Pyhalov } else { /* Chinese Charactor */
342*16d86563SAlexander Pyhalov st->_keepc[0] = **inbuf;
343*16d86563SAlexander Pyhalov st->_gstate = G10;
344*16d86563SAlexander Pyhalov }
345*16d86563SAlexander Pyhalov break;
346*16d86563SAlexander Pyhalov case G10:
347*16d86563SAlexander Pyhalov st->_keepc[1] = **inbuf;
348*16d86563SAlexander Pyhalov n = iso_cns_to_utf(st, *outbuf, *outbytesleft);
349*16d86563SAlexander Pyhalov if (n > 0) {
350*16d86563SAlexander Pyhalov (*outbuf) += n;
351*16d86563SAlexander Pyhalov (*outbytesleft) -= n;
352*16d86563SAlexander Pyhalov } else {
353*16d86563SAlexander Pyhalov errno = st->_errno;
354*16d86563SAlexander Pyhalov return (size_t)-1;
355*16d86563SAlexander Pyhalov }
356*16d86563SAlexander Pyhalov st->_gstate = G9;
357*16d86563SAlexander Pyhalov break;
358*16d86563SAlexander Pyhalov case G11:
359*16d86563SAlexander Pyhalov st->_bufcont = 0;
360*16d86563SAlexander Pyhalov if (**inbuf == SO) {
361*16d86563SAlexander Pyhalov st->_istate = OUT;
362*16d86563SAlexander Pyhalov st->_gstate = G9;
363*16d86563SAlexander Pyhalov } else if (**inbuf == ESC) {
364*16d86563SAlexander Pyhalov /*
365*16d86563SAlexander Pyhalov && *((*inbuf) + 1) == '$') {
366*16d86563SAlexander Pyhalov */
367*16d86563SAlexander Pyhalov st->_gstate = G0;
368*16d86563SAlexander Pyhalov continue;
369*16d86563SAlexander Pyhalov } else {
370*16d86563SAlexander Pyhalov **outbuf = **inbuf;
371*16d86563SAlexander Pyhalov (*outbuf)++;
372*16d86563SAlexander Pyhalov (*outbytesleft)--;
373*16d86563SAlexander Pyhalov }
374*16d86563SAlexander Pyhalov break;
375*16d86563SAlexander Pyhalov case G12:
376*16d86563SAlexander Pyhalov if (**inbuf == 'H') {
377*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = 'H';
378*16d86563SAlexander Pyhalov st->_gstate = G13;
379*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
380*16d86563SAlexander Pyhalov errno = st->_errno;
381*16d86563SAlexander Pyhalov return (size_t)-1;
382*16d86563SAlexander Pyhalov } else {
383*16d86563SAlexander Pyhalov st->_istate = IN;
384*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
385*16d86563SAlexander Pyhalov st->_gstate = G0;
386*16d86563SAlexander Pyhalov continue;
387*16d86563SAlexander Pyhalov }
388*16d86563SAlexander Pyhalov break;
389*16d86563SAlexander Pyhalov case G13:
390*16d86563SAlexander Pyhalov if (**inbuf == ESC) {
391*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = **inbuf;
392*16d86563SAlexander Pyhalov st->_gstate = G14;
393*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
394*16d86563SAlexander Pyhalov errno = st->_errno;
395*16d86563SAlexander Pyhalov return (size_t)-1;
396*16d86563SAlexander Pyhalov } else {
397*16d86563SAlexander Pyhalov st->_gstate = G0;
398*16d86563SAlexander Pyhalov st->_istate = IN;
399*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
400*16d86563SAlexander Pyhalov continue;
401*16d86563SAlexander Pyhalov }
402*16d86563SAlexander Pyhalov break;
403*16d86563SAlexander Pyhalov case G14:
404*16d86563SAlexander Pyhalov if (**inbuf == SS2) {
405*16d86563SAlexander Pyhalov st->_istate = OUT;
406*16d86563SAlexander Pyhalov st->_gstate = G15;
407*16d86563SAlexander Pyhalov st->_bufcont = 0;
408*16d86563SAlexander Pyhalov st->_last_plane = st->_plane = 2;
409*16d86563SAlexander Pyhalov } else if (**inbuf == '$') {
410*16d86563SAlexander Pyhalov st->_bufcont --;
411*16d86563SAlexander Pyhalov if (flush_buf(st, outbuf, outbytesleft) == -1) {
412*16d86563SAlexander Pyhalov errno = st->_errno;
413*16d86563SAlexander Pyhalov return (size_t)-1;
414*16d86563SAlexander Pyhalov } else {
415*16d86563SAlexander Pyhalov st->_gstate = G1;
416*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
417*16d86563SAlexander Pyhalov st->_istate = IN;
418*16d86563SAlexander Pyhalov continue;
419*16d86563SAlexander Pyhalov }
420*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
421*16d86563SAlexander Pyhalov errno = st->_errno;
422*16d86563SAlexander Pyhalov return (size_t)-1;
423*16d86563SAlexander Pyhalov } else {
424*16d86563SAlexander Pyhalov st->_gstate = G0;
425*16d86563SAlexander Pyhalov st->_istate = IN;
426*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
427*16d86563SAlexander Pyhalov continue;
428*16d86563SAlexander Pyhalov }
429*16d86563SAlexander Pyhalov break;
430*16d86563SAlexander Pyhalov case G15:
431*16d86563SAlexander Pyhalov if (**inbuf == SI) {
432*16d86563SAlexander Pyhalov st->_gstate = G16;
433*16d86563SAlexander Pyhalov st->_istate = IN;
434*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
435*16d86563SAlexander Pyhalov } else if (**inbuf == ESC) {
436*16d86563SAlexander Pyhalov /*
437*16d86563SAlexander Pyhalov && *((*inbuf) + 1) == '$') {
438*16d86563SAlexander Pyhalov */
439*16d86563SAlexander Pyhalov st->_bufcont = 0;
440*16d86563SAlexander Pyhalov st->_gstate = G0;
441*16d86563SAlexander Pyhalov continue;
442*16d86563SAlexander Pyhalov } else {
443*16d86563SAlexander Pyhalov st->_keepc[0] = **inbuf;
444*16d86563SAlexander Pyhalov st->_gstate = G18;
445*16d86563SAlexander Pyhalov }
446*16d86563SAlexander Pyhalov break;
447*16d86563SAlexander Pyhalov case G16:
448*16d86563SAlexander Pyhalov if (**inbuf == ESC) {
449*16d86563SAlexander Pyhalov st->_gstate = G17;
450*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = ESC;
451*16d86563SAlexander Pyhalov } else {
452*16d86563SAlexander Pyhalov **outbuf = **inbuf;
453*16d86563SAlexander Pyhalov (*outbuf) ++;
454*16d86563SAlexander Pyhalov (*outbytesleft) --;
455*16d86563SAlexander Pyhalov st->_bufcont = 0;
456*16d86563SAlexander Pyhalov }
457*16d86563SAlexander Pyhalov break;
458*16d86563SAlexander Pyhalov case G17:
459*16d86563SAlexander Pyhalov if (**inbuf == '$') {
460*16d86563SAlexander Pyhalov st->_gstate = G1;
461*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = '$';
462*16d86563SAlexander Pyhalov continue;
463*16d86563SAlexander Pyhalov } else if (**inbuf == SS2) {
464*16d86563SAlexander Pyhalov st->_bufcont = 0;
465*16d86563SAlexander Pyhalov st->_gstate = G15;
466*16d86563SAlexander Pyhalov st->_istate = OUT;
467*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
468*16d86563SAlexander Pyhalov errno = st->_errno;
469*16d86563SAlexander Pyhalov return (size_t)-1;
470*16d86563SAlexander Pyhalov } else {
471*16d86563SAlexander Pyhalov st->_gstate = G16;
472*16d86563SAlexander Pyhalov st->_istate = IN;
473*16d86563SAlexander Pyhalov }
474*16d86563SAlexander Pyhalov break;
475*16d86563SAlexander Pyhalov case G18:
476*16d86563SAlexander Pyhalov st->_keepc[1] = **inbuf;
477*16d86563SAlexander Pyhalov st->_gstate = G15;
478*16d86563SAlexander Pyhalov if ((n = iso_cns_to_utf(st, \
479*16d86563SAlexander Pyhalov *outbuf, \
480*16d86563SAlexander Pyhalov *outbytesleft)) > 0) {
481*16d86563SAlexander Pyhalov (*outbuf)+=n;
482*16d86563SAlexander Pyhalov (*outbytesleft)-=n;
483*16d86563SAlexander Pyhalov } else {
484*16d86563SAlexander Pyhalov errno = st->_errno;
485*16d86563SAlexander Pyhalov return (size_t)-1;
486*16d86563SAlexander Pyhalov }
487*16d86563SAlexander Pyhalov break;
488*16d86563SAlexander Pyhalov case G19: /* Plane #: 3 - 16 */
489*16d86563SAlexander Pyhalov c = **inbuf;
490*16d86563SAlexander Pyhalov if (c == 'I' || \
491*16d86563SAlexander Pyhalov c == 'J' || \
492*16d86563SAlexander Pyhalov c == 'K' || \
493*16d86563SAlexander Pyhalov c == 'L' || \
494*16d86563SAlexander Pyhalov c == 'M' || \
495*16d86563SAlexander Pyhalov c == 'N' || \
496*16d86563SAlexander Pyhalov c == 'O' || \
497*16d86563SAlexander Pyhalov c == 'P' || \
498*16d86563SAlexander Pyhalov c == 'Q' || \
499*16d86563SAlexander Pyhalov c == 'R' || \
500*16d86563SAlexander Pyhalov c == 'S' || \
501*16d86563SAlexander Pyhalov c == 'T' || \
502*16d86563SAlexander Pyhalov c == 'U' || \
503*16d86563SAlexander Pyhalov c == 'V') {
504*16d86563SAlexander Pyhalov st->_plane = c - 'I' + 3;
505*16d86563SAlexander Pyhalov st->_gstate = G20;
506*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
507*16d86563SAlexander Pyhalov errno = st->_errno;
508*16d86563SAlexander Pyhalov return (size_t)-1;
509*16d86563SAlexander Pyhalov } else {
510*16d86563SAlexander Pyhalov st->_gstate = G0;
511*16d86563SAlexander Pyhalov st->_errno = 0;
512*16d86563SAlexander Pyhalov st->_istate = IN;
513*16d86563SAlexander Pyhalov st->_plane = st->_last_plane;
514*16d86563SAlexander Pyhalov continue;
515*16d86563SAlexander Pyhalov }
516*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = c;
517*16d86563SAlexander Pyhalov break;
518*16d86563SAlexander Pyhalov case G20:
519*16d86563SAlexander Pyhalov if (**inbuf == ESC) {
520*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = **inbuf;
521*16d86563SAlexander Pyhalov st->_gstate = G21;
522*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
523*16d86563SAlexander Pyhalov errno = st->_errno;
524*16d86563SAlexander Pyhalov return (size_t)-1;
525*16d86563SAlexander Pyhalov } else {
526*16d86563SAlexander Pyhalov st->_gstate = G0;
527*16d86563SAlexander Pyhalov st->_istate = IN;
528*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
529*16d86563SAlexander Pyhalov continue;
530*16d86563SAlexander Pyhalov }
531*16d86563SAlexander Pyhalov break;
532*16d86563SAlexander Pyhalov case G21:
533*16d86563SAlexander Pyhalov if (**inbuf == SS3) {
534*16d86563SAlexander Pyhalov st->_istate = OUT;
535*16d86563SAlexander Pyhalov st->_gstate = G22;
536*16d86563SAlexander Pyhalov st->_bufcont = 0;
537*16d86563SAlexander Pyhalov } else if (**inbuf == '$') {
538*16d86563SAlexander Pyhalov st->_bufcont --;
539*16d86563SAlexander Pyhalov if (flush_buf(st, outbuf, outbytesleft) == -1) {
540*16d86563SAlexander Pyhalov errno = st->_errno;
541*16d86563SAlexander Pyhalov return (size_t)-1;
542*16d86563SAlexander Pyhalov } else {
543*16d86563SAlexander Pyhalov st->_istate = IN;
544*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
545*16d86563SAlexander Pyhalov st->_gstate = G1;
546*16d86563SAlexander Pyhalov continue;
547*16d86563SAlexander Pyhalov }
548*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
549*16d86563SAlexander Pyhalov errno = st->_errno;
550*16d86563SAlexander Pyhalov return (size_t)-1;
551*16d86563SAlexander Pyhalov } else {
552*16d86563SAlexander Pyhalov st->_gstate = G0;
553*16d86563SAlexander Pyhalov st->_istate = IN;
554*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
555*16d86563SAlexander Pyhalov continue;
556*16d86563SAlexander Pyhalov }
557*16d86563SAlexander Pyhalov break;
558*16d86563SAlexander Pyhalov case G22:
559*16d86563SAlexander Pyhalov if (**inbuf == SI) {
560*16d86563SAlexander Pyhalov st->_istate = IN;
561*16d86563SAlexander Pyhalov st->_gstate = G24;
562*16d86563SAlexander Pyhalov st->_last_plane = st->_plane;
563*16d86563SAlexander Pyhalov } else {
564*16d86563SAlexander Pyhalov st->_keepc[0] = (char)MBYTE;
565*16d86563SAlexander Pyhalov st->_keepc[1] = (char)(PMASK + st->_plane);
566*16d86563SAlexander Pyhalov st->_keepc[2] = **inbuf;
567*16d86563SAlexander Pyhalov st->_gstate = G23;
568*16d86563SAlexander Pyhalov }
569*16d86563SAlexander Pyhalov break;
570*16d86563SAlexander Pyhalov case G23:
571*16d86563SAlexander Pyhalov st->_keepc[3] = **inbuf;
572*16d86563SAlexander Pyhalov if ((n = iso_cns_to_utf(st, \
573*16d86563SAlexander Pyhalov *outbuf, \
574*16d86563SAlexander Pyhalov *outbytesleft)) > 0) {
575*16d86563SAlexander Pyhalov (*outbuf)+=n;
576*16d86563SAlexander Pyhalov (*outbytesleft-=n);
577*16d86563SAlexander Pyhalov } else {
578*16d86563SAlexander Pyhalov st->_errno = errno;
579*16d86563SAlexander Pyhalov return (size_t)-1;
580*16d86563SAlexander Pyhalov }
581*16d86563SAlexander Pyhalov st->_gstate = G22;
582*16d86563SAlexander Pyhalov break;
583*16d86563SAlexander Pyhalov case G24:
584*16d86563SAlexander Pyhalov if (**inbuf == ESC) {
585*16d86563SAlexander Pyhalov st->_gstate = G25;
586*16d86563SAlexander Pyhalov st->_buf[st->_bufcont++] = ESC;
587*16d86563SAlexander Pyhalov } else {
588*16d86563SAlexander Pyhalov **outbuf = **inbuf;
589*16d86563SAlexander Pyhalov (*outbuf)++;
590*16d86563SAlexander Pyhalov (*outbytesleft)--;
591*16d86563SAlexander Pyhalov st->_bufcont = 0;
592*16d86563SAlexander Pyhalov }
593*16d86563SAlexander Pyhalov break;
594*16d86563SAlexander Pyhalov case G25:
595*16d86563SAlexander Pyhalov if (**inbuf == '$') {
596*16d86563SAlexander Pyhalov st->_gstate = G1;
597*16d86563SAlexander Pyhalov continue;
598*16d86563SAlexander Pyhalov } else if (**inbuf == SS3) {
599*16d86563SAlexander Pyhalov st->_gstate = G22;
600*16d86563SAlexander Pyhalov st->_bufcont = 0;
601*16d86563SAlexander Pyhalov st->_istate = OUT;
602*16d86563SAlexander Pyhalov } else if (flush_buf(st, outbuf, outbytesleft) == -1) {
603*16d86563SAlexander Pyhalov errno = st->_errno;
604*16d86563SAlexander Pyhalov return (size_t)-1;
605*16d86563SAlexander Pyhalov } else {
606*16d86563SAlexander Pyhalov st->_gstate = G24;
607*16d86563SAlexander Pyhalov st->_istate = IN;
608*16d86563SAlexander Pyhalov }
609*16d86563SAlexander Pyhalov break;
610*16d86563SAlexander Pyhalov default: /* should never come here */
611*16d86563SAlexander Pyhalov st->_errno = errno = EILSEQ;
612*16d86563SAlexander Pyhalov st->_gstate = G0; /* reset state */
613*16d86563SAlexander Pyhalov break;
614*16d86563SAlexander Pyhalov } /* end of switch */
615*16d86563SAlexander Pyhalov
616*16d86563SAlexander Pyhalov (*inbuf)++;
617*16d86563SAlexander Pyhalov (*inbytesleft)--;
618*16d86563SAlexander Pyhalov
619*16d86563SAlexander Pyhalov if (st->_errno) {
620*16d86563SAlexander Pyhalov break;
621*16d86563SAlexander Pyhalov }
622*16d86563SAlexander Pyhalov if (errno)
623*16d86563SAlexander Pyhalov {
624*16d86563SAlexander Pyhalov return((size_t)(-1));
625*16d86563SAlexander Pyhalov }
626*16d86563SAlexander Pyhalov }
627*16d86563SAlexander Pyhalov
628*16d86563SAlexander Pyhalov if (*inbytesleft > 0 && *outbytesleft == 0) {
629*16d86563SAlexander Pyhalov errno = E2BIG;
630*16d86563SAlexander Pyhalov return((size_t)(-1));
631*16d86563SAlexander Pyhalov }
632*16d86563SAlexander Pyhalov return (size_t)(*inbytesleft);
633*16d86563SAlexander Pyhalov }
634*16d86563SAlexander Pyhalov
iso_gb_to_utf(_iconv_st * st,char * buf,size_t buflen)635*16d86563SAlexander Pyhalov int iso_gb_to_utf(_iconv_st * st, char* buf, size_t buflen)
636*16d86563SAlexander Pyhalov {
637*16d86563SAlexander Pyhalov char in_byte1, in_byte2;
638*16d86563SAlexander Pyhalov int idx;
639*16d86563SAlexander Pyhalov int unicode;
640*16d86563SAlexander Pyhalov
641*16d86563SAlexander Pyhalov if ( buflen < 2 ) {
642*16d86563SAlexander Pyhalov st->_errno = E2BIG;
643*16d86563SAlexander Pyhalov return -1;
644*16d86563SAlexander Pyhalov }
645*16d86563SAlexander Pyhalov
646*16d86563SAlexander Pyhalov in_byte1=st->_keepc[0];
647*16d86563SAlexander Pyhalov in_byte2=st->_keepc[1];
648*16d86563SAlexander Pyhalov
649*16d86563SAlexander Pyhalov idx = (((in_byte1 & 0xff) - 0x21) * 94) + (in_byte2 & 0xff) - 0x21;
650*16d86563SAlexander Pyhalov if (idx < 0 || idx > GBMAX - 1) {
651*16d86563SAlexander Pyhalov errno = EILSEQ;
652*16d86563SAlexander Pyhalov return -1;
653*16d86563SAlexander Pyhalov }
654*16d86563SAlexander Pyhalov unicode = Unicode[idx];
655*16d86563SAlexander Pyhalov if (unicode >= 0x0080 && unicode <= 0x07ff) {
656*16d86563SAlexander Pyhalov if ( buflen < 2 ) {
657*16d86563SAlexander Pyhalov errno = E2BIG;
658*16d86563SAlexander Pyhalov return 0;
659*16d86563SAlexander Pyhalov }
660*16d86563SAlexander Pyhalov *buf = ((unicode >> 6) & 0x1f) | 0xc0;
661*16d86563SAlexander Pyhalov *(buf+1) = (unicode & 0x3f) | MSB;
662*16d86563SAlexander Pyhalov return 2;
663*16d86563SAlexander Pyhalov }
664*16d86563SAlexander Pyhalov if (unicode >= 0x0800 && unicode <= 0xffff) {
665*16d86563SAlexander Pyhalov if ( buflen < 3 ) {
666*16d86563SAlexander Pyhalov errno = E2BIG;
667*16d86563SAlexander Pyhalov return 0;
668*16d86563SAlexander Pyhalov }
669*16d86563SAlexander Pyhalov *buf = ((unicode >> 12) & 0x0f) | 0xe0;
670*16d86563SAlexander Pyhalov *(buf+1) = ((unicode >> 6) & 0x3f) | MSB;
671*16d86563SAlexander Pyhalov *(buf+2) = (unicode & 0x3f) | MSB;
672*16d86563SAlexander Pyhalov return 3;
673*16d86563SAlexander Pyhalov }
674*16d86563SAlexander Pyhalov if ( buflen < 3 ) {
675*16d86563SAlexander Pyhalov errno = E2BIG;
676*16d86563SAlexander Pyhalov return 0;
677*16d86563SAlexander Pyhalov }
678*16d86563SAlexander Pyhalov
679*16d86563SAlexander Pyhalov *buf = UTF8_NON_ID_CHAR1;
680*16d86563SAlexander Pyhalov *(buf+1) = UTF8_NON_ID_CHAR2;
681*16d86563SAlexander Pyhalov *(buf+2) = UTF8_NON_ID_CHAR3;
682*16d86563SAlexander Pyhalov return 3;
683*16d86563SAlexander Pyhalov }
684*16d86563SAlexander Pyhalov
685*16d86563SAlexander Pyhalov /*
686*16d86563SAlexander Pyhalov * Return: > 0 - converted with enough space in output buffer
687*16d86563SAlexander Pyhalov * = 0 - no space in outbuf
688*16d86563SAlexander Pyhalov */
iso_cns_to_utf(_iconv_st * st,char * buf,size_t buflen)689*16d86563SAlexander Pyhalov int iso_cns_to_utf(_iconv_st * st, char* buf, size_t buflen) {
690*16d86563SAlexander Pyhalov char cns_str[3];
691*16d86563SAlexander Pyhalov unsigned long cns_val; /* MSB mask off CNS 11643 value */
692*16d86563SAlexander Pyhalov int unidx; /* binary search index */
693*16d86563SAlexander Pyhalov unsigned long utf_val; /* unicode code */
694*16d86563SAlexander Pyhalov
695*16d86563SAlexander Pyhalov if (st->_plane == 1) {
696*16d86563SAlexander Pyhalov cns_str[0] = st->_keepc[0] & MSB_OFF;
697*16d86563SAlexander Pyhalov cns_str[1] = st->_keepc[1] & MSB_OFF;
698*16d86563SAlexander Pyhalov } else {
699*16d86563SAlexander Pyhalov cns_str[0] = st->_keepc[0] & MSB_OFF;
700*16d86563SAlexander Pyhalov cns_str[1] = st->_keepc[1] & MSB_OFF;
701*16d86563SAlexander Pyhalov }
702*16d86563SAlexander Pyhalov cns_val = (cns_str[0] << 8) + cns_str[1];
703*16d86563SAlexander Pyhalov if (buflen < 2) {
704*16d86563SAlexander Pyhalov errno = E2BIG;
705*16d86563SAlexander Pyhalov return(0);
706*16d86563SAlexander Pyhalov }
707*16d86563SAlexander Pyhalov
708*16d86563SAlexander Pyhalov switch (st->_plane) {
709*16d86563SAlexander Pyhalov case 1:
710*16d86563SAlexander Pyhalov unidx = binsearch(cns_val, cns1_utf_tab, MAX_CNS1_NUM);
711*16d86563SAlexander Pyhalov if (unidx >= 0)
712*16d86563SAlexander Pyhalov utf_val = cns1_utf_tab[unidx].value;
713*16d86563SAlexander Pyhalov break;
714*16d86563SAlexander Pyhalov case 2:
715*16d86563SAlexander Pyhalov unidx = binsearch(cns_val, cns2_utf_tab, MAX_CNS2_NUM);
716*16d86563SAlexander Pyhalov if (unidx >= 0)
717*16d86563SAlexander Pyhalov utf_val = cns2_utf_tab[unidx].value;
718*16d86563SAlexander Pyhalov break;
719*16d86563SAlexander Pyhalov case 3:
720*16d86563SAlexander Pyhalov unidx = binsearch(cns_val, cns3_utf_tab, MAX_CNS3_NUM);
721*16d86563SAlexander Pyhalov if (unidx >= 0)
722*16d86563SAlexander Pyhalov utf_val = cns3_utf_tab[unidx].value;
723*16d86563SAlexander Pyhalov break;
724*16d86563SAlexander Pyhalov default:
725*16d86563SAlexander Pyhalov unidx = -1; /* no mapping from CNS to Unicode out of plane 1,2&3 */
726*16d86563SAlexander Pyhalov break;
727*16d86563SAlexander Pyhalov }
728*16d86563SAlexander Pyhalov
729*16d86563SAlexander Pyhalov
730*16d86563SAlexander Pyhalov if (unidx < 0) { /* no match from CNS to Unicode */
731*16d86563SAlexander Pyhalov *buf = UTF8_NON_ID_CHAR1;
732*16d86563SAlexander Pyhalov *(buf+1) = UTF8_NON_ID_CHAR2;
733*16d86563SAlexander Pyhalov *(buf+2) = UTF8_NON_ID_CHAR3;
734*16d86563SAlexander Pyhalov return 3;
735*16d86563SAlexander Pyhalov } else {
736*16d86563SAlexander Pyhalov if (utf_val >= 0x0080 && utf_val <= 0x07ff) {
737*16d86563SAlexander Pyhalov if ( buflen < 2 ) {
738*16d86563SAlexander Pyhalov errno = E2BIG;
739*16d86563SAlexander Pyhalov return 0;
740*16d86563SAlexander Pyhalov }
741*16d86563SAlexander Pyhalov *buf = ((utf_val >> 6) & 0x1f) | 0xc0;
742*16d86563SAlexander Pyhalov *(buf+1) = (utf_val & 0x3f) | MSB;
743*16d86563SAlexander Pyhalov return 2;
744*16d86563SAlexander Pyhalov }
745*16d86563SAlexander Pyhalov if (utf_val >= 0x0800 && utf_val <= 0xffff) {
746*16d86563SAlexander Pyhalov if ( buflen < 3 ) {
747*16d86563SAlexander Pyhalov errno = E2BIG;
748*16d86563SAlexander Pyhalov return 0;
749*16d86563SAlexander Pyhalov }
750*16d86563SAlexander Pyhalov *buf = ((utf_val >> 12) & 0x0f) | 0xe0;
751*16d86563SAlexander Pyhalov *(buf+1) = ((utf_val >> 6) & 0x3f) | MSB;
752*16d86563SAlexander Pyhalov *(buf+2) = (utf_val & 0x3f) | MSB;
753*16d86563SAlexander Pyhalov return 3;
754*16d86563SAlexander Pyhalov }
755*16d86563SAlexander Pyhalov if ( buflen < 3 ) {
756*16d86563SAlexander Pyhalov errno = E2BIG;
757*16d86563SAlexander Pyhalov return 0;
758*16d86563SAlexander Pyhalov }
759*16d86563SAlexander Pyhalov
760*16d86563SAlexander Pyhalov *buf = UTF8_NON_ID_CHAR1;
761*16d86563SAlexander Pyhalov *(buf+1) = UTF8_NON_ID_CHAR2;
762*16d86563SAlexander Pyhalov *(buf+2) = UTF8_NON_ID_CHAR3;
763*16d86563SAlexander Pyhalov return 3;
764*16d86563SAlexander Pyhalov }
765*16d86563SAlexander Pyhalov
766*16d86563SAlexander Pyhalov }
767*16d86563SAlexander Pyhalov
768*16d86563SAlexander Pyhalov /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */
binsearch(unsigned long x,table_t v[],int n)769*16d86563SAlexander Pyhalov int binsearch(unsigned long x, table_t v[], int n)
770*16d86563SAlexander Pyhalov {
771*16d86563SAlexander Pyhalov int low, high, mid;
772*16d86563SAlexander Pyhalov
773*16d86563SAlexander Pyhalov low = 0;
774*16d86563SAlexander Pyhalov high = n - 1;
775*16d86563SAlexander Pyhalov while (low <= high) {
776*16d86563SAlexander Pyhalov mid = (low + high) / 2;
777*16d86563SAlexander Pyhalov if (x < v[mid].key)
778*16d86563SAlexander Pyhalov high = mid - 1;
779*16d86563SAlexander Pyhalov else if (x > v[mid].key)
780*16d86563SAlexander Pyhalov low = mid + 1;
781*16d86563SAlexander Pyhalov else /* found match */
782*16d86563SAlexander Pyhalov return mid;
783*16d86563SAlexander Pyhalov }
784*16d86563SAlexander Pyhalov return (-1); /* no match */
785*16d86563SAlexander Pyhalov }
786*16d86563SAlexander Pyhalov
787*16d86563SAlexander Pyhalov
788*16d86563SAlexander Pyhalov #ifdef DEBUG
main(int argc,char ** argv)789*16d86563SAlexander Pyhalov main(int argc, char ** argv) {
790*16d86563SAlexander Pyhalov char *inbuf, *outbuf, *in_tmp, *out_tmp;
791*16d86563SAlexander Pyhalov size_t inbytesleft, outbytesleft;
792*16d86563SAlexander Pyhalov int fd;
793*16d86563SAlexander Pyhalov int i;
794*16d86563SAlexander Pyhalov struct stat s;
795*16d86563SAlexander Pyhalov _iconv_st * st;
796*16d86563SAlexander Pyhalov if (argc < 2) {
797*16d86563SAlexander Pyhalov fprintf(stderr, "Usage: %s input\n", argv[0]);
798*16d86563SAlexander Pyhalov exit(-1);
799*16d86563SAlexander Pyhalov }
800*16d86563SAlexander Pyhalov if ((fd = open(argv[1], O_RDONLY)) == -1) {
801*16d86563SAlexander Pyhalov perror("open");
802*16d86563SAlexander Pyhalov exit(-2);
803*16d86563SAlexander Pyhalov }
804*16d86563SAlexander Pyhalov if (fstat(fd, &s) == -1) {
805*16d86563SAlexander Pyhalov perror("stat");
806*16d86563SAlexander Pyhalov exit(-3);
807*16d86563SAlexander Pyhalov }
808*16d86563SAlexander Pyhalov inbytesleft = outbytesleft = s.st_size;
809*16d86563SAlexander Pyhalov in_tmp = inbuf = (char *)malloc(inbytesleft);
810*16d86563SAlexander Pyhalov out_tmp = outbuf = (char *)malloc(outbytesleft);
811*16d86563SAlexander Pyhalov if (!inbuf || !outbuf) {
812*16d86563SAlexander Pyhalov perror("malloc");
813*16d86563SAlexander Pyhalov exit(-1);
814*16d86563SAlexander Pyhalov }
815*16d86563SAlexander Pyhalov if (read(fd, inbuf, inbytesleft) != inbytesleft) {
816*16d86563SAlexander Pyhalov perror("read");
817*16d86563SAlexander Pyhalov exit(-4);
818*16d86563SAlexander Pyhalov }
819*16d86563SAlexander Pyhalov for (i = 0; i < inbytesleft; i++)
820*16d86563SAlexander Pyhalov fprintf(stderr, "%x\t", *(inbuf+i));
821*16d86563SAlexander Pyhalov fprintf(stderr, "\n");
822*16d86563SAlexander Pyhalov st = (_iconv_st *)_icv_open();
823*16d86563SAlexander Pyhalov if (st == (_iconv_st *) -1) {
824*16d86563SAlexander Pyhalov perror("_icv_open");
825*16d86563SAlexander Pyhalov exit(-1);
826*16d86563SAlexander Pyhalov }
827*16d86563SAlexander Pyhalov if (_icv_iconv(st, \
828*16d86563SAlexander Pyhalov &inbuf, &inbytesleft, \
829*16d86563SAlexander Pyhalov &outbuf, &outbytesleft) == -1) {
830*16d86563SAlexander Pyhalov perror("icv_iconv");
831*16d86563SAlexander Pyhalov fprintf(stderr, "\ninbytesleft = %d\n", inbytesleft);
832*16d86563SAlexander Pyhalov exit(-2);
833*16d86563SAlexander Pyhalov }
834*16d86563SAlexander Pyhalov if (write(1, out_tmp, s.st_size - outbytesleft) == -1) {
835*16d86563SAlexander Pyhalov perror("write");
836*16d86563SAlexander Pyhalov exit(-1);
837*16d86563SAlexander Pyhalov }
838*16d86563SAlexander Pyhalov free(in_tmp);
839*16d86563SAlexander Pyhalov free(out_tmp);
840*16d86563SAlexander Pyhalov close(fd);
841*16d86563SAlexander Pyhalov _icv_close(st);
842*16d86563SAlexander Pyhalov }
843*16d86563SAlexander Pyhalov #endif
844