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