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) 1995 by Sun Microsystems, Inc.
23 * All Rights Reserved.
24 */
25
26
27 #include <stdio.h>
28 #include <libintl.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include "ktable.h"
32 #include "hangulcode.h"
33
34 #define MSB 0x80
35
36
37 struct _cv_state {
38 int _st_status;
39 int _gstate;
40 };
41
42 enum _GSTATE { _nostate, _g0, _g1};
43
44 enum SHIFT_STAT {SHIFT_IN, SHIFT_OUT};
45
46
47 typedef struct __conv_desc {
48 enum { NDY, KSC5601 } designator;
49 enum { ASCII, WANSUNG } state;
50 } _conv_desc;
51
52
53 /**** _ I C V _ O P E N ****/
54
_icv_open()55 void* _icv_open()
56 {
57 _conv_desc* cd = (_conv_desc*)malloc(sizeof(_conv_desc));
58
59 if (cd == (_conv_desc*)NULL)
60 {
61 errno = ENOMEM;
62 return((void*)-1);
63 }
64
65 cd->designator = NDY;
66 cd->state = ASCII;
67
68 return((void*)cd);
69 } /* end of int _icv_open(). */
70
71
72 /**** _ I C V _ C L O S E ****/
73
_icv_close(_conv_desc * cd)74 void _icv_close(_conv_desc* cd)
75 {
76 if (!cd)
77 errno = EBADF;
78 else
79 free((void*)cd);
80 } /* end of void _icv_close(_conv_desc*). */
81
82
83 /**** _ I C V _ I C O N V ****/
84
_icv_iconv(_conv_desc * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)85 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft,
86 char** outbuf, size_t* outbufleft)
87 {
88 size_t ret_val = 0;
89 unsigned char* ib;
90 unsigned char* ob;
91 unsigned char* ibtail;
92 unsigned char* obtail;
93
94 if (!cd)
95 {
96 errno = EBADF;
97 return((size_t)-1);
98 }
99
100 if (!inbuf || !(*inbuf))
101 {
102 cd->designator = NDY;
103 cd->state = ASCII;
104 return((size_t)0);
105 }
106
107 ib = (unsigned char*)*inbuf;
108 ob = (unsigned char*)*outbuf;
109 ibtail = ib + *inbufleft;
110 obtail = ob + *outbufleft;
111
112 while (ib < ibtail)
113 {
114 if (cd->designator == NDY)
115 {
116 if (*ib == ESC)
117 {
118 if ((ibtail - ib) < 4)
119 {
120 errno = EINVAL;
121 ret_val = (size_t)-1;
122 break;
123 }
124
125 if (*(ib + 1) == '$' && *(ib + 2) == ')' &&
126 *(ib + 3) == 'C')
127 {
128 cd->designator = KSC5601;
129 ib += 4;
130 continue;
131 }
132 }
133
134 if (ob >= obtail)
135 {
136 errno = E2BIG;
137 ret_val = (size_t)-1;
138 break;
139 }
140 *ob++ = *ib++;
141 }
142 else
143 {
144 if (*ib == SI)
145 {
146 cd->state = ASCII;
147 ib++;
148 continue;
149 }
150 else if (*ib == SO)
151 {
152 cd->state = WANSUNG;
153 ib++;
154 continue;
155 }
156 else if ((*ib == ' ' && cd->state == WANSUNG) ||
157 cd->state == ASCII)
158 {
159 if (ob >= obtail)
160 {
161 errno = E2BIG;
162 ret_val = (size_t)-1;
163 break;
164 }
165 *ob++ = *ib++;
166 continue;
167 }
168
169 /* Pure KS C 5601 Wansung code */
170 if ((ibtail - ib) < 2)
171 {
172 errno = EINVAL;
173 ret_val = (size_t)-1;
174 break;
175 }
176
177 if (*ib < 0x21 || *ib > 0x7D || *(ib + 1) < 0x21 ||
178 *(ib + 1) == 0x7F)
179 {
180 errno = EILSEQ;
181 ret_val = (size_t)-1;
182 break;
183 }
184
185 if ((obtail - ob) < 2)
186 {
187 errno = E2BIG;
188 ret_val = (size_t)-1;
189 break;
190 }
191 *ob++ = *ib++ | 0x80;
192 *ob++ = *ib++ | 0x80;
193 }
194 }
195
196 *inbuf = (char*)ib;
197 *inbufleft = ibtail - ib;
198 *outbuf = (char*)ob;
199 *outbufleft = obtail - ob;
200
201 return(ret_val);
202 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/
203
204 void *
_cv_open()205 _cv_open()
206 {
207 struct _cv_state *st;
208
209 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL)
210 return ((void *)-1);
211
212 st->_st_status = SHIFT_IN;
213 st->_gstate = _nostate;
214
215 return (st);
216 }
217
218 void
_cv_close(struct _cv_state * st)219 _cv_close(struct _cv_state *st)
220 {
221 free(st);
222 }
223
224
225 size_t
_cv_enconv(struct _cv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)226 _cv_enconv(struct _cv_state *st, char **inbuf, size_t*inbytesleft,
227 char **outbuf, size_t*outbytesleft)
228 {
229 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
230 st->_st_status = SHIFT_IN;
231 st->_gstate = _nostate;
232 /*
233 * Note that no shift sequence is needed for
234 * the target encoding.
235 */
236 return (0);
237 }
238
239 if ( st->_gstate == _nostate )
240 st->_gstate = _g0;
241
242 while (*inbytesleft > 0 && *outbytesleft > 0) {
243 if ( st->_gstate == _g1 ) {
244 if (**inbuf == SO) {
245 st->_st_status = SHIFT_OUT;
246 } else if (**inbuf == SI) {
247 st->_st_status = SHIFT_IN;
248 } else {
249 if (st->_st_status == SHIFT_OUT) {
250 while (*inbytesleft > 0 && *outbytesleft > 0 &&
251 **inbuf != SI ) {
252 **outbuf = (**inbuf == ' ') ? ' ' : (MSB | **inbuf);
253 (*outbuf)++, (*outbytesleft)--;
254 (*inbuf)++, (*inbytesleft)--;
255 }
256 continue;
257 } else {
258 **outbuf = **inbuf;
259 (*outbuf)++, (*outbytesleft)--;
260 }
261 }
262 } else {
263 char *temp;
264
265 temp = *inbuf;
266
267 if ( *inbytesleft >= 4 && temp[0] == ESC && temp[1] == '$'
268 && temp[2] == ')' && temp[3] == 'C' ) {
269 st->_gstate = _g1;
270 *inbuf += 4;
271 *inbytesleft -= 4;
272 continue;
273 } else {
274 **outbuf = **inbuf;
275 (*outbuf)++, (*outbytesleft)--;
276 }
277 }
278
279 (*inbuf)++, (*inbytesleft)--;
280 }
281 return (*inbytesleft);
282 }
283