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