diff --git a/include/paths.h b/include/paths.h index 4f9e6080c5fe..0828e4b1c7cc 100644 --- a/include/paths.h +++ b/include/paths.h @@ -1,4 +1,4 @@ -/* $NetBSD: paths.h,v 1.22 2003/05/03 03:24:01 lukem Exp $ */ +/* $NetBSD: paths.h,v 1.23 2003/06/25 09:51:26 tshiozak Exp $ */ /* * Copyright (c) 1989, 1993 @@ -66,6 +66,9 @@ #define _PATH_DEVNULL "/dev/null" #define _PATH_DRUM "/dev/drum" #define _PATH_I18NMODULE "/usr/lib/i18n" +#define _PATH_ICONV "/usr/share/i18n/iconv" +#define _PATH_ESDB "/usr/share/i18n/esdb" +#define _PATH_CSMAPPER "/usr/share/i18n/csmapper" #define _PATH_KMEM "/dev/kmem" #define _PATH_KSYMS "/dev/ksyms" #define _PATH_KVMDB "/var/db/kvm.db" diff --git a/lib/libc/citrus/Makefile.inc b/lib/libc/citrus/Makefile.inc index ad026577e1d6..4fabba6ad7f0 100644 --- a/lib/libc/citrus/Makefile.inc +++ b/lib/libc/citrus/Makefile.inc @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.3 2003/03/05 20:18:15 tshiozak Exp $ +# $NetBSD: Makefile.inc,v 1.4 2003/06/25 09:51:26 tshiozak Exp $ # sources .PATH: ${ARCHDIR}/citrus ${.CURDIR}/citrus @@ -9,10 +9,10 @@ CITRUS?= yes MODULE_SHLIB_MAJOR!= . ${NETBSDSRCDIR}/lib/i18n_module/shlib_version ; echo $$major CPPFLAGS+= -DI18NMODULE_MAJOR=${MODULE_SHLIB_MAJOR} -SRCS+= citrus_ctype.c citrus_ctype_fallback.c citrus_module.c citrus_none.c - -# to be dynamically loaded - see lib/i18n_module -#SRCS+= citrus_big5.c citrus_euc.c citrus_euctw.c citrus_iso2022.c \ -# citrus_mskanji.c citrus_utf8.c +SRCS+= citrus_bcs.c citrus_csmapper.c citrus_ctype.c citrus_ctype_fallback.c \ + citrus_db.c citrus_db_hash.c citrus_esdb.c citrus_hash.c \ + citrus_iconv.c citrus_lookup.c \ + citrus_mapper.c citrus_memstream.c citrus_mmap.c citrus_module.c \ + citrus_none.c citrus_stdenc.c .endif diff --git a/lib/libc/citrus/citrus_bcs.c b/lib/libc/citrus/citrus_bcs.c new file mode 100644 index 000000000000..7f615b270e93 --- /dev/null +++ b/lib/libc/citrus/citrus_bcs.c @@ -0,0 +1,139 @@ +/* $NetBSD: citrus_bcs.c,v 1.1 2003/06/25 09:51:26 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_bcs.c,v 1.1 2003/06/25 09:51:26 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#ifndef HOSTPROG +#include "namespace.h" +#endif +#include +#include + +#include "citrus_namespace.h" +#include "citrus_bcs.h" + +int +_citrus_bcs_strcasecmp(const char * __restrict str1, + const char * __restrict str2) +{ + int c1=1, c2=1; + + while (c1 && c2 && c1==c2) { + c1 = _bcs_toupper(*str1++); + c2 = _bcs_toupper(*str2++); + } + + return ((c1==c2) ? 0 : ((c1>c2) ? 1:-1)); +} + +int +_citrus_bcs_strncasecmp(const char * __restrict str1, + const char * __restrict str2, size_t sz) +{ + int c1=1, c2=1; + + while (c1 && c2 && c1==c2 && sz!=0) { + c1 = _bcs_toupper(*str1++); + c2 = _bcs_toupper(*str2++); + sz--; + } + + return ((c1==c2) ? 0 : ((c1>c2) ? 1:-1)); +} + +const char * +_citrus_bcs_skip_ws(const char *p) +{ + + while (*p && _bcs_isspace(*p)) + p++; + + return (p); +} + +const char * +_citrus_bcs_skip_nonws(const char *p) +{ + + while (*p && !_bcs_isspace(*p)) + p++; + + return (p); +} + +const char * +_citrus_bcs_skip_ws_len(const char * __restrict p, size_t * __restrict len) +{ + + while (*p && *len>0 && _bcs_isspace(*p)) { + p++; + (*len)--; + } + + return (p); +} + +const char * +_citrus_bcs_skip_nonws_len(const char * __restrict p, size_t * __restrict len) +{ + + while (*p && *len>0 && !_bcs_isspace(*p)) { + p++; + (*len)--; + } + + return (p); +} + +void +_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len) +{ + + while (*len>0 && _bcs_isspace(p[*len-1])) + (*len)--; +} + +void +_citrus_bcs_convert_to_lower(char *s) +{ + while (*s) { + *s = _bcs_tolower(*s); + s++; + } +} + +void _citrus_bcs_convert_to_upper(char *s) +{ + while (*s) { + *s = _bcs_toupper(*s); + s++; + } +} diff --git a/lib/libc/citrus/citrus_bcs.h b/lib/libc/citrus/citrus_bcs.h new file mode 100644 index 000000000000..4fc27b92f4d1 --- /dev/null +++ b/lib/libc/citrus/citrus_bcs.h @@ -0,0 +1,80 @@ +/* $NetBSD: citrus_bcs.h,v 1.1 2003/06/25 09:51:26 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_BCS_H_ +#define _CITRUS_BCS_H_ + +/* + * predicate/conversion for basic character set. + */ + +#define _CITRUS_BCS_PRED(_name_, _cond_) \ +static __inline int _citrus_bcs_##_name_(u_int8_t c) { return (_cond_); } + +_CITRUS_BCS_PRED(isblank, c==' ' || c=='\t') +_CITRUS_BCS_PRED(iseol, c=='\n' || c=='\r') +_CITRUS_BCS_PRED(isspace, + _citrus_bcs_isblank(c) || _citrus_bcs_iseol(c) || + c=='\f' || c=='\v') +_CITRUS_BCS_PRED(isdigit, c>='0' && c<='9') +_CITRUS_BCS_PRED(isupper, c>='A' && c<='Z') +_CITRUS_BCS_PRED(islower, c>='a' && c<='z') +_CITRUS_BCS_PRED(isalpha, _citrus_bcs_isupper(c) || _citrus_bcs_islower(c)) +_CITRUS_BCS_PRED(isalnum, _citrus_bcs_isdigit(c) || _citrus_bcs_isalpha(c)) +_CITRUS_BCS_PRED(isxdigit, + _citrus_bcs_isdigit(c) || + (c>='A' && c<='F') || (c>='a' && c<='f')) + +static __inline u_int8_t +_citrus_bcs_toupper(u_int8_t c) +{ + return (_citrus_bcs_islower(c) ? (c-'a'+'A') : c); +} + +static __inline u_int8_t +_citrus_bcs_tolower(u_int8_t c) +{ + return (_citrus_bcs_isupper(c) ? (c-'A'+'a') : c); +} + +__BEGIN_DECLS +int _citrus_bcs_strcasecmp(const char * __restrict, const char * __restrict); +int _citrus_bcs_strncasecmp(const char * __restrict, const char * __restrict, + size_t); +const char *_citrus_bcs_skip_ws(const char * __restrict); +const char *_citrus_bcs_skip_nonws(const char * __restrict); +const char *_citrus_bcs_skip_ws_len(const char * __restrict, + size_t * __restrict); +const char *_citrus_bcs_skip_nonws_len(const char * __restrict, + size_t * __restrict); +void _citrus_bcs_trunc_rws_len(const char * __restrict, size_t * __restrict); +void _citrus_bcs_convert_to_lower(char *); +void _citrus_bcs_convert_to_upper(char *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_csmapper.c b/lib/libc/citrus/citrus_csmapper.c new file mode 100644 index 000000000000..bb5b04685253 --- /dev/null +++ b/lib/libc/citrus/citrus_csmapper.c @@ -0,0 +1,384 @@ +/* $NetBSD: citrus_csmapper.c,v 1.1 2003/06/25 09:51:27 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_csmapper.c,v 1.1 2003/06/25 09:51:27 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_csmapper.h" +#include "citrus_pivot_file.h" +#include "citrus_db.h" +#include "citrus_db_hash.h" +#include "citrus_lookup.h" + +#ifdef _REENTRANT +static rwlock_t lock = RWLOCK_INITIALIZER; +#endif +static struct _citrus_mapper_area *maparea = NULL; + +#define CS_ALIAS _PATH_CSMAPPER "/charset.alias" +#define CS_PIVOT _PATH_CSMAPPER "/charset.pivot" + + +/* ---------------------------------------------------------------------- */ + +static int +get32(struct _region *r, u_int32_t *rval) +{ + if (_region_size(r) != 4) + return EFTYPE; + + memcpy(rval, _region_head(r), 4); + *rval = be32toh(*rval); + + return 0; +} + +static int +open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src) +{ + int ret; + struct _region r; + + ret = _db_lookup_by_s(db, src, &r, NULL); + if (ret) + return ret; + ret = _db_open(subdb, &r, _CITRUS_PIVOT_SUB_MAGIC, _db_hash_std, NULL); + if (ret) + return ret; + + return 0; +} + + +#define NO_SUCH_FILE EOPNOTSUPP +static int +find_best_pivot_pvdb(const char *src, const char *dst, char *pivot, + size_t pvlen, unsigned long *rnorm) +{ + int ret, num, i; + struct _region fr, r1, r2; + struct _citrus_db *db1, *db2, *db3; + char buf[LINE_MAX]; + unsigned long norm; + u_int32_t val32; + + ret = _map_file(&fr, CS_PIVOT ".pvdb"); + if (ret) { + if (ret == ENOENT) + ret = NO_SUCH_FILE; + return ret; + } + ret = _db_open(&db1, &fr, _CITRUS_PIVOT_MAGIC, _db_hash_std, NULL); + if (ret) + goto quit1; + ret = open_subdb(&db2, db1, src); + if (ret) + goto quit2; + + num = _db_get_num_entries(db2); + *rnorm = ULONG_MAX; + for (i=0; idst, sizeof(pa->dst), + "%.*s", (int)(z1.end-z1.begin), z1.begin); + snprintf(buf, sizeof(buf), + "%.*s", (int)(z2.end-z2.begin), z2.begin); + pa->norm = strtoul(buf, NULL, 0); + + return 0; +} + +static int +find_dst(struct parse_arg *pasrc, const char *dst) +{ + int ret; + struct parse_arg padst; + struct _lookup *cl; + struct _region data; + + ret = _lookup_seq_open(&cl, CS_PIVOT); + if (ret) + return ret; + + ret = _lookup_seq_lookup(cl, pasrc->dst, &data); + while (ret == 0) { + ret = parse_line(&padst, &data); + if (ret) + break; + if (strcmp(dst, padst.dst) == 0) { + pasrc->norm += padst.norm; + break; + } + ret = _lookup_seq_next(cl, NULL, &data); + } + _lookup_seq_close(cl); + + return ret; +} + +static int +find_best_pivot_lookup(const char *src, const char *dst, char *pivot, + size_t pvlen, unsigned long *rnorm) +{ + int ret; + struct _lookup *cl; + struct _region data; + struct parse_arg pa; + unsigned long norm_min; + char pivot_min[PATH_MAX]; + + ret = _lookup_seq_open(&cl, CS_PIVOT); + if (ret) + return ret; + + norm_min = ULONG_MAX; + + /* find pivot code */ + ret = _lookup_seq_lookup(cl, src, &data); + while (ret == 0) { + ret = parse_line(&pa, &data); + if (ret) + break; + ret = find_dst(&pa, dst); + if (ret) + break; + if (pa.norm < norm_min) { + norm_min = pa.norm; + strcpy(pivot_min, pa.dst); + } + ret = _lookup_seq_next(cl, NULL, &data); + } + _lookup_seq_close(cl); + + if (ret != ENOENT) + return ret; + if (norm_min == ULONG_MAX) + return ENOENT; + strlcpy(pivot, pivot_min, pvlen); + if (rnorm) + *rnorm = norm_min; + + return 0; +} + +static int +find_best_pivot(const char *src, const char *dst, char *pivot, size_t pvlen, + unsigned long *rnorm) +{ + int ret; + + ret = find_best_pivot_pvdb(src, dst, pivot, pvlen, rnorm); + if (ret == NO_SUCH_FILE) + ret = find_best_pivot_lookup(src, dst, pivot, pvlen, rnorm); + + return ret; +} + +static __inline int +open_serial_mapper(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict * __restrict rcm, + const char *src, const char *pivot, const char *dst) +{ + char buf[PATH_MAX]; + + snprintf(buf, sizeof(buf), "%s/%s,%s/%s", src, pivot, pivot, dst); + + return _mapper_open_direct(ma, rcm, "mapper_serial", buf); +} + +static struct _citrus_csmapper *csm_none = NULL; +static int +get_none(struct _citrus_mapper_area *__restrict ma, + struct _citrus_csmapper *__restrict *__restrict rcsm) +{ + int ret; + + rwlock_wrlock(&lock); + if (csm_none) { + *rcsm = csm_none; + ret = 0; + goto quit; + } + + ret = _mapper_open_direct(ma, &csm_none, "mapper_none", ""); + if (ret) + goto quit; + _mapper_set_persistent(csm_none); + + *rcsm = csm_none; + ret = 0; +quit: + rwlock_unlock(&lock); + return ret; +} + +int +_citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm, + const char * __restrict src, const char * __restrict dst, + u_int32_t flags, unsigned long *rnorm) +{ + int ret; + char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX]; + const char *realsrc, *realdst; + unsigned long norm; + + ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER); + if (ret) + return ret; + + realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1)); + realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2)); + if (!strcmp(realsrc, realdst)) { + ret = get_none(maparea, rcsm); + if (ret == 0 && rnorm != NULL) + *rnorm = 0; + return ret; + } + + snprintf(key, sizeof(key), "%s/%s", realsrc, realdst); + + ret = _mapper_open(maparea, rcsm, key); + if (ret == 0) { + if (rnorm != NULL) + *rnorm = 0; + return 0; + } + if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0) + return ret; + + ret = find_best_pivot(realsrc, realdst, pivot, sizeof(pivot), &norm); + if (ret) + return ret; + + ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst); + if (ret == 0 && rnorm != NULL) + *rnorm = norm; + + return ret; +} diff --git a/lib/libc/citrus/citrus_csmapper.h b/lib/libc/citrus/citrus_csmapper.h new file mode 100644 index 000000000000..877fe754311a --- /dev/null +++ b/lib/libc/citrus/citrus_csmapper.h @@ -0,0 +1,48 @@ +/* $NetBSD: citrus_csmapper.h,v 1.1 2003/06/25 09:51:27 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_CSMAPPER_H_ +#define _CITRUS_CSMAPPER_H + +#define _citrus_csmapper _citrus_mapper +#define _citrus_csmapper_close _citrus_mapper_close +#define _citrus_csmapper_convert _citrus_mapper_convert +#define _citrus_csmapper_init_state _citrus_mapper_init_state +#define _citrus_csmapper_get_state_size _citrus_mapper_get_state_size +#define _citrus_csmapper_get_src_max _citrus_mapper_get_src_max +#define _citrus_csmapper_get_dst_max _citrus_mapper_get_dst_max + +#define _CITRUS_CSMAPPER_F_PREVENT_PIVOT 0x00000001 +__BEGIN_DECLS +int _citrus_csmapper_open(struct _citrus_csmapper *__restrict *__restrict, + const char *__restrict, + const char *__restrict, u_int32_t, + unsigned long *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_ctype_template.h b/lib/libc/citrus/citrus_ctype_template.h index ad4ccbb42f39..efa3a7b8fd84 100644 --- a/lib/libc/citrus/citrus_ctype_template.h +++ b/lib/libc/citrus/citrus_ctype_template.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype_template.h,v 1.21 2003/03/05 20:18:15 tshiozak Exp $ */ +/* $NetBSD: citrus_ctype_template.h,v 1.22 2003/06/25 09:51:28 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -399,14 +399,14 @@ _FUNCNAME(ctype_init)(void ** __restrict cl, *cl = (void *)cei; - return _FUNCNAME(stdencoding_init)(_CEI_TO_EI(cei), var, lenvar); + return _FUNCNAME(encoding_module_init)(_CEI_TO_EI(cei), var, lenvar); } static void _FUNCNAME(ctype_uninit)(void *cl) { if (cl) { - _FUNCNAME(stdencoding_uninit)(_CEI_TO_EI(_TO_CEI(cl))); + _FUNCNAME(encoding_module_uninit)(_CEI_TO_EI(_TO_CEI(cl))); free(cl); } } @@ -585,6 +585,8 @@ _FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc, err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))), wc, psenc, nresult); + if (err == E2BIG) + err = EINVAL; _RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc); return err; diff --git a/lib/libc/citrus/citrus_db.c b/lib/libc/citrus/citrus_db.c new file mode 100644 index 000000000000..dab02fc124db --- /dev/null +++ b/lib/libc/citrus/citrus_db.c @@ -0,0 +1,342 @@ +/* $NetBSD: citrus_db.c,v 1.1 2003/06/25 09:51:28 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_db.c,v 1.1 2003/06/25 09:51:28 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_db.h" +#include "citrus_db_file.h" + +struct _citrus_db { + /* private */ + struct _region db_region; + u_int32_t (*db_hashfunc)(void *, struct _citrus_region *); + void *db_hashfunc_closure; +}; + +int +_citrus_db_open(struct _citrus_db **rdb, struct _region *r, const char *magic, + u_int32_t (*hashfunc)(void *, struct _citrus_region *), + void *hashfunc_closure) +{ + struct _memstream ms; + struct _citrus_db *db; + struct _citrus_db_header_x *dhx; + + _memstream_bind(&ms, r); + + /* sanity check */ + dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx)); + if (dhx == NULL) + return EFTYPE; + if (strncmp(dhx->dhx_magic, magic, _CITRUS_DB_MAGIC_SIZE) != 0) + return EFTYPE; + if (_memstream_seek(&ms, be32toh(dhx->dhx_entry_offset), SEEK_SET)) + return EFTYPE; + + if (be32toh(dhx->dhx_num_entries)*_CITRUS_DB_ENTRY_SIZE > + _memstream_remainder(&ms)) + return EFTYPE; + + db = malloc(sizeof(*db)); + if (db==NULL) + return errno; + db->db_region = *r; + db->db_hashfunc = hashfunc; + db->db_hashfunc_closure = hashfunc_closure; + *rdb = db; + + return 0; +} + +void +_citrus_db_close(struct _citrus_db *db) +{ + free(db); +} + +int +_citrus_db_lookup(struct _citrus_db *db, struct _citrus_region *key, + struct _citrus_region *data, struct _citrus_db_locator *dl) +{ + u_int32_t hashval, num_entries; + size_t offset; + struct _memstream ms; + struct _citrus_db_header_x *dhx; + struct _citrus_db_entry_x *dex; + struct _citrus_region r; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx)); + _DIAGASSERT(dhx); + num_entries = be32toh(dhx->dhx_num_entries); + if (num_entries == 0) + return ENOENT; + + if (dl != NULL && dl->dl_offset>0) { + hashval = dl->dl_hashval; + offset = dl->dl_offset; + if (offset >= _region_size(&db->db_region)) + return ENOENT; + } else { + hashval = + db->db_hashfunc(db->db_hashfunc_closure, key)%num_entries; + offset = + be32toh(dhx->dhx_entry_offset) + + hashval * _CITRUS_DB_ENTRY_SIZE; + if (dl) + dl->dl_hashval = hashval; + } + do { + /* seek to the next entry */ + if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET)) + return EFTYPE; + /* get the entry record */ + dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE); + if (dex == NULL) + return EFTYPE; + + /* jump to next entry having the same hash value. */ + offset = be32toh(dex->dex_next_offset); + + /* save the current position */ + if (dl) { + dl->dl_offset = offset; + if (offset==0) + dl->dl_offset = _region_size(&db->db_region); + } + + /* compare hash value. */ + if (be32toh(dex->dex_hash_value) != hashval) + /* not found */ + break; + /* compare key length */ + if (be32toh(dex->dex_key_size) == _region_size(key)) { + /* seek to the head of the key. */ + if (_memstream_seek(&ms, be32toh(dex->dex_key_offset), + SEEK_SET)) + return EFTYPE; + /* get the region of the key */ + if (_memstream_getregion(&ms, &r, + _region_size(key)) == NULL) + return EFTYPE; + /* compare key byte stream */ + if (memcmp(_region_head(&r), _region_head(key), + _region_size(key)) == 0) { + /* match */ + if (_memstream_seek( + &ms, be32toh(dex->dex_data_offset), + SEEK_SET)) + return EFTYPE; + if (_memstream_getregion( + &ms, data, + be32toh(dex->dex_data_size)) == NULL) + return EFTYPE; + return 0; + } + } + } while (offset != 0); + + return ENOENT; +} + +int +_citrus_db_lookup_by_string(struct _citrus_db *db, const char *key, + struct _citrus_region *data, + struct _citrus_db_locator *dl) +{ + struct _region r; + + /* LINTED: discard const */ + _region_init(&r, (char *)key, strlen(key)); + + return _citrus_db_lookup(db, &r, data, dl); +} + +int +_citrus_db_lookup8_by_string(struct _citrus_db *db, const char *key, + u_int8_t *rval, struct _citrus_db_locator *dl) +{ + int ret; + struct _region r; + + ret = _citrus_db_lookup_by_string(db, key, &r, dl); + if (ret) + return ret; + + if (_region_size(&r) != 1) + return EFTYPE; + + if (rval) + memcpy(rval, _region_head(&r), 1); + + return 0; +} + +int +_citrus_db_lookup16_by_string(struct _citrus_db *db, const char *key, + u_int16_t *rval, struct _citrus_db_locator *dl) +{ + int ret; + struct _region r; + u_int16_t val; + + ret = _citrus_db_lookup_by_string(db, key, &r, dl); + if (ret) + return ret; + + if (_region_size(&r) != 2) + return EFTYPE; + + if (rval) { + memcpy(&val, _region_head(&r), 2); + *rval = be16toh(val); + } + + return 0; +} + +int +_citrus_db_lookup32_by_string(struct _citrus_db *db, const char *key, + u_int32_t *rval, struct _citrus_db_locator *dl) +{ + int ret; + struct _region r; + u_int32_t val; + + ret = _citrus_db_lookup_by_string(db, key, &r, dl); + if (ret) + return ret; + + if (_region_size(&r) != 4) + return EFTYPE; + + if (rval) { + memcpy(&val, _region_head(&r), 4); + *rval = be32toh(val); + } + + return 0; +} + +int +_citrus_db_lookup_string_by_string(struct _citrus_db *db, const char *key, + const char **rdata, + struct _citrus_db_locator *dl) +{ + int ret; + struct _region r; + + ret = _citrus_db_lookup_by_string(db, key, &r, dl); + if (ret) + return ret; + + if (_region_size(&r) == 0) + return EFTYPE; + + /* check whether the string is null terminated */ + if (*((const char*)_region_head(&r)+_region_size(&r)) != '\0') + return EFTYPE; + + if (rdata) + *rdata = _region_head(&r); + + return 0; +} + +int +_citrus_db_get_number_of_entries(struct _citrus_db *db) +{ + struct _memstream ms; + struct _citrus_db_header_x *dhx; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx)); + _DIAGASSERT(dhx); + return (int)be32toh(dhx->dhx_num_entries); +} + +int +_citrus_db_get_entry(struct _citrus_db *db, int idx, + struct _region *key, struct _region *data) +{ + u_int32_t num_entries; + size_t offset; + struct _memstream ms; + struct _citrus_db_header_x *dhx; + struct _citrus_db_entry_x *dex; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx)); + _DIAGASSERT(dhx); + num_entries = be32toh(dhx->dhx_num_entries); + if (idx<0 || (u_int32_t)idx>=num_entries) + return EINVAL; + + /* seek to the next entry */ + offset = be32toh(dhx->dhx_entry_offset) + idx * _CITRUS_DB_ENTRY_SIZE; + if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET)) + return EFTYPE; + /* get the entry record */ + dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE); + if (dex == NULL) + return EFTYPE; + /* seek to the head of the key. */ + if (_memstream_seek(&ms, be32toh(dex->dex_key_offset), SEEK_SET)) + return EFTYPE; + /* get the region of the key. */ + if (_memstream_getregion(&ms, key, be32toh(dex->dex_key_size))==NULL) + return EFTYPE; + /* seek to the head of the data. */ + if (_memstream_seek(&ms, be32toh(dex->dex_data_offset), SEEK_SET)) + return EFTYPE; + /* get the region of the data. */ + if (_memstream_getregion(&ms, data, be32toh(dex->dex_data_size))==NULL) + return EFTYPE; + + return 0; +} diff --git a/lib/libc/citrus/citrus_db.h b/lib/libc/citrus/citrus_db.h new file mode 100644 index 000000000000..16de7626c607 --- /dev/null +++ b/lib/libc/citrus/citrus_db.h @@ -0,0 +1,74 @@ +/* $NetBSD: citrus_db.h,v 1.1 2003/06/25 09:51:29 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_DB_H_ +#define _CITRUS_DB_H_ + +struct _citrus_db; +struct _citrus_db_locator { + u_int32_t dl_hashval; + size_t dl_offset; +}; + +__BEGIN_DECLS +int _citrus_db_open(struct _citrus_db **, struct _citrus_region *, + const char *, + u_int32_t (*)(void *, struct _citrus_region *), + void *); +void _citrus_db_close(struct _citrus_db *); +int _citrus_db_lookup(struct _citrus_db *, struct _citrus_region *, + struct _citrus_region *, + struct _citrus_db_locator *); +int _citrus_db_lookup_by_string(struct _citrus_db *, const char *, + struct _citrus_region *, + struct _citrus_db_locator *); +int _citrus_db_lookup8_by_string(struct _citrus_db *, const char *, + u_int8_t *, + struct _citrus_db_locator *); +int _citrus_db_lookup16_by_string(struct _citrus_db *, const char *, + u_int16_t *, + struct _citrus_db_locator *); +int _citrus_db_lookup32_by_string(struct _citrus_db *, const char *, + u_int32_t *, + struct _citrus_db_locator *); +int _citrus_db_lookup_string_by_string(struct _citrus_db *, const char *, + const char **, + struct _citrus_db_locator *); +int _citrus_db_get_number_of_entries(struct _citrus_db *); +int _citrus_db_get_entry(struct _citrus_db *, int, + struct _citrus_region *, struct _citrus_region *); +__END_DECLS + +static __inline void +_citrus_db_locator_init(struct _citrus_db_locator *dl) +{ + dl->dl_hashval = 0; + dl->dl_offset = 0; +} + +#endif diff --git a/lib/libc/citrus/citrus_db_factory.c b/lib/libc/citrus/citrus_db_factory.c new file mode 100644 index 000000000000..6b951d553e47 --- /dev/null +++ b/lib/libc/citrus/citrus_db_factory.c @@ -0,0 +1,351 @@ +/* $NetBSD: citrus_db_factory.c,v 1.1 2003/06/25 09:51:29 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_db_factory.c,v 1.1 2003/06/25 09:51:29 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __packed +#define __packed /* ignored */ +#endif +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_db_file.h" +#include "citrus_db_factory.h" + +struct _citrus_db_factory_entry { + SIMPLEQ_ENTRY(_citrus_db_factory_entry) de_entry; + struct _citrus_db_factory_entry *de_next; + u_int32_t de_hashvalue; + struct _region de_key; + int de_key_free; + struct _region de_data; + int de_data_free; + int de_idx; +}; + +struct _citrus_db_factory { + size_t df_num_entries; + SIMPLEQ_HEAD(, _citrus_db_factory_entry) df_entries; + size_t df_total_key_size; + size_t df_total_data_size; + u_int32_t (*df_hashfunc)(void *, struct _citrus_region *); + void *df_hashfunc_closure; +}; + +#define DB_ALIGN 16 + +int +_citrus_db_factory_create(struct _citrus_db_factory **rdf, + _citrus_db_hash_func_t hashfunc, + void *hashfunc_closure) +{ + struct _citrus_db_factory *df; + + df = malloc(sizeof(*df)); + if (df == NULL) + return errno; + df->df_num_entries = 0; + df->df_total_key_size = df->df_total_data_size = 0; + SIMPLEQ_INIT(&df->df_entries); + df->df_hashfunc = hashfunc; + df->df_hashfunc_closure = hashfunc_closure; + + *rdf = df; + + return 0; +} + +void +_citrus_db_factory_free(struct _citrus_db_factory *df) +{ + struct _citrus_db_factory_entry *de; + + while ((de = SIMPLEQ_FIRST(&df->df_entries)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&df->df_entries, de_entry); + if (de->de_key_free) + free(_region_head(&de->de_key)); + if (de->de_data_free) + free(_region_head(&de->de_data)); + free(de); + } + free(df); +} + +static __inline size_t +ceilto(size_t sz) +{ + return (sz+DB_ALIGN-1) & ~(DB_ALIGN-1); +} + +int +_citrus_db_factory_add(struct _citrus_db_factory *df, + struct _region *key, int keyfree, + struct _region *data, int datafree) +{ + struct _citrus_db_factory_entry *de; + + de = malloc(sizeof(*de)); + if (de == NULL) + return -1; + + de->de_hashvalue = df->df_hashfunc(df->df_hashfunc_closure, key); + de->de_key = *key; + de->de_key_free = keyfree; + de->de_data = *data; + de->de_data_free = datafree; + de->de_idx = -1; + + SIMPLEQ_INSERT_TAIL(&df->df_entries, de, de_entry); + df->df_total_key_size += _region_size(key); + df->df_total_data_size += ceilto(_region_size(data)); + df->df_num_entries++; + + return 0; + +} + +int +_citrus_db_factory_add_by_string(struct _citrus_db_factory *df, + const char *key, + struct _citrus_region *data, int datafree) +{ + struct _region r; + char *tmp; + tmp = strdup(key); + if (tmp == NULL) + return errno; + _region_init(&r, tmp, strlen(key)); + return _citrus_db_factory_add(df, &r, 1, data, datafree); +} + +int +_citrus_db_factory_add8_by_string(struct _citrus_db_factory *df, + const char *key, u_int8_t val) +{ + struct _region r; + u_int8_t *p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return errno; + *p = val; + _region_init(&r, p, 1); + return _citrus_db_factory_add_by_string(df, key, &r, 1); +} + +int +_citrus_db_factory_add16_by_string(struct _citrus_db_factory *df, + const char *key, u_int16_t val) +{ + struct _region r; + u_int16_t *p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return errno; + *p = htons(val); + _region_init(&r, p, 2); + return _citrus_db_factory_add_by_string(df, key, &r, 1); +} + +int +_citrus_db_factory_add32_by_string(struct _citrus_db_factory *df, + const char *key, u_int32_t val) +{ + struct _region r; + u_int32_t *p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return errno; + *p = htonl(val); + _region_init(&r, p, 4); + return _citrus_db_factory_add_by_string(df, key, &r, 1); +} + +int +_citrus_db_factory_add_string_by_string(struct _citrus_db_factory *df, + const char *key, const char *data) +{ + char *p; + struct _region r; + + p = strdup(data); + if (p == NULL) + return errno; + _region_init(&r, p, strlen(p)+1); + return _citrus_db_factory_add_by_string(df, key, &r, 1); +} + +size_t +_citrus_db_factory_calc_size(struct _citrus_db_factory *df) +{ + size_t sz; + + sz = ceilto(_CITRUS_DB_HEADER_SIZE); + sz += ceilto(_CITRUS_DB_ENTRY_SIZE * df->df_num_entries); + sz += ceilto(df->df_total_key_size); + sz += df->df_total_data_size; + + return sz; +} + +static __inline void +put8(struct _region *r, size_t *rofs, u_int8_t val) +{ + *(u_int8_t *)_region_offset(r, *rofs) = val; + *rofs += 1; +} + +static __inline void +put16(struct _region *r, size_t *rofs, u_int16_t val) +{ + val = htons(val); + memcpy(_region_offset(r, *rofs), &val, 2); + *rofs += 2; +} + +static __inline void +put32(struct _region *r, size_t *rofs, u_int32_t val) +{ + val = htonl(val); + memcpy(_region_offset(r, *rofs), &val, 4); + *rofs += 4; +} + +static __inline void +putpad(struct _region *r, size_t *rofs) +{ + size_t i; + for (i=ceilto(*rofs)-*rofs; i>0; i--) + put8(r, rofs, 0); +} + +static __inline void +dump_header(struct _region *r, const char *magic, size_t *rofs, + size_t num_entries) +{ + while (*rofs<_CITRUS_DB_MAGIC_SIZE) + put8(r, rofs, *magic++); + put32(r, rofs, num_entries); + put32(r, rofs, _CITRUS_DB_HEADER_SIZE); +} + +int +_citrus_db_factory_serialize(struct _citrus_db_factory *df, const char *magic, + struct _region *r) +{ + size_t i, ofs, keyofs, dataofs, nextofs; + struct _citrus_db_factory_entry *de, **depp, *det; + + ofs = 0; + /* check whether more than 0 entries exist */ + if (df->df_num_entries == 0) { + dump_header(r, magic, &ofs, 0); + return 0; + } + /* allocate hash table */ + depp = malloc(sizeof(*depp)*df->df_num_entries); + if (depp == NULL) + return -1; + for (i=0; idf_num_entries; i++) + *depp = NULL; + + /* step1: store the entries which are not conflicting */ + SIMPLEQ_FOREACH(de, &df->df_entries, de_entry) { + de->de_hashvalue %= df->df_num_entries; + de->de_idx = -1; + de->de_next = NULL; + if (depp[de->de_hashvalue] == NULL) { + depp[de->de_hashvalue] = de; + de->de_idx = (int)de->de_hashvalue; + } + } + + /* step2: resolve conflicts */ + i = 0; + SIMPLEQ_FOREACH(de, &df->df_entries, de_entry) { + if (de->de_idx == -1) { + det = depp[de->de_hashvalue]; + while (det->de_next != NULL) + det = det->de_next; + det->de_next = de; + while (depp[i] != NULL) + i++; + depp[i] = de; + de->de_idx = (int)i; + } + } + + keyofs = + _CITRUS_DB_HEADER_SIZE + + ceilto(df->df_num_entries*_CITRUS_DB_ENTRY_SIZE); + dataofs = keyofs + ceilto(df->df_total_key_size); + + /* dump header */ + dump_header(r, magic, &ofs, df->df_num_entries); + + /* dump entries */ + for (i=0; idf_num_entries; i++) { + de = depp[i]; + nextofs = 0; + if (de->de_next) { + nextofs = + _CITRUS_DB_HEADER_SIZE + + de->de_next->de_idx * _CITRUS_DB_ENTRY_SIZE; + } + put32(r, &ofs, de->de_hashvalue); + put32(r, &ofs, nextofs); + put32(r, &ofs, keyofs); + put32(r, &ofs, _region_size(&de->de_key)); + put32(r, &ofs, dataofs); + put32(r, &ofs, _region_size(&de->de_data)); + memcpy(_region_offset(r, keyofs), + _region_head(&de->de_key), _region_size(&de->de_key)); + keyofs += _region_size(&de->de_key); + memcpy(_region_offset(r, dataofs), + _region_head(&de->de_data), _region_size(&de->de_data)); + dataofs += _region_size(&de->de_data); + putpad(r, &dataofs); + } + putpad(r, &ofs); + putpad(r, &keyofs); + free(depp); + + return 0; +} diff --git a/lib/libc/citrus/citrus_db_factory.h b/lib/libc/citrus/citrus_db_factory.h new file mode 100644 index 000000000000..2a3c7268b359 --- /dev/null +++ b/lib/libc/citrus/citrus_db_factory.h @@ -0,0 +1,58 @@ +/* $NetBSD: citrus_db_factory.h,v 1.1 2003/06/25 09:51:30 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_DB_FACTORY_H_ +#define _CITRUS_DB_FACTORY_H_ + +struct _citrus_db_factory; +typedef u_int32_t (*_citrus_db_hash_func_t)(void *, struct _citrus_region *);; + +__BEGIN_DECLS +int _citrus_db_factory_create(struct _citrus_db_factory **, + _citrus_db_hash_func_t, void *); +void _citrus_db_factory_free(struct _citrus_db_factory *); +int _citrus_db_factory_add(struct _citrus_db_factory *, + struct _citrus_region *, int, + struct _citrus_region *, int); +int _citrus_db_factory_add_by_string(struct _citrus_db_factory *, + const char *, + struct _citrus_region *, int); +int _citrus_db_factory_add8_by_string(struct _citrus_db_factory *, + const char *, u_int8_t); +int _citrus_db_factory_add16_by_string(struct _citrus_db_factory *, + const char *, u_int16_t); +int _citrus_db_factory_add32_by_string(struct _citrus_db_factory *, + const char *, u_int32_t); +int _citrus_db_factory_add_string_by_string(struct _citrus_db_factory *, + const char *, const char *); +size_t _citrus_db_factory_calc_size(struct _citrus_db_factory *); +int _citrus_db_factory_serialize(struct _citrus_db_factory *, + const char *, struct _citrus_region *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_db_file.h b/lib/libc/citrus/citrus_db_file.h new file mode 100644 index 000000000000..daf32a27ff81 --- /dev/null +++ b/lib/libc/citrus/citrus_db_file.h @@ -0,0 +1,84 @@ +/* $NetBSD: citrus_db_file.h,v 1.1 2003/06/25 09:51:30 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_DB_FILE_H_ +#define _CITRUS_DB_FILE_H_ + +/* + * db format: + * +--- + * | header + * | - magic + * | - num entries + * +--- + * | entry directory + * | +------------ + * | | entry0 + * | | - hash value + * | | - next entry + * | | - key offset + * | | - key len + * | | - data offset + * | | - data size + * | |--- + * | | entry1 + * | | .. + * | | entryN + * | +--- + * +--- + * | key table + * | - key0 + * | ... + * | - keyN + * +--- + * | data table + * | - data0 + * | ... + * | - dataN + * +--- + */ + +#define _CITRUS_DB_MAGIC_SIZE 8 +#define _CITRUS_DB_HEADER_SIZE 16 +struct _citrus_db_header_x { + char dhx_magic[_CITRUS_DB_MAGIC_SIZE]; + u_int32_t dhx_num_entries; + u_int32_t dhx_entry_offset; +} __packed; + +struct _citrus_db_entry_x { + u_int32_t dex_hash_value; + u_int32_t dex_next_offset; + u_int32_t dex_key_offset; + u_int32_t dex_key_size; + u_int32_t dex_data_offset; + u_int32_t dex_data_size; +} __packed; +#define _CITRUS_DB_ENTRY_SIZE 24 + +#endif diff --git a/lib/libc/citrus/citrus_db_hash.c b/lib/libc/citrus/citrus_db_hash.c new file mode 100644 index 000000000000..675e5c3cc7a1 --- /dev/null +++ b/lib/libc/citrus/citrus_db_hash.c @@ -0,0 +1,67 @@ +/* $NetBSD: citrus_db_hash.c,v 1.1 2003/06/25 09:51:30 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_db_hash.c,v 1.1 2003/06/25 09:51:30 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#ifndef HOSTPROG +#include "namespace.h" +#endif +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_db_hash.h" + +u_int32_t +/*ARGSUSED*/ +_citrus_db_hash_std(void *closure, struct _region *r) +{ + const u_int8_t *p = _region_head(r); + u_int32_t hash = 0, tmp; + size_t i; + + for (i=_region_size(r); i>0; i--) { + hash <<= 4; + hash += _bcs_tolower(*p); + tmp = hash & 0xF0000000; + if (tmp != 0) { + hash ^= tmp; + hash ^= tmp >> 24; + } + p++; + } + return hash; +} diff --git a/lib/libc/citrus/citrus_db_hash.h b/lib/libc/citrus/citrus_db_hash.h new file mode 100644 index 000000000000..3187ac2bb346 --- /dev/null +++ b/lib/libc/citrus/citrus_db_hash.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_db_hash.h,v 1.1 2003/06/25 09:51:31 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_DB_HASH_H_ +#define _CITRUS_DB_HASH_H_ + +__BEGIN_DECLS +u_int32_t _citrus_db_hash_std(void *, struct _citrus_region *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_esdb.c b/lib/libc/citrus/citrus_esdb.c new file mode 100644 index 000000000000..97711b1e6ca6 --- /dev/null +++ b/lib/libc/citrus/citrus_esdb.c @@ -0,0 +1,343 @@ +/* $NetBSD: citrus_esdb.c,v 1.1 2003/06/25 09:51:31 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_esdb.c,v 1.1 2003/06/25 09:51:31 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_lookup.h" +#include "citrus_db.h" +#include "citrus_db_hash.h" +#include "citrus_esdb.h" +#include "citrus_esdb_file.h" + +#define ESDB_DIR "esdb.dir" +#define ESDB_ALIAS "esdb.alias" + +/* + * _citrus_esdb_alias: + * resolve encoding scheme name aliases. + */ +const char * +_citrus_esdb_alias(const char *esname, char *buf, size_t bufsize) +{ + return _lookup_alias(_PATH_ESDB "/" ESDB_ALIAS, esname, buf, bufsize); +} + + +/* + * conv_esdb: + * external representation -> local structure. + */ +static int +conv_esdb(struct _citrus_esdb *esdb, struct _region *fr) +{ + int ret; + struct _citrus_db *db; + u_int32_t version, num_charsets, csid, i, tmp; + char buf[100]; + const char *str; + + /* open db */ + ret = _db_open(&db, fr, _CITRUS_ESDB_MAGIC, &_db_hash_std, NULL); + if (ret) + goto err0; + + /* check version */ + ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_VERSION, &version, NULL); + if (ret) + goto err1; + switch (version) { + case 0x00000001: + /* current version */ + /* initial version */ + break; + default: + ret = EFTYPE; + goto err1; + } + + /* get encoding/variable */ + ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_ENCODING, &str, NULL); + if (ret) + goto err1; + esdb->db_encname = strdup(str); + if (esdb->db_encname == NULL) { + ret = errno; + goto err1; + } + + esdb->db_len_variable = 0; + esdb->db_variable = NULL; + ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_VARIABLE, &str, NULL); + if (ret==0) { + esdb->db_len_variable = strlen(str)+1; + esdb->db_variable = strdup(str); + if (esdb->db_variable == NULL) { + ret = errno; + goto err2; + } + } else if (ret != ENOENT) + goto err2; + + /* get number of charsets */ + ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_NUM_CHARSETS, + &num_charsets, NULL); + if (ret) + goto err3; + esdb->db_num_charsets = num_charsets; + + /* get invalid character */ + ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_INVALID, &tmp, NULL); + if (ret==0) { + esdb->db_use_invalid = 1; + esdb->db_invalid = tmp; + } else if (ret == ENOENT) + esdb->db_use_invalid = 0; + else + goto err3; + + /* get charsets */ + esdb->db_charsets = malloc(num_charsets * sizeof(*esdb->db_charsets)); + if (esdb->db_charsets == NULL) { + ret = errno; + goto err3; + } + for (i=0; idb_charsets[i].ec_csid = csid; + + sprintf(buf, _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i); + ret = _db_lookupstr_by_s(db, buf, &str, NULL); + if (ret) + goto err4; + esdb->db_charsets[i].ec_csname = strdup(str); + if (esdb->db_charsets[i].ec_csname == NULL) { + ret = errno; + goto err4; + } + } + + _db_close(db); + return 0; + +err4: + for (; i>0; i--) + free(esdb->db_charsets[i-1].ec_csname); + free(esdb->db_charsets); +err3: + free(esdb->db_variable); +err2: + free(esdb->db_encname); +err1: + _db_close(db); + if (ret == ENOENT) + ret = EFTYPE; +err0: + return ret; +} + +/* + * _citrus_esdb_open: + * open an ESDB file. + */ +int +_citrus_esdb_open(struct _citrus_esdb *db, const char *esname) +{ + int ret; + const char *realname, *encfile; + char buf1[PATH_MAX], buf2[PATH_MAX], path[PATH_MAX]; + struct _region fr; + + _DIAGASSERT(esname != NULL); + + snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_ALIAS); + realname = _lookup_alias(path, esname, buf1, sizeof(buf1)); + + snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_DIR); + encfile = _lookup_simple(path, realname, buf2, sizeof(buf2)); + if (encfile==NULL) + return ENOENT; + + /* open file */ + snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, encfile); + ret = _map_file(&fr, path); + if (ret) + return ret; + + ret = conv_esdb(db, &fr); + + _unmap_file(&fr); + + return ret; +} + +/* + * _citrus_esdb_close: + * free an ESDB. + */ +void +_citrus_esdb_close(struct _citrus_esdb *db) +{ + int i; + + _DIAGASSERT(db != NULL); + _DIAGASSERT(db->db_num_charsets == 0 || db->db_charsets != NULL); + + for (i=0; idb_num_charsets; i++) + free(db->db_charsets[i].ec_csname); + db->db_num_charsets = 0; + free(db->db_charsets); db->db_charsets = NULL; + free(db->db_encname); db->db_encname = NULL; + db->db_len_variable = 0; + free(db->db_variable); db->db_variable = NULL; +} + +/* + * _citrus_esdb_free_list: + * free the list. + */ +void +_citrus_esdb_free_list(char **list, size_t num) +{ + size_t i; + + for (i=0; i +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_hash.c,v 1.1 2003/06/25 09:51:32 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_region.h" +#include "citrus_hash.h" +#include "citrus_db_hash.h" + +int +_citrus_string_hash_func(const char *key, int hashsize) +{ + struct _region r; + + /* LINTED: discard const */ + _region_init(&r, (char *)key, strlen(key)); + + return (int)(_db_hash_std(NULL, &r) % (u_int32_t)hashsize); +} diff --git a/lib/libc/citrus/citrus_hash.h b/lib/libc/citrus/citrus_hash.h new file mode 100644 index 000000000000..06d4d02d7d9a --- /dev/null +++ b/lib/libc/citrus/citrus_hash.h @@ -0,0 +1,72 @@ +/* $NetBSD: citrus_hash.h,v 1.1 2003/06/25 09:51:33 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_HASH_H_ +#define _CITRUS_HASH_H_ + +#define _CITRUS_HASH_ENTRY(type) \ +struct { \ + struct type *che_next, **che_pprev; \ +} +#define _CITRUS_HASH_HEAD(headname, type, hashsize) \ +struct headname { \ + struct type *chh_table[hashsize]; \ +} +#define _CITRUS_HASH_INIT(head, hashsize) \ +do { \ + int _ch_loop; \ + for (_ch_loop=0; _ch_loopchh_table[_ch_loop] = NULL; \ +} while (/*CONSTCOND*/0) +#define _CITRUS_HASH_REMOVE(elm, field) \ +do { \ + if ((elm)->field.che_next) \ + (elm)->field.che_next->field.che_pprev = \ + (elm)->field.che_pprev; \ + *(elm)->field.che_pprev = (elm)->field.che_next; \ +} while (/*CONSTCOND*/0) +#define _CITRUS_HASH_INSERT(head, elm, field, hashval) \ +do { \ + (elm)->field.che_pprev = &(head)->chh_table[hashval]; \ + (elm)->field.che_next = (head)->chh_table[hashval]; \ + (head)->chh_table[hashval] = (elm); \ +} while (/*CONSTCOND*/0) +#define _CITRUS_HASH_SEARCH(head, elm, field, matchfunc, key, hashval) \ +do { \ + for ((elm)=(head)->chh_table[hashval]; \ + (elm); \ + (elm)=(elm)->field.che_next) \ + if (matchfunc((elm), key)==0) \ + break; \ +} while (/*CONSTCOND*/0) + +__BEGIN_DECLS +int _citrus_string_hash_func(const char *, int); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_iconv.c b/lib/libc/citrus/citrus_iconv.c new file mode 100644 index 000000000000..a1160263271c --- /dev/null +++ b/lib/libc/citrus/citrus_iconv.c @@ -0,0 +1,210 @@ +/* $NetBSD: citrus_iconv.c,v 1.1 2003/06/25 09:51:34 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_iconv.c,v 1.1 2003/06/25 09:51:34 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_lookup.h" +#include "citrus_iconv.h" + +#define _CITRUS_ICONV_DIR "iconv.dir" +#define _CITRUS_ICONV_ALIAS "iconv.alias" + +/* + * lookup_iconv_entry: + * lookup iconv.dir entry in the specified directory. + * + * line format of iconv.dir file: + * key module arg + * key : lookup key. + * module : iconv module name. + * arg : argument for the module (generally, description file name) + * + */ +static __inline int +lookup_iconv_entry(const char *curdir, const char *key, + char *linebuf, size_t linebufsize, + const char **module, const char **variable) +{ + const char *cp, *cq; + char *p, path[PATH_MAX]; + + /* iconv.dir path */ + snprintf(path, PATH_MAX, "%s/" _CITRUS_ICONV_DIR, curdir); + + /* lookup db */ + cp = p = _lookup_simple(path, key, linebuf, linebufsize); + if (p == NULL) + return ENOENT; + + /* get module name */ + *module = p; + cq = _bcs_skip_nonws(cp); + p[cq-cp] = '\0'; + p += cq-cp+1; + cq++; + + /* get variable */ + cp = _bcs_skip_ws(cq); + *variable = p += cp - cq; + cq = _bcs_skip_nonws(cp); + p[cq-cp] = '\0'; + + return 0; +} + +/* + * _citrus_iconv_open: + * open a converter for the specified in/out codes. + */ +int +_citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rci, + const char * __restrict basedir, + const char * __restrict src, const char * __restrict dst) +{ + int ret; + struct _citrus_iconv *ci; + _citrus_iconv_getops_t getops; + char realsrc[PATH_MAX], realdst[PATH_MAX], key[PATH_MAX]; + char linebuf[PATH_MAX], path[PATH_MAX]; + const char *module, *variable; + + /* resolve codeset name aliases */ + snprintf(path, sizeof(path), "%s/%s", basedir, _CITRUS_ICONV_ALIAS); + strlcpy(realsrc, _lookup_alias(path, src, linebuf, PATH_MAX), PATH_MAX); + strlcpy(realdst, _lookup_alias(path, dst, linebuf, PATH_MAX), PATH_MAX); + + /* sanity check */ + if (strchr(realsrc, '/') != NULL || strchr(realdst, '/')) + return EINVAL; + + /* search converter entry */ + snprintf(key, sizeof(key), "%s/%s", realsrc, realdst); + ret = lookup_iconv_entry(basedir, key, linebuf, PATH_MAX, + &module, &variable); + if (ret) { + if (ret == ENOENT) + /* fallback */ + ret = lookup_iconv_entry(basedir, "*", + linebuf, PATH_MAX, + &module, &variable); + if (ret) + return ret; + } + + /* initialize iconv handle */ + ci = malloc(sizeof(*ci)); + if (!ci) { + ret = errno; + goto err; + } + ci->ci_module = NULL; + ci->ci_ops = NULL; + ci->ci_closure = NULL; + + /* load module */ + ret = _citrus_load_module(&ci->ci_module, module); + if (ret) + goto err; + + /* get operators */ + getops = (_citrus_iconv_getops_t) + _citrus_find_getops(ci->ci_module, module, "iconv"); + if (!getops) { + ret = EOPNOTSUPP; + goto err; + } + ci->ci_ops = malloc(sizeof(*ci->ci_ops)); + if (!ci->ci_ops) { + ret = errno; + goto err; + } + ret = (*getops)(ci->ci_ops, sizeof(*ci->ci_ops), + _CITRUS_ICONV_ABI_VERSION); + if (ret) + goto err; + + if (!ci->ci_ops->io_init || + !ci->ci_ops->io_uninit || + !ci->ci_ops->io_convert) + goto err; + + /* initialize the converter */ + ret = (*ci->ci_ops->io_init)(ci, basedir, realsrc, realdst, + (const void *)variable, + strlen(variable)+1); + if (ret) + goto err; + + *rci = ci; + + return 0; +err: + _citrus_iconv_close(ci); + return ret; +} + +/* + * _citrus_iconv_close: + * close the specified converter. + */ +void +_citrus_iconv_close(struct _citrus_iconv *ci) +{ + if (ci) { + if (ci->ci_module) { + if (ci->ci_ops) { + if (ci->ci_closure) + (*ci->ci_ops->io_uninit)(ci); + free(ci->ci_ops); + } + _citrus_unload_module(ci->ci_module); + } + free(ci); + } +} diff --git a/lib/libc/citrus/citrus_iconv.h b/lib/libc/citrus/citrus_iconv.h new file mode 100644 index 000000000000..f622dd801ca6 --- /dev/null +++ b/lib/libc/citrus/citrus_iconv.h @@ -0,0 +1,69 @@ +/* $NetBSD: citrus_iconv.h,v 1.1 2003/06/25 09:51:34 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_ICONV_H_ +#define _CITRUS_ICONV_H_ + +struct _citrus_iconv; +struct _citrus_iconv_ops; + +__BEGIN_DECLS +int _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict, + const char * __restrict, + const char * __restrict, const char * __restrict); +void _citrus_iconv_close(struct _citrus_iconv *); +__END_DECLS + + +#include "citrus_iconv_local.h" + +#define _CITRUS_ICONV_F_HIDE_INVALID 0x0001 + +/* + * _citrus_iconv_convert: + * convert a string. + */ +static __inline int +_citrus_iconv_convert(struct _citrus_iconv * __restrict ci, + const char * __restrict * __restrict in, + size_t * __restrict inbytes, + char * __restrict * __restrict out, + size_t * __restrict outbytes, u_int32_t flags, + size_t * __restrict nresults) +{ + int ret; + + _DIAGASSERT(ci & ci->ci_ops && dst); + + ret = (*ci->ci_ops->io_convert)(ci, in, inbytes, out, outbytes, flags, + nresults); + + return ret; +} + +#endif diff --git a/lib/libc/citrus/citrus_iconv_local.h b/lib/libc/citrus/citrus_iconv_local.h new file mode 100644 index 000000000000..143c09e2bec9 --- /dev/null +++ b/lib/libc/citrus/citrus_iconv_local.h @@ -0,0 +1,89 @@ +/* $NetBSD: citrus_iconv_local.h,v 1.1 2003/06/25 09:51:34 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_ICONV_LOCAL_H_ +#define _CITRUS_ICONV_LOCAL_H_ + +#define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_) \ +int _n_(struct _citrus_iconv_ops *, size_t, u_int32_t) +#define _CITRUS_ICONV_GETOPS_FUNC(_n_) \ +_CITRUS_ICONV_GETOPS_FUNC_BASE(_citrus_##_n_##_iconv_getops) + +#define _CITRUS_ICONV_DECLS(_m_) \ +static int _citrus_##_m_##_iconv_init \ + (struct _citrus_iconv * __restrict, \ + const char * __restrict, \ + const char * __restrict, const char * __restrict, \ + const void * __restrict, size_t); \ +static void _citrus_##_m_##_iconv_uninit(struct _citrus_iconv *); \ +static int _citrus_##_m_##_iconv_convert \ + (struct _citrus_iconv * __restrict, \ + const char * __restrict * __restrict, size_t * __restrict, \ + char * __restrict * __restrict, size_t * __restrict outbytes, \ + u_int32_t, size_t * __restrict) + + +#define _CITRUS_ICONV_DEF_OPS(_m_) \ +struct _citrus_iconv_ops _citrus_##_m_##_iconv_ops = { \ + /* io_abi_version */ _CITRUS_ICONV_ABI_VERSION, \ + /* io_init */ &_citrus_##_m_##_iconv_init, \ + /* io_uninit */ &_citrus_##_m_##_iconv_uninit, \ + /* io_convert */ &_citrus_##_m_##_iconv_convert \ +} + +__BEGIN_DECLS +typedef _CITRUS_ICONV_GETOPS_FUNC_BASE((*_citrus_iconv_getops_t)); +typedef int (*_citrus_iconv_init_t)(struct _citrus_iconv * __restrict, + const char * __restrict, + const char * __restrict, + const char * __restrict, + const void * __restrict, size_t); +typedef void (*_citrus_iconv_uninit_t)(struct _citrus_iconv *); +typedef int (*_citrus_iconv_convert_t)(struct _citrus_iconv * __restrict, + const char *__restrict* __restrict, + size_t * __restrict, + char * __restrict * __restrict, + size_t * __restrict, u_int32_t, + size_t * __restrict); +__END_DECLS + +struct _citrus_iconv_ops { + u_int32_t io_abi_version; + _citrus_iconv_init_t io_init; + _citrus_iconv_uninit_t io_uninit; + _citrus_iconv_convert_t io_convert; +}; +#define _CITRUS_ICONV_ABI_VERSION 1 + +struct _citrus_iconv { + struct _citrus_iconv_ops *ci_ops; + void *ci_closure; + _citrus_module_t ci_module; +}; + +#endif diff --git a/lib/libc/citrus/citrus_lookup.c b/lib/libc/citrus/citrus_lookup.c new file mode 100644 index 000000000000..f5ecf90a8e60 --- /dev/null +++ b/lib/libc/citrus/citrus_lookup.c @@ -0,0 +1,351 @@ +/* $NetBSD: citrus_lookup.c,v 1.1 2003/06/25 09:51:34 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_lookup.c,v 1.1 2003/06/25 09:51:34 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_db.h" +#include "citrus_db_hash.h" +#include "citrus_lookup.h" +#include "citrus_lookup_file.h" + +struct _citrus_lookup { + union { + struct { + struct _citrus_db *db; + struct _citrus_region file; + int num, idx; + struct _db_locator locator; + } db; + struct { + struct _region r; + struct _memstream ms; + } plain; + } u; +#define cl_db u.db.db +#define cl_dbidx u.db.idx +#define cl_dbfile u.db.file +#define cl_dbnum u.db.num +#define cl_dblocator u.db.locator +#define cl_plainr u.plain.r +#define cl_plainms u.plain.ms + int cl_rewind; + char *cl_key; + size_t cl_keylen; + int (*cl_next)(struct _citrus_lookup *, struct _region *, + struct _region *); + int (*cl_lookup)(struct _citrus_lookup *, const char *, + struct _region *); + int (*cl_num_entries)(struct _citrus_lookup *); + void (*cl_close)(struct _citrus_lookup *); +}; + +static int +seq_get_num_entries_db(struct _citrus_lookup *cl) +{ + return cl->cl_dbnum; +} + +static int +seq_next_db(struct _citrus_lookup *cl, + struct _region *key, struct _region *data) +{ + + if (cl->cl_key) { + if (key) + _region_init(key, cl->cl_key, cl->cl_keylen); + return _db_lookup_by_s(cl->cl_db, cl->cl_key, data, + &cl->cl_dblocator); + } + + if (cl->cl_rewind) { + cl->cl_dbidx = 0; + } + cl->cl_rewind = 0; + if (cl->cl_dbidx >= cl->cl_dbnum) + return ENOENT; + + return _db_get_entry(cl->cl_db, cl->cl_dbidx++, key, data); +} + +static int +seq_lookup_db(struct _citrus_lookup *cl, const char *key, + struct _region *data) +{ + cl->cl_rewind = 0; + free(cl->cl_key); + cl->cl_key = strdup(key); + cl->cl_keylen = strlen(key); + _db_locator_init(&cl->cl_dblocator); + return _db_lookup_by_s(cl->cl_db, key, data, &cl->cl_dblocator); +} + +static void +seq_close_db(struct _citrus_lookup *cl) +{ + _db_close(cl->cl_db); + _unmap_file(&cl->cl_dbfile); +} + +static int +seq_open_db(struct _citrus_lookup *cl, const char *name) +{ + int ret; + struct _region r; + char path[PATH_MAX]; + + snprintf(path, sizeof(path), "%s.db", name); + ret = _map_file(&r, path); + if (ret) + return ret; + + ret = _db_open(&cl->cl_db, &r, _CITRUS_LOOKUP_MAGIC, + _db_hash_std, NULL); + if (ret) { + _unmap_file(&r); + return ret; + } + + cl->cl_dbfile = r; + cl->cl_dbnum = _db_get_num_entries(cl->cl_db); + cl->cl_dbidx = 0; + cl->cl_rewind = 1; + cl->cl_lookup = &seq_lookup_db; + cl->cl_next = &seq_next_db; + cl->cl_num_entries = &seq_get_num_entries_db; + cl->cl_close = &seq_close_db; + + return 0; +} + +#define T_COMM '#' +static int +seq_next_plain(struct _citrus_lookup *cl, struct _region *key, + struct _region *data) +{ + const char *p, *q; + size_t len; + + if (cl->cl_rewind) + _memstream_bind(&cl->cl_plainms, &cl->cl_plainr); + cl->cl_rewind = 0; + +retry: + p = _memstream_getln(&cl->cl_plainms, &len); + if (p == NULL) + return ENOENT; + /* ignore comment */ + q = memchr(p, T_COMM, len); + if (q) { + len = q-p; + } + /* ignore trailing spaces */ + _bcs_trunc_rws_len(p, &len); + p = _bcs_skip_ws_len(p, &len); + q = _bcs_skip_nonws_len(p, &len); + if (p==q) + goto retry; + if (cl->cl_key && (q-p != cl->cl_keylen || + memcmp(p, cl->cl_key, (size_t)(q-p)) != 0)) + goto retry; + + /* found a entry */ + if (key) + /* LINTED: discard const */ + _region_init(key, (char *)p, q-p); + p = _bcs_skip_ws_len(q, &len); + if (data) + /* LINTED: discard const */ + _region_init(data, len ? (char *)p : NULL, len); + + return 0; +} + +static int +seq_get_num_entries_plain(struct _citrus_lookup *cl) +{ + int num; + + num = 0; + while (seq_next_plain(cl, NULL, NULL) == 0) + num++; + + return num; +} + +static int +seq_lookup_plain(struct _citrus_lookup *cl, const char *key, + struct _region *data) +{ + size_t len; + const char *p; + + cl->cl_rewind = 0; + _memstream_bind(&cl->cl_plainms, &cl->cl_plainr); + p = _memstream_matchline(&cl->cl_plainms, key, &len, 0); + if (p == NULL) + return ENOENT; + free(cl->cl_key); + cl->cl_key = strdup(key); + cl->cl_keylen = strlen(key); + if (data) + /* LINTED: discard const */ + _region_init(data, (char *)p, len); + + return 0; +} + +static void +seq_close_plain(struct _citrus_lookup *cl) +{ + _unmap_file(&cl->cl_plainr); +} + +static int +seq_open_plain(struct _citrus_lookup *cl, const char *name) +{ + int ret; + + /* open read stream */ + ret = _map_file(&cl->cl_plainr, name); + if (ret) + return ret; + + cl->cl_rewind = 1; + cl->cl_next = &seq_next_plain; + cl->cl_lookup = &seq_lookup_plain; + cl->cl_num_entries = &seq_get_num_entries_plain; + cl->cl_close = &seq_close_plain; + + return 0; +} + +int +_citrus_lookup_seq_open(struct _citrus_lookup **rcl, const char *name) +{ + int ret; + struct _citrus_lookup *cl; + + cl = malloc(sizeof(*cl)); + if (cl == NULL) + return errno; + + cl->cl_key = NULL; + cl->cl_keylen = 0; + ret = seq_open_db(cl, name); + if (ret == ENOENT) + ret = seq_open_plain(cl, name); + if (!ret) + *rcl = cl; + else + free(cl); + + return ret; +} + +void +_citrus_lookup_seq_rewind(struct _citrus_lookup *cl) +{ + cl->cl_rewind = 1; + free(cl->cl_key); + cl->cl_key = NULL; + cl->cl_keylen = 0; +} + +int +_citrus_lookup_seq_next(struct _citrus_lookup *cl, + struct _region *key, struct _region *data) +{ + return (*cl->cl_next)(cl, key, data); +} + +int +_citrus_lookup_seq_lookup(struct _citrus_lookup *cl, const char *key, + struct _region *data) +{ + return (*cl->cl_lookup)(cl, key, data); +} + +int +_citrus_lookup_get_number_of_entries(struct _citrus_lookup *cl) +{ + return (*cl->cl_num_entries)(cl); +} + +void +_citrus_lookup_seq_close(struct _citrus_lookup *cl) +{ + free(cl->cl_key); + (*cl->cl_close)(cl); +} + +char * +_citrus_lookup_simple(const char *name, const char *key, + char *linebuf, size_t linebufsize) +{ + int ret; + struct _citrus_lookup *cl; + struct _region data; + + ret = _citrus_lookup_seq_open(&cl, name); + if (ret) + return NULL; + + ret = _citrus_lookup_seq_lookup(cl, key, &data); + if (ret) { + _citrus_lookup_seq_close(cl); + return NULL; + } + + snprintf(linebuf, linebufsize, "%.*s", + (int)_region_size(&data), (const char *)_region_head(&data)); + + _citrus_lookup_seq_close(cl); + + return linebuf; +} diff --git a/lib/libc/citrus/citrus_lookup.h b/lib/libc/citrus/citrus_lookup.h new file mode 100644 index 000000000000..1450850b0e76 --- /dev/null +++ b/lib/libc/citrus/citrus_lookup.h @@ -0,0 +1,57 @@ +/* $NetBSD: citrus_lookup.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_LOOKUP_H_ +#define _CITRUS_LOOKUP_H_ + +struct _citrus_lookup; +__BEGIN_DECLS +char *_citrus_lookup_simple(const char *, const char *, char *, size_t); +int _citrus_lookup_seq_open(struct _citrus_lookup **, const char *); +void _citrus_lookup_seq_rewind(struct _citrus_lookup *); +int _citrus_lookup_seq_next(struct _citrus_lookup *, + struct _region *, struct _region *); +int _citrus_lookup_seq_lookup(struct _citrus_lookup *, const char *, + struct _region *); +int _citrus_lookup_get_number_of_entries(struct _citrus_lookup *); +void _citrus_lookup_seq_close(struct _citrus_lookup *); +__END_DECLS + +static __inline const char * +_citrus_lookup_alias(const char *path, const char *key, char *buf, size_t n) +{ + const char *ret; + + ret = _citrus_lookup_simple(path, key, buf, n); + if (ret == NULL) + ret = key; + + return ret; +} + +#endif diff --git a/lib/libc/citrus/citrus_lookup_factory.c b/lib/libc/citrus/citrus_lookup_factory.c new file mode 100644 index 000000000000..89ed1de57b2c --- /dev/null +++ b/lib/libc/citrus/citrus_lookup_factory.c @@ -0,0 +1,122 @@ +/* $NetBSD: citrus_lookup_factory.c,v 1.1 2003/06/25 09:51:35 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_lookup_factory.c,v 1.1 2003/06/25 09:51:35 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_bcs.h" +#include "citrus_db_factory.h" +#include "citrus_db_hash.h" +#include "citrus_lookup_factory.h" +#include "citrus_lookup_file.h" + +#define T_COMM '#' +static int +convert_line(struct _citrus_db_factory *df, const char *line, size_t len) +{ + const char *p; + char key[LINE_MAX], data[LINE_MAX]; + + /* cut off trailing comment */ + p = memchr(line, T_COMM, len); + if (p) + len = p - line; + + /* key */ + line = _bcs_skip_ws_len(line, &len); + if (len == 0) + return 0; + p = _bcs_skip_nonws_len(line, &len); + if (p==line) + return 0; + snprintf(key, sizeof(key), "%.*s", (int)(p-line), line); + + /* data */ + line = _bcs_skip_ws_len(p, &len); + _bcs_trunc_rws_len(line, &len); + snprintf(data, sizeof(data), "%.*s", (int)len, line); + + return _db_factory_addstr_by_s(df, key, data); +} + +static int +dump_db(struct _citrus_db_factory *df, struct _region *r) +{ + size_t size; + void *ptr; + + size = _db_factory_calc_size(df); + ptr = malloc(size); + if (ptr == NULL) + return errno; + _region_init(r, ptr, size); + + return _db_factory_serialize(df, _CITRUS_LOOKUP_MAGIC, r); +} + +int +_citrus_lookup_factory_convert(FILE *out, FILE *in) +{ + struct _citrus_db_factory *df; + struct _region r; + char *line; + size_t size; + int ret; + + ret = _db_factory_create(&df, &_db_hash_std, NULL); + if (ret) + return ret; + + while ((line = fgetln(in, &size)) != NULL) + if ((ret = convert_line(df, line, size))) { + _db_factory_free(df); + return ret; + } + + ret = dump_db(df, &r); + _db_factory_free(df); + if (ret) + return ret; + + if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1) + return errno; + + return 0; +} diff --git a/lib/libc/citrus/citrus_lookup_factory.h b/lib/libc/citrus/citrus_lookup_factory.h new file mode 100644 index 000000000000..d50a1e89227c --- /dev/null +++ b/lib/libc/citrus/citrus_lookup_factory.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_lookup_factory.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_LOOKUP_FACTORY_H_ +#define _CITRUS_LOOKUP_FACTORY_H_ + +__BEGIN_DECLS +int _citrus_lookup_factory_convert(FILE *, FILE *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_lookup_file.h b/lib/libc/citrus/citrus_lookup_file.h new file mode 100644 index 000000000000..0c56b61263d1 --- /dev/null +++ b/lib/libc/citrus/citrus_lookup_file.h @@ -0,0 +1,34 @@ +/* $NetBSD: citrus_lookup_file.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_LOOKUP_FILE_H_ +#define _CITRUS_LOOKUP_FILE_H_ + +#define _CITRUS_LOOKUP_MAGIC "LOOKUP\0\0" + +#endif diff --git a/lib/libc/citrus/citrus_mapper.c b/lib/libc/citrus/citrus_mapper.c new file mode 100644 index 000000000000..37071889bb71 --- /dev/null +++ b/lib/libc/citrus/citrus_mapper.c @@ -0,0 +1,393 @@ +/* $NetBSD: citrus_mapper.c,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper.c,v 1.1 2003/06/25 09:51:36 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include "reentrant.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_bcs.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" + +#define _CITRUS_MAPPER_DIR "mapper.dir" + +#define CM_HASH_SIZE 101 +#define REFCOUNT_PERSISTENT -1 + +#ifdef _REENTRANT +static rwlock_t lock = RWLOCK_INITIALIZER; +#endif + +struct _citrus_mapper_area { + _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache; + char *ma_dir; +}; + +/* + * _citrus_mapper_create_area: + * create mapper area + */ + +int +_citrus_mapper_create_area( + struct _citrus_mapper_area *__restrict *__restrict rma, + const char *__restrict area) +{ + struct stat st; + int ret; + char path[PATH_MAX]; + struct _citrus_mapper_area *ma; + + rwlock_wrlock(&lock); + + if (*rma != NULL) { + ret = 0; + goto quit; + } + + snprintf(path, PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR); + + ret = stat(path, &st); + if (ret) + goto quit; + + ma = malloc(sizeof(*ma)); + if (ma == NULL) { + ret = errno; + goto quit; + } + ma->ma_dir = strdup(area); + if (ma->ma_dir == NULL) { + ret = errno; + free(ma->ma_dir); + goto quit; + } + _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE); + + *rma = ma; + ret = 0; +quit: + rwlock_unlock(&lock); + + return ret; +} + + +/* + * lookup_mapper_entry: + * lookup mapper.dir entry in the specified directory. + * + * line format of iconv.dir file: + * mapper module arg + * mapper : mapper name. + * module : mapper module name. + * arg : argument for the module (generally, description file name) + */ + +static int +lookup_mapper_entry(const char *dir, const char *mapname, + void *linebuf, size_t linebufsize, + const char **module, const char **variable) +{ + struct _region r; + struct _memstream ms; + int ret; + const char *cp, *cq; + char *p; + size_t len; + char path[PATH_MAX]; + + /* create mapper.dir path */ + snprintf(path, PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR); + + /* open read stream */ + ret = _map_file(&r, path); + if (ret) + return ret; + + _memstream_bind(&ms, &r); + + /* search the line matching to the map name */ + cp = _memstream_matchline(&ms, mapname, &len, 0); + if (!cp) { + ret = ENOENT; + goto quit; + } + if (!len || len>linebufsize-1) { + ret = EINVAL; + goto quit; + } + + p = linebuf; + /* get module name */ + *module = p; + cq = _bcs_skip_nonws_len(cp, &len); + strlcpy(p, cp, (size_t)(cq-cp+1)); + p += cq-cp+1; + + /* get variable */ + *variable = p; + cp = _bcs_skip_ws_len(cq, &len); + strlcpy(p, cp, len+1); + + ret = 0; + +quit: + _unmap_file(&r); + return ret; +} + +/* + * mapper_open: + */ +static int +mapper_open(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict * __restrict rcm, + const char * __restrict module, + const char * __restrict variable) +{ + int ret; + struct _citrus_mapper *cm; + _citrus_mapper_getops_t getops; + + /* initialize mapper handle */ + cm = malloc(sizeof(*cm)); + if (!cm) + return errno; + + cm->cm_module = NULL; + cm->cm_ops = NULL; + cm->cm_closure = NULL; + cm->cm_traits = NULL; + cm->cm_refcount = 0; + cm->cm_key = NULL; + + /* load module */ + ret = _citrus_load_module(&cm->cm_module, module); + if (ret) + goto err; + + /* get operators */ + getops = (_citrus_mapper_getops_t) + _citrus_find_getops(cm->cm_module, module, "mapper"); + if (!getops) { + ret = EOPNOTSUPP; + goto err; + } + cm->cm_ops = malloc(sizeof(*cm->cm_ops)); + if (!cm->cm_ops) { + ret = errno; + goto err; + } + ret = (*getops)(cm->cm_ops, sizeof(*cm->cm_ops), + _CITRUS_MAPPER_ABI_VERSION); + if (ret) + goto err; + + if (!cm->cm_ops->mo_init || + !cm->cm_ops->mo_uninit || + !cm->cm_ops->mo_convert || + !cm->cm_ops->mo_init_state) + goto err; + + /* allocate traits structure */ + cm->cm_traits = malloc(sizeof(*cm->cm_traits)); + if (cm->cm_traits == NULL) { + ret = errno; + goto err; + } + /* initialize the mapper */ + ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir, + (const void *)variable, + strlen(variable)+1, + cm->cm_traits, sizeof(*cm->cm_traits)); + if (ret) + goto err; + + *rcm = cm; + + return 0; +err: + _citrus_mapper_close(cm); + return ret; +} + +/* + * _citrus_mapper_open_direct: + * open a mapper. + */ +int +_citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict * __restrict rcm, + const char * __restrict module, + const char * __restrict variable) +{ + return mapper_open(ma, rcm, module, variable); +} + +/* + * hash_func + */ +static __inline int +hash_func(const char *key) +{ + return _string_hash_func(key, CM_HASH_SIZE); +} + +/* + * match_func + */ +static __inline int +match_func(struct _citrus_mapper *cm, const char *key) +{ + return strcmp(cm->cm_key, key); +} + +/* + * _citrus_mapper_open: + * open a mapper with looking up "mapper.dir". + */ +int +_citrus_mapper_open(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict * __restrict rcm, + const char * __restrict mapname) +{ + int ret; + char linebuf[PATH_MAX]; + const char *module, *variable; + struct _citrus_mapper *cm; + int hashval; + + rwlock_wrlock(&lock); + + /* search in the cache */ + hashval = hash_func(mapname); + _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname, + hashval); + if (cm) { + /* found */ + cm->cm_refcount++; + *rcm = cm; + ret = 0; + goto quit; + } + + /* search mapper entry */ + ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf, PATH_MAX, + &module, &variable); + if (ret) + goto quit; + + /* open mapper */ + ret = mapper_open(ma, &cm, module, variable); + if (ret) + goto quit; + cm->cm_key = strdup(mapname); + if (cm->cm_key == NULL) { + ret = errno; + rwlock_unlock(&lock); + _mapper_close(cm); + return ret; + } + + /* insert to the cache */ + cm->cm_refcount = 1; + _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval); + + *rcm = cm; + ret = 0; +quit: + rwlock_unlock(&lock); + return ret; +} + +/* + * _citrus_mapper_close: + * close the specified mapper. + */ +void +_citrus_mapper_close(struct _citrus_mapper *cm) +{ + if (cm) { + rwlock_wrlock(&lock); + if (cm->cm_refcount == REFCOUNT_PERSISTENT) { + rwlock_unlock(&lock); + return; + } + if (cm->cm_refcount > 0) { + if (--cm->cm_refcount > 0) { + rwlock_unlock(&lock); + return; + } else { + _CITRUS_HASH_REMOVE(cm, cm_entry); + } + } + if (cm->cm_module) { + if (cm->cm_ops) { + if (cm->cm_closure) + (*cm->cm_ops->mo_uninit)(cm); + free(cm->cm_ops); + } + _citrus_unload_module(cm->cm_module); + } + free(cm->cm_key); + free(cm->cm_traits); + free(cm); + rwlock_unlock(&lock); + } +} + +/* + * _citrus_mapper_set_persistent: + * set persistent count. + */ +void +_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm) +{ + rwlock_wrlock(&lock); + cm->cm_refcount = REFCOUNT_PERSISTENT; + rwlock_unlock(&lock); +} diff --git a/lib/libc/citrus/citrus_mapper.h b/lib/libc/citrus/citrus_mapper.h new file mode 100644 index 000000000000..3a7ebba36393 --- /dev/null +++ b/lib/libc/citrus/citrus_mapper.h @@ -0,0 +1,142 @@ +/* $NetBSD: citrus_mapper.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_H_ +#define _CITRUS_MAPPER_H_ + +struct _citrus_mapper_area; +struct _citrus_mapper; +struct _citrus_mapper_ops; +struct _citrus_mapper_traits; + +__BEGIN_DECLS +int _citrus_mapper_create_area( + struct _citrus_mapper_area *__restrict *__restrict, + const char *__restrict); +int _citrus_mapper_open(struct _citrus_mapper_area *__restrict, + struct _citrus_mapper *__restrict *__restrict, + const char *__restrict); +int _citrus_mapper_open_direct( + struct _citrus_mapper_area *__restrict, + struct _citrus_mapper *__restrict *__restrict, + const char *__restrict, const char *__restrict); +void _citrus_mapper_close(struct _citrus_mapper *); +void _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict); +__END_DECLS + +#include "citrus_mapper_local.h" + +/* return values of _citrus_mapper_convert */ +#define _CITRUS_MAPPER_CONVERT_SUCCESS (0) +#define _CITRUS_MAPPER_CONVERT_INVAL (1) +#define _CITRUS_MAPPER_CONVERT_SRC_MORE (2) +#define _CITRUS_MAPPER_CONVERT_DST_MORE (3) +#define _CITRUS_MAPPER_CONVERT_ILSEQ (4) +#define _CITRUS_MAPPER_CONVERT_FATAL (5) + +/* + * _citrus_mapper_convert: + * convert an index. + * - if the converter supports M:1 converter, the function may return + * _CITRUS_MAPPER_CONVERT_SRC_MORE and the storage pointed by dst + * may be unchanged in this case, although the internal status of + * the mapper is affected. + * - if the converter supports 1:N converter, the function may return + * _CITRUS_MAPPER_CONVERT_DST_MORE. In this case, the contiguous + * call of this function ignores src and changes the storage pointed + * by dst. + * - if the converter supports M:N converter, the function may behave + * the combination of the above. + * + */ +static __inline int +_citrus_mapper_convert(struct _citrus_mapper * __restrict cm, + _citrus_index_t * __restrict dst, + _citrus_index_t src, + void * __restrict ps) +{ + + _DIAGASSERT(cm && cm->cm_ops && cm->cm_ops->mo_convert && dst); + + return (*cm->cm_ops->mo_convert)(cm, dst, src, ps); +} + +/* + * _citrus_mapper_init_state: + * initialize the state. + */ +static __inline void +_citrus_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ + + _DIAGASSERT(cm && cm->cm_ops && cm->cm_ops_mo_init_state); + + (*cm->cm_ops->mo_init_state)(cm, ps); +} + +/* + * _citrus_mapper_get_state_size: + * get the size of state storage. + */ +static __inline size_t +_citrus_mapper_get_state_size(struct _citrus_mapper * __restrict cm) +{ + + _DIAGASSERT(cm && cm->cm_traits); + + return cm->cm_traits->mt_state_size; +} + +/* + * _citrus_mapper_get_src_max: + * get the maximum number of suspended sources. + */ +static __inline size_t +_citrus_mapper_get_src_max(struct _citrus_mapper * __restrict cm) +{ + + _DIAGASSERT(cm && cm->cm_traits); + + return cm->cm_traits->mt_src_max; +} + +/* + * _citrus_mapper_get_dst_max: + * get the maximum number of suspended destinations. + */ +static __inline size_t +_citrus_mapper_get_dst_max(struct _citrus_mapper * __restrict cm) +{ + + _DIAGASSERT(cm && cm->cm_traits); + + return cm->cm_traits->mt_dst_max; +} + +#endif diff --git a/lib/libc/citrus/citrus_mapper_local.h b/lib/libc/citrus/citrus_mapper_local.h new file mode 100644 index 000000000000..004b6acb0657 --- /dev/null +++ b/lib/libc/citrus/citrus_mapper_local.h @@ -0,0 +1,105 @@ +/* $NetBSD: citrus_mapper_local.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_LOCAL_H_ +#define _CITRUS_MAPPER_LOCAL_H_ + +#define _CITRUS_MAPPER_GETOPS_FUNC_BASE(_n_) \ +int _n_(struct _citrus_mapper_ops *, size_t, u_int32_t) +#define _CITRUS_MAPPER_GETOPS_FUNC(_n_) \ +_CITRUS_MAPPER_GETOPS_FUNC_BASE(_citrus_##_n_##_mapper_getops) + +#define _CITRUS_MAPPER_DECLS(_m_) \ +static int _citrus_##_m_##_mapper_init \ + (struct _citrus_mapper_area *__restrict, \ + struct _citrus_mapper * __restrict, const char * __restrict, \ + const void * __restrict, size_t, \ + struct _citrus_mapper_traits * __restrict, size_t); \ +static void _citrus_##_m_##_mapper_uninit(struct _citrus_mapper *); \ +static int _citrus_##_m_##_mapper_convert \ + (struct _citrus_mapper * __restrict, \ + _citrus_index_t * __restrict, _citrus_index_t, \ + void * __restrict); \ +static void _citrus_##_m_##_mapper_init_state \ + (struct _citrus_mapper * __restrict, void * __restrict); + +#define _CITRUS_MAPPER_DEF_OPS(_m_) \ +struct _citrus_mapper_ops _citrus_##_m_##_mapper_ops = { \ + /* mo_abi_version */ _CITRUS_MAPPER_ABI_VERSION, \ + /* mo_init */ &_citrus_##_m_##_mapper_init, \ + /* mo_uninit */ &_citrus_##_m_##_mapper_uninit, \ + /* mo_convert */ &_citrus_##_m_##_mapper_convert, \ + /* mo_init_state */ &_citrus_##_m_##_mapper_init_state \ +} + +typedef _CITRUS_MAPPER_GETOPS_FUNC_BASE((*_citrus_mapper_getops_t)); +typedef int (*_citrus_mapper_init_t)( + struct _citrus_mapper_area *__restrict, + struct _citrus_mapper *__restrict, const char *__restrict, + const void *__restrict, size_t, + struct _citrus_mapper_traits * __restrict, size_t); +typedef void (*_citrus_mapper_uninit_t)(struct _citrus_mapper *); +typedef int (*_citrus_mapper_convert_t)(struct _citrus_mapper * __restrict, + _citrus_index_t * __restrict, + _citrus_index_t, + void * __restrict); +typedef void (*_citrus_mapper_init_state_t)( + struct _citrus_mapper * __restrict, void * __restrict); + +/* + * ABI version change log + * 0x00000001 + * initial version + */ +#define _CITRUS_MAPPER_ABI_VERSION 0x00000001 +struct _citrus_mapper_ops { + uint32_t mo_abi_version; + /* version 0x00000001 */ + _citrus_mapper_init_t mo_init; + _citrus_mapper_uninit_t mo_uninit; + _citrus_mapper_convert_t mo_convert; + _citrus_mapper_init_state_t mo_init_state; +}; + +struct _citrus_mapper_traits { + /* version 0x00000001 */ + size_t mt_state_size; + size_t mt_src_max; + size_t mt_dst_max; +}; + +struct _citrus_mapper { + struct _citrus_mapper_ops *cm_ops; + void *cm_closure; + _citrus_module_t cm_module; + struct _citrus_mapper_traits *cm_traits; + _CITRUS_HASH_ENTRY(_citrus_mapper) cm_entry; + int cm_refcount; + char *cm_key; +}; +#endif diff --git a/lib/libc/citrus/citrus_memstream.c b/lib/libc/citrus/citrus_memstream.c new file mode 100644 index 000000000000..f58766d81555 --- /dev/null +++ b/lib/libc/citrus/citrus_memstream.c @@ -0,0 +1,153 @@ +/* $NetBSD: citrus_memstream.c,v 1.1 2003/06/25 09:51:37 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_memstream.c,v 1.1 2003/06/25 09:51:37 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_bcs.h" + +const char * +_citrus_memory_stream_getln(struct _citrus_memory_stream * __restrict ms, + size_t * __restrict rlen) +{ + int i; + const u_int8_t *h, *p; + size_t ret; + + if (ms->ms_pos>=_region_size(&ms->ms_region)) + return (NULL); + + h = p = (uint8_t *)_region_offset(&ms->ms_region, ms->ms_pos); + ret = 0; + for (i=_region_size(&ms->ms_region)-ms->ms_pos; i>0; i--) { + ret++; + if (_bcs_iseol(*p)) + break; + p++; + } + + ms->ms_pos += ret; + *rlen = ret; + return ((const char *)h); +} + +#define T_COMM '#' + +const char * +_citrus_memory_stream_matchline(struct _citrus_memory_stream * __restrict ms, + const char * __restrict key, + size_t * __restrict rlen, + int iscasesensitive) +{ + const char *p, *q; + size_t len, keylen; + + keylen = strlen(key); + while (/*CONSTCOND*/ 1) { + p = _citrus_memory_stream_getln(ms, &len); + if (p == NULL) + return (NULL); + + /* ignore comment */ + q = memchr(p, T_COMM, len); + if (q) { + len = q-p; + } + /* ignore trailing white space and newline */ + _bcs_trunc_rws_len(p, &len); + if (len == 0) + continue; /* ignore null line */ + + /* skip white spaces at the head of the line */ + p = _bcs_skip_ws_len(p, &len); + q = _bcs_skip_nonws_len(p, &len); + + if (q-p == keylen) { + if (iscasesensitive) { + if (memcmp(key, p, keylen) == 0) + break; /* match */ + } else { + if (_bcs_strncasecmp(key, p, keylen) == 0) + break; /* match */ + } + } + } + + p = _bcs_skip_ws_len(q, &len); + *rlen = len; + + return (p); +} + +void * +_citrus_memory_stream_chr(struct _citrus_memory_stream *ms, + struct _citrus_region *r, char ch) +{ + void *head, *chr; + size_t sz; + + if (ms->ms_pos >= _region_size(&ms->ms_region)) + return NULL; + + head = _region_offset(&ms->ms_region, ms->ms_pos); + chr = memchr(head, ch, _memstream_remainder(ms)); + if (chr == NULL) { + _region_init(r, head, _memstream_remainder(ms)); + ms->ms_pos = _region_size(&ms->ms_region); + return NULL; + } + sz = (char *)chr - (char *)head; + + _region_init(r, head, sz); + ms->ms_pos += sz+1; + + return chr; +} + +void +_citrus_memory_stream_skip_ws(struct _citrus_memory_stream *ms) +{ + int ch; + + while ((ch = _memstream_peek(ms)) != EOF) { + if (!_bcs_isspace(ch)) + break; + _memstream_getc(ms); + } +} diff --git a/lib/libc/citrus/citrus_memstream.h b/lib/libc/citrus/citrus_memstream.h new file mode 100644 index 000000000000..c2a0cf425a8f --- /dev/null +++ b/lib/libc/citrus/citrus_memstream.h @@ -0,0 +1,177 @@ +/* $NetBSD: citrus_memstream.h,v 1.1 2003/06/25 09:51:37 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _CITRUS_MEMSTREAM_H_ +#define _CITRUS_MEMSTREAM_H_ + +struct _citrus_memory_stream { + struct _citrus_region ms_region; + size_t ms_pos; +}; + +__BEGIN_DECLS +const char * _citrus_memory_stream_getln( + struct _citrus_memory_stream * __restrict, size_t * __restrict); +const char * _citrus_memory_stream_matchline( + struct _citrus_memory_stream * __restrict, const char * __restrict, + size_t * __restrict, int); +void * _citrus_memory_stream_chr(struct _citrus_memory_stream *, + struct _citrus_region *, char); +void _citrus_memory_stream_skip_ws(struct _citrus_memory_stream *); +__END_DECLS + +static __inline int +_citrus_memory_stream_iseof(struct _citrus_memory_stream *ms) +{ + return ms->ms_pos >= _citrus_region_size(&ms->ms_region); +} + +static __inline void +_citrus_memory_stream_bind(struct _citrus_memory_stream * __restrict ms, + const struct _citrus_region * __restrict r) +{ + ms->ms_region = *r; + ms->ms_pos = 0; +} + +static __inline void +_citrus_memory_stream_rewind(struct _citrus_memory_stream *ms) +{ + ms->ms_pos = 0; +} + +static __inline size_t +_citrus_memory_stream_remainder(struct _citrus_memory_stream *ms) +{ + size_t sz; + sz = _citrus_region_size(&ms->ms_region); + if (ms->ms_pos>sz) + return 0; + return sz-ms->ms_pos; +} + +static __inline int +_citrus_memory_stream_seek(struct _citrus_memory_stream *ms, size_t pos, int w) +{ + int sz; + + sz = _citrus_region_size(&ms->ms_region); + switch (w) { + case SEEK_SET: + if (pos>=sz) + return -1; + ms->ms_pos = pos; + break; + case SEEK_CUR: + pos += ms->ms_pos; + if (pos>=sz) + return -1; + break; + case SEEK_END: + if (szms_pos = sz - pos; + break; + } + return 0; +} + +static __inline int +_citrus_memory_stream_getc(struct _citrus_memory_stream *ms) +{ + if (_citrus_memory_stream_iseof(ms)) + return (EOF); + return _citrus_region_peek8(&ms->ms_region, ms->ms_pos++); +} + +static __inline int +_citrus_memory_stream_peek(struct _citrus_memory_stream *ms) +{ + if (_citrus_memory_stream_iseof(ms)) + return (EOF); + return _citrus_region_peek8(&ms->ms_region, ms->ms_pos); +} + +static __inline void * +_citrus_memory_stream_getregion(struct _citrus_memory_stream *ms, + struct _citrus_region *r, size_t sz) +{ + void *ret; + + if (ms->ms_pos + sz > _citrus_region_size(&ms->ms_region)) + return NULL; + + ret = _citrus_region_offset(&ms->ms_region, ms->ms_pos); + ms->ms_pos += sz; + if (r) + _citrus_region_init(r, ret, sz); + + return ret; +} + +static __inline int +_citrus_memory_stream_get8(struct _citrus_memory_stream *ms, uint8_t *rval) +{ + + if (ms->ms_pos + 1 > _citrus_region_size(&ms->ms_region)) + return -1; + + *rval = _citrus_region_peek8(&ms->ms_region, ms->ms_pos); + ms->ms_pos += 2; + + return 0; +} + +static __inline int +_citrus_memory_stream_get16(struct _citrus_memory_stream *ms, uint16_t *rval) +{ + + if (ms->ms_pos + 2 > _citrus_region_size(&ms->ms_region)) + return -1; + + *rval = _citrus_region_peek16(&ms->ms_region, ms->ms_pos); + ms->ms_pos += 2; + + return 0; +} + +static __inline int +_citrus_memory_stream_get32(struct _citrus_memory_stream *ms, uint32_t *rval) +{ + + if (ms->ms_pos + 4 > _citrus_region_size(&ms->ms_region)) + return -1; + + *rval = _citrus_region_peek32(&ms->ms_region, ms->ms_pos); + ms->ms_pos += 4; + + return 0; +} + +#endif diff --git a/lib/libc/citrus/citrus_mmap.c b/lib/libc/citrus/citrus_mmap.c new file mode 100644 index 000000000000..c54a93f2effa --- /dev/null +++ b/lib/libc/citrus/citrus_mmap.c @@ -0,0 +1,95 @@ +/* $NetBSD: citrus_mmap.c,v 1.1 2003/06/25 09:51:37 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mmap.c,v 1.1 2003/06/25 09:51:37 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_mmap.h" + +int +_citrus_map_file(struct _citrus_region * __restrict r, + const char * __restrict path) +{ + int fd, ret; + struct stat st; + void *head; + + _DIAGASSERT(r != NULL); + + _region_init(r, NULL, 0); + fd = open(path, O_RDONLY); + if (fd<0) + return (errno); + if (fstat(fd, &st)) { + ret = errno; + close(fd); + return ret; + } + if ((st.st_mode & S_IFMT) != S_IFREG) { + close(fd); + return EOPNOTSUPP; + } + head = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE, + fd, (off_t)0); + if (!head) { + ret = errno; + close(fd); + return ret; + } + _region_init(r, head, (size_t)st.st_size); + close(fd); + + return 0; +} + +void +_citrus_unmap_file(struct _citrus_region *r) +{ + + _DIAGASSERT(r != NULL); + + if (_region_head(r) != NULL) { + munmap(_region_head(r), _region_size(r)); + _region_init(r, NULL, 0); + } +} diff --git a/lib/libc/citrus/citrus_mmap.h b/lib/libc/citrus/citrus_mmap.h new file mode 100644 index 000000000000..1a968a4ca1f2 --- /dev/null +++ b/lib/libc/citrus/citrus_mmap.h @@ -0,0 +1,39 @@ +/* $NetBSD: citrus_mmap.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _CITRUS_MMAP_H_ +#define _CITRUS_MMAP_H_ + +__BEGIN_DECLS +int _citrus_map_file(struct _citrus_region * __restrict, + const char * __restrict); +void _citrus_unmap_file(struct _citrus_region *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_namespace.h b/lib/libc/citrus/citrus_namespace.h new file mode 100644 index 000000000000..701abadab769 --- /dev/null +++ b/lib/libc/citrus/citrus_namespace.h @@ -0,0 +1,220 @@ +/* $NetBSD: citrus_namespace.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_NAMESPACE_H_ +#define _CITRUS_NAMESPACE_H_ + +/* citrus_alias */ +#ifndef _CITRUS_ALIAS_NO_NAMESPACE +#define _alias_lookup _citrus_alias_lookup +#endif /* _CITRUS_ALIAS_NO_NAMESPACE */ + +/* citrus_bcs */ +#ifndef _CITRUS_BCS_NO_NAMESPACE +#define _bcs_isalnum _citrus_bcs_isalnum +#define _bcs_isalpha _citrus_bcs_isalpha +#define _bcs_isblank _citrus_bcs_isblank +#define _bcs_isdigit _citrus_bcs_isdigit +#define _bcs_islower _citrus_bcs_islower +#define _bcs_iseol _citrus_bcs_iseol +#define _bcs_isspace _citrus_bcs_isspace +#define _bcs_isupper _citrus_bcs_isupper +#define _bcs_isxdigit _citrus_bcs_isxdigit +#define _bcs_skip_nonws _citrus_bcs_skip_nonws +#define _bcs_skip_nonws_len _citrus_bcs_skip_nonws_len +#define _bcs_skip_ws _citrus_bcs_skip_ws +#define _bcs_skip_ws_len _citrus_bcs_skip_ws_len +#define _bcs_strcasecmp _citrus_bcs_strcasecmp +#define _bcs_strncasecmp _citrus_bcs_strncasecmp +#define _bcs_tolower _citrus_bcs_tolower +#define _bcs_toupper _citrus_bcs_toupper +#define _bcs_trunc_rws_len _citrus_bcs_trunc_rws_len +#define _bcs_convert_to_lower _citrus_bcs_convert_to_lower +#define _bcs_convert_to_upper _citrus_bcs_convert_to_upper +#endif /* _CITRUS_BCS_NO_NAMESPACE */ + +/* citrus_csmapper */ +#ifndef _CITRUS_CSMAPPER_NO_NAMESPACE +#define _csmapper _citrus_csmapper +#define _csmapper_open _citrus_csmapper_open +#define _csmapper_close _citrus_csmapper_close +#define _csmapper_convert _citrus_csmapper_convert +#define _csmapper_init_state _citrus_csmapper_init_state +#define _csmapper_get_state_size _citrus_csmapper_get_state_size +#define _csmapper_get_src_max _citrus_csmapper_get_src_max +#define _csmapper_get_dst_max _citrus_csmapper_get_dst_max +#define _CSMAPPER_F_PREVENT_PIVOT _CITRUS_CSMAPPER_F_PREVENT_PIVOT +#endif /* _CITRUS_CSMAPPER_NO_NAMESPACE */ + +/* citrus_db */ +#ifndef _CITRUS_DB_NO_NAMESPACE +#define _db_open _citrus_db_open +#define _db_close _citrus_db_close +#define _db_lookup _citrus_db_lookup +#define _db_lookup_by_s _citrus_db_lookup_by_string +#define _db_lookup8_by_s _citrus_db_lookup8_by_string +#define _db_lookup16_by_s _citrus_db_lookup16_by_string +#define _db_lookup32_by_s _citrus_db_lookup32_by_string +#define _db_lookupstr_by_s _citrus_db_lookup_string_by_string +#define _db_hash_std _citrus_db_hash_std +#define _db_get_num_entries _citrus_db_get_number_of_entries +#define _db_get_entry _citrus_db_get_entry +#define _db_locator _citrus_db_locator +#define _db_locator_init _citrus_db_locator_init +#endif /* _CITRUS_DB_NO_NAMESPACE */ + +/* citrus_db_factory */ +#ifndef _CITRUS_DB_FACTORY_NO_NAMESPACE +#define _db_factory _citrus_db_factory +#define _db_factory_create _citrus_db_factory_create +#define _db_factory_free _citrus_db_factory_free +#define _db_factory_add _citrus_db_factory_add +#define _db_factory_add_by_s _citrus_db_factory_add_by_string +#define _db_factory_add8_by_s _citrus_db_factory_add8_by_string +#define _db_factory_add16_by_s _citrus_db_factory_add16_by_string +#define _db_factory_add32_by_s _citrus_db_factory_add32_by_string +#define _db_factory_addstr_by_s _citrus_db_factory_add_string_by_string +#define _db_factory_calc_size _citrus_db_factory_calc_size +#define _db_factory_serialize _citrus_db_factory_serialize +#endif /* _CITRUS_DB_FACTORY_NO_NAMESPACE */ + +/* citrus_lookup */ +#ifndef _CITRUS_DB_NO_NAMESPACE +#define _lookup _citrus_lookup +#define _lookup_simple _citrus_lookup_simple +#define _lookup_alias _citrus_lookup_alias +#define _lookup_seq_open _citrus_lookup_seq_open +#define _lookup_seq_rewind _citrus_lookup_seq_rewind +#define _lookup_seq_next _citrus_lookup_seq_next +#define _lookup_seq_lookup _citrus_lookup_seq_lookup +#define _lookup_get_num_entries _citrus_lookup_get_number_of_entries +#define _lookup_seq_close _citrus_lookup_seq_close +#define _lookup_factory_convert _citrus_lookup_factory_convert +#endif /* _CITRUS_DB_NO_NAMESPACE */ + +/* citrus_esdb */ +#ifndef _CITRUS_ESDB_NO_NAMESPACE +#define _esdb _citrus_esdb +#define _esdb_charset _citrus_esdb_charset +#define _esdb_open _citrus_esdb_open +#define _esdb_close _citrus_esdb_close +#define _esdb_get_list _citrus_esdb_get_list +#define _esdb_free_list _citrus_esdb_free_list +#endif /* _CITRUS_ESDB_NO_NAMESPACE */ + +/* citrus_hash */ +#ifndef _CITRUS_HASH_NO_NAMESPACE +#define _citrus_string_hash_func _string_hash_func +#endif /* _CITRUS_HASH_NO_NAMESPACE */ + +/* citrus_mapper */ +#ifndef _CITRUS_MAPPER_NO_NAMESPACE +#define _mapper _citrus_mapper +#define _mapper_ops _citrus_mapper_ops +#define _mapper_traits _citrus_mapper_traits +#define _mapper_open _citrus_mapper_open +#define _mapper_open_direct _citrus_mapper_open_direct +#define _mapper_close _citrus_mapper_close +#define _MAPPER_CONVERT_SUCCESS _CITRUS_MAPPER_CONVERT_SUCCESS +#define _MAPPER_CONVERT_INVAL _CITRUS_MAPPER_CONVERT_INVAL +#define _MAPPER_CONVERT_SRC_MORE _CITRUS_MAPPER_CONVERT_SRC_MORE +#define _MAPPER_CONVERT_DST_MORE _CITRUS_MAPPER_CONVERT_DST_MORE +#define _MAPPER_CONVERT_ILSEQ _CITRUS_MAPPER_CONVERT_ILSEQ +#define _MAPPER_CONVERT_FATAL _CITRUS_MAPPER_CONVERT_FATAL +#define _mapper_convert _citrus_mapper_convert +#define _mapper_init_state _citrus_mapper_init_state +#define _mapper_get_state_size _citrus_mapper_get_state_size +#define _mapper_get_src_max _citrus_mapper_get_src_max +#define _mapper_get_dst_max _citrus_mapper_get_dst_max +#define _mapper_set_persistent _citrus_mapper_set_persistent +#endif /* _CITRUS_MAPPER_NO_NAMESPACE */ + +/* citrus_memstream */ +#ifndef _CITRUS_MEMSTREAM_NO_NAMESPACE +#define _memstream _citrus_memory_stream +#define _memstream_getln _citrus_memory_stream_getln +#define _memstream_matchline _citrus_memory_stream_matchline +#define _memstream_chr _citrus_memory_stream_chr +#define _memstream_skip_ws _citrus_memory_stream_skip_ws +#define _memstream_iseof _citrus_memory_stream_iseof +#define _memstream_bind _citrus_memory_stream_bind +#define _memstream_seek _citrus_memory_stream_seek +#define _memstream_rewind _citrus_memory_stream_rewind +#define _memstream_remainder _citrus_memory_stream_remainder +#define _memstream_getc _citrus_memory_stream_getc +#define _memstream_peek _citrus_memory_stream_peek +#define _memstream_getregion _citrus_memory_stream_getregion +#endif /* _CITRUS_MEMSTREAM_NO_NAMESPACE */ + +/* citrus_mmap */ +#ifndef _CITRUS_MMAP_NO_NAMESPACE +#define _map_file _citrus_map_file +#define _unmap_file _citrus_unmap_file +#endif /* _CITRUS_MMAP_NO_NAMESPACE */ + +#ifndef _CITRUS_PIVOT_NO_NAMESPACE +#define _pivot_factory_convert _citrus_pivot_factory_convert +#endif /* _CITRUS_PIVOT_NO_NAMESPACE */ + +/* citrus_region.h */ +#ifndef _CITRUS_REGION_NO_NAMESPACE +#define _region _citrus_region +#define _region_init _citrus_region_init +#define _region_head _citrus_region_head +#define _region_size _citrus_region_size +#define _region_check _citrus_region_check +#define _region_offset _citrus_region_offset +#define _region_peek8 _citrus_region_peek8 +#define _region_peek16 _citrus_region_peek16 +#define _region_peek32 _citrus_region_peek32 +#endif /* _CITRUS_REGION_NO_NAMESPACE */ + +/* citrus_stdenc.h */ +#ifndef _CITRUS_STDENC_NO_NAMESPACE +#define _stdenc _citrus_stdenc +#define _stdenc_ops _citrus_stdenc_ops +#define _stdenc_traits _citrus_stdenc_traits +#define _stdenc_open _citrus_stdenc_open +#define _stdenc_close _citrus_stdenc_close +#define _stdenc_init_state _citrus_stdenc_init_state +#define _stdenc_mbtocs _citrus_stdenc_mbtocs +#define _stdenc_cstomb _citrus_stdenc_cstomb +#define _stdenc_mbtowc _citrus_stdenc_mbtowc +#define _stdenc_wctomb _citrus_stdenc_wctomb +#define _stdenc_get_state_size _citrus_stdenc_get_state_size +#define _stdenc_get_mb_cur_max _citrus_stdenc_get_mb_cur_max +#endif /* _CITRUS_STDENC_NO_NAMESPACE */ + +/* citrus_types.h */ +#ifndef _CITRUS_TYPES_NO_NAMESPACE +#define _index_t _citrus_index_t +#define _csid_t _citrus_csid_t +#define _wc_t _citrus_wc_t +#endif /* _CITRUS_TYPES_NO_NAMESPACE */ + +#endif diff --git a/lib/libc/citrus/citrus_none.c b/lib/libc/citrus/citrus_none.c index b8f8cd3ec790..42d5465b2401 100644 --- a/lib/libc/citrus/citrus_none.c +++ b/lib/libc/citrus/citrus_none.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_none.c,v 1.8 2003/03/05 20:18:16 tshiozak Exp $ */ +/* $NetBSD: citrus_none.c,v 1.9 2003/06/25 09:51:38 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_none.c,v 1.8 2003/03/05 20:18:16 tshiozak Exp $"); +__RCSID("$NetBSD: citrus_none.c,v 1.9 2003/06/25 09:51:38 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -40,9 +40,13 @@ __RCSID("$NetBSD: citrus_none.c,v 1.8 2003/03/05 20:18:16 tshiozak Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" #include "citrus_none.h" +#include "citrus_stdenc.h" /* ---------------------------------------------------------------------- */ @@ -329,3 +333,135 @@ _citrus_NONE_ctype_wctob(_citrus_ctype_rec_t * __restrict cc, *cresult = (int)wc; return (0); } + +/* ---------------------------------------------------------------------- */ + +_CITRUS_STDENC_DECLS(NONE); +_CITRUS_STDENC_DEF_OPS(NONE); +struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = { + 0, /* et_state_size */ + 1, /* mb_cur_max */ +}; + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce, + const void *var, size_t lenvar, + struct _citrus_stdenc_traits * __restrict et) +{ + + et->et_state_size = 0; + et->et_mb_cur_max = 1; + + ce->ce_closure = NULL; + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce) +{ +} + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce, + void * __restrict ps) +{ + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce, + _csid_t *csid, _index_t *idx, + const char **s, size_t n, + void *ps, size_t *nresult) +{ + + _DIAGASSERT(csid != NULL && idx != NULL); + + if (n<1) { + *nresult = (size_t)-2; + return (0); + } + + *csid = 0; + *idx = (_index_t)(unsigned char)*(*s)++; + *nresult = *idx == 0 ? 0 : 1; + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce, + char *s, size_t n, + _csid_t csid, _index_t idx, + void *ps, size_t *nresult) +{ + + if (csid == _CITRUS_CSID_INVALID) { + *nresult = 0; + return (0); + } + if (n<1) { + *nresult = (size_t)-2; + return (0); + } + if (csid != 0 || (idx&0xFF) != idx) + return (EILSEQ); + + *s = (char)idx; + *nresult = 1; + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce, + _wc_t * __restrict pwc, + const char ** __restrict s, size_t n, + void * __restrict pspriv, + size_t * __restrict nresult) +{ + if (s == NULL) { + *nresult = 0; + return (0); + } + if (n == 0) { + *nresult = (size_t)-2; + return (0); + } + + if (pwc != NULL) + *pwc = (_wc_t)(unsigned char) **s; + + *nresult = *s == '\0' ? 0 : 1; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, + _wc_t wc, void * __restrict pspriv, + size_t * __restrict nresult) +{ + if ((wc&~0xFFU) != 0) { + *nresult = (size_t)-1; + return (EILSEQ); + } + if (n==0) { + *nresult = (size_t)-2; + return (0); + } + + *nresult = 1; + if (s!=NULL && n>0) + *s = (char)wc; + + return (0); +} diff --git a/lib/libc/citrus/citrus_none.h b/lib/libc/citrus/citrus_none.h index 944d3eb42880..1a75f2c0f13f 100644 --- a/lib/libc/citrus/citrus_none.h +++ b/lib/libc/citrus/citrus_none.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_none.h,v 1.2 2003/03/05 20:18:16 tshiozak Exp $ */ +/* $NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -29,7 +29,8 @@ #ifndef _CITRUS_NONE_H_ #define _CITRUS_NONE_H_ -extern struct _citrus_ctype_ops_rec _citrus_NONE_ctype_ops; -extern struct _citrus_iconv_stdencoding_ops_rec _citrus_NONE_iconv_stdencoding_ops; +extern struct _citrus_ctype_ops_rec _citrus_NONE_ctype_ops; +extern struct _citrus_stdenc_ops _citrus_NONE_stdenc_ops; +extern struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits; #endif diff --git a/lib/libc/citrus/citrus_pivot_factory.c b/lib/libc/citrus/citrus_pivot_factory.c new file mode 100644 index 000000000000..64dda3dd05ac --- /dev/null +++ b/lib/libc/citrus/citrus_pivot_factory.c @@ -0,0 +1,225 @@ +/* $NetBSD: citrus_pivot_factory.c,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_pivot_factory.c,v 1.1 2003/06/25 09:51:39 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_bcs.h" +#include "citrus_db_factory.h" +#include "citrus_db_hash.h" +#include "citrus_pivot_file.h" +#include "citrus_pivot_factory.h" + +struct src_entry { + char *se_name; + struct _citrus_db_factory *se_df; + SIMPLEQ_ENTRY(src_entry) se_entry; +}; +SIMPLEQ_HEAD(src_head, src_entry); + +static int +find_src(struct src_head *sh, struct src_entry **rse, const char *name) +{ + int ret; + struct src_entry *se; + + SIMPLEQ_FOREACH(se, sh, se_entry) { + if (_bcs_strcasecmp(se->se_name, name) == 0) { + *rse = se; + return 0; + } + } + se = malloc(sizeof(*se)); + if (se == NULL) + return errno; + se->se_name = strdup(name); + if (se->se_name == NULL) { + ret = errno; + free(se); + return ret; + } + ret = _db_factory_create(&se->se_df, &_db_hash_std, NULL); + if (ret) { + free(se->se_name); + free(se); + return ret; + } + SIMPLEQ_INSERT_TAIL(sh, se, se_entry); + *rse = se; + + return 0; +} + +static void +free_src(struct src_head *sh) +{ + struct src_entry *se; + + while((se = SIMPLEQ_FIRST(sh)) != NULL) { + SIMPLEQ_REMOVE_HEAD(sh, se_entry); + _db_factory_free(se->se_df); + free(se->se_name); + free(se); + } +} + + +#define T_COMM '#' +static int +convert_line(struct src_head *sh, const char *line, size_t len) +{ + int ret; + struct src_entry *se; + const char *p; + char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX]; + u_int32_t val; + + /* cut off trailing comment */ + p = memchr(line, T_COMM, len); + if (p) + len = p - line; + + /* key1 */ + line = _bcs_skip_ws_len(line, &len); + if (len == 0) + return 0; + p = _bcs_skip_nonws_len(line, &len); + if (p==line) + return 0; + snprintf(key1, sizeof(key1), "%.*s", (int)(p-line), line); + + /* key2 */ + line = _bcs_skip_ws_len(p, &len); + if (len == 0) + return 0; + p = _bcs_skip_nonws_len(line, &len); + if (p==line) + return 0; + snprintf(key2, sizeof(key2), "%.*s", (int)(p-line), line); + + /* data */ + line = _bcs_skip_ws_len(p, &len); + _bcs_trunc_rws_len(line, &len); + snprintf(data, sizeof(data), "%.*s", (int)len, line); + /* LINTED: discard const */ + val = strtoul(data, (char **)&p, 0); + if (*p != '\0') + return EFTYPE; + + /* insert to DB */ + ret = find_src(sh, &se, key1); + if (ret) + return ret; + + return _db_factory_add32_by_s(se->se_df, key2, val); +} + +static int +dump_db(struct src_head *sh, struct _region *r) +{ + int ret; + struct _db_factory *df; + struct src_entry *se; + size_t size; + void *ptr; + struct _region subr; + + ret = _db_factory_create(&df, &_db_hash_std, NULL); + if (ret) + return ret; + + SIMPLEQ_FOREACH(se, sh, se_entry) { + size = _db_factory_calc_size(se->se_df); + ptr = malloc(size); + if (ptr == NULL) + goto quit; + _region_init(&subr, ptr, size); + ret = _db_factory_serialize(se->se_df, _CITRUS_PIVOT_SUB_MAGIC, + &subr); + if (ret) + goto quit; + ret = _db_factory_add_by_s(df, se->se_name, &subr, 1); + if (ret) + goto quit; + } + + size = _db_factory_calc_size(df); + ptr = malloc(size); + if (ptr == NULL) + goto quit; + _region_init(r, ptr, size); + + ret = _db_factory_serialize(df, _CITRUS_PIVOT_MAGIC, r); + ptr = NULL; + +quit: + free(ptr); + _db_factory_free(df); + return ret; +} + +int +_citrus_pivot_factory_convert(FILE *out, FILE *in) +{ + struct src_head sh; + struct _region r; + char *line; + size_t size; + int ret; + + SIMPLEQ_INIT(&sh); + + while ((line = fgetln(in, &size)) != NULL) + if ((ret = convert_line(&sh, line, size))) { + free_src(&sh); + return ret; + } + + ret = dump_db(&sh, &r); + free_src(&sh); + if (ret) + return ret; + + if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1) + return errno; + + return 0; +} diff --git a/lib/libc/citrus/citrus_pivot_factory.h b/lib/libc/citrus/citrus_pivot_factory.h new file mode 100644 index 000000000000..dd5d80488c3e --- /dev/null +++ b/lib/libc/citrus/citrus_pivot_factory.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_pivot_factory.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_PIVOT_FACTORY_H_ +#define _CITRUS_PIVOT_FACTORY_H_ + +__BEGIN_DECLS +int _citrus_pivot_factory_convert(FILE *, FILE *); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/citrus_pivot_file.h b/lib/libc/citrus/citrus_pivot_file.h new file mode 100644 index 000000000000..eb50645a155e --- /dev/null +++ b/lib/libc/citrus/citrus_pivot_file.h @@ -0,0 +1,35 @@ +/* $NetBSD: citrus_pivot_file.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_PIVOT_FILE_H_ +#define _CITRUS_PIVOT_FILE_H_ + +#define _CITRUS_PIVOT_MAGIC "CSPIVOT\0" +#define _CITRUS_PIVOT_SUB_MAGIC "CSPIVSUB" + +#endif diff --git a/lib/libc/citrus/citrus_region.h b/lib/libc/citrus/citrus_region.h new file mode 100644 index 000000000000..ea59e2a8d756 --- /dev/null +++ b/lib/libc/citrus/citrus_region.h @@ -0,0 +1,93 @@ +/* $NetBSD: citrus_region.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _CITRUS_REGION_H_ +#define _CITRUS_REGION_H_ + +struct _citrus_region { +/* private: */ + void *r_head; + size_t r_size; +}; + +static __inline void +_citrus_region_init(struct _citrus_region *r, void *h, size_t sz) +{ + _DIAGASSERT(r); + r->r_head = h; + r->r_size = sz; +} + +static __inline void * +_citrus_region_head(const struct _citrus_region *r) +{ + return r->r_head; +} + +static __inline size_t +_citrus_region_size(const struct _citrus_region *r) +{ + return r->r_size; +} + +static __inline int +_citrus_region_check(const struct _citrus_region *r, size_t ofs, size_t sz) +{ + return r->r_size >= ofs + sz ? 0 : -1; +} + +static __inline void * +_citrus_region_offset(const struct _citrus_region *r, size_t pos) +{ + return (void *)((uint8_t *)r->r_head + pos); +} + +static __inline uint8_t +_citrus_region_peek8(const struct _citrus_region *r, size_t pos) +{ + return *(uint8_t *)_citrus_region_offset(r, pos); +} + +static __inline uint16_t +_citrus_region_peek16(const struct _citrus_region *r, size_t pos) +{ + uint16_t val; + memcpy(&val, _citrus_region_offset(r, pos), 2); + return val; +} + +static __inline uint32_t +_citrus_region_peek32(const struct _citrus_region *r, size_t pos) +{ + uint32_t val; + memcpy(&val, _citrus_region_offset(r, pos), 4); + return val; +} + +#endif diff --git a/lib/libc/citrus/citrus_stdenc.c b/lib/libc/citrus/citrus_stdenc.c new file mode 100644 index 000000000000..aff03893df1d --- /dev/null +++ b/lib/libc/citrus/citrus_stdenc.c @@ -0,0 +1,183 @@ +/* $NetBSD: citrus_stdenc.c,v 1.1 2003/06/25 09:51:40 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_stdenc.c,v 1.1 2003/06/25 09:51:40 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include "namespace.h" +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_none.h" + +struct _citrus_stdenc _citrus_stdenc_default = { + &_citrus_NONE_stdenc_ops, /* ce_ops */ + NULL, /* ce_closure */ + NULL, /* ce_module */ + &_citrus_NONE_stdenc_traits, /* ce_traits */ +}; + +#ifdef _I18N_DYNAMIC + +int +_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce, + char const * __restrict encname, + const void * __restrict variable, size_t lenvar) +{ + int ret; + _citrus_module_t handle; + struct _citrus_stdenc *ce; + _citrus_stdenc_getops_t getops; + + _DIAGASSERT(encname != NULL); + _DIAGASSERT(!lenvar || variable!=NULL); + _DIAGASSERT(rcc != NULL); + + if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) { + *rce = &_citrus_stdenc_default; + return (0); + } + ce = malloc(sizeof(*ce)); + if (ce==NULL) { + ret = errno; + goto bad; + } + ce->ce_ops = NULL; + ce->ce_closure = NULL; + ce->ce_module = NULL; + ce->ce_traits = NULL; + + ret = _citrus_load_module(&handle, encname); + if (ret) + goto bad; + + ce->ce_module = handle; + + getops = + (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module, + encname, "stdenc"); + if (getops == NULL) { + ret = EINVAL; + goto bad; + } + + ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops)); + if (ce->ce_ops == NULL) { + ret = errno; + goto bad; + } + + ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops), + _CITRUS_STDENC_ABI_VERSION); + if (ret) + goto bad; + + /* If return ABI version is not expected, should fixup it */ + + /* validation check */ + if (ce->ce_ops->eo_init == NULL || + ce->ce_ops->eo_uninit == NULL || + ce->ce_ops->eo_init_state == NULL || + ce->ce_ops->eo_mbtocs == NULL || + ce->ce_ops->eo_cstomb == NULL || + ce->ce_ops->eo_mbtowc == NULL || + ce->ce_ops->eo_wctomb == NULL) + goto bad; + + /* allocate traits */ + ce->ce_traits = malloc(sizeof(*ce->ce_traits)); + if (ce->ce_traits == NULL) { + ret = errno; + goto bad; + } + /* init and get closure */ + ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits); + if (ret) + goto bad; + + *rce = ce; + + return (0); + +bad: + _citrus_stdenc_close(ce); + return (ret); +} + +void +_citrus_stdenc_close(struct _citrus_stdenc *ce) +{ + + _DIAGASSERT(ci != NULL); + + if (ce == &_citrus_stdenc_default) + return; + + if (ce->ce_module) { + if (ce->ce_ops) { + if (ce->ce_closure && ce->ce_ops->eo_uninit) + (*ce->ce_ops->eo_uninit)(ce); + free(ce->ce_ops); + } + free(ce->ce_traits); + _citrus_unload_module(ce->ce_module); + } + free(ce); +} + +#else +/* !_I18N_DYNAMIC */ + +int +/*ARGSUSED*/ +_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce, + char const * __restrict encname, + const void * __restrict variable, size_t lenvar) +{ + if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) { + *rce = &_citrus_stdenc_default; + return (0); + } + return (EINVAL); +} + +void +/*ARGSUSED*/ +_citrus_stdenc_close(struct _citrus_stdenc *ce) +{ +} + +#endif diff --git a/lib/libc/citrus/citrus_stdenc.h b/lib/libc/citrus/citrus_stdenc.h new file mode 100644 index 000000000000..d80d78d83421 --- /dev/null +++ b/lib/libc/citrus/citrus_stdenc.h @@ -0,0 +1,108 @@ +/* $NetBSD: citrus_stdenc.h,v 1.1 2003/06/25 09:51:40 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _CITRUS_STDENC_H_ +#define _CITRUS_STDENC_H_ + +struct _citrus_stdenc; +struct _citrus_stdenc_ops; +struct _citrus_stdenc_traits; + +#include "citrus_stdenc_local.h" + +__BEGIN_DECLS +int _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict, + char const * __restrict, + const void * __restrict, size_t); +void _citrus_stdenc_close(struct _citrus_stdenc *); +__END_DECLS + +static __inline int +_citrus_stdenc_init_state(struct _citrus_stdenc * __restrict ce, + void * __restrict ps) +{ + _DIAGASSERT(ce && ce->ci_ops && ce->ce_ops->eo_init_state); + return (*ce->ce_ops->eo_init_state)(ce, ps); +} + +static __inline int +_citrus_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce, + _citrus_csid_t * __restrict csid, + _citrus_index_t * __restrict idx, + const char ** __restrict s, size_t n, + void * __restrict ps, size_t * __restrict nresult) +{ + _DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_mbtocs); + return (*ce->ce_ops->eo_mbtocs)(ce, csid, idx, s, n, ps, nresult); +} + +static __inline int +_citrus_stdenc_cstomb(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, + _citrus_csid_t csid, _citrus_index_t idx, + void * __restrict ps, size_t * __restrict nresult) +{ + _DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_cstomb); + return (*ce->ce_ops->eo_cstomb)(ce, s, n, csid, idx, ps, nresult); +} + +static __inline int +_citrus_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce, + _citrus_wc_t * __restrict wc, + const char ** __restrict s, size_t n, + void * __restrict ps, size_t * __restrict nresult) +{ + _DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_mbtocs); + return (*ce->ce_ops->eo_mbtowc)(ce, wc, s, n, ps, nresult); +} + +static __inline int +_citrus_stdenc_wctomb(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, _citrus_wc_t wc, + void * __restrict ps, size_t * __restrict nresult) +{ + _DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_cstomb); + return (*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult); +} + +static __inline size_t +_citrus_stdenc_get_state_size(struct _citrus_stdenc *ce) +{ + _DIAGASSERT(ce && ce->ce_traits); + return ce->ce_traits->et_state_size; +} + +static __inline size_t +_citrus_stdenc_get_mb_cur_max(struct _citrus_stdenc *ce) +{ + _DIAGASSERT(ce && ce->ce_traits); + return ce->ce_traits->et_mb_cur_max; +} + +#endif diff --git a/lib/libc/citrus/citrus_stdenc_local.h b/lib/libc/citrus/citrus_stdenc_local.h new file mode 100644 index 000000000000..d6870b250eda --- /dev/null +++ b/lib/libc/citrus/citrus_stdenc_local.h @@ -0,0 +1,137 @@ +/* $NetBSD: citrus_stdenc_local.h,v 1.1 2003/06/25 09:51:40 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _CITRUS_STDENC_LOCAL_H_ +#define _CITRUS_STDENC_LOCAL_H_ + +#define _CITRUS_STDENC_GETOPS_FUNC_BASE(n) \ +int n(struct _citrus_stdenc_ops *, size_t, u_int32_t) +#define _CITRUS_STDENC_GETOPS_FUNC(_e_) \ +_CITRUS_STDENC_GETOPS_FUNC_BASE(_citrus_##_e_##_stdenc_getops) +typedef _CITRUS_STDENC_GETOPS_FUNC_BASE((*_citrus_stdenc_getops_t)); + + +#define _CITRUS_STDENC_DECLS(_e_) \ +static int _citrus_##_e_##_stdenc_init \ + (struct _citrus_stdenc * __restrict, const void * __restrict, \ + size_t, struct _citrus_stdenc_traits * __restrict); \ +static void _citrus_##_e_##_stdenc_uninit(struct _citrus_stdenc *); \ +static int _citrus_##_e_##_stdenc_init_state \ + (struct _citrus_stdenc * __restrict, void * __restrict); \ +static int _citrus_##_e_##_stdenc_mbtocs \ + (struct _citrus_stdenc * __restrict, \ + _citrus_csid_t * __restrict, _citrus_index_t * __restrict, \ + const char ** __restrict, size_t, \ + void * __restrict, size_t * __restrict); \ +static int _citrus_##_e_##_stdenc_cstomb \ + (struct _citrus_stdenc * __restrict, char * __restrict, \ + size_t, _citrus_csid_t, _citrus_index_t, \ + void * __restrict, size_t * __restrict); \ +static int _citrus_##_e_##_stdenc_mbtowc \ + (struct _citrus_stdenc * __restrict, \ + _citrus_wc_t * __restrict, \ + const char ** __restrict, size_t, \ + void * __restrict, size_t * __restrict); \ +static int _citrus_##_e_##_stdenc_wctomb \ + (struct _citrus_stdenc * __restrict, char * __restrict, size_t, \ + _citrus_wc_t, void * __restrict, size_t * __restrict) + +#define _CITRUS_STDENC_DEF_OPS(_e_) \ +struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \ + /* eo_abi_version */ _CITRUS_STDENC_ABI_VERSION, \ + /* eo_init */ &_citrus_##_e_##_stdenc_init, \ + /* eo_uninit */ &_citrus_##_e_##_stdenc_uninit, \ + /* eo_init_state */ &_citrus_##_e_##_stdenc_init_state, \ + /* eo_mbtocs */ &_citrus_##_e_##_stdenc_mbtocs, \ + /* eo_cstomb */ &_citrus_##_e_##_stdenc_cstomb, \ + /* eo_mbtowc */ &_citrus_##_e_##_stdenc_mbtowc, \ + /* eo_wctomb */ &_citrus_##_e_##_stdenc_wctomb, \ +} + +typedef int (*_citrus_stdenc_init_t) + (struct _citrus_stdenc * __reatrict, const void * __restrict , size_t, + struct _citrus_stdenc_traits * __restrict); +typedef void (*_citrus_stdenc_uninit_t)(struct _citrus_stdenc * __restrict); +typedef int (*_citrus_stdenc_init_state_t) + (struct _citrus_stdenc * __restrict, void * __restrict); +typedef int (*_citrus_stdenc_mbtocs_t) + (struct _citrus_stdenc * __restrict, + _citrus_csid_t * __restrict, _citrus_index_t * __restrict, + const char ** __restrict, size_t, + void * __restrict, size_t * __restrict); +typedef int (*_citrus_stdenc_cstomb_t) + (struct _citrus_stdenc *__restrict, char * __restrict, size_t, + _citrus_csid_t, _citrus_index_t, void * __restrict, + size_t * __restrict); +typedef int (*_citrus_stdenc_mbtowc_t) + (struct _citrus_stdenc * __restrict, + _citrus_wc_t * __restrict, + const char ** __restrict, size_t, + void * __restrict, size_t * __restrict); +typedef int (*_citrus_stdenc_wctomb_t) + (struct _citrus_stdenc *__restrict, char * __restrict, size_t, + _citrus_wc_t, void * __restrict, size_t * __restrict); + +/* + * ABI version change log + * 0x00000001 + * initial version + */ +#define _CITRUS_STDENC_ABI_VERSION 0x00000001 +struct _citrus_stdenc_ops { + u_int32_t eo_abi_version; + /* version 0x00000001 */ + _citrus_stdenc_init_t eo_init; + _citrus_stdenc_uninit_t eo_uninit; + _citrus_stdenc_init_state_t eo_init_state; + _citrus_stdenc_mbtocs_t eo_mbtocs; + _citrus_stdenc_cstomb_t eo_cstomb; + _citrus_stdenc_mbtowc_t eo_mbtowc; + _citrus_stdenc_wctomb_t eo_wctomb; +}; + +struct _citrus_stdenc_traits { + /* version 0x00000001 */ + size_t et_state_size; + size_t et_mb_cur_max; +}; + +struct _citrus_stdenc { + /* public */ + /* version 0x00000001 */ + struct _citrus_stdenc_ops *ce_ops; + void *ce_closure; + /* private */ + _citrus_module_t ce_module; + struct _citrus_stdenc_traits *ce_traits; +}; + +#define _CITRUS_DEFAULT_STDENC_NAME "NONE" + +#endif diff --git a/lib/libc/citrus/citrus_stdenc_template.h b/lib/libc/citrus/citrus_stdenc_template.h new file mode 100644 index 000000000000..0ae57d278f79 --- /dev/null +++ b/lib/libc/citrus/citrus_stdenc_template.h @@ -0,0 +1,171 @@ +/* $NetBSD: citrus_stdenc_template.h,v 1.1 2003/06/25 09:51:41 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * CAUTION: THIS IS NOT STANDALONE FILE + * + * function templates of iconv standard encoding handler for each encodings. + * + */ + +/* + * macros + */ + +#undef _TO_EI +#undef _CE_TO_EI +#undef _TO_STATE +#define _TO_EI(_cl_) ((_ENCODING_INFO*)(_cl_)) +#define _CE_TO_EI(_ce_) (_TO_EI((_ce_)->ce_closure)) +#define _TO_STATE(_ps_) ((_ENCODING_STATE*)(_ps_)) + +/* ---------------------------------------------------------------------- + * templates for public functions + */ + +int +_FUNCNAME(stdenc_getops)(struct _citrus_stdenc_ops *ops, size_t lenops, + u_int32_t expected_version) +{ + if (expected_version<_CITRUS_STDENC_ABI_VERSION || lenops 0) { + ei = calloc(1, sizeof(_ENCODING_INFO)); + if (ei == NULL) { + return errno; + } + } + + ret = _FUNCNAME(encoding_module_init)(ei, var, lenvar); + if (ret) { + free((void *)ei); + return ret; + } + + ce->ce_closure = ei; + et->et_state_size = sizeof(_ENCODING_STATE); + et->et_mb_cur_max = _ENCODING_MB_CUR_MAX(_CE_TO_EI(ce)); + + return 0; +} + +static void +_FUNCNAME(stdenc_uninit)(struct _citrus_stdenc * __restrict ce) +{ + if (ce) { + _FUNCNAME(encoding_module_uninit)(_CE_TO_EI(ce)); + free(ce->ce_closure); + } +} + +static int +_FUNCNAME(stdenc_init_state)(struct _citrus_stdenc * __restrict ce, + void * __restrict ps) +{ + _FUNCNAME(init_state)(_CE_TO_EI(ce), _TO_STATE(ps)); + + return 0; +} + +static int +_FUNCNAME(stdenc_mbtocs)(struct _citrus_stdenc * __restrict ce, + _citrus_csid_t * __restrict csid, + _citrus_index_t * __restrict idx, + const char ** __restrict s, size_t n, + void * __restrict ps, size_t * __restrict nresult) +{ + int ret; + wchar_t wc; + + _DIAGASSERT(nresult != NULL); + + ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), &wc, s, n, + _TO_STATE(ps), nresult); + + if (!ret && *nresult != (size_t)-2) + _FUNCNAME(stdenc_wctocs)(_CE_TO_EI(ce), csid, idx, wc); + + return ret; +} + +static int +_FUNCNAME(stdenc_cstomb)(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, + _citrus_csid_t csid, _citrus_index_t idx, + void * __restrict ps, size_t * __restrict nresult) +{ + int ret; + wchar_t wc; + + _DIAGASSERT(nresult != NULL); + + wc = 0; + + if (csid != _CITRUS_CSID_INVALID) { + ret = _FUNCNAME(stdenc_cstowc)(_CE_TO_EI(ce), &wc, csid, idx); + if (ret) + return ret; + } + + return _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps), + nresult); +} + +static int +_FUNCNAME(stdenc_mbtowc)(struct _citrus_stdenc * __restrict ce, + _citrus_wc_t * __restrict wc, + const char ** __restrict s, size_t n, + void * __restrict ps, size_t * __restrict nresult) +{ + return _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), wc, s, n, + _TO_STATE(ps), nresult); +} + +static int +_FUNCNAME(stdenc_wctomb)(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, _citrus_wc_t wc, + void * __restrict ps, size_t * __restrict nresult) +{ + return _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps), + nresult); +} diff --git a/lib/libc/citrus/citrus_types.h b/lib/libc/citrus/citrus_types.h new file mode 100644 index 000000000000..265090ada99d --- /dev/null +++ b/lib/libc/citrus/citrus_types.h @@ -0,0 +1,37 @@ +/* $NetBSD: citrus_types.h,v 1.1 2003/06/25 09:51:41 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_TYPES_H_ +#define _CITRUS_TYPES_H_ + +typedef uint32_t _citrus_wc_t; +typedef uint32_t _citrus_index_t; +typedef uint32_t _citrus_csid_t; +#define _CITRUS_CSID_INVALID ((_citrus_csid_t)-1) + +#endif diff --git a/lib/libc/citrus/modules/citrus_big5.c b/lib/libc/citrus/modules/citrus_big5.c index 4e53fea10783..8ca68eb34fc8 100644 --- a/lib/libc/citrus/modules/citrus_big5.c +++ b/lib/libc/citrus/modules/citrus_big5.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_big5.c,v 1.5 2002/03/28 10:53:48 yamt Exp $ */ +/* $NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -64,7 +64,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_big5.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); +__RCSID("$NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -77,8 +77,12 @@ __RCSID("$NetBSD: citrus_big5.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_big5.h" /* ---------------------------------------------------------------------- @@ -166,8 +170,8 @@ _citrus_BIG5_check2(u_int c) static int /*ARGSUSED*/ -_citrus_BIG5_stdencoding_init(_BIG5EncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) { _DIAGASSERT(ei != NULL); @@ -178,7 +182,7 @@ _citrus_BIG5_stdencoding_init(_BIG5EncodingInfo * __restrict ei, static void /*ARGSUSED*/ -_citrus_BIG5_stdencoding_uninit(_BIG5EncodingInfo *ei) +_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei) { } @@ -281,30 +285,43 @@ _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, size_t n, wchar_t wc, _BIG5State * __restrict psenc, size_t * __restrict nresult) { - int l; + int l, ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(nresult != 0); _DIAGASSERT(s != NULL); + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + /* check invalid sequence */ - if (wc & ~0xffff) - goto ilseq; + if (wc & ~0xffff) { + ret = EILSEQ; + goto err; + } if (wc & 0x8000) { if (_citrus_BIG5_check((wc >> 8) & 0xff) != 2 || - !_citrus_BIG5_check2(wc & 0xff)) - goto ilseq; + !_citrus_BIG5_check2(wc & 0xff)) { + ret = EILSEQ; + goto err; + } l = 2; } else { - if (wc & ~0xff || !_citrus_BIG5_check(wc & 0xff)) - goto ilseq; + if (wc & ~0xff || !_citrus_BIG5_check(wc & 0xff)) { + ret = EILSEQ; + goto err; + } l = 1; } if (n < l) { /* bound check failure */ - goto ilseq; + ret = E2BIG; + goto err; } if (l == 2) { @@ -315,13 +332,62 @@ _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, *nresult = l; - return (0); + return 0; -ilseq: +err: *nresult = (size_t)-1; - return (EILSEQ); + return ret; } +static __inline int +/*ARGSUSED*/ +_citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + + _DIAGASSERT(csid != NULL && idx != NULL); + + if (wc<0x100) + *csid = 0; + else + *csid = 1; + *idx = (_index_t)wc; + + return 0; +} + +static __inline int +/*ARGSUSED*/ +_citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + u_int8_t h, l; + + _DIAGASSERT(wc != NULL); + + switch (csid) { + case 0: + if (idx>=0x80U) + return EILSEQ; + *wc = (wchar_t)idx; + break; + case 1: + if (idx>=0x10000U) + return EILSEQ; + h = idx >> 8; + l = idx; + if (h<0xA1 || h>0xF9 || l<0x40 || l>0xFE) + return EILSEQ; + *wc = (wchar_t)idx; + break; + default: + return EILSEQ; + } + + return 0; +} /* ---------------------------------------------------------------------- * public interface for ctype @@ -331,3 +397,13 @@ _CITRUS_CTYPE_DECLS(BIG5); _CITRUS_CTYPE_DEF_OPS(BIG5); #include "citrus_ctype_template.h" + + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(BIG5); +_CITRUS_STDENC_DEF_OPS(BIG5); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_big5.h b/lib/libc/citrus/modules/citrus_big5.h index b9df87157477..60a0f59904a7 100644 --- a/lib/libc/citrus/modules/citrus_big5.h +++ b/lib/libc/citrus/modules/citrus_big5.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_big5.h,v 1.1 2002/03/17 22:14:22 tshiozak Exp $ */ +/* $NetBSD: citrus_big5.h,v 1.2 2003/06/25 09:51:41 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(BIG5); +_CITRUS_STDENC_GETOPS_FUNC(BIG5); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_euc.c b/lib/libc/citrus/modules/citrus_euc.c index 93dd818e3859..7c22e1c901cf 100644 --- a/lib/libc/citrus/modules/citrus_euc.c +++ b/lib/libc/citrus/modules/citrus_euc.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euc.c,v 1.5 2002/03/28 10:53:48 yamt Exp $ */ +/* $NetBSD: citrus_euc.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -64,7 +64,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_euc.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); +__RCSID("$NetBSD: citrus_euc.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -77,8 +77,12 @@ __RCSID("$NetBSD: citrus_euc.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_euc.h" @@ -299,12 +303,18 @@ _citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc, _EUCState *psenc, size_t *nresult) { wchar_t m, nm; - int cs, i; + int cs, i, ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(nresult != 0); _DIAGASSERT(s != NULL); + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + m = wc & ei->mask; nm = wc & ~m; @@ -319,8 +329,10 @@ _citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc, cs = 1; i = ei->count[cs]; - if (n < i) - goto ilseq; + if (n < i) { + ret = E2BIG; + goto err; + } m = (cs % 2) ? 0x80 : 0x00; switch (cs) { case 2: @@ -339,15 +351,51 @@ _citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc, *nresult = (size_t)ei->count[cs]; return 0; -ilseq: +err: *nresult = (size_t)-1; - return EILSEQ; /*XXX*/ + return ret; +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + wchar_t m, nm; + + _DIAGASSERT(ei != NULL && csid != NULL && idx != NULL); + + m = wc & ei->mask; + nm = wc & ~m; + + *csid = (_citrus_csid_t)m; + *idx = (_citrus_index_t)nm; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(ei != NULL && wc != NULL); + + if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0) + return (EINVAL); + + *wc = (wchar_t)csid | (wchar_t)idx; + + return (0); } static int /*ARGSUSED*/ -_citrus_EUC_stdencoding_init(_EUCEncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_EUC_encoding_module_init(_EUCEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) { _DIAGASSERT(ei != NULL); @@ -357,7 +405,7 @@ _citrus_EUC_stdencoding_init(_EUCEncodingInfo * __restrict ei, static void /*ARGSUSED*/ -_citrus_EUC_stdencoding_uninit(_EUCEncodingInfo * __restrict ei) +_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * __restrict ei) { } @@ -369,3 +417,12 @@ _CITRUS_CTYPE_DECLS(EUC); _CITRUS_CTYPE_DEF_OPS(EUC); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(EUC); +_CITRUS_STDENC_DEF_OPS(EUC); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_euc.h b/lib/libc/citrus/modules/citrus_euc.h index 95c83f57a93d..9f67756ca283 100644 --- a/lib/libc/citrus/modules/citrus_euc.h +++ b/lib/libc/citrus/modules/citrus_euc.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euc.h,v 1.1 2002/03/17 22:14:22 tshiozak Exp $ */ +/* $NetBSD: citrus_euc.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(EUC); +_CITRUS_STDENC_GETOPS_FUNC(EUC); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_euctw.c b/lib/libc/citrus/modules/citrus_euctw.c index 9f6abbf46633..c0c8e0fb84d1 100644 --- a/lib/libc/citrus/modules/citrus_euctw.c +++ b/lib/libc/citrus/modules/citrus_euctw.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euctw.c,v 1.5 2002/03/28 10:53:48 yamt Exp $ */ +/* $NetBSD: citrus_euctw.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -56,7 +56,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_euctw.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); +__RCSID("$NetBSD: citrus_euctw.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -69,8 +69,12 @@ __RCSID("$NetBSD: citrus_euctw.c,v 1.5 2002/03/28 10:53:48 yamt Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_euctw.h" @@ -168,8 +172,8 @@ _citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei, static int /*ARGSUSED*/ -_citrus_EUCTW_stdencoding_init(_EUCTWEncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) { _DIAGASSERT(ei != NULL); @@ -181,7 +185,7 @@ _citrus_EUCTW_stdencoding_init(_EUCTWEncodingInfo * __restrict ei, static void /*ARGSUSED*/ -_citrus_EUCTW_stdencoding_uninit(_EUCTWEncodingInfo *ei) +_citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei) { } @@ -295,12 +299,18 @@ _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei, { wchar_t cs = wc & 0x7f000080; wchar_t v; - int i, len, clen; + int i, len, clen, ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(nresult != 0); _DIAGASSERT(s != NULL); + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + clen = 1; if (wc & 0x00007f00) clen = 2; @@ -310,38 +320,86 @@ _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei, if (clen == 1 && cs == 0x00000000) { /* ASCII */ len = 1; - if (n < len) - goto ilseq; + if (n < len) { + ret = E2BIG; + goto err; + } v = wc & 0x0000007f; } else if (clen == 2 && cs == ('G' << 24)) { /* CNS-11643-1 */ len = 2; - if (n < len) - goto ilseq; + if (n < len) { + ret = E2BIG; + goto err; + } v = wc & 0x00007f7f; v |= 0x00008080; } else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') { /* CNS-11643-[2-7] */ len = 4; - if (n < len) - goto ilseq; + if (n < len) { + ret = E2BIG; + goto err; + } *s++ = _SS2; *s++ = (cs >> 24) - 'H' + 0xa2; v = wc & 0x00007f7f; v |= 0x00008080; - } else - goto ilseq; + } else { + ret = EILSEQ; + goto err; + } i = clen; while (i-- > 0) *s++ = (v >> (i << 3)) & 0xff; *nresult = len; - return (0); + return 0; -ilseq: +err: *nresult = (size_t)-1; - return (EILSEQ); + return ret; +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + + _DIAGASSERT(ei != NULL && csid != NULL && idx != NULL); + + *csid = (_csid_t)(wc >> 24) & 0xFF; + *idx = (_index_t)(wc & 0x7F7F); + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(ei != NULL && wc != NULL); + + if (csid > 7 || (idx & ~0x7F7F) != 0) + return (EINVAL); + + if (csid==0) { + if ((idx & ~0x7F) != 0) + return (EINVAL); + *wc = (wchar_t)idx; + } else { + if ((idx & ~0x7F7F) != 0) + return (EINVAL); + *wc = (wchar_t)idx | ((wchar_t)csid<<24); + } + + return (0); } /* ---------------------------------------------------------------------- @@ -352,3 +410,12 @@ _CITRUS_CTYPE_DECLS(EUCTW); _CITRUS_CTYPE_DEF_OPS(EUCTW); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(EUCTW); +_CITRUS_STDENC_DEF_OPS(EUCTW); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_euctw.h b/lib/libc/citrus/modules/citrus_euctw.h index 78310b9dfe3c..dc01412ee8f5 100644 --- a/lib/libc/citrus/modules/citrus_euctw.h +++ b/lib/libc/citrus/modules/citrus_euctw.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euctw.h,v 1.1 2002/03/17 22:14:23 tshiozak Exp $ */ +/* $NetBSD: citrus_euctw.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(EUCTW); +_CITRUS_STDENC_GETOPS_FUNC(EUCTW); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_gbk2k.c b/lib/libc/citrus/modules/citrus_gbk2k.c index 442a79e5ed94..03c7edf00e46 100644 --- a/lib/libc/citrus/modules/citrus_gbk2k.c +++ b/lib/libc/citrus/modules/citrus_gbk2k.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_gbk2k.c,v 1.2 2003/05/08 20:42:39 petrov Exp $ */ +/* $NetBSD: citrus_gbk2k.c,v 1.3 2003/06/25 09:51:42 tshiozak Exp $ */ /*- * Copyright (c)2003 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_gbk2k.c,v 1.2 2003/05/08 20:42:39 petrov Exp $"); +__RCSID("$NetBSD: citrus_gbk2k.c,v 1.3 2003/06/25 09:51:42 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -41,8 +41,13 @@ __RCSID("$NetBSD: citrus_gbk2k.c,v 1.2 2003/05/08 20:42:39 petrov Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_gbk2k.h" @@ -56,8 +61,9 @@ typedef struct _GBK2KState { } _GBK2KState; typedef struct { - int dummy; + int ei_mode; } _GBK2KEncodingInfo; +#define _MODE_2BYTE 0x0001 typedef struct { _GBK2KEncodingInfo ei; @@ -217,7 +223,8 @@ _citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei, case 2: if (_mb_trailbyte (_PSENC)) goto convert; - if (_mb_surrogate (_PSENC)) + if ((ei->ei_mode & _MODE_2BYTE) == 0 && + _mb_surrogate (_PSENC)) continue; goto ilseq; case 3: @@ -267,35 +274,52 @@ _citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei, _GBK2KState * __restrict psenc, size_t * __restrict nresult) { - int len; + int len, ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(s != NULL); _DIAGASSERT(psenc != NULL); - if (psenc->chlen != 0) - goto invalid; + if (psenc->chlen != 0) { + ret = EINVAL; + goto err; + } + + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } len = _mb_count(wc); - if (n < len) - goto ilseq; + if (n < len) { + ret = E2BIG; + goto err; + } switch (len) { case 1: - if (!_mb_singlebyte(_PUSH_PSENC(wc ))) - goto ilseq; + if (!_mb_singlebyte(_PUSH_PSENC(wc ))) { + ret = EILSEQ; + goto err; + } break; case 2: if (!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) || - !_mb_trailbyte (_PUSH_PSENC(wc ))) - goto ilseq; + !_mb_trailbyte (_PUSH_PSENC(wc ))) { + ret = EILSEQ; + goto err; + } break; case 4: - if (!_mb_leadbyte (_PUSH_PSENC(wc >> 24)) || + if ((ei->ei_mode & _MODE_2BYTE) != 0 || + !_mb_leadbyte (_PUSH_PSENC(wc >> 24)) || !_mb_surrogate (_PUSH_PSENC(wc >> 16)) || !_mb_leadbyte (_PUSH_PSENC(wc >> 8)) || - !_mb_surrogate (_PUSH_PSENC(wc ))) - goto ilseq; + !_mb_surrogate (_PUSH_PSENC(wc ))) { + ret = EILSEQ; + goto err; + } break; } @@ -308,28 +332,117 @@ _citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei, return (0); -invalid: - return (EINVAL); - -ilseq: +err: *nresult = (size_t)-1; - return (EILSEQ); + return ret; +} + +static __inline int +/*ARGSUSED*/ +_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + u_int8_t ch, cl; + + _DIAGASSERT(csid != NULL && idx != NULL); + + if ((u_int32_t)wc<0x80) { + /* ISO646 */ + *csid = 0; + *idx = (_index_t)wc; + } else if ((u_int32_t)wc>=0x10000) { + /* GBKUCS : XXX */ + *csid = 3; + *idx = (_index_t)wc; + } else { + ch = (u_int8_t)(wc >> 8); + cl = (u_int8_t)wc; + if (ch>=0xA1 && cl>=0xA1) { + /* EUC G1 */ + *csid = 1; + *idx = (_index_t)wc & 0x7F7FU; + } else { + /* extended area (0x8140-) */ + *csid = 2; + *idx = (_index_t)wc; + } + } + + return 0; +} + +static __inline int +/*ARGSUSED*/ +_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(wc != NULL); + + switch (csid) { + case 0: + /* ISO646 */ + *wc = (wchar_t)idx; + break; + case 1: + /* EUC G1 */ + *wc = (wchar_t)idx | 0x8080U; + break; + case 2: + /* extended area */ + *wc = (wchar_t)idx; + break; + case 3: + /* GBKUCS : XXX */ + if ((ei->ei_mode & _MODE_2BYTE) != 0) + return EINVAL; + *wc = (wchar_t)idx; + break; + default: + return EILSEQ; + } + + return 0; } static int /*ARGSUSED*/ -_citrus_GBK2K_stdencoding_init(_GBK2KEncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) { + const char *p; + _DIAGASSERT(ei != NULL); + p = var; +#define MATCH(x, act) \ +do { \ + if (lenvar >= (sizeof(#x)-1) && \ + _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) { \ + act; \ + lenvar -= sizeof(#x)-1; \ + p += sizeof(#x)-1; \ + } \ +} while (/*CONSTCOND*/0) + while (lenvar>0) { + switch (_bcs_tolower(*p)) { + case '2': + MATCH("2byte", ei->ei_mode |= _MODE_2BYTE); + break; + } + p++; + lenvar--; + } + memset((void *)ei, 0, sizeof(*ei)); return (0); } static void /*ARGSUSED*/ -_citrus_GBK2K_stdencoding_uninit(_GBK2KEncodingInfo *ei) +_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei) { } @@ -342,3 +455,12 @@ _CITRUS_CTYPE_DECLS(GBK2K); _CITRUS_CTYPE_DEF_OPS(GBK2K); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(GBK2K); +_CITRUS_STDENC_DEF_OPS(GBK2K); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_gbk2k.h b/lib/libc/citrus/modules/citrus_gbk2k.h index bc629c6f8161..d0ea49115ffc 100644 --- a/lib/libc/citrus/modules/citrus_gbk2k.h +++ b/lib/libc/citrus/modules/citrus_gbk2k.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_gbk2k.h,v 1.1 2003/03/25 18:26:54 tshiozak Exp $ */ +/* $NetBSD: citrus_gbk2k.h,v 1.2 2003/06/25 09:51:43 tshiozak Exp $ */ /*- * Copyright (c)2003 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(GBK2K); +_CITRUS_STDENC_GETOPS_FUNC(GBK2K); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_iconv_none.c b/lib/libc/citrus/modules/citrus_iconv_none.c new file mode 100644 index 000000000000..e0702c25a418 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_iconv_none.c @@ -0,0 +1,111 @@ +/* $NetBSD: citrus_iconv_none.c,v 1.1 2003/06/25 09:51:43 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_iconv_none.c,v 1.1 2003/06/25 09:51:43 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_iconv.h" +#include "citrus_iconv_none.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_ICONV_DECLS(iconv_none); +_CITRUS_ICONV_DEF_OPS(iconv_none); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_iconv_none_iconv_getops(struct _citrus_iconv_ops *ops, size_t lenops, + uint32_t expected_version) +{ + if (expected_version<_CITRUS_ICONV_ABI_VERSION || lenopsci_closure = NULL; + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_iconv_none_iconv_uninit(struct _citrus_iconv * __restrict ci) +{ +} + +static int +/*ARGSUSED*/ +_citrus_iconv_none_iconv_convert(struct _citrus_iconv * __restrict ci, + const char * __restrict * __restrict in, + size_t * __restrict inbytes, + char * __restrict * __restrict out, + size_t * __restrict outbytes, + u_int32_t flags, size_t * __restrict invalids) +{ + int e2big; + size_t len; + + len = *inbytes; + e2big = 0; + if (*outbytes +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_iconv_std.c,v 1.1 2003/06/25 09:51:43 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_mmap.h" +#include "citrus_iconv.h" +#include "citrus_stdenc.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_csmapper.h" +#include "citrus_memstream.h" +#include "citrus_iconv_std.h" +#include "citrus_esdb.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_ICONV_DECLS(iconv_std); +_CITRUS_ICONV_DEF_OPS(iconv_std); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_iconv_std_iconv_getops(struct _citrus_iconv_ops *ops, size_t lenops, + u_int32_t expected_version) +{ + if (expected_version<_CITRUS_ICONV_ABI_VERSION || lenopsse_ps) + memcpy(se->se_pssaved, se->se_ps, + _stdenc_get_state_size(se->se_handle)); +} + +static __inline void +restore_encoding_state(struct _citrus_iconv_std_encoding *se) +{ + if (se->se_ps) + memcpy(se->se_ps, se->se_pssaved, + _stdenc_get_state_size(se->se_handle)); +} + +static __inline void +init_encoding_state(struct _citrus_iconv_std_encoding *se) +{ + if (se->se_ps) + _stdenc_init_state(se->se_handle, se->se_ps); +} + +static __inline int +mbtocsx(struct _citrus_iconv_std_encoding *se, + _csid_t *csid, _index_t *idx, const char **s, size_t n, + size_t *nresult) +{ + return _stdenc_mbtocs(se->se_handle, csid, idx, s, n, se->se_ps, + nresult); +} + +static __inline int +cstombx(struct _citrus_iconv_std_encoding *se, + char *s, size_t n, _csid_t csid, _index_t idx, size_t *nresult) +{ + return _stdenc_cstomb(se->se_handle, s, n, csid, idx, se->se_ps, + nresult); +} + +static __inline int +wctombx(struct _citrus_iconv_std_encoding *se, + char *s, size_t n, _wc_t wc, size_t *nresult) +{ + return _stdenc_wctomb(se->se_handle, s, n, wc, se->se_ps, nresult); +} + + +/* + * open/close an encoding. + */ +static __inline void +close_encoding(struct _citrus_iconv_std_encoding *se) +{ + free(se->se_ps); se->se_ps = NULL; + free(se->se_pssaved); se->se_pssaved = NULL; +} + +static __inline int +open_encoding(struct _citrus_iconv_std_encoding *se, struct _esdb *db) +{ + int ret; + + se->se_ps = se->se_pssaved = NULL; + ret = _stdenc_open(&se->se_handle, db->db_encname, + db->db_variable, db->db_len_variable); + if (ret) + return ret; + + if (_stdenc_get_state_size(se->se_handle) == 0) + return 0; + + se->se_ps = malloc(_stdenc_get_state_size(se->se_handle)); + if (se->se_ps == NULL) { + ret = errno; + goto err; + } + ret = _stdenc_init_state(se->se_handle, se->se_ps); + if (ret) + goto err; + se->se_pssaved = malloc(_stdenc_get_state_size(se->se_handle)); + if (se->se_pssaved == NULL) { + ret = errno; + goto err; + } + ret = _stdenc_init_state(se->se_handle, se->se_pssaved); + if (ret) + goto err; + return 0; + +err: + close_encoding(se); + return ret; +} + +static int +open_csmapper(struct _csmapper **rcm, const char *src, const char *dst, + unsigned long *rnorm) +{ + int ret; + struct _csmapper *cm; + + ret = _csmapper_open(&cm, src, dst, 0, rnorm); + if (ret) + return ret; + if (_csmapper_get_src_max(cm) != 1 || _csmapper_get_dst_max(cm) != 1 || + _csmapper_get_state_size(cm) != 0) { + _csmapper_close(cm); + return EINVAL; + } + + *rcm = cm; + + return 0; +} + +static void +close_dsts(struct _citrus_iconv_std_dst_list *dl) +{ + struct _citrus_iconv_std_dst *sd; + + while ((sd=TAILQ_FIRST(dl)) != NULL) { + TAILQ_REMOVE(dl, sd, sd_entry); + _csmapper_close(sd->sd_mapper); + free(sd); + } +} + +static int +open_dsts(struct _citrus_iconv_std_dst_list *dl, + struct _esdb_charset *ec, struct _esdb *dbdst) +{ + int i, ret; + struct _citrus_iconv_std_dst *sd, *sdtmp; + unsigned long norm; + + sd = malloc(sizeof(*sd)); + if (sd == NULL) + return errno; + + for (i=0; idb_num_charsets; i++) { + ret = open_csmapper(&sd->sd_mapper,ec->ec_csname, + dbdst->db_charsets[i].ec_csname, &norm); + if (ret == 0) { + sd->sd_csid = dbdst->db_charsets[i].ec_csid; + sd->sd_norm = norm; + /* insert this mapper by sorted order. */ + TAILQ_FOREACH(sdtmp, dl, sd_entry) { + if (sdtmp->sd_norm > norm) { + TAILQ_INSERT_BEFORE(sdtmp, sd, + sd_entry); + sd = NULL; + break; + } + } + if (sd) + TAILQ_INSERT_TAIL(dl, sd, sd_entry); + sd = malloc(sizeof(*sd)); + if (sd == NULL) { + ret = errno; + close_dsts(dl); + return ret; + } + } else if (ret != ENOENT) { + close_dsts(dl); + free(sd); + return ret; + } + } + free(sd); + return 0; +} + +static void +close_srcs(struct _citrus_iconv_std_src_list *sl) +{ + struct _citrus_iconv_std_src *ss; + + while ((ss=TAILQ_FIRST(sl)) != NULL) { + TAILQ_REMOVE(sl, ss, ss_entry); + close_dsts(&ss->ss_dsts); + free(ss); + } +} + +static int +open_srcs(struct _citrus_iconv_std_src_list *sl, + struct _esdb *dbsrc, struct _esdb *dbdst) +{ + int i, ret, count = 0; + struct _citrus_iconv_std_src *ss; + + ss = malloc(sizeof(*ss)); + if (ss == NULL) + return errno; + + TAILQ_INIT(&ss->ss_dsts); + + for (i=0; idb_num_charsets; i++) { + ret = open_dsts(&ss->ss_dsts, &dbsrc->db_charsets[i], dbdst); + if (ret) + goto err; + if (!TAILQ_EMPTY(&ss->ss_dsts)) { + ss->ss_csid = dbsrc->db_charsets[i].ec_csid; + TAILQ_INSERT_TAIL(sl, ss, ss_entry); + ss = malloc(sizeof(*ss)); + if (ss == NULL) { + ret = errno; + goto err; + } + count++; + TAILQ_INIT(&ss->ss_dsts); + } + } + free(ss); + + return count ? 0 : ENOENT; + +err: + free(ss); + close_srcs(sl); + return ret; +} + +/* do convert a character */ +#define E_NO_CORRESPONDING_CHAR ENOENT /* XXX */ +static int +do_conv(struct _citrus_iconv_std *is, _csid_t *csid, _index_t *idx) +{ + _index_t tmpidx; + int ret; + struct _citrus_iconv_std_src *ss; + struct _citrus_iconv_std_dst *sd; + + TAILQ_FOREACH(ss, &is->is_srcs, ss_entry) { + if (ss->ss_csid == *csid) { + TAILQ_FOREACH(sd, &ss->ss_dsts, sd_entry) { + ret = _csmapper_convert(sd->sd_mapper, + &tmpidx, *idx, NULL); + switch (ret) { + case _CITRUS_MAPPER_CONVERT_SUCCESS: + *csid = sd->sd_csid; + *idx = tmpidx; + return 0; + case _CITRUS_MAPPER_CONVERT_INVAL: + break; + case _CITRUS_MAPPER_CONVERT_SRC_MORE: + /*FALLTHROUGH*/ + case _CITRUS_MAPPER_CONVERT_DST_MORE: + /*FALLTHROUGH*/ + case _CITRUS_MAPPER_CONVERT_FATAL: + return EINVAL; + case _CITRUS_MAPPER_CONVERT_ILSEQ: + return EILSEQ; + } + } + break; + } + } + + return E_NO_CORRESPONDING_CHAR; +} +/* ---------------------------------------------------------------------- */ + +static int +/*ARGSUSED*/ +_citrus_iconv_std_iconv_init(struct _citrus_iconv *ci, + const char * __restrict curdir, + const char * __restrict src, + const char * __restrict dst, + const void * __restrict var, size_t lenvar) +{ + int ret; + struct _citrus_iconv_std *is; + struct _citrus_esdb esdbsrc, esdbdst; + + is = malloc(sizeof(*is)); + if (is==NULL) { + ret = errno; + goto err0; + } + ret = _citrus_esdb_open(&esdbsrc, src); + if (ret) + goto err1; + ret = _citrus_esdb_open(&esdbdst, dst); + if (ret) + goto err2; + ret = open_encoding(&is->is_src_encoding, &esdbsrc); + if (ret) + goto err3; + ret = open_encoding(&is->is_dst_encoding, &esdbdst); + if (ret) + goto err4; + is->is_use_invalid = esdbdst.db_use_invalid; + is->is_invalid = esdbdst.db_invalid; + + TAILQ_INIT(&is->is_srcs); + ret = open_srcs(&is->is_srcs, &esdbsrc, &esdbdst); + if (ret) + goto err5; + + _esdb_close(&esdbsrc); + _esdb_close(&esdbdst); + ci->ci_closure = is; + + return 0; + +err5: + close_encoding(&is->is_dst_encoding); +err4: + close_encoding(&is->is_src_encoding); +err3: + _esdb_close(&esdbdst); +err2: + _esdb_close(&esdbsrc); +err1: + free(is); +err0: + return ret; +} + +static void +/*ARGSUSED*/ +_citrus_iconv_std_iconv_uninit(struct _citrus_iconv *ci) +{ + struct _citrus_iconv_std *is; + + if (ci->ci_closure == NULL) + return; + + is = ci->ci_closure; + close_encoding(&is->is_src_encoding); + close_encoding(&is->is_dst_encoding); + close_srcs(&is->is_srcs); + free(is); +} + +static int +/*ARGSUSED*/ +_citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict ci, + const char * __restrict * __restrict in, + size_t * __restrict inbytes, + char * __restrict * __restrict out, + size_t * __restrict outbytes, u_int32_t flags, + size_t * __restrict invalids) +{ + struct _citrus_iconv_std *is = ci->ci_closure; + _index_t idx; + _csid_t csid; + int ret; + size_t szrin, szrout; + size_t inval; + const char *tmpin; + + inval = 0; + if (in==NULL || *in==NULL) { + /* special cases */ + if (out!=NULL && *out!=NULL) { + /* init output state */ + save_encoding_state(&is->is_src_encoding); + save_encoding_state(&is->is_dst_encoding); + szrout = 0; + + ret = cstombx(&is->is_dst_encoding, + *out, *outbytes, + _CITRUS_CSID_INVALID, + 0, &szrout); + if (ret) + goto err; + + if (szrout == (size_t)-2) { + /* too small to store the character */ + ret = EINVAL; + goto err; + } + *out += szrout; + *outbytes -= szrout; + } + *invalids = 0; + init_encoding_state(&is->is_src_encoding); + return 0; + } + + /* normal case */ + for (;;) { + /* save the encoding states for the error recovery */ + save_encoding_state(&is->is_src_encoding); + save_encoding_state(&is->is_dst_encoding); + + /* mb -> csid/index */ + tmpin = *in; + szrin = szrout = 0; + ret = mbtocsx(&is->is_src_encoding, &csid, &idx, + &tmpin, *inbytes, &szrin); + if (ret) + goto err; + + if (szrin == (size_t)-2) { + /* incompleted character */ + ret = EINVAL; + goto err; + } + /* convert the character */ + ret = do_conv(is, &csid, &idx); + if (ret) { + if (ret == E_NO_CORRESPONDING_CHAR) { + inval ++; + if ((flags&_CITRUS_ICONV_F_HIDE_INVALID)==0 && + is->is_use_invalid) { + ret = wctombx(&is->is_dst_encoding, + *out, *outbytes, + is->is_invalid, + &szrout); + if (ret) + goto err; + } + goto next; + } else { + goto err; + } + } + /* csid/index -> mb */ + ret = cstombx(&is->is_dst_encoding, + *out, *outbytes, csid, idx, &szrout); + if (ret) + goto err; +next: + _DIAGASSERT(*inbytes>=szrin && *outbytes>=szrout); + *inbytes -= tmpin-*in; /* szrin is insufficient on \0. */ + *in = tmpin; + *outbytes -= szrout; + *out += szrout; + if (*inbytes==0) + break; + if (*outbytes == 0) { + ret = E2BIG; + goto err_norestore; + } + } + *invalids = inval; + + return 0; + +err: + restore_encoding_state(&is->is_src_encoding); + restore_encoding_state(&is->is_dst_encoding); +err_norestore: + *invalids = inval; + + return ret; +} diff --git a/lib/libc/citrus/modules/citrus_iconv_std.h b/lib/libc/citrus/modules/citrus_iconv_std.h new file mode 100644 index 000000000000..c1d43018a651 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_iconv_std.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_iconv_std.h,v 1.1 2003/06/25 09:51:44 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_ICONV_STD_H_ +#define _CITRUS_ICONV_STD_H_ + +#include "citrus_iconv_std_local.h" + +_CITRUS_ICONV_GETOPS_FUNC(iconv_std); + +#endif diff --git a/lib/libc/citrus/modules/citrus_iconv_std_local.h b/lib/libc/citrus/modules/citrus_iconv_std_local.h new file mode 100644 index 000000000000..503616cf7481 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_iconv_std_local.h @@ -0,0 +1,73 @@ +/* $NetBSD: citrus_iconv_std_local.h,v 1.1 2003/06/25 09:51:44 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_ICONV_STD_LOCAL_H_ +#define _CITRUS_ICONV_STD_LOCAL_H_ + +/* + * encoding + */ +struct _citrus_iconv_std_encoding { + struct _citrus_stdenc *se_handle; + void *se_ps; + void *se_pssaved; +}; + +/* + * dst + */ +struct _citrus_iconv_std_dst { + TAILQ_ENTRY(_citrus_iconv_std_dst) sd_entry; + _citrus_csid_t sd_csid; + unsigned long sd_norm; + struct _citrus_csmapper *sd_mapper; +}; +TAILQ_HEAD(_citrus_iconv_std_dst_list, _citrus_iconv_std_dst); + +/* + * src + */ +struct _citrus_iconv_std_src { + TAILQ_ENTRY(_citrus_iconv_std_src) ss_entry; + _citrus_csid_t ss_csid; + struct _citrus_iconv_std_dst_list ss_dsts; +}; +TAILQ_HEAD(_citrus_iconv_std_src_list, _citrus_iconv_std_src); + +/* + * iconv_std handle + */ +struct _citrus_iconv_std { + struct _citrus_iconv_std_encoding is_src_encoding; + struct _citrus_iconv_std_encoding is_dst_encoding; + struct _citrus_iconv_std_src_list is_srcs; + int is_use_invalid; + _citrus_wc_t is_invalid; +}; + +#endif diff --git a/lib/libc/citrus/modules/citrus_iso2022.c b/lib/libc/citrus/modules/citrus_iso2022.c index 7fa6cee006f1..1d26f03db57c 100644 --- a/lib/libc/citrus/modules/citrus_iso2022.c +++ b/lib/libc/citrus/modules/citrus_iso2022.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_iso2022.c,v 1.6 2002/03/28 10:53:49 yamt Exp $ */ +/* $NetBSD: citrus_iso2022.c,v 1.7 2003/06/25 09:51:44 tshiozak Exp $ */ /*- * Copyright (c)1999, 2002 Citrus Project, @@ -30,7 +30,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_iso2022.c,v 1.6 2002/03/28 10:53:49 yamt Exp $"); +__RCSID("$NetBSD: citrus_iso2022.c,v 1.7 2003/06/25 09:51:44 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -43,8 +43,12 @@ __RCSID("$NetBSD: citrus_iso2022.c,v 1.6 2002/03/28 10:53:49 yamt Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_iso2022.h" @@ -364,13 +368,13 @@ _citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei, e = v; while (*e && *e != ' ' && *e != '\t') ++e; - if (*e) { - len = e-v; - if (len>=sizeof(buf)) - goto parsefail; - sprintf(buf, "%.*s", len, v); - ++e; - } + + len = e-v; + if (len == 0) + break; + if (len>=sizeof(buf)) + goto parsefail; + sprintf(buf, "%.*s", len, v); if ((ret = get_recommend(ei, buf)) != _NOTMATCH) ; @@ -441,8 +445,9 @@ _citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei, static int /*ARGSUSED*/ -_citrus_ISO2022_stdencoding_init(_ISO2022EncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei, + const void * __restrict var, + size_t lenvar) { _DIAGASSERT(ei != NULL); @@ -452,7 +457,7 @@ _citrus_ISO2022_stdencoding_init(_ISO2022EncodingInfo * __restrict ei, static void /*ARGSUSED*/ -_citrus_ISO2022_stdencoding_uninit(_ISO2022EncodingInfo *ei) +_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei) { } @@ -996,7 +1001,7 @@ recommendation(_ISO2022EncodingInfo * __restrict ei, } static int -_ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t c, +_ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc, char * __restrict string, size_t n, char ** __restrict result, _ISO2022State * __restrict psenc) @@ -1014,13 +1019,13 @@ _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t c, /* result may be NULL */ /* state appears to be unused */ - if (iscntl(c & 0xff)) { + if (iscntl(wc & 0xff)) { /* go back to ASCII on control chars */ cs.type = CS94; cs.final = 'B'; cs.interm = '\0'; - } else if (!(c & ~0xff)) { - if (c & 0x80) { + } else if (!(wc & ~0xff)) { + if (wc & 0x80) { /* special treatment for ISO-8859-1 */ cs.type = CS96; cs.final = 'A'; @@ -1032,15 +1037,15 @@ _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t c, cs.interm = '\0'; } } else { - cs.final = (c >> 24) & 0x7f; - if ((c >> 16) & 0x80) - cs.interm = (c >> 16) & 0x7f; + cs.final = (wc >> 24) & 0x7f; + if ((wc >> 16) & 0x80) + cs.interm = (wc >> 16) & 0x7f; else cs.interm = '\0'; - if (c & 0x80) - cs.type = (c & 0x00007f00) ? CS96MULTI : CS96; + if (wc & 0x80) + cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96; else - cs.type = (c & 0x00007f00) ? CS94MULTI : CS94; + cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94; } target = recommendation(ei, &cs); p = tmp; @@ -1071,7 +1076,6 @@ _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t c, psenc->g[target].interm = cs.interm; planeok: - /* invoke the plane onto GL or GR. */ if (psenc->gl == target) goto sideok; @@ -1146,8 +1150,9 @@ sideok: i = isthree(cs.final) ? 3 : 2; break; } - while (i-- > 0) - *p++ = ((c >> (i << 3)) & 0x7f) | mask; + if (wc != 0) + while (i-- > 0) + *p++ = ((wc >> (i << 3)) & 0x7f) | mask; /* reset single shift state */ psenc->singlegl = psenc->singlegr = -1; @@ -1172,7 +1177,7 @@ _citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei, { char buf[MB_LEN_MAX]; char *result; - int len; + int len, ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(nresult != 0); @@ -1182,17 +1187,62 @@ _citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei, len = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc); if (sizeof(buf) < len || n < len) { /* XXX should recover state? */ - goto ilseq; + ret = E2BIG; + goto err; } memcpy(s, buf, len); *nresult = (size_t)len; return (0); -ilseq: +err: /* bound check failure */ *nresult = (size_t)-1; - return (EILSEQ); + return ret; +} + +static __inline int +/*ARGSUSED*/ +_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + wchar_t m, nm; + + _DIAGASSERT(csid != NULL && idx != NULL); + + m = wc & 0x7FFF8080; + nm = wc & 0x007F7F7F; + if (m & 0x00800000) { + nm &= 0x00007F7F; + } else { + m &= 0x7F008080; + } + if (nm & 0x007F0000) { + /* ^3 mark */ + m |= 0x007F0000; + } else if (nm & 0x00007F00) { + /* ^2 mark */ + m |= 0x00007F00; + } + *csid = (_csid_t)m; + *idx = (_index_t)nm; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(ei != NULL && wc != NULL); + + *wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx; + + return (0); } /* ---------------------------------------------------------------------- @@ -1203,3 +1253,12 @@ _CITRUS_CTYPE_DECLS(ISO2022); _CITRUS_CTYPE_DEF_OPS(ISO2022); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(ISO2022); +_CITRUS_STDENC_DEF_OPS(ISO2022); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_iso2022.h b/lib/libc/citrus/modules/citrus_iso2022.h index 1f6da04f2fe4..e82e0b3acff8 100644 --- a/lib/libc/citrus/modules/citrus_iso2022.h +++ b/lib/libc/citrus/modules/citrus_iso2022.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_iso2022.h,v 1.1 2002/03/17 22:14:23 tshiozak Exp $ */ +/* $NetBSD: citrus_iso2022.h,v 1.2 2003/06/25 09:51:44 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(ISO2022); +_CITRUS_STDENC_GETOPS_FUNC(ISO2022); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_mapper_646.c b/lib/libc/citrus/modules/citrus_mapper_646.c new file mode 100644 index 000000000000..ec78f91cd33e --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_646.c @@ -0,0 +1,257 @@ +/* $NetBSD: citrus_mapper_646.c,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper_646.c,v 1.1 2003/06/25 09:51:45 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_646.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_646); +_CITRUS_MAPPER_DEF_OPS(mapper_646); + +/* ---------------------------------------------------------------------- */ + +#define INVALID 0xFFFFFFFF +#define SPECIALS(x) \ + x(0x23) \ + x(0x24) \ + x(0x40) \ + x(0x5B) \ + x(0x5C) \ + x(0x5D) \ + x(0x5E) \ + x(0x60) \ + x(0x7B) \ + x(0x7C) \ + x(0x7D) \ + x(0x7E) + +#define INDEX(x) INDEX_##x, + +enum { + SPECIALS(INDEX) + NUM_OF_SPECIALS +}; +struct _citrus_mapper_646 { + int m6_forward; + _index_t m6_map[NUM_OF_SPECIALS]; +}; + +int +_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops, + size_t lenops, uint32_t expected_version) +{ + if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenopsm6_map[i] = strtoul(buf, (char **)&p, 0); + p = _bcs_skip_ws(buf); + if (*p != T_COMM && !*p) { + ret = EINVAL; + break; + } + } + _unmap_file(&r); + + return ret; +}; + +static int +parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms, + const char *dir) +{ + struct _region r; + char path[PATH_MAX]; + + m6->m6_forward = 1; + _memstream_skip_ws(ms); + /* whether backward */ + if (_memstream_peek(ms) == '!') { + _memstream_getc(ms); + m6->m6_forward = 0; + } + /* get description file path */ + _memstream_getregion(ms, &r, _memstream_remainder(ms)); + snprintf(path, sizeof(path), "%s/%.*s", + dir, (int)_region_size(&r), (char *)_region_head(&r)); + /* remove trailing white spaces */ + path[_bcs_skip_nonws(path)-path] = '\0'; + return parse_file(m6, path); +} + +static int +/*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) +{ + struct _citrus_mapper_646 *m6; + struct _memstream ms; + struct _region r; + int ret; + + _DIAGASSERT(cm && dir && mt); + + if (lenmtcm_closure = m6; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return 0; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm) +{ + if (cm && cm->cm_closure) { + free(cm->cm_closure); + } +} + +static int +/*ARGSUSED*/ +_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, + void * __restrict ps) +{ + struct _citrus_mapper_646 *m6; + + _DIAGASSERT(cm && cm->cm_closure); + + m6 = cm->cm_closure; + if (m6->m6_forward) { + /* forward */ + if (src>=0x80) + return _MAPPER_CONVERT_INVAL; +#define FORWARD(x) \ +if (src==(x)) { \ + if (m6->m6_map[INDEX_##x]==INVALID) \ + return _MAPPER_CONVERT_INVAL; \ + *dst = m6->m6_map[INDEX_##x]; \ + return 0; \ +} else + SPECIALS(FORWARD); + *dst = src; + } else { + /* backward */ +#define BACKWARD(x) \ +if (m6->m6_map[INDEX_##x]!=INVALID && src==m6->m6_map[INDEX_##x]) { \ + *dst = (x); \ + return 0; \ +} else if (src==(x)) \ + return _MAPPER_CONVERT_INVAL; \ +else + SPECIALS(BACKWARD); + if (src>=0x80) + return _MAPPER_CONVERT_INVAL; + *dst = src; + } + + return _MAPPER_CONVERT_SUCCESS; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_646_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ +} diff --git a/lib/libc/citrus/modules/citrus_mapper_646.h b/lib/libc/citrus/modules/citrus_mapper_646.h new file mode 100644 index 000000000000..cdacae0f3c9b --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_646.h @@ -0,0 +1,37 @@ +/* $NetBSD: citrus_mapper_646.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_646_H_ +#define _CITRUS_MAPPER_646_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_646); +_CITRUS_MAPPER_GETOPS_FUNC(mapper_646); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_none.c b/lib/libc/citrus/modules/citrus_mapper_none.c new file mode 100644 index 000000000000..452feafce8d5 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_none.c @@ -0,0 +1,110 @@ +/* $NetBSD: citrus_mapper_none.c,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper_none.c,v 1.1 2003/06/25 09:51:45 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_none.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_none); +_CITRUS_MAPPER_DEF_OPS(mapper_none); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_mapper_none_mapper_getops(struct _citrus_mapper_ops *ops, + size_t lenops, uint32_t expected_version) +{ + if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenopscm_closure = NULL; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return 0; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_none_mapper_uninit(struct _citrus_mapper *cm) +{ +} + +static int +/*ARGSUSED*/ +_citrus_mapper_none_mapper_convert(struct _citrus_mapper * __restrict cm, + _citrus_index_t * __restrict dst, + _citrus_index_t src, void * __restrict ps) +{ + *dst = src; + return _CITRUS_MAPPER_CONVERT_SUCCESS; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_none_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ +} diff --git a/lib/libc/citrus/modules/citrus_mapper_none.h b/lib/libc/citrus/modules/citrus_mapper_none.h new file mode 100644 index 000000000000..c0d6a7193809 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_none.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_mapper_none.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_NONE_H_ +#define _CITRUS_MAPPER_NONE_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_none); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_serial.c b/lib/libc/citrus/modules/citrus_mapper_serial.c new file mode 100644 index 000000000000..8a9b1a8811e8 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_serial.c @@ -0,0 +1,262 @@ +/* $NetBSD: citrus_mapper_serial.c,v 1.1 2003/06/25 09:51:46 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper_serial.c,v 1.1 2003/06/25 09:51:46 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_serial.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_serial); +_CITRUS_MAPPER_DEF_OPS(mapper_serial); + +#define _citrus_mapper_parallel_mapper_init \ + _citrus_mapper_serial_mapper_init +#define _citrus_mapper_parallel_mapper_uninit \ + _citrus_mapper_serial_mapper_uninit +#define _citrus_mapper_parallel_mapper_init_state \ + _citrus_mapper_serial_mapper_init_state +static int _citrus_mapper_parallel_mapper_convert( + struct _citrus_mapper * __restrict, _index_t * __restrict, _index_t, + void * __restrict); +_CITRUS_MAPPER_DEF_OPS(mapper_parallel); +#undef _citrus_mapper_parallel_mapper_init +#undef _citrus_mapper_parallel_mapper_uninit +#undef _citrus_mapper_parallel_mapper_init_state + + +/* ---------------------------------------------------------------------- */ + +struct maplink { + SIMPLEQ_ENTRY(maplink) ml_entry; + struct _mapper *ml_mapper; +}; +SIMPLEQ_HEAD(maplist, maplink); + +struct _citrus_mapper_serial { + struct maplist sr_mappers; +}; + +int +_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops, + size_t lenops, uint32_t expected_version) +{ + if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenopssr_mappers)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); + _mapper_close(ml->ml_mapper); + free(ml); + } +} + +static int +parse_var(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper_serial *sr, struct _memstream *ms) +{ + int ret; + struct _region r; + char mapname[PATH_MAX]; + struct maplink *ml; + + SIMPLEQ_INIT(&sr->sr_mappers); + while (1) { + /* remove beginning white spaces */ + _memstream_skip_ws(ms); + if (_memstream_iseof(ms)) + break; + /* cut down a mapper name */ + _memstream_chr(ms, &r, ','); + snprintf(mapname, sizeof(mapname), "%.*s", + (int)_region_size(&r), (char *)_region_head(&r)); + /* remove trailing white spaces */ + mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; + /* create a new mapper record */ + ml = malloc(sizeof(*ml)); + if (ml == NULL) + return errno; + ret = _mapper_open(ma, &ml->ml_mapper, mapname); + if (ret) { + free(ml); + return ret; + } + /* support only 1:1 and stateless converter */ + if (_mapper_get_src_max(ml->ml_mapper) != 1 || + _mapper_get_dst_max(ml->ml_mapper) != 1 || + _mapper_get_state_size(ml->ml_mapper) != 0) { + free(ml); + return EINVAL; + } + SIMPLEQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); + } + return 0; +} + +static int +/*ARGSUSED*/ +_citrus_mapper_serial_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) +{ + struct _citrus_mapper_serial *sr; + struct _memstream ms; + struct _region r; + + _DIAGASSERT(cm && dir && mt); + + if (lenmtcm_closure = sr; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return 0; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) +{ + if (cm && cm->cm_closure) { + uninit(cm->cm_closure); + free(cm->cm_closure); + } +} + +static int +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, + void * __restrict ps) +{ + int ret; + struct _citrus_mapper_serial *sr; + struct maplink *ml; + + _DIAGASSERT(cm && cm->cm_closure); + + sr = cm->cm_closure; + SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { + ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); + if (ret != _MAPPER_CONVERT_SUCCESS) + return ret; + } + *dst = src; + return _MAPPER_CONVERT_SUCCESS; +} + +static int +/*ARGSUSED*/ +_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, + void * __restrict ps) +{ + int ret; + struct _citrus_mapper_serial *sr; + struct maplink *ml; + _index_t tmp; + + _DIAGASSERT(cm && cm->cm_closure); + + sr = cm->cm_closure; + SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { + ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); + if (ret == _MAPPER_CONVERT_SUCCESS) { + *dst = tmp; + return _MAPPER_CONVERT_SUCCESS; + } + } + return _MAPPER_CONVERT_INVAL; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ +} diff --git a/lib/libc/citrus/modules/citrus_mapper_serial.h b/lib/libc/citrus/modules/citrus_mapper_serial.h new file mode 100644 index 000000000000..107f0ed6cfdf --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_serial.h @@ -0,0 +1,37 @@ +/* $NetBSD: citrus_mapper_serial.h,v 1.1 2003/06/25 09:51:46 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_SERIAL_H_ +#define _CITRUS_MAPPER_SERIAL_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_serial); +_CITRUS_MAPPER_GETOPS_FUNC(mapper_parallel); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_std.c b/lib/libc/citrus/modules/citrus_mapper_std.c new file mode 100644 index 000000000000..bd4eeacfcebc --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_std.c @@ -0,0 +1,319 @@ +/* $NetBSD: citrus_mapper_std.c,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper_std.c,v 1.1 2003/06/25 09:51:47 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_db.h" +#include "citrus_db_hash.h" + +#include "citrus_mapper_std.h" +#include "citrus_mapper_std_file.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_std); +_CITRUS_MAPPER_DEF_OPS(mapper_std); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops, size_t lenops, + u_int32_t expected_version) +{ + if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenopsms_rowcol; + _index_t row, col, idx; + u_int32_t conv; + + if (rc->rc_src_col_bits == 32) { + row = 0; + col = src; + } else { + row = src >> rc->rc_src_col_bits; + col = src & ((1U<rc_src_col_bits)-1); + } + if (row < rc->rc_src_row_begin || row > rc->rc_src_row_end || + col < rc->rc_src_col_begin || col > rc->rc_src_col_end) { + *dst = rc->rc_dst_invalid; + return _MAPPER_CONVERT_INVAL; + } + + idx = + (row - rc->rc_src_row_begin)*rc->rc_src_col_width + + (col - rc->rc_src_col_begin); + + switch (rc->rc_dst_unit_bits) { + case 8: + conv = _region_peek8(&rc->rc_table, idx); + break; + case 16: + conv = be16toh(_region_peek16(&rc->rc_table, idx*2)); + break; + case 32: + conv = be32toh(_region_peek32(&rc->rc_table, idx*4)); + break; + } + + if (conv == rc->rc_dst_invalid) { + *dst = rc->rc_dst_invalid; + return _MAPPER_CONVERT_INVAL; + } + + *dst = conv; + + return _MAPPER_CONVERT_SUCCESS; +} + + +static int +rowcol_init(struct _citrus_mapper_std *ms) +{ + int ret; + struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol; + const struct _citrus_mapper_std_rowcol_info_x *rcx; + struct _region r; + u_int64_t table_size; + + ms->ms_convert = &rowcol_convert; + ms->ms_uninit = NULL; + + /* get table region */ + ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE, + &rc->rc_table, NULL); + if (ret) { + if (ret==ENOENT) + ret = EFTYPE; + return ret; + } + + /* get table information */ + ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL); + if (ret) { + if (ret==ENOENT) + ret =EFTYPE; + return ret; + } + if (_region_size(&r) < sizeof(*rcx)) + return EFTYPE; + rcx = _region_head(&r); + + /* convert */ +#define CONV_ROWCOL(rc, rcx, elem) \ +do { \ + (rc)->rc_##elem = be32toh((rcx)->rcx_##elem); \ +} while (/*CONSTCOND*/0) + CONV_ROWCOL(rc, rcx, src_col_bits); + CONV_ROWCOL(rc, rcx, dst_invalid); + CONV_ROWCOL(rc, rcx, src_row_begin); + CONV_ROWCOL(rc, rcx, src_row_end); + CONV_ROWCOL(rc, rcx, src_col_begin); + CONV_ROWCOL(rc, rcx, src_col_end); + CONV_ROWCOL(rc, rcx, dst_unit_bits); + + rc->rc_src_col_width = rc->rc_src_col_end - rc->rc_src_col_begin +1; + + /* validation checks */ + if (rc->rc_src_col_end < rc->rc_src_col_begin || + rc->rc_src_row_end < rc->rc_src_row_begin || + !(rc->rc_dst_unit_bits==8 || rc->rc_dst_unit_bits==16 || + rc->rc_dst_unit_bits==32) || + !(rc->rc_src_col_bits >= 0 && rc->rc_src_col_bits <= 32)) + return EFTYPE; + + /* calcurate expected table size */ + table_size = rc->rc_src_row_end - rc->rc_src_row_begin + 1; + table_size *= rc->rc_src_col_width; + table_size *= rc->rc_dst_unit_bits/8; + + if (table_size > UINT32_MAX || + _region_size(&rc->rc_table) < table_size) + return EFTYPE; + + return 0; +} + +typedef int (*initfunc_t)(struct _citrus_mapper_std *); +static struct { + const char *t_name; + initfunc_t t_init; +} types[] = { + { _CITRUS_MAPPER_STD_TYPE_ROWCOL, &rowcol_init }, +}; +#define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0]))) + +static int +/*ARGSUSED*/ +_citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict cm, + const char * __restrict curdir, + const void * __restrict var, size_t lenvar, + struct _citrus_mapper_traits * __restrict mt, + size_t lenmt) +{ + char path[PATH_MAX]; + const char *type; + int ret, id; + struct _citrus_mapper_std *ms; + + /* set traits */ + if (lenmtmt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + /* alloc mapper std structure */ + ms = malloc(sizeof(*ms)); + if (ms==NULL) { + ret = errno; + goto err0; + } + + /* open mapper file */ + snprintf(path, sizeof(path), + "%s/%.*s", curdir, (int)lenvar, (const char *)var); + ret = _map_file(&ms->ms_file, path); + if (ret) + goto err1; + + ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC, + &_db_hash_std, NULL); + if (ret) + goto err2; + + /* get mapper type */ + ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE, + &type, NULL); + if (ret) { + if (ret==ENOENT) + ret = EFTYPE; + goto err3; + } + for (id=0; idcm_closure = ms; + + return 0; + +err3: + _db_close(ms->ms_db); +err2: + _unmap_file(&ms->ms_file); +err1: + free(ms); +err0: + return ret; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm) +{ + struct _citrus_mapper_std *ms; + + _DIAGASSERT(cm!=NULL & cm->cm_closure!=NULL); + + ms = cm->cm_closure; + if (ms->ms_uninit) + (*ms->ms_uninit)(ms); + _db_close(ms->ms_db); + _unmap_file(&ms->ms_file); + free(ms); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_std_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ +} + +static int +/*ARGSUSED*/ +_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, + void * __restrict ps) +{ + struct _citrus_mapper_std *ms; + + _DIAGASSERT(cm!=NULL && cm->cm_closure!=NULL); + + ms = cm->cm_closure; + + _DIAGASSERT(ms->ms_convert != NULL); + + return (*ms->ms_convert)(ms, dst, src, ps); +} diff --git a/lib/libc/citrus/modules/citrus_mapper_std.h b/lib/libc/citrus/modules/citrus_mapper_std.h new file mode 100644 index 000000000000..83eae823788a --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_std.h @@ -0,0 +1,38 @@ +/* $NetBSD: citrus_mapper_std.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_STD_H_ +#define _CITRUS_MAPPER_STD_H_ + +#include "citrus_mapper_std_local.h" + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_std); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_std_file.h b/lib/libc/citrus/modules/citrus_mapper_std_file.h new file mode 100644 index 000000000000..b3557162afc3 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_std_file.h @@ -0,0 +1,51 @@ +/* $NetBSD: citrus_mapper_std_file.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_STD_FILE_H_ +#define _CITRUS_MAPPER_STD_FILE_H_ + +#define _CITRUS_MAPPER_STD_MAGIC "MAPPER\0\0" + +#define _CITRUS_MAPPER_STD_SYM_TYPE "type" +#define _CITRUS_MAPPER_STD_SYM_INFO "info" +#define _CITRUS_MAPPER_STD_SYM_TABLE "table" + +#define _CITRUS_MAPPER_STD_TYPE_ROWCOL "rowcol" +struct _citrus_mapper_std_rowcol_info_x { + u_int32_t rcx_src_col_bits; + u_int32_t rcx_dst_invalid; + u_int32_t rcx_src_row_begin; + u_int32_t rcx_src_row_end; + u_int32_t rcx_src_col_begin; + u_int32_t rcx_src_col_end; + u_int32_t rcx_dst_unit_bits; + u_int32_t rcx_pad; +} __packed; +#define _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE 32 + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_std_local.h b/lib/libc/citrus/modules/citrus_mapper_std_local.h new file mode 100644 index 000000000000..d472575dfb1b --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_std_local.h @@ -0,0 +1,64 @@ +/* $NetBSD: citrus_mapper_std_local.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_STD_LOCAL_H_ +#define _CITRUS_MAPPER_STD_LOCAL_H_ + +typedef u_int32_t (*_citrus_mapper_std_getvalfunc_t)(const void *, u_int32_t); + +struct _citrus_mapper_std_rowcol { + struct _citrus_region rc_table; + int rc_src_col_bits; + _citrus_index_t rc_dst_invalid; + _citrus_index_t rc_src_row_begin; + _citrus_index_t rc_src_row_end; + _citrus_index_t rc_src_col_begin; + _citrus_index_t rc_src_col_end; + _citrus_index_t rc_src_col_width; + _citrus_index_t rc_dst_unit_bits; +}; + +struct _citrus_mapper_std; + +typedef int (*_citrus_mapper_std_convert_t)( + struct _citrus_mapper_std *__restrict, + _index_t *__restrict, _index_t, void *__restrict); +typedef void (*_citrus_mapper_std_uninit_t)(struct _citrus_mapper_std *); + +struct _citrus_mapper_std { + struct _citrus_region ms_file; + struct _citrus_db *ms_db; + _citrus_mapper_std_convert_t ms_convert; + _citrus_mapper_std_uninit_t ms_uninit; + union { + struct _citrus_mapper_std_rowcol rowcol; + } u; +#define ms_rowcol u.rowcol +}; + +#endif diff --git a/lib/libc/citrus/modules/citrus_mapper_zone.c b/lib/libc/citrus/modules/citrus_mapper_zone.c new file mode 100644 index 000000000000..a95301397c22 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_zone.c @@ -0,0 +1,394 @@ +/* $NetBSD: citrus_mapper_zone.c,v 1.1 2003/06/25 09:51:48 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_mapper_zone.c,v 1.1 2003/06/25 09:51:48 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_zone.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_zone); +_CITRUS_MAPPER_DEF_OPS(mapper_zone); + + +/* ---------------------------------------------------------------------- */ + +struct _zone { + u_int32_t z_begin; + u_int32_t z_end; +}; + +struct _citrus_mapper_zone { + struct _zone mz_row; + struct _zone mz_col; + int mz_col_bits; + int32_t mz_row_offset; + int32_t mz_col_offset; +}; + +struct _parse_state { + enum { S_BEGIN, S_OFFSET } ps_state; + union { + u_int32_t u_imm; + int32_t s_imm; + struct _zone zone; + } u; +#define ps_u_imm u.u_imm +#define ps_s_imm u.s_imm +#define ps_zone u.zone + int ps_top; +}; + +int +_citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops, + size_t lenops, uint32_t expected_version) +{ + if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenopsps_u_imm = strtoul(buf, &p, 0); + if ((p-buf) != i) + return T_ERR; + if (sign == '-') + ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm; + return T_IMM; +} + +static int +get_tok(struct _memstream *ms, struct _parse_state *ps) +{ + int c; + +loop: + c = _memstream_peek(ms); + if (c==0x00) + return EOF; + if (_bcs_isspace(c)) { + _memstream_getc(ms); + goto loop; + } + + switch (ps->ps_state) { + case S_BEGIN: + switch (c) { + case ':': + case '-': + case '/': + _memstream_getc(ms); + return c; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return get_imm(ms, ps); + } + break; + case S_OFFSET: + switch (c) { + case '/': + _memstream_getc(ms); + return c; + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return get_imm(ms, ps); + } + break; + } + return T_ERR; +} + +static int +parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z) +{ + if (get_tok(ms, ps) != T_IMM) + return -1; + z->z_begin = ps->ps_u_imm; + if (get_tok(ms, ps) != '-') + return -1; + if (get_tok(ms, ps) != T_IMM) + return -1; + z->z_end = ps->ps_u_imm; + + if (z->z_begin > z->z_end) + return -1; + + return 0; +} + +static int +check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval) +{ + u_int32_t remain; + + if (maxval != 0 && z->z_end >= maxval) + return -1; + + if (ofs > 0) { + if (maxval == 0) { + /* this should 0x100000000 - z->z_end */ + if (z->z_end == 0) { + remain = 0xFFFFFFFF; + } else { + remain = 0xFFFFFFFF - z->z_end + 1; + } + } else + remain = maxval - z->z_end; + if ((u_int32_t)ofs > remain) + return -1; + } else if (ofs < 0) { + if (z->z_begin < (u_int32_t)-ofs) + return -1; + } + + return 0; +} + +static int +parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms) +{ + struct _parse_state ps; + int ret, isrc; + uint32_t rowmax, colmax; + + ps.ps_state = S_BEGIN; + + if (parse_zone(ms, &ps, &mz->mz_col)) + return -1; + + ret = get_tok(ms, &ps); + if (ret == '/') { + /* rowzone / colzone / bits */ + isrc = 1; + mz->mz_row = mz->mz_col; + + if (parse_zone(ms, &ps, &mz->mz_col)) + return -1; + if (get_tok(ms, &ps) != '/') + return -1; + if (get_tok(ms, &ps) != T_IMM) + return -1; + mz->mz_col_bits = ps.ps_u_imm; + if (mz->mz_col_bits<0 || mz->mz_col_bits>32) + return -1; + ret = get_tok(ms, &ps); + } else { + /* colzone */ + isrc = 0; + mz->mz_col_bits = 32; + mz->mz_row.z_begin = mz->mz_row.z_end = 0; + } + if (ret == ':') { + /* offset */ + ps.ps_state = S_OFFSET; + if (get_tok(ms, &ps) != T_IMM) + return -1; + mz->mz_col_offset = ps.ps_s_imm; + if (isrc) { + /* row/col */ + mz->mz_row_offset = mz->mz_col_offset; + if (get_tok(ms, &ps) != '/') + return -1; + if (get_tok(ms, &ps) != T_IMM) + return -1; + mz->mz_col_offset = ps.ps_s_imm; + } else + mz->mz_row_offset = 0; + ret = get_tok(ms, &ps); + } + if (ret != EOF) + return -1; + + /* sanity check */ + if (mz->mz_col_bits==32) + colmax = 0; + else + colmax = 1 << mz->mz_col_bits; + if (mz->mz_col_bits==0) + rowmax = 0; + else + rowmax = 1 << (32-mz->mz_col_bits); + if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax)) + return -1; + if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax)) + return -1; + + return 0; +} + +static int +/*ARGSUSED*/ +_citrus_mapper_zone_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) +{ + struct _citrus_mapper_zone *mz; + struct _memstream ms; + struct _region r; + + _DIAGASSERT(cm && dir && mt); + + if (lenmtcm_closure = mz; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return 0; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm) +{ +} + +static int +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm, + _citrus_index_t * __restrict dst, + _citrus_index_t src, void * __restrict ps) +{ + u_int32_t row, col; + struct _citrus_mapper_zone *mz = cm->cm_closure; + + if (mz->mz_col_bits == 32) { + col = src; + row = 0; + if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end) + return _CITRUS_MAPPER_CONVERT_INVAL; + if (mz->mz_col_offset>0) + col += (u_int32_t)mz->mz_col_offset; + else + col -= (u_int32_t)-mz->mz_col_offset; + *dst = col; + } else { + col = src & (((u_int32_t)1<mz_col_bits)-1); + row = src >> mz->mz_col_bits; + if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end || + col < mz->mz_col.z_begin || col > mz->mz_col.z_end) + return _CITRUS_MAPPER_CONVERT_INVAL; + if (mz->mz_col_offset>0) + col += (u_int32_t)mz->mz_col_offset; + else + col -= (u_int32_t)-mz->mz_col_offset; + if (mz->mz_row_offset>0) + row += (u_int32_t)mz->mz_row_offset; + else + row -= (u_int32_t)-mz->mz_row_offset; + *dst = col | (row << mz->mz_col_bits); + } + return _CITRUS_MAPPER_CONVERT_SUCCESS; +} + +static void +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_init_state(struct _citrus_mapper * __restrict cm, + void * __restrict ps) +{ +} diff --git a/lib/libc/citrus/modules/citrus_mapper_zone.h b/lib/libc/citrus/modules/citrus_mapper_zone.h new file mode 100644 index 000000000000..d975dd127a72 --- /dev/null +++ b/lib/libc/citrus/modules/citrus_mapper_zone.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_mapper_zone.h,v 1.1 2003/06/25 09:51:48 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_MAPPER_ZONE_H_ +#define _CITRUS_MAPPER_ZONE_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_zone); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_mskanji.c b/lib/libc/citrus/modules/citrus_mskanji.c index 058eea565e25..688645a23d7f 100644 --- a/lib/libc/citrus/modules/citrus_mskanji.c +++ b/lib/libc/citrus/modules/citrus_mskanji.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_mskanji.c,v 1.5 2002/03/28 10:53:49 yamt Exp $ */ +/* $NetBSD: citrus_mskanji.c,v 1.6 2003/06/25 09:51:48 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -62,7 +62,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_mskanji.c,v 1.5 2002/03/28 10:53:49 yamt Exp $"); +__RCSID("$NetBSD: citrus_mskanji.c,v 1.6 2003/06/25 09:51:48 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -75,8 +75,12 @@ __RCSID("$NetBSD: citrus_mskanji.c,v 1.5 2002/03/28 10:53:49 yamt Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_mskanji.h" @@ -265,45 +269,167 @@ _citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei, _MSKanjiState * __restrict psenc, size_t * __restrict nresult) { + int ret; _DIAGASSERT(ei != NULL); _DIAGASSERT(psenc != NULL); _DIAGASSERT(s != NULL); + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + /* check invalid sequence */ - if (wc & ~0xffff) - goto ilseq; + if (wc & ~0xffff) { + ret = EILSEQ; + goto err; + } if (wc & 0xff00) { - if (n < 2) - goto ilseq; + if (n < 2) { + ret = E2BIG; + goto err; + } s[0] = (wc >> 8) & 0xff; s[1] = wc & 0xff; - if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) - goto ilseq; + if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) { + ret = EILSEQ; + goto err; + } *nresult = 2; - return (0); + return 0; } else { s[0] = wc & 0xff; - if (_mskanji1(s[0] & 0xff)) - goto ilseq; + if (_mskanji1(s[0] & 0xff)) { + ret = EILSEQ; + goto err; + } *nresult = 1; - return (0); + return 0; } -ilseq: +err: *nresult = (size_t)-1; - return EILSEQ; + return ret; } +static __inline int +/*ARGSUSED*/ +_citrus_MSKanji_stdenc_wctocs(_MSKanjiEncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + _index_t row, col; + + _DIAGASSERT(csid != NULL && idx != NULL); + + if ((_wc_t)wc < 0x80) { + /* ISO-646 */ + *csid = 0; + *idx = (_index_t)wc; + } else if ((_wc_t)wc < 0x100) { + /* KANA */ + *csid = 1; + *idx = (_index_t)wc & 0x7F; + } else if ((0x8140 <= (_wc_t)wc && (_wc_t)wc <= 0x9FFC) || + (0xE040 <= (_wc_t)wc && (_wc_t)wc <= 0xFCFC)) { + /* Kanji (containing Gaiji zone) */ + /* + * 94^2 zone (contains a part of Gaiji (0xED40 - 0xEEFC)): + * 0x8140 - 0x817E -> 0x2121 - 0x215F + * 0x8180 - 0x819E -> 0x2160 - 0x217E + * 0x819F - 0x81FC -> 0x2221 - 0x227E + * + * 0x8240 - 0x827E -> 0x2321 - 0x235F + * ... + * 0x9F9F - 0x9FFc -> 0x5E21 - 0x5E7E + * + * 0xE040 - 0xE07E -> 0x5F21 - 0x5F5F + * ... + * 0xEF9F - 0xEFFC -> 0x7E21 - 0x7E7E + * + * extended Gaiji zone: + * 0xF040 - 0xFCFC + */ + *csid = 2; + row = ((_wc_t)wc >> 8) - 0x81; + if (row >= 0x5F) + row -= 0x40; + row = row * 2 + 0x21; + col = (wc & 0xFF) - 0x1F; + if (col >= 0x61) + col -= 1; + if (col > 0x7E) { + row += 1; + col -= 0x5E; + } + *idx = ((_index_t)row << 8) | col; + } else + return EILSEQ; + + return 0; +} + +static __inline int +/*ARGSUSED*/ +_citrus_MSKanji_stdenc_cstowc(_MSKanjiEncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + u_int32_t row, col; + + _DIAGASSERT(wc != NULL); + + switch (csid) { + case 0: + /* ISO-646 */ + if (idx >= 0x80) + return EILSEQ; + *wc = (wchar_t)idx; + break; + case 1: + /* kana */ + if (idx >= 0x80) + return EILSEQ; + *wc = (wchar_t)idx + 0x80; + break; + case 2: + /* kanji */ + row = (idx >> 8); + col = idx & 0x7F; + if (row<0x21 || row>0x97 || col<0x21 || col>0x7E) + return EILSEQ; + row -= 0x21; col -= 0x21; + if ((row & 1)==0) { + col += 0x40; + if (col>=0x7F) + col += 1; + } else + col += 0x9F; + if (row<0x3E) + row = row/2 + 0x81; + else + row = row/2 + 0xc1; + *wc = ((wchar_t)row << 8) | col; + break; + default: + return EILSEQ; + } + + return 0; +} + static int /*ARGSUSED*/ -_citrus_MSKanji_stdencoding_init(_MSKanjiEncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_MSKanji_encoding_module_init(_MSKanjiEncodingInfo * __restrict ei, + const void * __restrict var, + size_t lenvar) { _DIAGASSERT(cl != NULL); @@ -312,7 +438,7 @@ _citrus_MSKanji_stdencoding_init(_MSKanjiEncodingInfo * __restrict ei, } static void -_citrus_MSKanji_stdencoding_uninit(_MSKanjiEncodingInfo *ei) +_citrus_MSKanji_encoding_module_uninit(_MSKanjiEncodingInfo *ei) { } @@ -324,3 +450,12 @@ _CITRUS_CTYPE_DECLS(MSKanji); _CITRUS_CTYPE_DEF_OPS(MSKanji); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(MSKanji); +_CITRUS_STDENC_DEF_OPS(MSKanji); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_mskanji.h b/lib/libc/citrus/modules/citrus_mskanji.h index 850eebf01113..90aebe1b1587 100644 --- a/lib/libc/citrus/modules/citrus_mskanji.h +++ b/lib/libc/citrus/modules/citrus_mskanji.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_mskanji.h,v 1.1 2002/03/17 22:14:23 tshiozak Exp $ */ +/* $NetBSD: citrus_mskanji.h,v 1.2 2003/06/25 09:51:48 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(MSKanji); +_CITRUS_STDENC_GETOPS_FUNC(MSKanji); __END_DECLS #endif diff --git a/lib/libc/citrus/modules/citrus_utf1632.c b/lib/libc/citrus/modules/citrus_utf1632.c new file mode 100644 index 000000000000..68bae6186a2c --- /dev/null +++ b/lib/libc/citrus/modules/citrus_utf1632.c @@ -0,0 +1,444 @@ +/* $NetBSD $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: citrus_utf1632.c,v 1.1 2003/06/25 09:51:49 tshiozak Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_bcs.h" + +#include "citrus_utf1632.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + u_int8_t ch[4]; + int chlen; + int current_endian; +} _UTF1632State; + +typedef struct { + int preffered_endian; + unsigned int cur_max; +#define _ENDIAN_UNKNOWN 0 +#define _ENDIAN_BIG 1 +#define _ENDIAN_LITTLE 2 + u_int32_t mode; +#define _MODE_UTF32 0x00000001U +#define _MODE_FORCE_ENDIAN 0x00000002U +} _UTF1632EncodingInfo; + +#define _FUNCNAME(m) _citrus_UTF1632_##m +#define _ENCODING_INFO _UTF1632EncodingInfo +#define _ENCODING_STATE _UTF1632State +#define _ENCODING_MB_CUR_MAX(_ei_) ((_ei_)->cur_max) +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static __inline void +/*ARGSUSED*/ +_citrus_UTF1632_init_state(_UTF1632EncodingInfo *ei, _UTF1632State *s) +{ + memset(s, 0, sizeof(*s)); +} + +static int +_citrus_UTF1632_mbrtowc_priv(_UTF1632EncodingInfo *ei, wchar_t *pwc, + const char **s, size_t n, _UTF1632State *psenc, + size_t *nresult) +{ + int chlenbak, endian, needlen; + wchar_t wc; + size_t result; + const char *s0; + + _DIAGASSERT(nresult != 0); + _DIAGASSERT(ei != NULL); + _DIAGASSERT(s != NULL); + _DIAGASSERT(psenc != NULL); + + s0 = *s; + + if (s0 == NULL) { + _citrus_UTF1632_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + result = 0; + chlenbak = psenc->chlen; + +refetch: + if ((ei->mode & _MODE_UTF32) != 0 || chlenbak>=2) + needlen = 4; + else + needlen = 2; + + while (chlenbak < needlen) { + if (n==0) + goto restart; + psenc->ch[chlenbak++] = *s0++; + n--; + result++; + } + + /* judge endian marker */ + if ((ei->mode & _MODE_UTF32) == 0) { + /* UTF16 */ + if (psenc->ch[0]==0xFE && psenc->ch[1]==0xFF) { + psenc->current_endian = _ENDIAN_BIG; + chlenbak = 0; + goto refetch; + } else if (psenc->ch[0]==0xFF && psenc->ch[1]==0xFE) { + psenc->current_endian = _ENDIAN_LITTLE; + chlenbak = 0; + goto refetch; + } + } else { + /* UTF32 */ + if (psenc->ch[0]==0x00 && psenc->ch[1]==0x00 && + psenc->ch[2]==0xFE && psenc->ch[3]==0xFF) { + psenc->current_endian = _ENDIAN_BIG; + chlenbak = 0; + goto refetch; + } else if (psenc->ch[0]==0xFF && psenc->ch[1]==0xFE && + psenc->ch[2]==0x00 && psenc->ch[3]==0x00) { + psenc->current_endian = _ENDIAN_LITTLE; + chlenbak = 0; + goto refetch; + } + } + if ((ei->mode & _MODE_FORCE_ENDIAN) != 0 || + psenc->current_endian == _ENDIAN_UNKNOWN) + endian = ei->preffered_endian; + else + endian = psenc->current_endian; + + /* get wc */ + if ((ei->mode & _MODE_UTF32) == 0) { + /* UTF16 */ + if (needlen==2) { + switch (endian) { + case _ENDIAN_LITTLE: + wc = (psenc->ch[0] | + ((wchar_t)psenc->ch[1] << 8)); + break; + case _ENDIAN_BIG: + wc = (psenc->ch[1] | + ((wchar_t)psenc->ch[0] << 8)); + break; + } + if (wc >= 0xD800 && wc <= 0xDBFF) { + /* surrogate high */ + needlen=4; + goto refetch; + } + } else { + /* surrogate low */ + wc -= 0xD800; /* wc : surrogate high (see above) */ + wc <<= 10; + switch (endian) { + case _ENDIAN_LITTLE: + if (psenc->ch[2]<0xDC || psenc->ch[2]>0xDF) + goto ilseq; + wc |= psenc->ch[2]; + wc |= (wchar_t)(psenc->ch[3] & 3) << 8; + break; + case _ENDIAN_BIG: + if (psenc->ch[3]<0xDC || psenc->ch[3]>0xDF) + goto ilseq; + wc |= psenc->ch[3]; + wc |= (wchar_t)(psenc->ch[2] & 3) << 8; + break; + } + wc += 0x10000; + } + } else { + /* UTF32 */ + switch (endian) { + case _ENDIAN_LITTLE: + wc = (psenc->ch[0] | + ((wchar_t)psenc->ch[1] << 8) | + ((wchar_t)psenc->ch[2] << 16) | + ((wchar_t)psenc->ch[3] << 24)); + break; + case _ENDIAN_BIG: + wc = (psenc->ch[3] | + ((wchar_t)psenc->ch[2] << 8) | + ((wchar_t)psenc->ch[1] << 16) | + ((wchar_t)psenc->ch[0] << 24)); + break; + } + } + + + *pwc = wc; + psenc->chlen = 0; + *nresult = result; + *s = s0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + psenc->chlen = 0; + return (EILSEQ); + +restart: + *nresult = (size_t)-2; + psenc->chlen = chlenbak; + *s = s0; + return (0); +} + +static int +_citrus_UTF1632_wcrtomb_priv(_UTF1632EncodingInfo *ei, char *s, size_t n, + wchar_t wc, _UTF1632State *psenc, + size_t *nresult) +{ + int ret; + wchar_t wc2; + + _DIAGASSERT(ei != NULL); + _DIAGASSERT(nresult != 0); + _DIAGASSERT(s != NULL); + + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + + wc2 = 0; + if ((ei->mode & _MODE_UTF32)==0) { + /* UTF16 */ + if (wc>0xFFFF) { + /* surrogate */ + if (wc>0x10FFFF) { + ret = EILSEQ; + goto err; + } + if (n < 4) { + ret = E2BIG; + goto err; + } + wc -= 0x10000; + wc2 = (wc & 0x3FF) | 0xDC00; + wc = (wc>>10) | 0xD800; + *nresult = (size_t)4; + } else { + if (n < 2) { + ret = E2BIG; + goto err; + } + *nresult = (size_t)2; + } + +surrogate: + switch (ei->preffered_endian) { + case _ENDIAN_BIG: + s[1] = wc; + s[0] = (wc >>= 8); + break; + case _ENDIAN_LITTLE: + s[0] = wc; + s[1] = (wc >>= 8); + break; + } + if (wc2!=0) { + wc = wc2; + wc2 = 0; + s += 2; + goto surrogate; + } + } else { + /* UTF32 */ + if (n < 4) { + ret = E2BIG; + goto err; + } + switch (ei->preffered_endian) { + case _ENDIAN_BIG: + s[3] = wc; + s[2] = (wc >>= 8); + s[1] = (wc >>= 8); + s[0] = (wc >>= 8); + break; + case _ENDIAN_LITTLE: + s[0] = wc; + s[1] = (wc >>= 8); + s[2] = (wc >>= 8); + s[3] = (wc >>= 8); + break; + } + *nresult = (size_t)4; + } + + return 0; + +err: + *nresult = (size_t)-1; + return ret; +} + +static void +parse_variable(_UTF1632EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ +#define MATCH(x, act) \ +do { \ + if (lenvar >= (sizeof(#x)-1) && \ + _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) { \ + act; \ + lenvar -= sizeof(#x)-1; \ + p += sizeof(#x)-1; \ + } \ +} while (/*CONSTCOND*/0) + const char *p; + p = var; + while (lenvar>0) { + switch (*p) { + case 'B': + case 'b': + MATCH(big, ei->preffered_endian = _ENDIAN_BIG); + break; + case 'L': + case 'l': + MATCH(little, ei->preffered_endian = _ENDIAN_LITTLE); + break; + case 'F': + case 'f': + MATCH(force, ei->mode |= _MODE_FORCE_ENDIAN); + break; + case 'U': + case 'u': + MATCH(utf32, ei->mode |= _MODE_UTF32); + break; + } + p++; + lenvar--; + } +} + +static int +/*ARGSUSED*/ +_citrus_UTF1632_encoding_module_init(_UTF1632EncodingInfo * __restrict ei, + const void * __restrict var, + size_t lenvar) +{ + _DIAGASSERT(ei != NULL); + + memset((void *)ei, 0, sizeof(*ei)); + + parse_variable(ei, var, lenvar); + + if ((ei->mode&_MODE_UTF32)==0) + ei->cur_max = 6; /* endian + surrogate */ + else + ei->cur_max = 8; /* endian + normal */ + + if (ei->preffered_endian == _ENDIAN_UNKNOWN) { +#if BYTE_ORDER == BIG_ENDIAN + ei->preffered_endian = _ENDIAN_BIG; +#else + ei->preffered_endian = _ENDIAN_LITTLE; +#endif + } + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_UTF1632_encoding_module_uninit(_UTF1632EncodingInfo *ei) +{ +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF1632_stdenc_wctocs(_UTF1632EncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, + _wc_t wc) +{ + + _DIAGASSERT(csid != NULL && idx != NULL); + + *csid = 0; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF1632_stdenc_cstowc(_UTF1632EncodingInfo * __restrict ei, + _wc_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(wc != NULL); + + if (csid != 0) + return (EILSEQ); + + *wc = (_wc_t)idx; + + return (0); +} + + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UTF1632); +_CITRUS_STDENC_DEF_OPS(UTF1632); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_utf1632.h b/lib/libc/citrus/modules/citrus_utf1632.h new file mode 100644 index 000000000000..0fac6f3123ad --- /dev/null +++ b/lib/libc/citrus/modules/citrus_utf1632.h @@ -0,0 +1,36 @@ +/* $NetBSD: citrus_utf1632.h,v 1.1 2003/06/25 09:51:49 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _CITRUS_UTF1632_H_ +#define _CITRUS_UTF1632_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(UTF1632); +__END_DECLS + +#endif diff --git a/lib/libc/citrus/modules/citrus_utf8.c b/lib/libc/citrus/modules/citrus_utf8.c index 0d218ed5b9b7..cfa52c20ab62 100644 --- a/lib/libc/citrus/modules/citrus_utf8.c +++ b/lib/libc/citrus/modules/citrus_utf8.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_utf8.c,v 1.7 2003/03/25 17:35:36 tshiozak Exp $ */ +/* $NetBSD: citrus_utf8.c,v 1.8 2003/06/25 09:51:49 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -64,7 +64,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_utf8.c,v 1.7 2003/03/25 17:35:36 tshiozak Exp $"); +__RCSID("$NetBSD: citrus_utf8.c,v 1.8 2003/06/25 09:51:49 tshiozak Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -77,8 +77,12 @@ __RCSID("$NetBSD: citrus_utf8.c,v 1.7 2003/03/25 17:35:36 tshiozak Exp $"); #include #include #include + +#include "citrus_namespace.h" +#include "citrus_types.h" #include "citrus_module.h" #include "citrus_ctype.h" +#include "citrus_stdenc.h" #include "citrus_utf8.h" @@ -102,6 +106,7 @@ typedef struct { typedef struct { } _UTF8EncodingInfo; + typedef struct { _UTF8EncodingInfo ei; struct { @@ -289,21 +294,29 @@ static int _citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei, char *s, size_t n, wchar_t wc, _UTF8State *psenc, size_t *nresult) { - int cnt, i; + int cnt, i, ret; wchar_t c; _DIAGASSERT(ei != NULL); _DIAGASSERT(nresult != 0); _DIAGASSERT(s != NULL); + /* reset state */ + if (wc == 0) { + *nresult = 0; /* stateless */ + return 0; + } + cnt = _UTF8_findlen(wc); if (cnt <= 0 || cnt > 6) { /* invalid UCS4 value */ - goto ilseq; + ret = EILSEQ; + goto err; } if (n < cnt) { /* bound check failure */ - goto ilseq; + ret = E2BIG; + goto err; } c = wc; @@ -322,30 +335,62 @@ _citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei, char *s, size_t n, wchar_t wc, } *nresult = (size_t)cnt; - return (0); + return 0; -ilseq: +err: *nresult = (size_t)-1; - return (EILSEQ); + return ret; } +static __inline int +/*ARGSUSED*/ +_citrus_UTF8_stdenc_wctocs(_UTF8EncodingInfo * __restrict ei, + _csid_t * __restrict csid, + _index_t * __restrict idx, + wchar_t wc) +{ + + _DIAGASSERT(csid != NULL && idx != NULL); + + *csid = 0; + *idx = (_citrus_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF8_stdenc_cstowc(_UTF8EncodingInfo * __restrict ei, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + _DIAGASSERT(wc != NULL); + + if (csid != 0) + return (EILSEQ); + + *wc = (wchar_t)idx; + + return (0); +} static int /*ARGSUSED*/ -_citrus_UTF8_stdencoding_init(_UTF8EncodingInfo * __restrict ei, - const void * __restrict var, size_t lenvar) +_citrus_UTF8_encoding_module_init(_UTF8EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) { _DIAGASSERT(ei != NULL); _UTF8_init_count(); memset((void *)ei, 0, sizeof(*ei)); - return (0); + return 0; } static void /*ARGSUSED*/ -_citrus_UTF8_stdencoding_uninit(_UTF8EncodingInfo *ei) +_citrus_UTF8_encoding_module_uninit(_UTF8EncodingInfo *ei) { } @@ -358,3 +403,12 @@ _CITRUS_CTYPE_DECLS(UTF8); _CITRUS_CTYPE_DEF_OPS(UTF8); #include "citrus_ctype_template.h" + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UTF8); +_CITRUS_STDENC_DEF_OPS(UTF8); + +#include "citrus_stdenc_template.h" diff --git a/lib/libc/citrus/modules/citrus_utf8.h b/lib/libc/citrus/modules/citrus_utf8.h index a8cfd9e1eba2..9e57b6b69796 100644 --- a/lib/libc/citrus/modules/citrus_utf8.h +++ b/lib/libc/citrus/modules/citrus_utf8.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_utf8.h,v 1.1 2002/03/17 22:14:24 tshiozak Exp $ */ +/* $NetBSD: citrus_utf8.h,v 1.2 2003/06/25 09:51:49 tshiozak Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -31,6 +31,7 @@ __BEGIN_DECLS _CITRUS_CTYPE_GETOPS_FUNC(UTF8); +_CITRUS_STDENC_GETOPS_FUNC(UTF8); __END_DECLS #endif