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