1219019Sgabor/* $FreeBSD: releng/10.3/lib/libiconv_modules/mapper_646/citrus_mapper_646.c 219019 2011-02-25 00:04:39Z gabor $ */
2219019Sgabor/*	$NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $	*/
3219019Sgabor
4219019Sgabor/*-
5219019Sgabor * Copyright (c)2003 Citrus Project,
6219019Sgabor * All rights reserved.
7219019Sgabor *
8219019Sgabor * Redistribution and use in source and binary forms, with or without
9219019Sgabor * modification, are permitted provided that the following conditions
10219019Sgabor * are met:
11219019Sgabor * 1. Redistributions of source code must retain the above copyright
12219019Sgabor *    notice, this list of conditions and the following disclaimer.
13219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright
14219019Sgabor *    notice, this list of conditions and the following disclaimer in the
15219019Sgabor *    documentation and/or other materials provided with the distribution.
16219019Sgabor *
17219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20219019Sgabor * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27219019Sgabor * SUCH DAMAGE.
28219019Sgabor */
29219019Sgabor
30219019Sgabor#include <sys/cdefs.h>
31219019Sgabor#include <sys/queue.h>
32219019Sgabor
33219019Sgabor#include <assert.h>
34219019Sgabor#include <errno.h>
35219019Sgabor#include <limits.h>
36219019Sgabor#include <stdio.h>
37219019Sgabor#include <stdlib.h>
38219019Sgabor#include <string.h>
39219019Sgabor
40219019Sgabor#include "citrus_namespace.h"
41219019Sgabor#include "citrus_types.h"
42219019Sgabor#include "citrus_bcs.h"
43219019Sgabor#include "citrus_module.h"
44219019Sgabor#include "citrus_region.h"
45219019Sgabor#include "citrus_memstream.h"
46219019Sgabor#include "citrus_mmap.h"
47219019Sgabor#include "citrus_hash.h"
48219019Sgabor#include "citrus_mapper.h"
49219019Sgabor#include "citrus_mapper_646.h"
50219019Sgabor
51219019Sgabor/* ---------------------------------------------------------------------- */
52219019Sgabor
53219019Sgabor_CITRUS_MAPPER_DECLS(mapper_646);
54219019Sgabor_CITRUS_MAPPER_DEF_OPS(mapper_646);
55219019Sgabor
56219019Sgabor/* ---------------------------------------------------------------------- */
57219019Sgabor
58219019Sgabor#define ILSEQ	0xFFFFFFFE
59219019Sgabor#define INVALID	0xFFFFFFFF
60219019Sgabor#define SPECIALS(x)				\
61219019Sgabor	x(0x23)					\
62219019Sgabor	x(0x24)					\
63219019Sgabor	x(0x40)					\
64219019Sgabor	x(0x5B)					\
65219019Sgabor	x(0x5C)					\
66219019Sgabor	x(0x5D)					\
67219019Sgabor	x(0x5E)					\
68219019Sgabor	x(0x60)					\
69219019Sgabor	x(0x7B)					\
70219019Sgabor	x(0x7C)					\
71219019Sgabor	x(0x7D)					\
72219019Sgabor	x(0x7E)
73219019Sgabor
74219019Sgabor#define INDEX(x) INDEX_##x,
75219019Sgabor
76219019Sgaborenum {
77219019Sgabor	SPECIALS(INDEX)
78219019Sgabor	NUM_OF_SPECIALS
79219019Sgabor};
80219019Sgaborstruct _citrus_mapper_646 {
81219019Sgabor	_index_t	 m6_map[NUM_OF_SPECIALS];
82219019Sgabor	int		 m6_forward;
83219019Sgabor};
84219019Sgabor
85219019Sgaborint
86219019Sgabor_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops)
87219019Sgabor{
88219019Sgabor
89219019Sgabor	memcpy(ops, &_citrus_mapper_646_mapper_ops,
90219019Sgabor	    sizeof(_citrus_mapper_646_mapper_ops));
91219019Sgabor
92219019Sgabor	return (0);
93219019Sgabor}
94219019Sgabor
95219019Sgabor#define T_COMM '#'
96219019Sgaborstatic int
97219019Sgaborparse_file(struct _citrus_mapper_646 *m6, const char *path)
98219019Sgabor{
99219019Sgabor	struct _memstream ms;
100219019Sgabor	struct _region r;
101219019Sgabor	const char *p;
102219019Sgabor	char *pp;
103219019Sgabor	size_t len;
104219019Sgabor	char buf[PATH_MAX];
105219019Sgabor	int i, ret;
106219019Sgabor
107219019Sgabor	ret = _map_file(&r, path);
108219019Sgabor	if (ret)
109219019Sgabor		return (ret);
110219019Sgabor	_memstream_bind(&ms, &r);
111219019Sgabor	for (i = 0; i < NUM_OF_SPECIALS; i++) {
112219019Sgaborretry:
113219019Sgabor		p = _memstream_getln(&ms, &len);
114219019Sgabor		if (p == NULL) {
115219019Sgabor			ret = EINVAL;
116219019Sgabor			break;
117219019Sgabor		}
118219019Sgabor		p = _bcs_skip_ws_len(p, &len);
119219019Sgabor		if (*p == T_COMM || len==0)
120219019Sgabor			goto retry;
121219019Sgabor		if (!_bcs_isdigit(*p)) {
122219019Sgabor			ret = EINVAL;
123219019Sgabor			break;
124219019Sgabor		}
125219019Sgabor		snprintf(buf, sizeof(buf), "%.*s", (int)len, p);
126219019Sgabor		pp = __DECONST(void *, p);
127219019Sgabor		m6->m6_map[i] = strtoul(buf, (char **)&pp, 0);
128219019Sgabor		p = _bcs_skip_ws(buf);
129219019Sgabor		if (*p != T_COMM && !*p) {
130219019Sgabor			ret = EINVAL;
131219019Sgabor			break;
132219019Sgabor		}
133219019Sgabor	}
134219019Sgabor	_unmap_file(&r);
135219019Sgabor
136219019Sgabor	return (ret);
137219019Sgabor};
138219019Sgabor
139219019Sgaborstatic int
140219019Sgaborparse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms,
141219019Sgabor    const char *dir)
142219019Sgabor{
143219019Sgabor	struct _region r;
144219019Sgabor	char path[PATH_MAX];
145219019Sgabor
146219019Sgabor	m6->m6_forward = 1;
147219019Sgabor	_memstream_skip_ws(ms);
148219019Sgabor	/* whether backward */
149219019Sgabor	if (_memstream_peek(ms) == '!') {
150219019Sgabor		_memstream_getc(ms);
151219019Sgabor		m6->m6_forward = 0;
152219019Sgabor	}
153219019Sgabor	/* get description file path */
154219019Sgabor	_memstream_getregion(ms, &r, _memstream_remainder(ms));
155219019Sgabor	snprintf(path, sizeof(path), "%s/%.*s",
156219019Sgabor		 dir, (int)_region_size(&r), (char *)_region_head(&r));
157219019Sgabor	/* remove trailing white spaces */
158219019Sgabor	path[_bcs_skip_nonws(path)-path] = '\0';
159219019Sgabor	return (parse_file(m6, path));
160219019Sgabor}
161219019Sgabor
162219019Sgaborstatic int
163219019Sgabor/*ARGSUSED*/
164219019Sgabor_citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
165219019Sgabor    struct _citrus_mapper * __restrict cm, const char * __restrict dir,
166219019Sgabor    const void * __restrict var, size_t lenvar,
167219019Sgabor    struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
168219019Sgabor{
169219019Sgabor	struct _citrus_mapper_646 *m6;
170219019Sgabor	struct _memstream ms;
171219019Sgabor	struct _region r;
172219019Sgabor	int ret;
173219019Sgabor
174219019Sgabor	if (lenmt < sizeof(*mt))
175219019Sgabor		return (EINVAL);
176219019Sgabor
177219019Sgabor	m6 = malloc(sizeof(*m6));
178219019Sgabor	if (m6 == NULL)
179219019Sgabor		return (errno);
180219019Sgabor
181219019Sgabor	_region_init(&r, __DECONST(void *, var), lenvar);
182219019Sgabor	_memstream_bind(&ms, &r);
183219019Sgabor	ret = parse_var(m6, &ms, dir);
184219019Sgabor	if (ret) {
185219019Sgabor		free(m6);
186219019Sgabor		return (ret);
187219019Sgabor	}
188219019Sgabor
189219019Sgabor	cm->cm_closure = m6;
190219019Sgabor	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
191219019Sgabor	mt->mt_state_size = 0;			/* stateless */
192219019Sgabor
193219019Sgabor	return (0);
194219019Sgabor}
195219019Sgabor
196219019Sgaborstatic void
197219019Sgabor/*ARGSUSED*/
198219019Sgabor_citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm)
199219019Sgabor{
200219019Sgabor
201219019Sgabor	if (cm && cm->cm_closure)
202219019Sgabor		free(cm->cm_closure);
203219019Sgabor}
204219019Sgabor
205219019Sgaborstatic int
206219019Sgabor/*ARGSUSED*/
207219019Sgabor_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,
208219019Sgabor    _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
209219019Sgabor{
210219019Sgabor	struct _citrus_mapper_646 *m6;
211219019Sgabor
212219019Sgabor	m6 = cm->cm_closure;
213219019Sgabor	if (m6->m6_forward) {
214219019Sgabor		/* forward */
215219019Sgabor		if (src >= 0x80)
216219019Sgabor			return (_MAPPER_CONVERT_ILSEQ);
217219019Sgabor#define FORWARD(x)					\
218219019Sgaborif (src == (x))	{					\
219219019Sgabor	if (m6->m6_map[INDEX_##x]==INVALID)		\
220219019Sgabor		return (_MAPPER_CONVERT_NONIDENTICAL);	\
221219019Sgabor	*dst = m6->m6_map[INDEX_##x];			\
222219019Sgabor	return (0);					\
223219019Sgabor} else
224219019Sgabor		SPECIALS(FORWARD);
225219019Sgabor		*dst = src;
226219019Sgabor	} else {
227219019Sgabor		/* backward */
228219019Sgabor#define BACKWARD(x)							\
229219019Sgaborif (m6->m6_map[INDEX_##x] != INVALID && src == m6->m6_map[INDEX_##x]) {	\
230219019Sgabor	*dst = (x);							\
231219019Sgabor	return (0);							\
232219019Sgabor} else if (src == (x))							\
233219019Sgabor	return (_MAPPER_CONVERT_ILSEQ);					\
234219019Sgaborelse
235219019Sgabor		SPECIALS(BACKWARD);
236219019Sgabor		if (src >= 0x80)
237219019Sgabor			return (_MAPPER_CONVERT_NONIDENTICAL);
238219019Sgabor		*dst = src;
239219019Sgabor	}
240219019Sgabor
241219019Sgabor	return (_MAPPER_CONVERT_SUCCESS);
242219019Sgabor}
243219019Sgabor
244219019Sgaborstatic void
245219019Sgabor/*ARGSUSED*/
246219019Sgabor_citrus_mapper_646_mapper_init_state(void)
247219019Sgabor{
248219019Sgabor
249219019Sgabor}
250