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 "nbyte_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->cur_stat = 1;
45 	cd->hbuf[1] = cd->hbuf[2] = cd->hbuf[3] = cd->hbuf[4] = '\0';
46 	cd->cur_act = 0;
47 
48 	return((void*)cd);
49 }  /* end of int _icv_open(). */
50 
51 
52 /****  _ I C V _ C L O S E  ****/
53 
_icv_close(_conv_desc * cd)54 void _icv_close(_conv_desc* cd)
55 {
56 	if (!cd)
57 		errno = EBADF;
58 	else
59 		free((void*)cd);
60 }  /* end of void _icv_close(_conv_desc*). */
61 
62 
63 /****  _ I C V _ I C O N V  ****/
64 
_icv_iconv(_conv_desc * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)65 size_t _icv_iconv(_conv_desc* cd, char** inbuf, size_t* inbufleft,
66 			char** outbuf, size_t* outbufleft)
67 {
68 	size_t		ret_val = 0;
69 	unsigned char*	ib;
70 	unsigned char*	ob;
71 	unsigned char*	ibtail;
72 	unsigned char*	obtail;
73 
74 	if (!cd)
75 	{
76 		errno = EBADF;
77 		return((size_t)-1);
78 	}
79 
80 	if (!inbuf || !(*inbuf))
81 	{
82 		cd->cur_stat = 1;
83 		cd->hbuf[1] = cd->hbuf[2] = cd->hbuf[3] = cd->hbuf[4] = '\0';
84 		cd->cur_act = 0;
85 		return((size_t)0);
86 	}
87 
88 	ib = (unsigned char*)*inbuf;
89 	ob = (unsigned char*)*outbuf;
90 	ibtail = ib + *inbufleft;
91 	obtail = ob + *outbufleft;
92 
93 	while (ib < ibtail)
94 	{
95 		int		cur_input, action, state;
96 		unsigned long	ci, v, cf;
97 		char		result;
98 		int		input_conv(char);
99 		unsigned short	make_johap_code(int, char*);
100 		extern char	_johap_to_utf8(unsigned long*, unsigned long*,
101 						unsigned long*, unsigned short);
102 
103 		cur_input = input_conv(*ib);
104 		action = next_act[cd->cur_stat][cur_input];
105 		state = next_stat[cd->cur_stat][cur_input];
106 		if (action == 4)
107 		{
108 			if (ob >= obtail)
109 			{
110 				errno = E2BIG;
111 				ret_val = (size_t)-1;
112 				break;
113 			}
114 			*ob++ = *ib;
115 		}
116 		else if (action >= 5 && action <= 8)
117 			cd->hbuf[action - 4] = *ib;
118 		else if (action == 9)
119 		{
120 			ADD_CONVERTED_CODE(0, 0);
121 			cd->hbuf[1] = *ib;
122 		}
123 		else if (action == 10)
124 		{
125 			ADD_CONVERTED_CODE(0, 0);
126 			cd->hbuf[2] = *ib;
127 			ADD_CONVERTED_CODE(0, 0);
128 		}
129 		else if (action == 11 || action == 12)
130 		{
131 			ADD_CONVERTED_CODE(0, 0);
132 		}
133 		else if (action == 13)
134 		{
135 			ADD_CONVERTED_CODE(0, 1);
136 			*ob++ = *ib;
137 		}
138 		else if (action == 14)
139 		{
140 			register char c1 = cd->hbuf[2], c2 = *ib;
141 
142 			if (c1 == 'l' && c2 == 'b')  /* _|_ && |- */
143 				cd->hbuf[2] = 'm';
144 			else if (c1 == 'l' && c2 == 'c')  /* _|_ && H */
145 				cd->hbuf[2] = 'n';
146 			else if (c1 == 'l' && c2 == '|')  /* _|_ && | */
147 				cd->hbuf[2] = 'o';
148 			else if (c1 == 's' && c2 == 'f')  /* T && -| */
149 				cd->hbuf[2] = 't';
150 			else if (c1 == 's' && c2 == 'g')  /* T && -|| */
151 				cd->hbuf[2] = 'u';
152 			else if (c1 == 's' && c2 == '|')  /* T && | */
153 				cd->hbuf[2] = 'v';
154 			else if (c1 == 'z' && c2 == '|')  /* __ && | */
155 				cd->hbuf[2] = '{';
156 			else
157 				cd->hbuf[2] = *ib;  /* Just in case. */
158 		}
159 		else if (action == 15)
160 		{
161 			cd->hbuf[2] = *ib;
162 			ADD_CONVERTED_CODE(0, 0);
163 		}
164 		else if (action == 16)
165 		{
166 			ADD_CONVERTED_CODE(0, 0);
167 		}
168 		else if (action == 17)
169 		{
170 			ADD_CONVERTED_CODE(1, 0);
171 			cd->hbuf[2] = *ib;
172 		}
173 		cd->cur_act = action;
174 		cd->cur_stat = state;
175 		ib++;
176 	}
177 
178 	*inbuf = (char*)ib;
179 	*inbufleft = ibtail - ib;
180 	*outbuf = (char*)ob;
181 	*outbufleft = obtail - ob;
182 
183 	return(ret_val);
184 }  /* end of size_t _icv_iconv(_conv_desc*, char**, size_t*, char**, size_t*).*/
185 
186 
187 /****  I N P U T _ C O N V  ****/
188 
input_conv(char c)189 int input_conv(char c)
190 {
191 	switch (c)
192 	{
193 		case 'H':	/* dd */
194 		case 'S':	/* bb */
195 		case 'Y':	/* jj */
196 			return(1);
197 
198 		case 'A':	/* g */
199 			return(2);
200 
201 		case 'D':	/* n */
202 			return(3);
203 
204 		case 'I':	/* r */
205 			return(4);
206 
207 		case 'R':	/* b */
208 			return(5);
209 
210 		case 'B':	/* gg */
211 		case 'G':	/* d */
212 		case 'V':	/* ss */
213 		case 'W':	/* o */
214 		case 'Z':	/* ch */
215 		case '[':	/* k */
216 			return(6);
217 
218 		case 'U':	/* s */
219 			return(7);
220 
221 		case 'X':	/* j */
222 			return(8);
223 
224 		case '^':	/* h */
225 			return(9);
226 
227 		case 'Q':	/* m */
228 		case ']':	/* p */
229 		case '\\':	/* t */
230 			return(10);
231 
232 		case 'k':	/* =|| */
233 		case 'd':	/* |= */
234 		case 'e':	/* |=| */
235 		case 'j':	/* =| */
236 		case 'r':	/* _||_ */
237 		case 'w':	/* TT */
238 			return(11);
239 
240 		case 'b':	/* |- */
241 		case 'c':	/* H */
242 			return(12);
243 
244 		case 'f':	/* -| */
245 		case 'g':	/* -|| */
246 			return(13);
247 
248 		case '|':	/* | */
249 			return(14);
250 
251 		case 'l':	/* _|_ */
252 			return(15);
253 
254 		case 's':	/* T */
255 			return(16);
256 
257 		case 'z':	/* __ */
258 			return(17);
259 
260 		case '\016':
261 			return(18);
262 
263 		case '\017':
264 		case '\024':
265 			return(19);
266 
267 		default:
268 			return(20);
269 	}
270 }  /* end of int input_conv(char). */
271 
272 
273 /****  M A K E _ J O H A P _ C O D E  ****/
274 
make_johap_code(int n,char * temp)275 unsigned short make_johap_code(int n, char* temp)
276 {
277 	register unsigned short code = 0;
278 	char 			save ='\0';
279 
280 	if (n == 1)
281 	{
282 		if (temp[4] == '\0')
283 		{
284 			save = temp[3];
285 			temp[3] = '\0';
286 		}
287 		else
288 		{
289 			save = temp[4];
290 			temp[4] = '\0';
291 		}
292 	}
293 
294 	code = (temp[1] >= 'A' && temp[1] <= '^') ?
295 			(unsigned short)X32_19[temp[1] - '@']
296 			: (unsigned short)9;
297 	code = (code << 5) | (unsigned short)((temp[2] >= 'b' &&
298 				temp[2] <= '|') ? X32_21[temp[2] - '`']
299 						    : 1);
300 	code = (code << 5) | (unsigned short)((temp[3] >= 'A' &&
301 				temp[3] <= '^') ? X32_28[temp[3] - '@']
302 						    : 1);
303 
304 	if (temp[4] >= 'A')
305 	{
306 		if (temp[3] == 'A' && temp[4] == 'U')  /* gs */
307 			code += 2;
308 		else if (temp[3] == 'D' && temp[4] == 'X')  /* nj */
309 			code++;
310 		else if (temp[3] == 'D' && temp[4] == '^')  /* nh */
311 			code += 2;
312 		else if (temp[3] == 'I' && temp[4] == 'A')  /* rg */
313 			code++;
314 		else if (temp[3] == 'I' && temp[4] == 'Q')  /* rm */
315 			code += 2;
316 		else if (temp[3] == 'I' && temp[4] == 'R')  /* rb */
317 			code += 3;
318 		else if (temp[3] == 'I' && temp[4] == 'U')  /* rs */
319 			code += 4;
320 		else if (temp[3] == 'I' && temp[4] == '\\')  /* rt */
321 			code += 5;
322 		else if (temp[3] == 'I' && temp[4] == ']')  /* rp */
323 			code += 6;
324 		else if (temp[3] == 'I' && temp[4] == '^')  /* rh */
325 			code += 7;
326 		else if (temp[3] == 'R' && temp[4] == 'U')  /* bs */
327 			code++;
328 		else if (temp[3] == 'U' && temp[4] == 'U')  /* ss */
329 			code++;
330 	}
331 
332 	temp[1] = (n == 1) ? save : '\0';
333 	temp[2] = temp[3] = temp[4] = '\0';
334 	return(code | 0x8000);
335 }  /* end of unsigned short make_johap_code(int, char*). */
336