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) 1996 by Sun Microsystems, Inc.
23 */
24
25
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <widec.h>
29 #include "common_han.h"
30 #include "euc_utf_api.h"
31
32 #define ESC 0x1B
33 #define SO 0x0E
34 #define SI 0x0F
35
36 typedef struct __conv_desc {
37 enum { NOT_DEFINED_YET, KSC5601 } designator;
38 enum { ASCII, HANGUL } state;
39 } _conv_desc;
40
41 /**** _ I C V _ O P E N ****/
42
_icv_open()43 void* _icv_open()
44 {
45 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc));
46
47 if (cd == (_conv_desc*)NULL)
48 {
49 errno = ENOMEM;
50 return((void*)-1);
51 }
52
53 cd->designator = NOT_DEFINED_YET;
54 cd->state = ASCII;
55
56 return((void*)cd);
57 } /* end of int _icv_open(). */
58
59
60 /**** _ I C V _ C L O S E ****/
61
_icv_close(_conv_desc * cd)62 void _icv_close(_conv_desc* cd)
63 {
64 if (!cd)
65 errno = EBADF;
66 else
67 free((void*)cd);
68 } /* end of void _icv_close(_conv_desc*). */
69
70
71 /**** _ I C V _ I C O N V ****/
72
_icv_iconv(_conv_desc * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)73 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft,
74 char** outbuf, size_t* outbufleft)
75 {
76 size_t ret_val = 0;
77 unsigned char* ib;
78 unsigned char* ob;
79 unsigned char* ibtail;
80 unsigned char* obtail;
81
82 if (!cd)
83 {
84 errno = EBADF;
85 return((size_t)-1);
86 }
87
88 if (!inbuf || !(*inbuf))
89 {
90 cd->designator = NOT_DEFINED_YET;
91 cd->state = ASCII;
92 return((size_t)0);
93 }
94
95 ib = (unsigned char*)*inbuf;
96 ob = (unsigned char*)*outbuf;
97 ibtail = ib + *inbufleft;
98 obtail = ob + *outbufleft;
99
100 while (ib < ibtail)
101 {
102 if (cd->designator == KSC5601)
103 {
104 hcode_type euc_code, utf_code;
105
106 if (*ib == SI)
107 {
108 cd->state = ASCII;
109 ib++;
110 continue;
111 }
112 else if (*ib == SO)
113 {
114 cd->state = HANGUL;
115 ib++;
116 continue;
117 }
118 else if ((*ib == ' ' && cd->state == HANGUL) ||
119 cd->state == ASCII)
120 {
121 if (ob >= obtail)
122 {
123 errno = E2BIG;
124 ret_val = (size_t)-1;
125 break;
126 }
127 *ob++ = *ib++;
128 continue;
129 }
130
131 /* Pure KS C 5601 Wansung code */
132 if ((ibtail - ib) < 2)
133 {
134 errno = EINVAL;
135 ret_val = (size_t)-1;
136 break;
137 }
138
139 if (*ib < 0x21 || *ib > 0x7E || *(ib + 1) < 0x21 ||
140 *(ib + 1) == 0x7F)
141 {
142 errno = EILSEQ;
143 ret_val = (size_t)-1;
144 break;
145 }
146
147 euc_code.code = 0;
148 euc_code.byte.byte3 = *ib;
149 euc_code.byte.byte4 = *(ib + 1);
150 euc_code.wansung.msb1 = 1;
151 euc_code.wansung.msb2 = 1;
152
153 utf_code = _wansung_to_utf8(euc_code);
154
155 if (utf_code.code != 0)
156 {
157 if ((obtail - ob) < 3)
158 {
159 errno = E2BIG;
160 ret_val = (size_t)-1;
161 break;
162 }
163 /* UTF8 code from 2 bytes is always 3 bytes */
164 *ob++ = (char)utf_code.byte.byte2;
165 *ob++ = (char)utf_code.byte.byte3;
166 *ob++ = (char)utf_code.byte.byte4;
167 }
168 else /* FAILED - this means input char isn't belong to
169 * input codeset. */
170 {
171 errno = EILSEQ;
172 ret_val = (size_t)-1;
173 break;
174 }
175 ib += 2;
176
177 }
178 else
179 {
180 if (*ib == ESC)
181 {
182 if ((ibtail - ib) < 4)
183 {
184 errno = EINVAL;
185 ret_val = (size_t)-1;
186 break;
187 }
188
189 if (*(ib + 1) == '$' && *(ib + 2) == ')' &&
190 *(ib + 3) == 'C')
191 {
192 cd->designator = KSC5601;
193 ib += 4;
194 continue;
195 }
196 }
197
198 if (ob >= obtail)
199 {
200 errno = E2BIG;
201 ret_val = (size_t)-1;
202 break;
203 }
204 *ob++ = *ib++;
205 }
206 }
207
208 *inbuf = (char*)ib;
209 *inbufleft = ibtail - ib;
210 *outbuf = (char*)ob;
211 *outbufleft = obtail - ob;
212
213 return(ret_val);
214 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/
215