xref: /illumos-gate/usr/src/lib/iconv_modules/ko/common/iso2022-7_to_UTF2.c (revision cadd68ea0014761eda6a293664086dfa80686d85)
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 
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 
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 
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