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 #define MSB_OFF 0x7f
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 char designated;
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->designated = 0;
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 if (cd->state == WANSUNG)
103 {
104 if (outbufleft && *outbufleft >= 1 && outbuf && *outbuf)
105 {
106 **outbuf = SI;
107 (*outbuf)++;
108 (*outbufleft)--;
109 }
110 else
111 {
112 errno = E2BIG;
113 return((size_t)-1);
114 }
115 }
116
117 cd->designated = 0;
118 cd->state = ASCII;
119 return((size_t)0);
120 }
121
122 ib = (unsigned char*)*inbuf;
123 ob = (unsigned char*)*outbuf;
124 ibtail = ib + *inbufleft;
125 obtail = ob + *outbufleft;
126
127 while (ib < ibtail)
128 {
129 if (!(*ib & 0x80)) /* 7 bits */
130 {
131 if (cd->state == WANSUNG)
132 {
133 if (ob >= obtail)
134 {
135 errno = E2BIG;
136 ret_val = (size_t)-1;
137 break;
138 }
139 *ob++ = SI;
140 cd->state = ASCII;
141 }
142 if (ob >= obtail)
143 {
144 errno = E2BIG;
145 ret_val = (size_t)-1;
146 break;
147 }
148 *ob++ = *ib++;
149 }
150 else
151 {
152 if ((ibtail - ib) < 2)
153 {
154 errno = EINVAL;
155 ret_val = (size_t)-1;
156 break;
157 }
158
159 if (!cd->designated)
160 {
161 if ((obtail - ob) < 4)
162 {
163 errno = E2BIG;
164 ret_val = (size_t)-1;
165 break;
166 }
167 *ob++ = ESC; *ob++ = '$';
168 *ob++ = ')'; *ob++ = 'C';
169 cd->designated = 1;
170 }
171 if (cd->state == ASCII)
172 {
173 if (ob >= obtail)
174 {
175 errno = E2BIG;
176 ret_val = (size_t)-1;
177 break;
178 }
179 *ob++ = SO;
180 cd->state = WANSUNG;
181 }
182
183 if ((obtail - ob) < 2)
184 {
185 errno = E2BIG;
186 ret_val = (size_t)-1;
187 break;
188 }
189 *ob++ = *ib++ & 0x7F;
190 *ob++ = *ib++ & 0x7F;
191 }
192 }
193
194 *inbuf = (char*)ib;
195 *inbufleft = ibtail - ib;
196 *outbuf = (char*)ob;
197 *outbufleft = obtail - ob;
198
199 return(ret_val);
200 } /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/
201
202 void *
_cv_open()203 _cv_open()
204 {
205 struct _cv_state *st;
206
207 if ((st = (struct _cv_state *)malloc(sizeof(struct _cv_state))) == NULL)
208 return ((void *)-1);
209
210 st->_st_status = SHIFT_IN;
211 st->_gstate = _nostate;
212
213 return (st);
214 }
215
216 void
_cv_close(struct _cv_state * st)217 _cv_close(struct _cv_state *st)
218 {
219 free(st);
220 }
221
222
223 size_t
_cv_enconv(struct _cv_state * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)224 _cv_enconv(struct _cv_state *st, char **inbuf, size_t*inbytesleft,
225 char **outbuf, size_t*outbytesleft)
226 {
227 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
228 if (st->_st_status == SHIFT_OUT && *outbytesleft > 0)
229 {
230 **outbuf = SI;
231 (*outbytesleft)--;
232 (*outbuf)++;
233 }
234 st->_st_status = SHIFT_IN;
235 st->_gstate = _nostate;
236 /*
237 * Note that no shift sequence is needed for
238 * thetarget encoding.
239 */
240 return (0);
241 }
242
243 if ( st->_gstate == _nostate )
244 st->_gstate = _g0;
245
246 while (*inbytesleft > 0 && *outbytesleft > 0) {
247 if ( **inbuf & MSB ) {
248 if (st->_st_status == SHIFT_IN ) {
249 if ( st->_gstate == _g0 ) {
250 /*
251 * Check the outbytesleft : enough to hold ESC sequence
252 */
253 if ( *outbytesleft < 4 ) {
254 break;
255 }
256
257 st->_gstate = _g1;
258
259 **outbuf = ESC;
260 (*outbuf)++, (*outbytesleft)--;
261 **outbuf = '$';
262 (*outbuf)++, (*outbytesleft)--;
263 **outbuf = ')';
264 (*outbuf)++, (*outbytesleft)--;
265 **outbuf = 'C';
266 (*outbuf)++, (*outbytesleft)--;
267
268 if ( *outbytesleft <= 0 )
269 break;
270 }
271
272 st->_st_status = SHIFT_OUT;
273 **outbuf = SO;
274 (*outbuf)++, (*outbytesleft)--;
275
276 if ( *outbytesleft <= 0 )
277 break;
278 }
279
280 **outbuf = **inbuf & MSB_OFF;
281 (*outbuf)++, (*outbytesleft)--;
282
283 } else {
284 if (st->_st_status == SHIFT_OUT) {
285 st->_st_status = SHIFT_IN;
286 **outbuf = SI;
287 (*outbuf)++, (*outbytesleft)--;
288
289 if ( *outbytesleft <= 0 )
290 break;
291 }
292
293 **outbuf = **inbuf;
294 (*outbuf)++, (*outbytesleft)--;
295
296 }
297
298 (*inbuf)++, (*inbytesleft)--;
299 }
300 return (*inbytesleft);
301 }
302