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