xref: /freebsd/lib/libiconv_modules/EUCTW/citrus_euctw.c (revision 734e82fe33aa764367791a7d603b383996c6b40b)
1 /*	$NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c)2002 Citrus Project,
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /*-
32  * Copyright (c)1999 Citrus Project,
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
45  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54  * SUCH DAMAGE.
55  *
56  *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $
57  */
58 
59 #include <sys/cdefs.h>
60 #include <sys/types.h>
61 
62 #include <assert.h>
63 #include <errno.h>
64 #include <limits.h>
65 #include <stddef.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <wchar.h>
70 
71 #include "citrus_namespace.h"
72 #include "citrus_types.h"
73 #include "citrus_module.h"
74 #include "citrus_stdenc.h"
75 #include "citrus_euctw.h"
76 
77 
78 /* ----------------------------------------------------------------------
79  * private stuffs used by templates
80  */
81 
82 typedef struct {
83 	int	 chlen;
84 	char	 ch[4];
85 } _EUCTWState;
86 
87 typedef struct {
88 	int	 dummy;
89 } _EUCTWEncodingInfo;
90 
91 #define	_SS2	0x008e
92 #define	_SS3	0x008f
93 
94 #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
95 #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
96 
97 #define _FUNCNAME(m)			_citrus_EUCTW_##m
98 #define _ENCODING_INFO			_EUCTWEncodingInfo
99 #define _ENCODING_STATE			_EUCTWState
100 #define _ENCODING_MB_CUR_MAX(_ei_)	4
101 #define _ENCODING_IS_STATE_DEPENDENT	0
102 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
103 
104 static __inline int
105 _citrus_EUCTW_cs(unsigned int c)
106 {
107 
108 	c &= 0xff;
109 
110 	return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0);
111 }
112 
113 static __inline int
114 _citrus_EUCTW_count(int cs)
115 {
116 
117 	switch (cs) {
118 	case 0:
119 		/*FALLTHROUGH*/
120 	case 1:
121 		/*FALLTHROUGH*/
122 	case 2:
123 		return (1 << cs);
124 	case 3:
125 		abort();
126 		/*NOTREACHED*/
127 	}
128 	return (0);
129 }
130 
131 static __inline void
132 /*ARGSUSED*/
133 _citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei __unused,
134     _EUCTWState * __restrict s)
135 {
136 
137 	memset(s, 0, sizeof(*s));
138 }
139 
140 #if 0
141 static __inline void
142 /*ARGSUSED*/
143 _citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei __unused,
144     void * __restrict pspriv, const _EUCTWState * __restrict s)
145 {
146 
147 	memcpy(pspriv, (const void *)s, sizeof(*s));
148 }
149 
150 static __inline void
151 /*ARGSUSED*/
152 _citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei __unused,
153     _EUCTWState * __restrict s, const void * __restrict pspriv)
154 {
155 
156 	memcpy((void *)s, pspriv, sizeof(*s));
157 }
158 #endif
159 
160 static int
161 /*ARGSUSED*/
162 _citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei,
163     const void * __restrict var __unused, size_t lenvar __unused)
164 {
165 
166 	memset((void *)ei, 0, sizeof(*ei));
167 
168 	return (0);
169 }
170 
171 static void
172 /*ARGSUSED*/
173 _citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei __unused)
174 {
175 
176 }
177 
178 static int
179 _citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei,
180     wchar_t * __restrict pwc, char ** __restrict s,
181     size_t n, _EUCTWState * __restrict psenc, size_t * __restrict nresult)
182 {
183 	char *s0;
184 	wchar_t wchar;
185 	int c, chlenbak, cs;
186 
187 	s0 = *s;
188 
189 	if (s0 == NULL) {
190 		_citrus_EUCTW_init_state(ei, psenc);
191 		*nresult = 0; /* state independent */
192 		return (0);
193 	}
194 
195 	chlenbak = psenc->chlen;
196 
197 	/* make sure we have the first byte in the buffer */
198 	switch (psenc->chlen) {
199 	case 0:
200 		if (n < 1)
201 			goto restart;
202 		psenc->ch[0] = *s0++;
203 		psenc->chlen = 1;
204 		n--;
205 		break;
206 	case 1:
207 	case 2:
208 		break;
209 	default:
210 		/* illgeal state */
211 		goto ilseq;
212 	}
213 
214 	c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff));
215 	if (c == 0)
216 		goto ilseq;
217 	while (psenc->chlen < c) {
218 		if (n < 1)
219 			goto ilseq;
220 		psenc->ch[psenc->chlen] = *s0++;
221 		psenc->chlen++;
222 		n--;
223 	}
224 
225 	wchar = 0;
226 	switch (cs) {
227 	case 0:
228 		if (psenc->ch[0] & 0x80)
229 			goto ilseq;
230 		wchar = psenc->ch[0] & 0xff;
231 		break;
232 	case 1:
233 		if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80))
234 			goto ilseq;
235 		wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
236 		wchar |= 'G' << 24;
237 		break;
238 	case 2:
239 		if ((unsigned char)psenc->ch[1] < 0xa1 ||
240 		    0xa7 < (unsigned char)psenc->ch[1])
241 			goto ilseq;
242 		if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80))
243 			goto ilseq;
244 		wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff);
245 		wchar |= ('G' + psenc->ch[1] - 0xa1) << 24;
246 		break;
247 	default:
248 		goto ilseq;
249 	}
250 
251 	*s = s0;
252 	psenc->chlen = 0;
253 
254 	if (pwc)
255 		*pwc = wchar;
256 	*nresult = wchar ? c - chlenbak : 0;
257 	return (0);
258 
259 ilseq:
260 	psenc->chlen = 0;
261 	*nresult = (size_t)-1;
262 	return (EILSEQ);
263 
264 restart:
265 	*s = s0;
266 	*nresult = (size_t)-1;
267 	return (0);
268 }
269 
270 static int
271 _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei __unused,
272     char * __restrict s, size_t n, wchar_t wc,
273     _EUCTWState * __restrict psenc __unused, size_t * __restrict nresult)
274 {
275 	wchar_t cs, v;
276 	int clen, i, ret;
277 	size_t len;
278 
279 	cs = wc & 0x7f000080;
280 	clen = 1;
281 	if (wc & 0x00007f00)
282 		clen = 2;
283 	if ((wc & 0x007f0000) && !(wc & 0x00800000))
284 		clen = 3;
285 
286 	if (clen == 1 && cs == 0x00000000) {
287 		/* ASCII */
288 		len = 1;
289 		if (n < len) {
290 			ret = E2BIG;
291 			goto err;
292 		}
293 		v = wc & 0x0000007f;
294 	} else if (clen == 2 && cs == ('G' << 24)) {
295 		/* CNS-11643-1 */
296 		len = 2;
297 		if (n < len) {
298 			ret = E2BIG;
299 			goto err;
300 		}
301 		v = wc & 0x00007f7f;
302 		v |= 0x00008080;
303 	} else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') {
304 		/* CNS-11643-[2-7] */
305 		len = 4;
306 		if (n < len) {
307 			ret = E2BIG;
308 			goto err;
309 		}
310 		*s++ = _SS2;
311 		*s++ = (cs >> 24) - 'H' + 0xa2;
312 		v = wc & 0x00007f7f;
313 		v |= 0x00008080;
314 	} else {
315 		ret = EILSEQ;
316 		goto err;
317 	}
318 
319 	i = clen;
320 	while (i-- > 0)
321 		*s++ = (v >> (i << 3)) & 0xff;
322 
323 	*nresult = len;
324 	return (0);
325 
326 err:
327 	*nresult = (size_t)-1;
328 	return (ret);
329 }
330 
331 static __inline int
332 /*ARGSUSED*/
333 _citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei __unused,
334     _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
335 {
336 
337 	*csid = (_csid_t)(wc >> 24) & 0xFF;
338 	*idx  = (_index_t)(wc & 0x7F7F);
339 
340 	return (0);
341 }
342 
343 static __inline int
344 /*ARGSUSED*/
345 _citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei __unused,
346     wchar_t * __restrict wc, _csid_t csid, _index_t idx)
347 {
348 
349 	if (csid == 0) {
350 		if ((idx & ~0x7F) != 0)
351 			return (EINVAL);
352 		*wc = (wchar_t)idx;
353 	} else {
354 		if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0)
355 			return (EINVAL);
356 		*wc = (wchar_t)idx | ((wchar_t)csid << 24);
357 	}
358 
359 	return (0);
360 }
361 
362 static __inline int
363 /*ARGSUSED*/
364 _citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei __unused,
365     _EUCTWState * __restrict psenc, int * __restrict rstate)
366 {
367 
368 	*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
369 	    _STDENC_SDGEN_INCOMPLETE_CHAR;
370 	return (0);
371 }
372 
373 /* ----------------------------------------------------------------------
374  * public interface for stdenc
375  */
376 
377 _CITRUS_STDENC_DECLS(EUCTW);
378 _CITRUS_STDENC_DEF_OPS(EUCTW);
379 
380 #include "citrus_stdenc_template.h"
381