1*0d5acd74SJohn Marino /* $FreeBSD: head/lib/libiconv_modules/mapper_646/citrus_mapper_646.c 219019 2011-02-25 00:04:39Z gabor $ */
2*0d5acd74SJohn Marino /*	$NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $	*/
3*0d5acd74SJohn Marino 
4*0d5acd74SJohn Marino /*-
5*0d5acd74SJohn Marino  * Copyright (c)2003 Citrus Project,
6*0d5acd74SJohn Marino  * All rights reserved.
7*0d5acd74SJohn Marino  *
8*0d5acd74SJohn Marino  * Redistribution and use in source and binary forms, with or without
9*0d5acd74SJohn Marino  * modification, are permitted provided that the following conditions
10*0d5acd74SJohn Marino  * are met:
11*0d5acd74SJohn Marino  * 1. Redistributions of source code must retain the above copyright
12*0d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer.
13*0d5acd74SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
14*0d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
15*0d5acd74SJohn Marino  *    documentation and/or other materials provided with the distribution.
16*0d5acd74SJohn Marino  *
17*0d5acd74SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*0d5acd74SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*0d5acd74SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*0d5acd74SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*0d5acd74SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*0d5acd74SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*0d5acd74SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*0d5acd74SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*0d5acd74SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*0d5acd74SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*0d5acd74SJohn Marino  * SUCH DAMAGE.
28*0d5acd74SJohn Marino  */
29*0d5acd74SJohn Marino 
30*0d5acd74SJohn Marino #include <sys/cdefs.h>
31*0d5acd74SJohn Marino #include <sys/queue.h>
32*0d5acd74SJohn Marino 
33*0d5acd74SJohn Marino #include <assert.h>
34*0d5acd74SJohn Marino #include <errno.h>
35*0d5acd74SJohn Marino #include <limits.h>
36*0d5acd74SJohn Marino #include <stdio.h>
37*0d5acd74SJohn Marino #include <stdlib.h>
38*0d5acd74SJohn Marino #include <string.h>
39*0d5acd74SJohn Marino 
40*0d5acd74SJohn Marino #include "citrus_namespace.h"
41*0d5acd74SJohn Marino #include "citrus_types.h"
42*0d5acd74SJohn Marino #include "citrus_bcs.h"
43*0d5acd74SJohn Marino #include "citrus_module.h"
44*0d5acd74SJohn Marino #include "citrus_region.h"
45*0d5acd74SJohn Marino #include "citrus_memstream.h"
46*0d5acd74SJohn Marino #include "citrus_mmap.h"
47*0d5acd74SJohn Marino #include "citrus_hash.h"
48*0d5acd74SJohn Marino #include "citrus_mapper.h"
49*0d5acd74SJohn Marino #include "citrus_mapper_646.h"
50*0d5acd74SJohn Marino 
51*0d5acd74SJohn Marino /* ---------------------------------------------------------------------- */
52*0d5acd74SJohn Marino 
53*0d5acd74SJohn Marino _CITRUS_MAPPER_DECLS(mapper_646);
54*0d5acd74SJohn Marino _CITRUS_MAPPER_DEF_OPS(mapper_646);
55*0d5acd74SJohn Marino 
56*0d5acd74SJohn Marino /* ---------------------------------------------------------------------- */
57*0d5acd74SJohn Marino 
58*0d5acd74SJohn Marino #define ILSEQ	0xFFFFFFFE
59*0d5acd74SJohn Marino #define INVALID	0xFFFFFFFF
60*0d5acd74SJohn Marino #define SPECIALS(x)				\
61*0d5acd74SJohn Marino 	x(0x23)					\
62*0d5acd74SJohn Marino 	x(0x24)					\
63*0d5acd74SJohn Marino 	x(0x40)					\
64*0d5acd74SJohn Marino 	x(0x5B)					\
65*0d5acd74SJohn Marino 	x(0x5C)					\
66*0d5acd74SJohn Marino 	x(0x5D)					\
67*0d5acd74SJohn Marino 	x(0x5E)					\
68*0d5acd74SJohn Marino 	x(0x60)					\
69*0d5acd74SJohn Marino 	x(0x7B)					\
70*0d5acd74SJohn Marino 	x(0x7C)					\
71*0d5acd74SJohn Marino 	x(0x7D)					\
72*0d5acd74SJohn Marino 	x(0x7E)
73*0d5acd74SJohn Marino 
74*0d5acd74SJohn Marino #define INDEX(x) INDEX_##x,
75*0d5acd74SJohn Marino 
76*0d5acd74SJohn Marino enum {
77*0d5acd74SJohn Marino 	SPECIALS(INDEX)
78*0d5acd74SJohn Marino 	NUM_OF_SPECIALS
79*0d5acd74SJohn Marino };
80*0d5acd74SJohn Marino struct _citrus_mapper_646 {
81*0d5acd74SJohn Marino 	_index_t	 m6_map[NUM_OF_SPECIALS];
82*0d5acd74SJohn Marino 	int		 m6_forward;
83*0d5acd74SJohn Marino };
84*0d5acd74SJohn Marino 
85*0d5acd74SJohn Marino int
_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops * ops)86*0d5acd74SJohn Marino _citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops)
87*0d5acd74SJohn Marino {
88*0d5acd74SJohn Marino 
89*0d5acd74SJohn Marino 	memcpy(ops, &_citrus_mapper_646_mapper_ops,
90*0d5acd74SJohn Marino 	    sizeof(_citrus_mapper_646_mapper_ops));
91*0d5acd74SJohn Marino 
92*0d5acd74SJohn Marino 	return (0);
93*0d5acd74SJohn Marino }
94*0d5acd74SJohn Marino 
95*0d5acd74SJohn Marino #define T_COMM '#'
96*0d5acd74SJohn Marino static int
parse_file(struct _citrus_mapper_646 * m6,const char * path)97*0d5acd74SJohn Marino parse_file(struct _citrus_mapper_646 *m6, const char *path)
98*0d5acd74SJohn Marino {
99*0d5acd74SJohn Marino 	struct _memstream ms;
100*0d5acd74SJohn Marino 	struct _region r;
101*0d5acd74SJohn Marino 	const char *p;
102*0d5acd74SJohn Marino 	char *pp;
103*0d5acd74SJohn Marino 	size_t len;
104*0d5acd74SJohn Marino 	char buf[PATH_MAX];
105*0d5acd74SJohn Marino 	int i, ret;
106*0d5acd74SJohn Marino 
107*0d5acd74SJohn Marino 	ret = _map_file(&r, path);
108*0d5acd74SJohn Marino 	if (ret)
109*0d5acd74SJohn Marino 		return (ret);
110*0d5acd74SJohn Marino 	_memstream_bind(&ms, &r);
111*0d5acd74SJohn Marino 	for (i = 0; i < NUM_OF_SPECIALS; i++) {
112*0d5acd74SJohn Marino retry:
113*0d5acd74SJohn Marino 		p = _memstream_getln(&ms, &len);
114*0d5acd74SJohn Marino 		if (p == NULL) {
115*0d5acd74SJohn Marino 			ret = EINVAL;
116*0d5acd74SJohn Marino 			break;
117*0d5acd74SJohn Marino 		}
118*0d5acd74SJohn Marino 		p = _bcs_skip_ws_len(p, &len);
119*0d5acd74SJohn Marino 		if (*p == T_COMM || len==0)
120*0d5acd74SJohn Marino 			goto retry;
121*0d5acd74SJohn Marino 		if (!_bcs_isdigit(*p)) {
122*0d5acd74SJohn Marino 			ret = EINVAL;
123*0d5acd74SJohn Marino 			break;
124*0d5acd74SJohn Marino 		}
125*0d5acd74SJohn Marino 		snprintf(buf, sizeof(buf), "%.*s", (int)len, p);
126*0d5acd74SJohn Marino 		pp = __DECONST(void *, p);
127*0d5acd74SJohn Marino 		m6->m6_map[i] = strtoul(buf, (char **)&pp, 0);
128*0d5acd74SJohn Marino 		p = _bcs_skip_ws(buf);
129*0d5acd74SJohn Marino 		if (*p != T_COMM && !*p) {
130*0d5acd74SJohn Marino 			ret = EINVAL;
131*0d5acd74SJohn Marino 			break;
132*0d5acd74SJohn Marino 		}
133*0d5acd74SJohn Marino 	}
134*0d5acd74SJohn Marino 	_unmap_file(&r);
135*0d5acd74SJohn Marino 
136*0d5acd74SJohn Marino 	return (ret);
137*0d5acd74SJohn Marino };
138*0d5acd74SJohn Marino 
139*0d5acd74SJohn Marino static int
parse_var(struct _citrus_mapper_646 * m6,struct _memstream * ms,const char * dir)140*0d5acd74SJohn Marino parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms,
141*0d5acd74SJohn Marino     const char *dir)
142*0d5acd74SJohn Marino {
143*0d5acd74SJohn Marino 	struct _region r;
144*0d5acd74SJohn Marino 	char path[PATH_MAX];
145*0d5acd74SJohn Marino 
146*0d5acd74SJohn Marino 	m6->m6_forward = 1;
147*0d5acd74SJohn Marino 	_memstream_skip_ws(ms);
148*0d5acd74SJohn Marino 	/* whether backward */
149*0d5acd74SJohn Marino 	if (_memstream_peek(ms) == '!') {
150*0d5acd74SJohn Marino 		_memstream_getc(ms);
151*0d5acd74SJohn Marino 		m6->m6_forward = 0;
152*0d5acd74SJohn Marino 	}
153*0d5acd74SJohn Marino 	/* get description file path */
154*0d5acd74SJohn Marino 	_memstream_getregion(ms, &r, _memstream_remainder(ms));
155*0d5acd74SJohn Marino 	snprintf(path, sizeof(path), "%s/%.*s",
156*0d5acd74SJohn Marino 		 dir, (int)_region_size(&r), (char *)_region_head(&r));
157*0d5acd74SJohn Marino 	/* remove trailing white spaces */
158*0d5acd74SJohn Marino 	path[_bcs_skip_nonws(path)-path] = '\0';
159*0d5acd74SJohn Marino 	return (parse_file(m6, path));
160*0d5acd74SJohn Marino }
161*0d5acd74SJohn Marino 
162*0d5acd74SJohn Marino static int
163*0d5acd74SJohn Marino /*ARGSUSED*/
_citrus_mapper_646_mapper_init(struct _citrus_mapper_area * __restrict ma __unused,struct _citrus_mapper * __restrict cm,const char * __restrict dir,const void * __restrict var,size_t lenvar,struct _citrus_mapper_traits * __restrict mt,size_t lenmt)164*0d5acd74SJohn Marino _citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
165*0d5acd74SJohn Marino     struct _citrus_mapper * __restrict cm, const char * __restrict dir,
166*0d5acd74SJohn Marino     const void * __restrict var, size_t lenvar,
167*0d5acd74SJohn Marino     struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
168*0d5acd74SJohn Marino {
169*0d5acd74SJohn Marino 	struct _citrus_mapper_646 *m6;
170*0d5acd74SJohn Marino 	struct _memstream ms;
171*0d5acd74SJohn Marino 	struct _region r;
172*0d5acd74SJohn Marino 	int ret;
173*0d5acd74SJohn Marino 
174*0d5acd74SJohn Marino 	if (lenmt < sizeof(*mt))
175*0d5acd74SJohn Marino 		return (EINVAL);
176*0d5acd74SJohn Marino 
177*0d5acd74SJohn Marino 	m6 = malloc(sizeof(*m6));
178*0d5acd74SJohn Marino 	if (m6 == NULL)
179*0d5acd74SJohn Marino 		return (errno);
180*0d5acd74SJohn Marino 
181*0d5acd74SJohn Marino 	_region_init(&r, __DECONST(void *, var), lenvar);
182*0d5acd74SJohn Marino 	_memstream_bind(&ms, &r);
183*0d5acd74SJohn Marino 	ret = parse_var(m6, &ms, dir);
184*0d5acd74SJohn Marino 	if (ret) {
185*0d5acd74SJohn Marino 		free(m6);
186*0d5acd74SJohn Marino 		return (ret);
187*0d5acd74SJohn Marino 	}
188*0d5acd74SJohn Marino 
189*0d5acd74SJohn Marino 	cm->cm_closure = m6;
190*0d5acd74SJohn Marino 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
191*0d5acd74SJohn Marino 	mt->mt_state_size = 0;			/* stateless */
192*0d5acd74SJohn Marino 
193*0d5acd74SJohn Marino 	return (0);
194*0d5acd74SJohn Marino }
195*0d5acd74SJohn Marino 
196*0d5acd74SJohn Marino static void
197*0d5acd74SJohn Marino /*ARGSUSED*/
_citrus_mapper_646_mapper_uninit(struct _citrus_mapper * cm)198*0d5acd74SJohn Marino _citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm)
199*0d5acd74SJohn Marino {
200*0d5acd74SJohn Marino 
201*0d5acd74SJohn Marino 	if (cm && cm->cm_closure)
202*0d5acd74SJohn Marino 		free(cm->cm_closure);
203*0d5acd74SJohn Marino }
204*0d5acd74SJohn Marino 
205*0d5acd74SJohn Marino static int
206*0d5acd74SJohn Marino /*ARGSUSED*/
_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,_index_t * __restrict dst,_index_t src,void * __restrict ps __unused)207*0d5acd74SJohn Marino _citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,
208*0d5acd74SJohn Marino     _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
209*0d5acd74SJohn Marino {
210*0d5acd74SJohn Marino 	struct _citrus_mapper_646 *m6;
211*0d5acd74SJohn Marino 
212*0d5acd74SJohn Marino 	m6 = cm->cm_closure;
213*0d5acd74SJohn Marino 	if (m6->m6_forward) {
214*0d5acd74SJohn Marino 		/* forward */
215*0d5acd74SJohn Marino 		if (src >= 0x80)
216*0d5acd74SJohn Marino 			return (_MAPPER_CONVERT_ILSEQ);
217*0d5acd74SJohn Marino #define FORWARD(x)					\
218*0d5acd74SJohn Marino if (src == (x))	{					\
219*0d5acd74SJohn Marino 	if (m6->m6_map[INDEX_##x]==INVALID)		\
220*0d5acd74SJohn Marino 		return (_MAPPER_CONVERT_NONIDENTICAL);	\
221*0d5acd74SJohn Marino 	*dst = m6->m6_map[INDEX_##x];			\
222*0d5acd74SJohn Marino 	return (0);					\
223*0d5acd74SJohn Marino } else
224*0d5acd74SJohn Marino 		SPECIALS(FORWARD);
225*0d5acd74SJohn Marino 		*dst = src;
226*0d5acd74SJohn Marino 	} else {
227*0d5acd74SJohn Marino 		/* backward */
228*0d5acd74SJohn Marino #define BACKWARD(x)							\
229*0d5acd74SJohn Marino if (m6->m6_map[INDEX_##x] != INVALID && src == m6->m6_map[INDEX_##x]) {	\
230*0d5acd74SJohn Marino 	*dst = (x);							\
231*0d5acd74SJohn Marino 	return (0);							\
232*0d5acd74SJohn Marino } else if (src == (x))							\
233*0d5acd74SJohn Marino 	return (_MAPPER_CONVERT_ILSEQ);					\
234*0d5acd74SJohn Marino else
235*0d5acd74SJohn Marino 		SPECIALS(BACKWARD);
236*0d5acd74SJohn Marino 		if (src >= 0x80)
237*0d5acd74SJohn Marino 			return (_MAPPER_CONVERT_NONIDENTICAL);
238*0d5acd74SJohn Marino 		*dst = src;
239*0d5acd74SJohn Marino 	}
240*0d5acd74SJohn Marino 
241*0d5acd74SJohn Marino 	return (_MAPPER_CONVERT_SUCCESS);
242*0d5acd74SJohn Marino }
243*0d5acd74SJohn Marino 
244*0d5acd74SJohn Marino static void
245*0d5acd74SJohn Marino /*ARGSUSED*/
_citrus_mapper_646_mapper_init_state(void)246*0d5acd74SJohn Marino _citrus_mapper_646_mapper_init_state(void)
247*0d5acd74SJohn Marino {
248*0d5acd74SJohn Marino 
249*0d5acd74SJohn Marino }
250