1 1.2 tshiozak /* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 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.2 tshiozak __RCSID("$NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 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.1 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_serial.h" 52 1.1 tshiozak 53 1.1 tshiozak /* ---------------------------------------------------------------------- */ 54 1.1 tshiozak 55 1.1 tshiozak _CITRUS_MAPPER_DECLS(mapper_serial); 56 1.1 tshiozak _CITRUS_MAPPER_DEF_OPS(mapper_serial); 57 1.1 tshiozak 58 1.1 tshiozak #define _citrus_mapper_parallel_mapper_init \ 59 1.1 tshiozak _citrus_mapper_serial_mapper_init 60 1.1 tshiozak #define _citrus_mapper_parallel_mapper_uninit \ 61 1.1 tshiozak _citrus_mapper_serial_mapper_uninit 62 1.1 tshiozak #define _citrus_mapper_parallel_mapper_init_state \ 63 1.1 tshiozak _citrus_mapper_serial_mapper_init_state 64 1.1 tshiozak static int _citrus_mapper_parallel_mapper_convert( 65 1.1 tshiozak struct _citrus_mapper * __restrict, _index_t * __restrict, _index_t, 66 1.1 tshiozak void * __restrict); 67 1.1 tshiozak _CITRUS_MAPPER_DEF_OPS(mapper_parallel); 68 1.1 tshiozak #undef _citrus_mapper_parallel_mapper_init 69 1.1 tshiozak #undef _citrus_mapper_parallel_mapper_uninit 70 1.1 tshiozak #undef _citrus_mapper_parallel_mapper_init_state 71 1.1 tshiozak 72 1.1 tshiozak 73 1.1 tshiozak /* ---------------------------------------------------------------------- */ 74 1.1 tshiozak 75 1.1 tshiozak struct maplink { 76 1.1 tshiozak SIMPLEQ_ENTRY(maplink) ml_entry; 77 1.1 tshiozak struct _mapper *ml_mapper; 78 1.1 tshiozak }; 79 1.1 tshiozak SIMPLEQ_HEAD(maplist, maplink); 80 1.1 tshiozak 81 1.1 tshiozak struct _citrus_mapper_serial { 82 1.1 tshiozak struct maplist sr_mappers; 83 1.1 tshiozak }; 84 1.1 tshiozak 85 1.1 tshiozak int 86 1.1 tshiozak _citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops, 87 1.1 tshiozak size_t lenops, uint32_t expected_version) 88 1.1 tshiozak { 89 1.1 tshiozak if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops)) 90 1.1 tshiozak return EINVAL; 91 1.1 tshiozak 92 1.1 tshiozak memcpy(ops, &_citrus_mapper_serial_mapper_ops, 93 1.1 tshiozak sizeof(_citrus_mapper_serial_mapper_ops)); 94 1.1 tshiozak 95 1.1 tshiozak return 0; 96 1.1 tshiozak } 97 1.1 tshiozak 98 1.1 tshiozak int 99 1.1 tshiozak _citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops, 100 1.1 tshiozak size_t lenops, uint32_t expected_version) 101 1.1 tshiozak { 102 1.1 tshiozak if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops)) 103 1.1 tshiozak return EINVAL; 104 1.1 tshiozak 105 1.1 tshiozak memcpy(ops, &_citrus_mapper_parallel_mapper_ops, 106 1.1 tshiozak sizeof(_citrus_mapper_parallel_mapper_ops)); 107 1.1 tshiozak 108 1.1 tshiozak return 0; 109 1.1 tshiozak } 110 1.1 tshiozak 111 1.1 tshiozak static void 112 1.1 tshiozak uninit(struct _citrus_mapper_serial *sr) 113 1.1 tshiozak { 114 1.1 tshiozak struct maplink *ml; 115 1.1 tshiozak 116 1.1 tshiozak while ((ml = SIMPLEQ_FIRST(&sr->sr_mappers)) != NULL) { 117 1.1 tshiozak SIMPLEQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); 118 1.1 tshiozak _mapper_close(ml->ml_mapper); 119 1.1 tshiozak free(ml); 120 1.1 tshiozak } 121 1.1 tshiozak } 122 1.1 tshiozak 123 1.1 tshiozak static int 124 1.1 tshiozak parse_var(struct _citrus_mapper_area *__restrict ma, 125 1.1 tshiozak struct _citrus_mapper_serial *sr, struct _memstream *ms) 126 1.1 tshiozak { 127 1.1 tshiozak int ret; 128 1.1 tshiozak struct _region r; 129 1.1 tshiozak char mapname[PATH_MAX]; 130 1.1 tshiozak struct maplink *ml; 131 1.1 tshiozak 132 1.1 tshiozak SIMPLEQ_INIT(&sr->sr_mappers); 133 1.1 tshiozak while (1) { 134 1.1 tshiozak /* remove beginning white spaces */ 135 1.1 tshiozak _memstream_skip_ws(ms); 136 1.1 tshiozak if (_memstream_iseof(ms)) 137 1.1 tshiozak break; 138 1.1 tshiozak /* cut down a mapper name */ 139 1.1 tshiozak _memstream_chr(ms, &r, ','); 140 1.1 tshiozak snprintf(mapname, sizeof(mapname), "%.*s", 141 1.1 tshiozak (int)_region_size(&r), (char *)_region_head(&r)); 142 1.1 tshiozak /* remove trailing white spaces */ 143 1.1 tshiozak mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; 144 1.1 tshiozak /* create a new mapper record */ 145 1.1 tshiozak ml = malloc(sizeof(*ml)); 146 1.1 tshiozak if (ml == NULL) 147 1.1 tshiozak return errno; 148 1.1 tshiozak ret = _mapper_open(ma, &ml->ml_mapper, mapname); 149 1.1 tshiozak if (ret) { 150 1.1 tshiozak free(ml); 151 1.1 tshiozak return ret; 152 1.1 tshiozak } 153 1.1 tshiozak /* support only 1:1 and stateless converter */ 154 1.1 tshiozak if (_mapper_get_src_max(ml->ml_mapper) != 1 || 155 1.1 tshiozak _mapper_get_dst_max(ml->ml_mapper) != 1 || 156 1.1 tshiozak _mapper_get_state_size(ml->ml_mapper) != 0) { 157 1.1 tshiozak free(ml); 158 1.1 tshiozak return EINVAL; 159 1.1 tshiozak } 160 1.1 tshiozak SIMPLEQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); 161 1.1 tshiozak } 162 1.1 tshiozak return 0; 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_serial_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_serial *sr; 175 1.1 tshiozak struct _memstream ms; 176 1.1 tshiozak struct _region r; 177 1.1 tshiozak 178 1.1 tshiozak _DIAGASSERT(cm && dir && mt); 179 1.1 tshiozak 180 1.1 tshiozak if (lenmt<sizeof(*mt)) 181 1.1 tshiozak return EINVAL; 182 1.1 tshiozak 183 1.1 tshiozak sr = malloc(sizeof(*sr)); 184 1.1 tshiozak if (sr == NULL) 185 1.1 tshiozak return errno; 186 1.1 tshiozak 187 1.1 tshiozak _region_init(&r, (void *)var, lenvar); 188 1.1 tshiozak _memstream_bind(&ms, &r); 189 1.1 tshiozak if (parse_var(ma, sr, &ms)) { 190 1.1 tshiozak uninit(sr); 191 1.1 tshiozak free(sr); 192 1.1 tshiozak return EINVAL; 193 1.1 tshiozak } 194 1.1 tshiozak cm->cm_closure = sr; 195 1.1 tshiozak mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 196 1.1 tshiozak mt->mt_state_size = 0; /* stateless */ 197 1.1 tshiozak 198 1.1 tshiozak return 0; 199 1.1 tshiozak } 200 1.1 tshiozak 201 1.1 tshiozak static void 202 1.1 tshiozak /*ARGSUSED*/ 203 1.1 tshiozak _citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) 204 1.1 tshiozak { 205 1.1 tshiozak if (cm && cm->cm_closure) { 206 1.1 tshiozak uninit(cm->cm_closure); 207 1.1 tshiozak free(cm->cm_closure); 208 1.1 tshiozak } 209 1.1 tshiozak } 210 1.1 tshiozak 211 1.1 tshiozak static int 212 1.1 tshiozak /*ARGSUSED*/ 213 1.1 tshiozak _citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, 214 1.1 tshiozak _index_t * __restrict dst, _index_t src, 215 1.1 tshiozak void * __restrict ps) 216 1.1 tshiozak { 217 1.1 tshiozak int ret; 218 1.1 tshiozak struct _citrus_mapper_serial *sr; 219 1.1 tshiozak struct maplink *ml; 220 1.1 tshiozak 221 1.1 tshiozak _DIAGASSERT(cm && cm->cm_closure); 222 1.1 tshiozak 223 1.1 tshiozak sr = cm->cm_closure; 224 1.1 tshiozak SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 225 1.1 tshiozak ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); 226 1.1 tshiozak if (ret != _MAPPER_CONVERT_SUCCESS) 227 1.1 tshiozak return ret; 228 1.1 tshiozak } 229 1.1 tshiozak *dst = src; 230 1.1 tshiozak return _MAPPER_CONVERT_SUCCESS; 231 1.1 tshiozak } 232 1.1 tshiozak 233 1.1 tshiozak static int 234 1.1 tshiozak /*ARGSUSED*/ 235 1.1 tshiozak _citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, 236 1.1 tshiozak _index_t * __restrict dst, _index_t src, 237 1.1 tshiozak void * __restrict ps) 238 1.1 tshiozak { 239 1.1 tshiozak int ret; 240 1.1 tshiozak struct _citrus_mapper_serial *sr; 241 1.1 tshiozak struct maplink *ml; 242 1.1 tshiozak _index_t tmp; 243 1.1 tshiozak 244 1.1 tshiozak _DIAGASSERT(cm && cm->cm_closure); 245 1.1 tshiozak 246 1.1 tshiozak sr = cm->cm_closure; 247 1.1 tshiozak SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 248 1.1 tshiozak ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); 249 1.1 tshiozak if (ret == _MAPPER_CONVERT_SUCCESS) { 250 1.1 tshiozak *dst = tmp; 251 1.1 tshiozak return _MAPPER_CONVERT_SUCCESS; 252 1.2 tshiozak } else if (ret == _MAPPER_CONVERT_ILSEQ) 253 1.2 tshiozak return _MAPPER_CONVERT_ILSEQ; 254 1.1 tshiozak } 255 1.2 tshiozak return _MAPPER_CONVERT_NONIDENTICAL; 256 1.1 tshiozak } 257 1.1 tshiozak 258 1.1 tshiozak static void 259 1.1 tshiozak /*ARGSUSED*/ 260 1.1 tshiozak _citrus_mapper_serial_mapper_init_state(struct _citrus_mapper * __restrict cm, 261 1.1 tshiozak void * __restrict ps) 262 1.1 tshiozak { 263 1.1 tshiozak } 264