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