1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright(c) 2001 Sun Microsystems, Inc.
23  * All rights reserved.
24  */
25 #include <stdio.h>
26 #include <errno.h>
27 #include <strings.h>
28 #include <stdlib.h>
29 #include "pc-iscii.h"
30 
31 #define MSB          0x80
32 #define REPLACE_CHAR '?'
33 
34 typedef struct _icv_state {
35     int dummy;
36 } _iconv_st;
37 
38 static uchar
traverse_table(Entry * entry,int num,uchar pc_iscii)39 traverse_table(Entry *entry , int num, uchar pc_iscii)
40 {
41     int   i=0;
42     uchar iscii=0;
43 
44     for ( ; i < num; ++i) {
45         Entry en = entry[i];
46 
47         if ( pc_iscii < en.pc_iscii ) break;
48         if ( pc_iscii >= en.pc_iscii && pc_iscii < en.pc_iscii + en.count ) {
49             iscii = (pc_iscii - en.pc_iscii) + en.iscii;
50             break;
51         }
52     }
53 
54     return iscii;
55 }
56 
57 void *
_icv_open()58 _icv_open()
59 {
60     _iconv_st *st;
61 
62     if ((st = (_iconv_st*)malloc(sizeof(_iconv_st))) == NULL) {
63         errno = ENOMEM;
64         return ((void*)-1);
65     }
66 
67     bzero(st, sizeof(_iconv_st));
68 
69     return ((void*)st);
70 }
71 
72 /*
73  * Close; called from iconv_close()
74  */
75 void
_icv_close(_iconv_st * st)76 _icv_close(_iconv_st *st)
77 {
78     if (!st)
79         errno = EBADF;
80     else
81         free(st);
82 }
83 
84 size_t
_icv_iconv(_iconv_st * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)85 _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft,
86        char **outbuf, size_t *outbytesleft)
87 {
88     if (st == NULL) {
89         errno = EBADF;
90         return ((size_t) -1);
91     }
92 
93     if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
94         return ((size_t)0);
95     }
96 
97     /* a state machine for interpreting ISCII code */
98     while (*inbytesleft > 0 && *outbytesleft > 0) {
99         uchar c = (uchar)**inbuf;
100 
101         if ( c & MSB ) {
102             uchar iscii = traverse_table(pciscii_isc_tbl,
103                     sizeof(pciscii_isc_tbl)/sizeof(Entry), c);
104             if ( iscii ) **outbuf = iscii;
105             else **outbuf = REPLACE_CHAR;
106         } else { /* ASCII */
107             **outbuf = c;
108         }
109 
110         (*inbuf)++;
111         (*inbytesleft)--;
112         (*outbuf)++;
113         (*outbytesleft)--;
114     }
115 
116     if ( *inbytesleft > 0 && *outbytesleft == 0 ) {
117          errno = E2BIG;
118          return ((size_t)-1);
119     }
120 
121     return ((size_t)(*inbytesleft));
122 }
123