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
34void* _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
54void _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
65size_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
189int 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
275unsigned 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