1*0e0aa086Stshiozak /* $NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $ */
204e58308Stshiozak
304e58308Stshiozak /*-
404e58308Stshiozak * Copyright (c)2003 Citrus Project,
504e58308Stshiozak * All rights reserved.
604e58308Stshiozak *
704e58308Stshiozak * Redistribution and use in source and binary forms, with or without
804e58308Stshiozak * modification, are permitted provided that the following conditions
904e58308Stshiozak * are met:
1004e58308Stshiozak * 1. Redistributions of source code must retain the above copyright
1104e58308Stshiozak * notice, this list of conditions and the following disclaimer.
1204e58308Stshiozak * 2. Redistributions in binary form must reproduce the above copyright
1304e58308Stshiozak * notice, this list of conditions and the following disclaimer in the
1404e58308Stshiozak * documentation and/or other materials provided with the distribution.
1504e58308Stshiozak *
1604e58308Stshiozak * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1704e58308Stshiozak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1804e58308Stshiozak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1904e58308Stshiozak * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2004e58308Stshiozak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2104e58308Stshiozak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2204e58308Stshiozak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2304e58308Stshiozak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2404e58308Stshiozak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2504e58308Stshiozak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2604e58308Stshiozak * SUCH DAMAGE.
2704e58308Stshiozak */
2804e58308Stshiozak
2904e58308Stshiozak #include <sys/cdefs.h>
3004e58308Stshiozak #if defined(LIBC_SCCS) && !defined(lint)
31*0e0aa086Stshiozak __RCSID("$NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $");
3204e58308Stshiozak #endif /* LIBC_SCCS and not lint */
3304e58308Stshiozak
3404e58308Stshiozak #include <assert.h>
3504e58308Stshiozak #include <errno.h>
3604e58308Stshiozak #include <stdio.h>
3704e58308Stshiozak #include <stdlib.h>
3804e58308Stshiozak #include <string.h>
3904e58308Stshiozak #include <limits.h>
4082d5554eStshiozak #include <sys/queue.h>
4104e58308Stshiozak
4204e58308Stshiozak #include "citrus_namespace.h"
4304e58308Stshiozak #include "citrus_types.h"
4404e58308Stshiozak #include "citrus_bcs.h"
4504e58308Stshiozak #include "citrus_module.h"
4604e58308Stshiozak #include "citrus_region.h"
4704e58308Stshiozak #include "citrus_memstream.h"
4804e58308Stshiozak #include "citrus_mmap.h"
4904e58308Stshiozak #include "citrus_hash.h"
5004e58308Stshiozak #include "citrus_mapper.h"
5104e58308Stshiozak #include "citrus_mapper_646.h"
5204e58308Stshiozak
5304e58308Stshiozak /* ---------------------------------------------------------------------- */
5404e58308Stshiozak
5504e58308Stshiozak _CITRUS_MAPPER_DECLS(mapper_646);
5604e58308Stshiozak _CITRUS_MAPPER_DEF_OPS(mapper_646);
5704e58308Stshiozak
5804e58308Stshiozak /* ---------------------------------------------------------------------- */
5904e58308Stshiozak
60c1e771abStshiozak #define ILSEQ 0xFFFFFFFE
6104e58308Stshiozak #define INVALID 0xFFFFFFFF
6204e58308Stshiozak #define SPECIALS(x) \
6304e58308Stshiozak x(0x23) \
6404e58308Stshiozak x(0x24) \
6504e58308Stshiozak x(0x40) \
6604e58308Stshiozak x(0x5B) \
6704e58308Stshiozak x(0x5C) \
6804e58308Stshiozak x(0x5D) \
6904e58308Stshiozak x(0x5E) \
7004e58308Stshiozak x(0x60) \
7104e58308Stshiozak x(0x7B) \
7204e58308Stshiozak x(0x7C) \
7304e58308Stshiozak x(0x7D) \
7404e58308Stshiozak x(0x7E)
7504e58308Stshiozak
7604e58308Stshiozak #define INDEX(x) INDEX_##x,
7704e58308Stshiozak
7804e58308Stshiozak enum {
7904e58308Stshiozak SPECIALS(INDEX)
8004e58308Stshiozak NUM_OF_SPECIALS
8104e58308Stshiozak };
8204e58308Stshiozak struct _citrus_mapper_646 {
8304e58308Stshiozak int m6_forward;
8404e58308Stshiozak _index_t m6_map[NUM_OF_SPECIALS];
8504e58308Stshiozak };
8604e58308Stshiozak
8704e58308Stshiozak int
_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops * ops,size_t lenops,uint32_t expected_version)8804e58308Stshiozak _citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops,
8904e58308Stshiozak size_t lenops, uint32_t expected_version)
9004e58308Stshiozak {
9104e58308Stshiozak if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
9204e58308Stshiozak return EINVAL;
9304e58308Stshiozak
9404e58308Stshiozak memcpy(ops, &_citrus_mapper_646_mapper_ops,
9504e58308Stshiozak sizeof(_citrus_mapper_646_mapper_ops));
9604e58308Stshiozak
9704e58308Stshiozak return 0;
9804e58308Stshiozak }
9904e58308Stshiozak
10004e58308Stshiozak #define T_COMM '#'
10104e58308Stshiozak static int
parse_file(struct _citrus_mapper_646 * m6,const char * path)10204e58308Stshiozak parse_file(struct _citrus_mapper_646 *m6, const char *path)
10304e58308Stshiozak {
10404e58308Stshiozak int ret, i;
10504e58308Stshiozak struct _region r;
10604e58308Stshiozak struct _memstream ms;
10704e58308Stshiozak const char *p;
10804e58308Stshiozak size_t len;
10904e58308Stshiozak char buf[PATH_MAX];
11004e58308Stshiozak
11104e58308Stshiozak ret = _map_file(&r, path);
11204e58308Stshiozak if (ret)
11304e58308Stshiozak return ret;
11404e58308Stshiozak _memstream_bind(&ms, &r);
11504e58308Stshiozak for (i=0; i<NUM_OF_SPECIALS; i++) {
11604e58308Stshiozak retry:
11704e58308Stshiozak p = _memstream_getln(&ms, &len);
11804e58308Stshiozak if (p==NULL) {
11904e58308Stshiozak ret = EINVAL;
12004e58308Stshiozak break;
12104e58308Stshiozak }
12204e58308Stshiozak p = _bcs_skip_ws_len(p, &len);
12304e58308Stshiozak if (*p == T_COMM || len==0)
12404e58308Stshiozak goto retry;
12504e58308Stshiozak if (!_bcs_isdigit(*p)) {
12604e58308Stshiozak ret = EINVAL;
12704e58308Stshiozak break;
12804e58308Stshiozak }
12904e58308Stshiozak snprintf(buf, sizeof(buf), "%.*s", (int)len, p);
13004e58308Stshiozak m6->m6_map[i] = strtoul(buf, (char **)&p, 0);
13104e58308Stshiozak p = _bcs_skip_ws(buf);
13204e58308Stshiozak if (*p != T_COMM && !*p) {
13304e58308Stshiozak ret = EINVAL;
13404e58308Stshiozak break;
13504e58308Stshiozak }
13604e58308Stshiozak }
13704e58308Stshiozak _unmap_file(&r);
13804e58308Stshiozak
13904e58308Stshiozak return ret;
14004e58308Stshiozak };
14104e58308Stshiozak
14204e58308Stshiozak static int
parse_var(struct _citrus_mapper_646 * m6,struct _memstream * ms,const char * dir)14304e58308Stshiozak parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms,
14404e58308Stshiozak const char *dir)
14504e58308Stshiozak {
14604e58308Stshiozak struct _region r;
14704e58308Stshiozak char path[PATH_MAX];
14804e58308Stshiozak
14904e58308Stshiozak m6->m6_forward = 1;
15004e58308Stshiozak _memstream_skip_ws(ms);
15104e58308Stshiozak /* whether backward */
15204e58308Stshiozak if (_memstream_peek(ms) == '!') {
15304e58308Stshiozak _memstream_getc(ms);
15404e58308Stshiozak m6->m6_forward = 0;
15504e58308Stshiozak }
15604e58308Stshiozak /* get description file path */
15704e58308Stshiozak _memstream_getregion(ms, &r, _memstream_remainder(ms));
15804e58308Stshiozak snprintf(path, sizeof(path), "%s/%.*s",
15904e58308Stshiozak dir, (int)_region_size(&r), (char *)_region_head(&r));
16004e58308Stshiozak /* remove trailing white spaces */
16104e58308Stshiozak path[_bcs_skip_nonws(path)-path] = '\0';
16204e58308Stshiozak return parse_file(m6, path);
16304e58308Stshiozak }
16404e58308Stshiozak
16504e58308Stshiozak static int
16604e58308Stshiozak /*ARGSUSED*/
_citrus_mapper_646_mapper_init(struct _citrus_mapper_area * __restrict ma,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)16704e58308Stshiozak _citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma,
16804e58308Stshiozak struct _citrus_mapper * __restrict cm,
16904e58308Stshiozak const char * __restrict dir,
17004e58308Stshiozak const void * __restrict var, size_t lenvar,
17104e58308Stshiozak struct _citrus_mapper_traits * __restrict mt,
17204e58308Stshiozak size_t lenmt)
17304e58308Stshiozak {
17404e58308Stshiozak struct _citrus_mapper_646 *m6;
17504e58308Stshiozak struct _memstream ms;
17604e58308Stshiozak struct _region r;
17704e58308Stshiozak int ret;
17804e58308Stshiozak
17904e58308Stshiozak _DIAGASSERT(cm && dir && mt);
18004e58308Stshiozak
18104e58308Stshiozak if (lenmt<sizeof(*mt))
18204e58308Stshiozak return EINVAL;
18304e58308Stshiozak
18404e58308Stshiozak m6 = malloc(sizeof(*m6));
18504e58308Stshiozak if (m6 == NULL)
18604e58308Stshiozak return errno;
18704e58308Stshiozak
18804e58308Stshiozak _region_init(&r, (void *)var, lenvar);
18904e58308Stshiozak _memstream_bind(&ms, &r);
19004e58308Stshiozak ret = parse_var(m6, &ms, dir);
19104e58308Stshiozak if (ret) {
19204e58308Stshiozak free(m6);
19304e58308Stshiozak return ret;
19404e58308Stshiozak }
19504e58308Stshiozak
19604e58308Stshiozak cm->cm_closure = m6;
19704e58308Stshiozak mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
19804e58308Stshiozak mt->mt_state_size = 0; /* stateless */
19904e58308Stshiozak
20004e58308Stshiozak return 0;
20104e58308Stshiozak }
20204e58308Stshiozak
20304e58308Stshiozak static void
20404e58308Stshiozak /*ARGSUSED*/
_citrus_mapper_646_mapper_uninit(struct _citrus_mapper * cm)20504e58308Stshiozak _citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm)
20604e58308Stshiozak {
20704e58308Stshiozak if (cm && cm->cm_closure) {
20804e58308Stshiozak free(cm->cm_closure);
20904e58308Stshiozak }
21004e58308Stshiozak }
21104e58308Stshiozak
21204e58308Stshiozak static int
21304e58308Stshiozak /*ARGSUSED*/
_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,_index_t * __restrict dst,_index_t src,void * __restrict ps)21404e58308Stshiozak _citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,
21504e58308Stshiozak _index_t * __restrict dst, _index_t src,
21604e58308Stshiozak void * __restrict ps)
21704e58308Stshiozak {
21804e58308Stshiozak struct _citrus_mapper_646 *m6;
21904e58308Stshiozak
22004e58308Stshiozak _DIAGASSERT(cm && cm->cm_closure);
22104e58308Stshiozak
22204e58308Stshiozak m6 = cm->cm_closure;
22304e58308Stshiozak if (m6->m6_forward) {
22404e58308Stshiozak /* forward */
22504e58308Stshiozak if (src>=0x80)
226c1e771abStshiozak return _MAPPER_CONVERT_ILSEQ;
22704e58308Stshiozak #define FORWARD(x) \
22804e58308Stshiozak if (src==(x)) { \
22904e58308Stshiozak if (m6->m6_map[INDEX_##x]==INVALID) \
230c1e771abStshiozak return _MAPPER_CONVERT_NONIDENTICAL; \
23104e58308Stshiozak *dst = m6->m6_map[INDEX_##x]; \
23204e58308Stshiozak return 0; \
23304e58308Stshiozak } else
23404e58308Stshiozak SPECIALS(FORWARD);
23504e58308Stshiozak *dst = src;
23604e58308Stshiozak } else {
23704e58308Stshiozak /* backward */
23804e58308Stshiozak #define BACKWARD(x) \
23904e58308Stshiozak if (m6->m6_map[INDEX_##x]!=INVALID && src==m6->m6_map[INDEX_##x]) { \
24004e58308Stshiozak *dst = (x); \
24104e58308Stshiozak return 0; \
24204e58308Stshiozak } else if (src==(x)) \
243c1e771abStshiozak return _MAPPER_CONVERT_ILSEQ; \
24404e58308Stshiozak else
24504e58308Stshiozak SPECIALS(BACKWARD);
24604e58308Stshiozak if (src>=0x80)
247*0e0aa086Stshiozak return _MAPPER_CONVERT_NONIDENTICAL;
24804e58308Stshiozak *dst = src;
24904e58308Stshiozak }
25004e58308Stshiozak
25104e58308Stshiozak return _MAPPER_CONVERT_SUCCESS;
25204e58308Stshiozak }
25304e58308Stshiozak
25404e58308Stshiozak static void
25504e58308Stshiozak /*ARGSUSED*/
_citrus_mapper_646_mapper_init_state(struct _citrus_mapper * __restrict cm,void * __restrict ps)25604e58308Stshiozak _citrus_mapper_646_mapper_init_state(struct _citrus_mapper * __restrict cm,
25704e58308Stshiozak void * __restrict ps)
25804e58308Stshiozak {
25904e58308Stshiozak }
260