diff options
Diffstat (limited to 'lib/libc/iconv')
62 files changed, 8775 insertions, 0 deletions
diff --git a/lib/libc/iconv/Makefile.inc b/lib/libc/iconv/Makefile.inc new file mode 100644 index 0000000..8c43a20 --- /dev/null +++ b/lib/libc/iconv/Makefile.inc @@ -0,0 +1,18 @@ +# $FreeBSD$ + +# iconv sources +.PATH: ${.CURDIR}/iconv + +MAN+= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 __iconv_get_list.3 +MLINKS+= iconv.3 iconv_open.3 \ + iconv.3 iconv_open_into.3 \ + iconv.3 iconv_close.3 \ + iconv.3 __iconv.3 \ + __iconv_get_list.3 __iconv_free_list.3 +SRCS+= citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \ + citrus_csmapper.c citrus_db.c citrus_db_factory.c citrus_db_hash.c \ + citrus_esdb.c citrus_hash.c citrus_iconv.c citrus_lookup.c \ + citrus_lookup_factory.c citrus_mapper.c citrus_memstream.c \ + citrus_mmap.c citrus_module.c citrus_none.c citrus_pivot_factory.c \ + citrus_prop.c citrus_stdenc.c iconv.c +SYM_MAPS+= ${.CURDIR}/iconv/Symbol.map diff --git a/lib/libc/iconv/Symbol.map b/lib/libc/iconv/Symbol.map new file mode 100644 index 0000000..515cddc --- /dev/null +++ b/lib/libc/iconv/Symbol.map @@ -0,0 +1,101 @@ +/* + * $FreeBSD$ + */ + +FBSD_1.2 { + __iconv; + __iconv_free_list; + __iconv_get_list; + _citrus_bcs_convert_to_lower; + _citrus_bcs_convert_to_upper; + _citrus_bcs_isalnum; + _citrus_bcs_isalpha; + _citrus_bcs_isblank; + _citrus_bcs_isdigit; + _citrus_bcs_iseol; + _citrus_bcs_islower; + _citrus_bcs_isspace; + _citrus_bcs_isupper; + _citrus_bcs_isxdigit; + _citrus_bcs_skip_nonws; + _citrus_bcs_skip_nonws_len; + _citrus_bcs_skip_ws; + _citrus_bcs_skip_ws_len; + _citrus_bcs_strcasecmp; + _citrus_bcs_strncasecmp; + _citrus_bcs_strtol; + _citrus_bcs_strtoul; + _citrus_bcs_tolower; + _citrus_bcs_toupper; + _citrus_bcs_trunc_ws_len; + _citrus_csmapper_open; + _citrus_csmapper_close; + _citrus_db_factory_add_by_string; + _citrus_db_factory_add_string_by_string; + _citrus_db_factory_add32_by_string; + _citrus_db_factory_calc_size; + _citrus_db_factory_create; + _citrus_db_factory_serialize; + _citrus_db_hash_std; + _citrus_db_close; + _citrus_db_get_entry; + _citrus_db_get_number_of_entries; + _citrus_db_lookup; + _citrus_db_lookup_by_string; + _citrus_db_lookup8_by_string; + _citrus_db_lookup16_by_string; + _citrus_db_lookup_string_by_string; + _citrus_db_open; + _citrus_esdb_close; + _citrus_esdb_open; + _citrus_lookup_factory_convert; + _citrus_map_file; + _citrus_mapper_close; + _citrus_mapper_convert; + _citrus_mapper_create_area; + _citrus_mapper_get_dst_max; + _citrus_mapper_get_src_max; + _citrus_mapper_get_state_size; + _citrus_mapper_init_state; + _citrus_mapper_open; + _citrus_mapper_open_direct; + _citrus_mapper_set_persistent; + _citrus_memory_stream_bind; + _citrus_memory_stream_chr; + _citrus_memory_stream_getc; + _citrus_memory_stream_getln; + _citrus_memory_stream_getln_region; + _citrus_memory_stream_getregion; + _citrus_memory_stream_iseof; + _citrus_memory_stream_matchline; + _citrus_memory_stream_peek; + _citrus_memory_stream_remainder; + _citrus_memory_stream_rewind; + _citrus_memory_stream_seek; + _citrus_memory_stream_skip_ws; + _citrus_memory_stream_tell; + _citrus_memory_stream_ungetc; + _citrus_pivot_factory_convert; + _citrus_prop_object_init; + _citrus_prop_object_uninit; + _citrus_prop_parse_variable; + _citrus_prop_read_bool; + _citrus_prop_read_character; + _citrus_prop_read_character_common; + _citrus_prop_read_element; + _citrus_prop_read_num; + _citrus_prop_read_str; + _citrus_prop_read_symbol; + _citrus_stdenc_close; + _citrus_stdenc_open; + _citrus_unmap_file; + _libiconv_version; + iconv_canonicalize; + libiconv; + libiconv_close; + libiconv_open; + libiconv_open_into; + libiconv_set_relocation_prefix; + libiconvctl; + libiconvlist; +}; diff --git a/lib/libc/iconv/__iconv_get_list.3 b/lib/libc/iconv/__iconv_get_list.3 new file mode 100644 index 0000000..7c8d015 --- /dev/null +++ b/lib/libc/iconv/__iconv_get_list.3 @@ -0,0 +1,95 @@ +.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org> +.\" 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. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD$ +.\" +.Dd October 20, 2009 +.Dt __ICONV_GET_LIST 3 +.Os +.Sh NAME +.Nm __iconv_get_list +.Nm __iconv_free_list +.Nd retrieving a list of character encodings supported by +.Xr iconv 3 +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In iconv.h +.Ft int +.Fn __iconv_get_list "char ***names" "size_t count" "bool paired" +.Ft void +.Fn __iconv_free_list "char **names" "size_t count" +.Sh DESCRIPTION +The +.Fn __iconv_get_list +function obtains a list of character encodings that are supported by the +.Xr iconv 3 +call. +The list of the encoding names will be stored in +.Fa names +and the number of the entries is stored in +.Fa count . +If the +.Fa paired +variable is true, the list will be arranged into +canonical/alias name pairs. +.Pp +The +.Fn __iconv_free_list +function is to free the allocated memory during the call of +.Fn __iconv_get_list . +.Sh RETURN VALUES +Upon successful completion +.Fn __iconv_get_list +returns 0 and set the +.Fa names +and +.Fa count +arguments. +Otherwise, \-1 is returned and errno is set to indicate the error. +.Sh SEE ALSO +.Xr iconv 3 , +.Xr iconvlist 3 +.Sh STANDARDS +The +.Nm __iconv_get_list +and +.Nm __iconv_free_list +functions are non-standard interfaces, which appeared in +the implementation of the Citrus Project. +The iconv implementation of the Citrus Project was adopted in +.Fx 9 . +.Sh AUTHORS +This manual page was written by +.An Gabor Kovesdan Aq gabor@FreeBSD.org . diff --git a/lib/libc/iconv/_strtol.h b/lib/libc/iconv/_strtol.h new file mode 100644 index 0000000..d2d9d84 --- /dev/null +++ b/lib/libc/iconv/_strtol.h @@ -0,0 +1,167 @@ +/* $FreeBSD$ */ +/* $NetBSD: _strtol.h,v 1.2 2009/05/20 22:03:29 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * Original version ID: + * NetBSD: src/lib/libc/locale/_wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp + */ + +/* + * function template for strtol, strtoll and strtoimax. + * + * parameters: + * _FUNCNAME : function name + * __INT : return type + * __INT_MIN : lower limit of the return type + * __INT_MAX : upper limit of the return type + */ + +__INT +_FUNCNAME(const char *nptr, char **endptr, int base) +{ + const char *s; + __INT acc, cutoff; + unsigned char c; + int any, cutlim, i, neg; + + /* check base value */ + if (base && (base < 2 || base > 36)) { +#if !defined(_KERNEL) && !defined(_STANDALONE) + errno = EINVAL; + if (endptr != NULL) + /* LINTED interface specification */ + *endptr = __DECONST(void *, nptr); + return (0); +#else + panic("%s: invalid base %d", __func__, base); +#endif + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = (c == '0' ? 8 : 10); + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = (neg ? __INT_MIN : __INT_MAX); + cutlim = (int)(cutoff % base); + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + i = c - '0'; + else if (isalpha(c)) + i = c - (isupper(c) ? 'A' - 10 : 'a' - 10); + else + break; + if (i >= base) + break; + if (any < 0) + continue; + if (neg) { + if (acc < cutoff || (acc == cutoff && i > cutlim)) { + acc = __INT_MIN; +#if !defined(_KERNEL) && !defined(_STANDALONE) + any = -1; + errno = ERANGE; +#else + any = 0; + break; +#endif + } else { + any = 1; + acc *= base; + acc -= i; + } + } else { + if (acc > cutoff || (acc == cutoff && i > cutlim)) { + acc = __INT_MAX; +#if !defined(_KERNEL) && !defined(_STANDALONE) + any = -1; + errno = ERANGE; +#else + any = 0; + break; +#endif + } else { + any = 1; + acc *= base; + acc += i; + } + } + } + if (endptr != NULL) + /* LINTED interface specification */ + *endptr = __DECONST(void *, any ? s - 1 : nptr); + return(acc); +} diff --git a/lib/libc/iconv/_strtoul.h b/lib/libc/iconv/_strtoul.h new file mode 100644 index 0000000..64e0d46 --- /dev/null +++ b/lib/libc/iconv/_strtoul.h @@ -0,0 +1,126 @@ +/* $FreeBSD$ */ +/* $NetBSD: _strtoul.h,v 1.1 2008/08/20 12:42:26 joerg Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * Original version ID: + * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp + */ + +/* + * function template for strtoul, strtoull and strtoumax. + * + * parameters: + * _FUNCNAME : function name + * __UINT : return type + * __UINT_MAX : upper limit of the return type + */ + +__UINT +_FUNCNAME(const char *nptr, char **endptr, int base) +{ + const char *s; + __UINT acc, cutoff; + unsigned char c; + int any, cutlim, i, neg; + + /* check base value */ + if (base && (base < 2 || base > 36)) { +#if !defined(_KERNEL) && !defined(_STANDALONE) + errno = EINVAL; + return (0); +#else + panic("%s: invalid base %d", __func__, base); +#endif + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = (c == '0' ? 8 : 10); + + /* + * See strtol for comments as to the logic used. + */ + cutoff = __UINT_MAX / (__UINT)base; + cutlim = (int)(__UINT_MAX % (__UINT)base); + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + i = c - '0'; + else if (isalpha(c)) + i = c - (isupper(c) ? 'A' - 10 : 'a' - 10); + else + break; + if (i >= base) + break; + if (any < 0) + continue; + if (acc > cutoff || (acc == cutoff && i > cutlim)) { + acc = __UINT_MAX; +#if !defined(_KERNEL) && !defined(_STANDALONE) + any = -1; + errno = ERANGE; +#else + any = 0; + break; +#endif + } else { + any = 1; + acc *= (__UINT)base; + acc += i; + } + } + if (neg && any > 0) + acc = -acc; + if (endptr != NULL) + /* LINTED interface specification */ + *endptr = __DECONST(void *, any ? s - 1 : nptr); + return (acc); +} diff --git a/lib/libc/iconv/citrus_aliasname_local.h b/lib/libc/iconv/citrus_aliasname_local.h new file mode 100644 index 0000000..687362b --- /dev/null +++ b/lib/libc/iconv/citrus_aliasname_local.h @@ -0,0 +1,49 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_aliasname_local.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c)2008 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_ALIASNAME_LOCAL_H_ +#define _CITRUS_ALIASNAME_LOCAL_H_ + +static __inline const char * +__unaliasname(const char *dbname, const char *alias, + void *buf, size_t bufsize) +{ + + return (_lookup_simple(dbname, alias, + buf, bufsize, _LOOKUP_CASE_SENSITIVE)); +} + +static __inline int +__isforcemapping(const char *name) +{ + + return (_bcs_strcasecmp("/force", name)); +} + +#endif /*_CITRUS_ALIASNAME_LOCAL_H_*/ diff --git a/lib/libc/iconv/citrus_bcs.c b/lib/libc/iconv/citrus_bcs.c new file mode 100644 index 0000000..e86fb37 --- /dev/null +++ b/lib/libc/iconv/citrus_bcs.c @@ -0,0 +1,168 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_bcs.c,v 1.5 2005/05/14 17:55:42 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 <sys/cdefs.h> + +#include <assert.h> +#include <stdlib.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" + +/* + * case insensitive comparison between two C strings. + */ +int +_citrus_bcs_strcasecmp(const char * __restrict str1, + const char * __restrict str2) +{ + int c1, c2; + + c1 = c2 = 1; + + while (c1 && c2 && c1 == c2) { + c1 = _bcs_toupper(*str1++); + c2 = _bcs_toupper(*str2++); + } + + return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1)); +} + +/* + * case insensitive comparison between two C strings with limitation of length. + */ +int +_citrus_bcs_strncasecmp(const char * __restrict str1, + const char * __restrict str2, size_t sz) +{ + int c1, c2; + + c1 = 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)); +} + +/* + * skip white space characters. + */ +const char * +_citrus_bcs_skip_ws(const char *p) +{ + + while (*p && _bcs_isspace(*p)) + p++; + + return (p); +} + +/* + * skip non white space characters. + */ +const char * +_citrus_bcs_skip_nonws(const char *p) +{ + + while (*p && !_bcs_isspace(*p)) + p++; + + return (p); +} + +/* + * skip white space characters with limitation of length. + */ +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); +} + +/* + * skip non white space characters with limitation of length. + */ +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); +} + +/* + * truncate trailing white space characters. + */ +void +_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len) +{ + + while (*len > 0 && _bcs_isspace(p[*len - 1])) + (*len)--; +} + +/* + * destructive transliterate to lowercase. + */ +void +_citrus_bcs_convert_to_lower(char *s) +{ + + while (*s) { + *s = _bcs_tolower(*s); + s++; + } +} + +/* + * destructive transliterate to uppercase. + */ +void +_citrus_bcs_convert_to_upper(char *s) +{ + + while (*s) { + *s = _bcs_toupper(*s); + s++; + } +} diff --git a/lib/libc/iconv/citrus_bcs.h b/lib/libc/iconv/citrus_bcs.h new file mode 100644 index 0000000..3b1f537 --- /dev/null +++ b/lib/libc/iconv/citrus_bcs.h @@ -0,0 +1,102 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_bcs.h,v 1.6 2009/01/11 02:46:24 christos 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 <sys/types.h> + +#ifndef _CITRUS_BCS_H_ +#define _CITRUS_BCS_H_ + +/* + * predicate/conversion for basic character set. + * + * `Basic character set' is a term defined in the ISO C standard. + * Citrus bcs is, if anything, close to `portable character set' + * defined in the POSIX. + */ + +#define _CITRUS_BCS_PRED(_name_, _cond_) \ +static __inline int _citrus_bcs_##_name_(uint8_t c) { return (_cond_); } + +/* + * predicates. + * Unlike predicates defined in ctype.h, these do not accept EOF. + */ +_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')) + +/* + * transliterate between uppercase and lowercase. + * Unlike transliterator defined in ctype.h, these do not accept EOF. + */ +static __inline uint8_t +_citrus_bcs_toupper(uint8_t c) +{ + + return (_citrus_bcs_islower(c) ? (c - 'a' + 'A') : c); +} + +static __inline uint8_t +_citrus_bcs_tolower(uint8_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 *); + +long int _citrus_bcs_strtol(const char * __restrict, + char ** __restrict, int); +unsigned long _citrus_bcs_strtoul(const char * __restrict, + char ** __restrict, int); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_bcs_strtol.c b/lib/libc/iconv/citrus_bcs_strtol.c new file mode 100644 index 0000000..4073622 --- /dev/null +++ b/lib/libc/iconv/citrus_bcs_strtol.c @@ -0,0 +1,57 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_bcs_strtol.c,v 1.2 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c) 2005 The DragonFly Project. All rights reserved. + * Copyright (c) 2003, 2008 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 <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" + +#define _FUNCNAME _bcs_strtol +#define __INT long int + +#undef isspace +#define isspace(c) _bcs_isspace(c) + +#undef isdigit +#define isdigit(c) _bcs_isdigit(c) + +#undef isalpha +#define isalpha(c) _bcs_isalpha(c) + +#undef isupper +#define isupper(c) _bcs_isupper(c) + +#include "_strtol.h" diff --git a/lib/libc/iconv/citrus_bcs_strtoul.c b/lib/libc/iconv/citrus_bcs_strtoul.c new file mode 100644 index 0000000..d9fa97c --- /dev/null +++ b/lib/libc/iconv/citrus_bcs_strtoul.c @@ -0,0 +1,57 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_bcs_strtoul.c,v 1.3 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c) 2005 The DragonFly Project. All rights reserved. + * Copyright (c) 2003, 2008 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 <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" + +#define _FUNCNAME _bcs_strtoul +#define __UINT unsigned long int + +#undef isspace +#define isspace(c) _bcs_isspace(c) + +#undef isdigit +#define isdigit(c) _bcs_isdigit(c) + +#undef isalpha +#define isalpha(c) _bcs_isalpha(c) + +#undef isupper +#define isupper(c) _bcs_isupper(c) + +#include "_strtoul.h" diff --git a/lib/libc/iconv/citrus_csmapper.c b/lib/libc/iconv/citrus_csmapper.c new file mode 100644 index 0000000..5e0a01a --- /dev/null +++ b/lib/libc/iconv/citrus_csmapper.c @@ -0,0 +1,383 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_csmapper.c,v 1.10 2009/01/11 02:46:24 christos 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 <sys/cdefs.h> +#include <sys/endian.h> +#include <sys/types.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_lock.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" + +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, uint32_t *rval) +{ + + if (_region_size(r) != 4) + return (EFTYPE); + + memcpy(rval, _region_head(r), (size_t)4); + *rval = be32toh(*rval); + + return (0); +} + +static int +open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src) +{ + struct _region r; + int ret; + + 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) +{ + struct _citrus_db *db1, *db2, *db3; + struct _region fr, r1, r2; + char buf[LINE_MAX]; + uint32_t val32; + unsigned long norm; + int i, num, ret; + + 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; i < num; i++) { + /* iterate each pivot */ + ret = _db_get_entry(db2, i, &r1, &r2); + if (ret) + goto quit3; + /* r1:pivot name, r2:norm among src and pivot */ + ret = get32(&r2, &val32); + if (ret) + goto quit3; + norm = val32; + snprintf(buf, sizeof(buf), "%.*s", + (int)_region_size(&r1), (char *)_region_head(&r1)); + /* buf: pivot name */ + ret = open_subdb(&db3, db1, buf); + if (ret) + goto quit3; + if (_db_lookup_by_s(db3, dst, &r2, NULL) != 0) + goto quit4; + /* r2: norm among pivot and dst */ + ret = get32(&r2, &val32); + if (ret) + goto quit4; + norm += val32; + /* judge minimum norm */ + if (norm < *rnorm) { + *rnorm = norm; + strlcpy(pivot, buf, pvlen); + } +quit4: + _db_close(db3); + if (ret) + goto quit3; + } +quit3: + _db_close(db2); +quit2: + _db_close(db1); +quit1: + _unmap_file(&fr); + if (ret) + return (ret); + + if (*rnorm == ULONG_MAX) + return (ENOENT); + + return (0); +} + +/* ---------------------------------------------------------------------- */ + +struct zone { + const char *begin, *end; +}; + +struct parse_arg { + char dst[PATH_MAX]; + unsigned long norm; +}; + +static int +parse_line(struct parse_arg *pa, struct _region *r) +{ + struct zone z1, z2; + char buf[20]; + size_t len; + + len = _region_size(r); + z1.begin = _bcs_skip_ws_len(_region_head(r), &len); + if (len == 0) + return (EFTYPE); + z1.end = _bcs_skip_nonws_len(z1.begin, &len); + if (len == 0) + return (EFTYPE); + z2.begin = _bcs_skip_ws_len(z1.end, &len); + if (len == 0) + return (EFTYPE); + z2.end = _bcs_skip_nonws_len(z2.begin, &len); + + /* z1 : dst name, z2 : norm */ + snprintf(pa->dst, 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 = _bcs_strtoul(buf, NULL, 0); + + return (0); +} + +static int +find_dst(struct parse_arg *pasrc, const char *dst) +{ + struct _lookup *cl; + struct parse_arg padst; + struct _region data; + int ret; + + ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); + 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) +{ + struct _lookup *cl; + struct _region data; + struct parse_arg pa; + char pivot_min[PATH_MAX]; + unsigned long norm_min; + int ret; + + ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); + 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; + strlcpy(pivot_min, pa.dst, sizeof(pivot_min)); + } + 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; + + WLOCK; + 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: + UNLOCK; + return (ret); +} + +int +_citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm, + const char * __restrict src, const char * __restrict dst, uint32_t flags, + unsigned long *rnorm) +{ + const char *realsrc, *realdst; + char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX]; + unsigned long norm; + int ret; + + norm = 0; + + ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER); + if (ret) + return (ret); + + realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1), + _LOOKUP_CASE_IGNORE); + realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2), + _LOOKUP_CASE_IGNORE); + 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/iconv/citrus_csmapper.h b/lib/libc/iconv/citrus_csmapper.h new file mode 100644 index 0000000..dd178da --- /dev/null +++ b/lib/libc/iconv/citrus_csmapper.h @@ -0,0 +1,48 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_csmapper.h,v 1.2 2008/02/09 14:56:20 junyoung 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, uint32_t, + unsigned long *); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_db.c b/lib/libc/iconv/citrus_db.c new file mode 100644 index 0000000..2de848b --- /dev/null +++ b/lib/libc/iconv/citrus_db.c @@ -0,0 +1,331 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db.c,v 1.5 2008/02/09 14:56:20 junyoung 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 <sys/cdefs.h> +#include <sys/endian.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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_factory.h" +#include "citrus_db_file.h" + +struct _citrus_db { + struct _region db_region; + _citrus_db_hash_func_t db_hashfunc; + void *db_hashfunc_closure; +}; + +int +_citrus_db_open(struct _citrus_db **rdb, struct _region *r, const char *magic, + _citrus_db_hash_func_t hashfunc, void *hashfunc_closure) +{ + struct _citrus_db *db; + struct _citrus_db_header_x *dhx; + struct _memstream ms; + + _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) +{ + struct _citrus_db_entry_x *dex; + struct _citrus_db_header_x *dhx; + struct _citrus_region r; + struct _memstream ms; + uint32_t hashval, num_entries; + size_t offset; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*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(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; + + _region_init(&r, __DECONST(void *, key), strlen(key)); + + return (_citrus_db_lookup(db, &r, data, dl)); +} + +int +_citrus_db_lookup8_by_string(struct _citrus_db *db, const char *key, + uint8_t *rval, struct _citrus_db_locator *dl) +{ + struct _region r; + int ret; + + 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, + uint16_t *rval, struct _citrus_db_locator *dl) +{ + struct _region r; + int ret; + uint16_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, + uint32_t *rval, struct _citrus_db_locator *dl) +{ + struct _region r; + uint32_t val; + int ret; + + 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) +{ + struct _region r; + int ret; + + ret = _citrus_db_lookup_by_string(db, key, &r, dl); + if (ret) + return (ret); + + /* check whether the string is null terminated */ + if (_region_size(&r) == 0) + return (EFTYPE); + if (*((const char*)_region_head(&r)+_region_size(&r)-1) != '\0') + return (EFTYPE); + + if (rdata) + *rdata = _region_head(&r); + + return (0); +} + +int +_citrus_db_get_number_of_entries(struct _citrus_db *db) +{ + struct _citrus_db_header_x *dhx; + struct _memstream ms; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*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) +{ + struct _citrus_db_entry_x *dex; + struct _citrus_db_header_x *dhx; + struct _memstream ms; + uint32_t num_entries; + size_t offset; + + _memstream_bind(&ms, &db->db_region); + + dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx)); + num_entries = be32toh(dhx->dhx_num_entries); + if (idx < 0 || (uint32_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/iconv/citrus_db.h b/lib/libc/iconv/citrus_db.h new file mode 100644 index 0000000..27e16f3 --- /dev/null +++ b/lib/libc/iconv/citrus_db.h @@ -0,0 +1,70 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db.h,v 1.2 2008/02/09 14:56:20 junyoung 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_ + +#include "citrus_db_factory.h" + +struct _citrus_db; +struct _citrus_db_locator { + uint32_t dl_hashval; + size_t dl_offset; +}; + +__BEGIN_DECLS +int _citrus_db_open(struct _citrus_db **, struct _citrus_region *, + const char *, _citrus_db_hash_func_t, 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 *, + uint8_t *, struct _citrus_db_locator *); +int _citrus_db_lookup16_by_string(struct _citrus_db *, const char *, + uint16_t *, struct _citrus_db_locator *); +int _citrus_db_lookup32_by_string(struct _citrus_db *, const char *, + uint32_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/iconv/citrus_db_factory.c b/lib/libc/iconv/citrus_db_factory.c new file mode 100644 index 0000000..9a3edf2 --- /dev/null +++ b/lib/libc/iconv/citrus_db_factory.c @@ -0,0 +1,348 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db_factory.c,v 1.9 2008/02/09 14:56:20 junyoung 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 <sys/cdefs.h> +#include <sys/types.h> +#include <sys/queue.h> + +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_region.h" +#include "citrus_db_file.h" +#include "citrus_db_factory.h" + +struct _citrus_db_factory_entry { + STAILQ_ENTRY(_citrus_db_factory_entry) de_entry; + struct _citrus_db_factory_entry *de_next; + uint32_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; + STAILQ_HEAD(, _citrus_db_factory_entry) df_entries; + size_t df_total_key_size; + size_t df_total_data_size; + uint32_t (*df_hashfunc)(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; + STAILQ_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 = STAILQ_FIRST(&df->df_entries)) != NULL) { + STAILQ_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(key); + de->de_key = *key; + de->de_key_free = keyfree; + de->de_data = *data; + de->de_data_free = datafree; + de->de_idx = -1; + + STAILQ_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, uint8_t val) +{ + struct _region r; + uint8_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, uint16_t val) +{ + struct _region r; + uint16_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, uint32_t val) +{ + struct _region r; + uint32_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, uint8_t val) +{ + + *(uint8_t *)_region_offset(r, *rofs) = val; + *rofs += 1; +} + +static __inline void +put16(struct _region *r, size_t *rofs, uint16_t val) +{ + + val = htons(val); + memcpy(_region_offset(r, *rofs), &val, 2); + *rofs += 2; +} + +static __inline void +put32(struct _region *r, size_t *rofs, uint32_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) +{ + struct _citrus_db_factory_entry *de, **depp, *det; + size_t dataofs, i, keyofs, nextofs, ofs; + + 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; i < df->df_num_entries; i++) + depp[i] = NULL; + + /* step1: store the entries which are not conflicting */ + STAILQ_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; + STAILQ_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; i < df->df_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/iconv/citrus_db_factory.h b/lib/libc/iconv/citrus_db_factory.h new file mode 100644 index 0000000..b98b19c --- /dev/null +++ b/lib/libc/iconv/citrus_db_factory.h @@ -0,0 +1,57 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db_factory.h,v 1.3 2008/02/09 14:56:20 junyoung 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 uint32_t (*_citrus_db_hash_func_t)(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 *, uint8_t); +int _citrus_db_factory_add16_by_string(struct _citrus_db_factory *, + const char *, uint16_t); +int _citrus_db_factory_add32_by_string(struct _citrus_db_factory *, + const char *, uint32_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/iconv/citrus_db_file.h b/lib/libc/iconv/citrus_db_file.h new file mode 100644 index 0000000..aed07e8 --- /dev/null +++ b/lib/libc/iconv/citrus_db_file.h @@ -0,0 +1,85 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db_file.h,v 1.4 2008/02/10 05:58:22 junyoung 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]; + uint32_t dhx_num_entries; + uint32_t dhx_entry_offset; +} __packed; + +struct _citrus_db_entry_x { + uint32_t dex_hash_value; + uint32_t dex_next_offset; + uint32_t dex_key_offset; + uint32_t dex_key_size; + uint32_t dex_data_offset; + uint32_t dex_data_size; +} __packed; +#define _CITRUS_DB_ENTRY_SIZE 24 + +#endif diff --git a/lib/libc/iconv/citrus_db_hash.c b/lib/libc/iconv/citrus_db_hash.c new file mode 100644 index 0000000..2c599ff --- /dev/null +++ b/lib/libc/iconv/citrus_db_hash.c @@ -0,0 +1,64 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db_hash.c,v 1.5 2008/02/09 14:56:20 junyoung 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_db_hash.h" + +uint32_t +_citrus_db_hash_std(struct _region *r) +{ + const uint8_t *p; + uint32_t hash, tmp; + size_t i; + + hash = 0; + p = _region_head(r); + + 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/iconv/citrus_db_hash.h b/lib/libc/iconv/citrus_db_hash.h new file mode 100644 index 0000000..549af26 --- /dev/null +++ b/lib/libc/iconv/citrus_db_hash.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_db_hash.h,v 1.2 2008/02/09 14:56:20 junyoung 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 +uint32_t _citrus_db_hash_std(struct _citrus_region *); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c new file mode 100644 index 0000000..578cbc1 --- /dev/null +++ b/lib/libc/iconv/citrus_esdb.c @@ -0,0 +1,374 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <paths.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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, + _LOOKUP_CASE_IGNORE)); +} + + +/* + * conv_esdb: + * external representation -> local structure. + */ +static int +conv_esdb(struct _citrus_esdb *esdb, struct _region *fr) +{ + struct _citrus_db *db; + const char *str; + char buf[100]; + uint32_t csid, i, num_charsets, tmp, version; + int ret; + + /* 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; i < num_charsets; i++) { + snprintf(buf, sizeof(buf), + _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i); + ret = _db_lookup32_by_s(db, buf, &csid, NULL); + if (ret) + goto err4; + esdb->db_charsets[i].ec_csid = csid; + + snprintf(buf, sizeof(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) +{ + struct _region fr; + const char *realname, *encfile; + char buf1[PATH_MAX], buf2[PATH_MAX], path[PATH_MAX]; + int ret; + + snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_ALIAS); + realname = _lookup_alias(path, esname, buf1, sizeof(buf1), + _LOOKUP_CASE_IGNORE); + + snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_DIR); + encfile = _lookup_simple(path, realname, buf2, sizeof(buf2), + _LOOKUP_CASE_IGNORE); + 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) +{ + + for (int i = 0; i < db->db_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) +{ + + for (size_t i = 0; i < num; i++) + free(list[i]); + free(list); +} + +/* + * _citrus_esdb_get_list: + * get esdb entries. + */ +int +_citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted) +{ + struct _citrus_lookup *cla, *cld; + struct _region key, data; + char **list, **q; + char buf[PATH_MAX]; + size_t num; + int ret; + + num = 0; + + ret = _lookup_seq_open(&cla, _PATH_ESDB "/" ESDB_ALIAS, + _LOOKUP_CASE_IGNORE); + if (ret) + goto quit0; + + ret = _lookup_seq_open(&cld, _PATH_ESDB "/" ESDB_DIR, + _LOOKUP_CASE_IGNORE); + if (ret) + goto quit1; + + /* count number of entries */ + num = _lookup_get_num_entries(cla) + _lookup_get_num_entries(cld); + + _lookup_seq_rewind(cla); + _lookup_seq_rewind(cld); + + /* allocate list pointer space */ + list = malloc(num * sizeof(char *)); + num = 0; + if (list == NULL) { + ret = errno; + goto quit3; + } + + /* get alias entries */ + while ((ret = _lookup_seq_next(cla, &key, &data)) == 0) { + if (sorted) + snprintf(buf, sizeof(buf), "%.*s/%.*s", + (int)_region_size(&data), + (const char *)_region_head(&data), + (int)_region_size(&key), + (const char *)_region_head(&key)); + else + snprintf(buf, sizeof(buf), "%.*s/%.*s", + (int)_region_size(&data), + (const char *)_region_head(&data), + (int)_region_size(&key), + (const char *)_region_head(&key)); + _bcs_convert_to_upper(buf); + list[num] = strdup(buf); + if (list[num] == NULL) { + ret = errno; + goto quit3; + } + num++; + } + if (ret != ENOENT) + goto quit3; + /* get dir entries */ + while ((ret = _lookup_seq_next(cld, &key, &data)) == 0) { + if (!sorted) + snprintf(buf, sizeof(buf), "%.*s", + (int)_region_size(&key), + (const char *)_region_head(&key)); + else { + /* check duplicated entry */ + char *p; + char buf1[PATH_MAX]; + + snprintf(buf1, sizeof(buf1), "%.*s", + (int)_region_size(&data), + (const char *)_region_head(&data)); + if ((p = strchr(buf1, '/')) != NULL) + memcpy(buf1, p + 1, strlen(p) - 1); + if ((p = strstr(buf1, ".esdb")) != NULL) + *p = '\0'; + snprintf(buf, sizeof(buf), "%s/%.*s", buf1, + (int)_region_size(&key), + (const char *)_region_head(&key)); + } + _bcs_convert_to_upper(buf); + ret = _lookup_seq_lookup(cla, buf, NULL); + if (ret) { + if (ret != ENOENT) + goto quit3; + /* not duplicated */ + list[num] = strdup(buf); + if (list[num] == NULL) { + ret = errno; + goto quit3; + } + num++; + } + } + if (ret != ENOENT) + goto quit3; + + ret = 0; + /* XXX: why reallocing the list space posteriorly? + shouldn't be done earlier? */ + q = realloc(list, num * sizeof(char *)); + if (!q) { + ret = ENOMEM; + goto quit3; + } + list = q; + *rlist = list; + *rnum = num; +quit3: + if (ret) + _citrus_esdb_free_list(list, num); + _lookup_seq_close(cld); +quit1: + _lookup_seq_close(cla); +quit0: + return (ret); +} diff --git a/lib/libc/iconv/citrus_esdb.h b/lib/libc/iconv/citrus_esdb.h new file mode 100644 index 0000000..f82a398 --- /dev/null +++ b/lib/libc/iconv/citrus_esdb.h @@ -0,0 +1,58 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_esdb.h,v 1.1 2003/06/25 09:51:32 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_ESDB_H_ +#define _CITRUS_ESDB_H_ + +#include "citrus_types.h" + +struct _citrus_esdb_charset { + _citrus_csid_t ec_csid; + char *ec_csname; +}; + +struct _citrus_esdb { + char *db_encname; + void *db_variable; + size_t db_len_variable; + int db_num_charsets; + struct _citrus_esdb_charset *db_charsets; + int db_use_invalid; + _citrus_wc_t db_invalid; +}; + +__BEGIN_DECLS +const char *_citrus_esdb_alias(const char *, char *, size_t); +int _citrus_esdb_open(struct _citrus_esdb *, const char *); +void _citrus_esdb_close(struct _citrus_esdb *); +void _citrus_esdb_free_list(char **, size_t); +int _citrus_esdb_get_list(char ***, size_t *, bool); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_esdb_file.h b/lib/libc/iconv/citrus_esdb_file.h new file mode 100644 index 0000000..98609d1 --- /dev/null +++ b/lib/libc/iconv/citrus_esdb_file.h @@ -0,0 +1,45 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_esdb_file.h,v 1.1 2003/06/25 09:51:32 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_ESDB_FILE_H_ +#define _CITRUS_ESDB_FILE_H_ + +#define _CITRUS_ESDB_MAGIC "ESDB\0\0\0\0" + +#define _CITRUS_ESDB_SYM_VERSION "version" +#define _CITRUS_ESDB_SYM_ENCODING "encoding" +#define _CITRUS_ESDB_SYM_VARIABLE "variable" +#define _CITRUS_ESDB_SYM_NUM_CHARSETS "num_charsets" +#define _CITRUS_ESDB_SYM_INVALID "invalid" +#define _CITRUS_ESDB_SYM_CSNAME_PREFIX "csname_" +#define _CITRUS_ESDB_SYM_CSID_PREFIX "csid_" + +#define _CITRUS_ESDB_VERSION 0x00000001 + +#endif diff --git a/lib/libc/iconv/citrus_fix_grouping.h b/lib/libc/iconv/citrus_fix_grouping.h new file mode 100644 index 0000000..fbb1788 --- /dev/null +++ b/lib/libc/iconv/citrus_fix_grouping.h @@ -0,0 +1,53 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_fix_grouping.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c)2008 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_FIX_GROUPING_H_ +#define _CITRUS_FIX_GROUPING_H_ + +#define _CITRUS_LC_GROUPING_VALUE_MIN 0 +#define _CITRUS_LC_GROUPING_VALUE_MAX 126 +#define _CITRUS_LC_GROUPING_VALUE_NO_FUTHER 127 + +#if CHAR_MAX != _CITRUS_LC_GROUPING_VALUE_NO_FUTHER +static __inline void +_citrus_fixup_char_max_md(char *grouping) +{ + char *p; + + for (p = grouping; *p != '\0'; ++p) + if (*p == _CITRUS_LC_GROUPING_VALUE_NO_FUTHER) + *p = (char)CHAR_MAX; +} +#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) \ + _citrus_fixup_char_max_md(__DECONST(void *, grouping)) +#else +#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) /* nothing to do */ +#endif + +#endif /*_CITRUS_FIX_GROUPING_H_*/ diff --git a/lib/libc/iconv/citrus_hash.c b/lib/libc/iconv/citrus_hash.c new file mode 100644 index 0000000..4db1bda --- /dev/null +++ b/lib/libc/iconv/citrus_hash.c @@ -0,0 +1,51 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_hash.c,v 1.3 2008/02/09 14:56:20 junyoung 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#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; + + _region_init(&r, __DECONST(void *, key), strlen(key)); + + return ((int)(_db_hash_std(&r) % (uint32_t)hashsize)); +} diff --git a/lib/libc/iconv/citrus_hash.h b/lib/libc/iconv/citrus_hash.h new file mode 100644 index 0000000..c3e7311 --- /dev/null +++ b/lib/libc/iconv/citrus_hash.h @@ -0,0 +1,59 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_hash.h,v 1.3 2004/01/02 21:49:35 itojun 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) LIST_ENTRY(type) +#define _CITRUS_HASH_HEAD(headname, type, hashsize) \ +struct headname { \ + LIST_HEAD(, type) chh_table[hashsize]; \ +} +#define _CITRUS_HASH_INIT(head, hashsize) \ +do { \ + int _ch_loop; \ + \ + for (_ch_loop = 0; _ch_loop < hashsize; _ch_loop++) \ + LIST_INIT(&(head)->chh_table[_ch_loop]); \ +} while (0) +#define _CITRUS_HASH_REMOVE(elm, field) LIST_REMOVE(elm, field) +#define _CITRUS_HASH_INSERT(head, elm, field, hashval) \ + LIST_INSERT_HEAD(&(head)->chh_table[hashval], elm, field) +#define _CITRUS_HASH_SEARCH(head, elm, field, matchfunc, key, hashval) \ +do { \ + LIST_FOREACH((elm), &(head)->chh_table[hashval], field) \ + if (matchfunc((elm), key) == 0) \ + break; \ +} while (0) + +__BEGIN_DECLS +int _citrus_string_hash_func(const char *, int); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_iconv.c b/lib/libc/iconv/citrus_iconv.c new file mode 100644 index 0000000..941ee02 --- /dev/null +++ b/lib/libc/iconv/citrus_iconv.c @@ -0,0 +1,335 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv.c,v 1.7 2008/07/25 14:05:25 christos 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 <sys/cdefs.h> +#include <sys/types.h> +#include <sys/queue.h> + +#include <assert.h> +#include <dirent.h> +#include <errno.h> +#include <iconv.h> +#include <langinfo.h> +#include <limits.h> +#include <paths.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_esdb.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_lock.h" +#include "citrus_lookup.h" +#include "citrus_hash.h" +#include "citrus_iconv.h" + +#define _CITRUS_ICONV_DIR "iconv.dir" +#define _CITRUS_ICONV_ALIAS "iconv.alias" + +#define CI_HASH_SIZE 101 +#define CI_INITIAL_MAX_REUSE 5 +#define CI_ENV_MAX_REUSE "ICONV_MAX_REUSE" + +static bool isinit = false; +static int shared_max_reuse, shared_num_unused; +static _CITRUS_HASH_HEAD(, _citrus_iconv_shared, CI_HASH_SIZE) shared_pool; +static TAILQ_HEAD(, _citrus_iconv_shared) shared_unused; + +static __inline void +init_cache(void) +{ + + WLOCK; + if (!isinit) { + _CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE); + TAILQ_INIT(&shared_unused); + shared_max_reuse = -1; + if (!issetugid() && getenv(CI_ENV_MAX_REUSE)) + shared_max_reuse = atoi(getenv(CI_ENV_MAX_REUSE)); + if (shared_max_reuse < 0) + shared_max_reuse = CI_INITIAL_MAX_REUSE; + isinit = true; + } + UNLOCK; +} + +static __inline void +close_shared(struct _citrus_iconv_shared *ci) +{ + + if (ci) { + if (ci->ci_module) { + if (ci->ci_ops) { + if (ci->ci_closure) + (*ci->ci_ops->io_uninit_shared)(ci); + free(ci->ci_ops); + } + _citrus_unload_module(ci->ci_module); + } + free(ci); + } +} + +static __inline int +open_shared(struct _citrus_iconv_shared * __restrict * __restrict rci, + const char * __restrict convname, const char * __restrict src, + const char * __restrict dst) +{ + struct _citrus_iconv_shared *ci; + _citrus_iconv_getops_t getops; + const char *module; + size_t len_convname; + int ret; + + module = (strcmp(src, dst) != 0) ? "iconv_std" : "iconv_none"; + + /* initialize iconv handle */ + len_convname = strlen(convname); + ci = malloc(sizeof(*ci) + len_convname + 1); + if (!ci) { + ret = errno; + goto err; + } + ci->ci_module = NULL; + ci->ci_ops = NULL; + ci->ci_closure = NULL; + ci->ci_convname = (void *)&ci[1]; + memcpy(ci->ci_convname, convname, len_convname + 1); + + /* 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); + if (ret) + goto err; + + if (ci->ci_ops->io_init_shared == NULL || + ci->ci_ops->io_uninit_shared == NULL || + ci->ci_ops->io_init_context == NULL || + ci->ci_ops->io_uninit_context == NULL || + ci->ci_ops->io_convert == NULL) + goto err; + + /* initialize the converter */ + ret = (*ci->ci_ops->io_init_shared)(ci, src, dst); + if (ret) + goto err; + + *rci = ci; + + return (0); +err: + close_shared(ci); + return (ret); +} + +static __inline int +hash_func(const char *key) +{ + + return (_string_hash_func(key, CI_HASH_SIZE)); +} + +static __inline int +match_func(struct _citrus_iconv_shared * __restrict ci, + const char * __restrict key) +{ + + return (strcmp(ci->ci_convname, key)); +} + +static int +get_shared(struct _citrus_iconv_shared * __restrict * __restrict rci, + const char *src, const char *dst) +{ + struct _citrus_iconv_shared * ci; + char convname[PATH_MAX]; + int hashval, ret = 0; + + snprintf(convname, sizeof(convname), "%s/%s", src, dst); + + WLOCK; + + /* lookup alread existing entry */ + hashval = hash_func(convname); + _CITRUS_HASH_SEARCH(&shared_pool, ci, ci_hash_entry, match_func, + convname, hashval); + if (ci != NULL) { + /* found */ + if (ci->ci_used_count == 0) { + TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry); + shared_num_unused--; + } + ci->ci_used_count++; + *rci = ci; + goto quit; + } + + /* create new entry */ + ret = open_shared(&ci, convname, src, dst); + if (ret) + goto quit; + + _CITRUS_HASH_INSERT(&shared_pool, ci, ci_hash_entry, hashval); + ci->ci_used_count = 1; + *rci = ci; + +quit: + UNLOCK; + + return (ret); +} + +static void +release_shared(struct _citrus_iconv_shared * __restrict ci) +{ + + WLOCK; + ci->ci_used_count--; + if (ci->ci_used_count == 0) { + /* put it into unused list */ + shared_num_unused++; + TAILQ_INSERT_TAIL(&shared_unused, ci, ci_tailq_entry); + /* flood out */ + while (shared_num_unused > shared_max_reuse) { + ci = TAILQ_FIRST(&shared_unused); + TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry); + _CITRUS_HASH_REMOVE(ci, ci_hash_entry); + shared_num_unused--; + close_shared(ci); + } + } + + UNLOCK; +} + +/* + * _citrus_iconv_open: + * open a converter for the specified in/out codes. + */ +int +_citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rcv, + const char * __restrict src, const char * __restrict dst) +{ + struct _citrus_iconv *cv; + struct _citrus_iconv_shared *ci = NULL; + char realdst[PATH_MAX], realsrc[PATH_MAX]; + char buf[PATH_MAX], path[PATH_MAX]; + int ret; + + init_cache(); + + /* GNU behaviour, using locale encoding if "" or "char" is specified */ + if ((strcmp(src, "") == 0) || (strcmp(src, "char") == 0)) + src = nl_langinfo(CODESET); + if ((strcmp(dst, "") == 0) || (strcmp(dst, "char") == 0)) + dst = nl_langinfo(CODESET); + + /* resolve codeset name aliases */ + strlcpy(realsrc, _lookup_alias(path, src, buf, (size_t)PATH_MAX, + _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX); + strlcpy(realdst, _lookup_alias(path, dst, buf, (size_t)PATH_MAX, + _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX); + + /* sanity check */ + if (strchr(realsrc, '/') != NULL || strchr(realdst, '/')) + return (EINVAL); + + /* get shared record */ + ret = get_shared(&ci, realsrc, realdst); + if (ret) + return (ret); + + /* create/init context */ + if (*rcv == NULL) { + cv = malloc(sizeof(*cv)); + if (cv == NULL) { + ret = errno; + release_shared(ci); + return (ret); + } + *rcv = cv; + } + (*rcv)->cv_shared = ci; + ret = (*ci->ci_ops->io_init_context)(*rcv); + if (ret) { + release_shared(ci); + free(*rcv); + return (ret); + } + return (0); +} + +/* + * _citrus_iconv_close: + * close the specified converter. + */ +void +_citrus_iconv_close(struct _citrus_iconv *cv) +{ + + if (cv) { + (*cv->cv_shared->ci_ops->io_uninit_context)(cv); + release_shared(cv->cv_shared); + free(cv); + } +} + +const char +*_citrus_iconv_canonicalize(const char *name) +{ + char *buf; + + if ((buf = malloc((size_t)PATH_MAX)) == NULL) + return (NULL); + memset((void *)buf, 0, (size_t)PATH_MAX); + _citrus_esdb_alias(name, buf, (size_t)PATH_MAX); + return (buf); +} diff --git a/lib/libc/iconv/citrus_iconv.h b/lib/libc/iconv/citrus_iconv.h new file mode 100644 index 0000000..99604e9 --- /dev/null +++ b/lib/libc/iconv/citrus_iconv.h @@ -0,0 +1,64 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv.h,v 1.5 2008/02/09 14:56:20 junyoung 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_shared; +struct _citrus_iconv_ops; +struct _citrus_iconv; + +__BEGIN_DECLS +int _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict, + const char * __restrict, const char * __restrict); +void _citrus_iconv_close(struct _citrus_iconv *); +const char *_citrus_iconv_canonicalize(const char *); +__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 cv, + char * __restrict * __restrict in, size_t * __restrict inbytes, + char * __restrict * __restrict out, size_t * __restrict outbytes, + uint32_t flags, size_t * __restrict nresults) +{ + + return (*cv->cv_shared->ci_ops->io_convert)(cv, in, inbytes, out, + outbytes, flags, nresults); +} + +#endif diff --git a/lib/libc/iconv/citrus_iconv_local.h b/lib/libc/iconv/citrus_iconv_local.h new file mode 100644 index 0000000..db20363 --- /dev/null +++ b/lib/libc/iconv/citrus_iconv_local.h @@ -0,0 +1,107 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_local.h,v 1.3 2008/02/09 14:56:20 junyoung 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_ + +#include <iconv.h> + +#define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_) \ + int _n_(struct _citrus_iconv_ops *) +#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_shared \ + (struct _citrus_iconv_shared * __restrict, \ + const char * __restrict, const char * __restrict); \ +static void _citrus_##_m_##_iconv_uninit_shared \ + (struct _citrus_iconv_shared *); \ +static int _citrus_##_m_##_iconv_convert \ + (struct _citrus_iconv * __restrict, \ + char * __restrict * __restrict, \ + size_t * __restrict, \ + char * __restrict * __restrict, \ + size_t * __restrict outbytes, \ + uint32_t, size_t * __restrict); \ +static int _citrus_##_m_##_iconv_init_context \ + (struct _citrus_iconv *); \ +static void _citrus_##_m_##_iconv_uninit_context \ + (struct _citrus_iconv *) + + +#define _CITRUS_ICONV_DEF_OPS(_m_) \ +struct _citrus_iconv_ops _citrus_##_m_##_iconv_ops = { \ + /* io_init_shared */ &_citrus_##_m_##_iconv_init_shared, \ + /* io_uninit_shared */ &_citrus_##_m_##_iconv_uninit_shared, \ + /* io_init_context */ &_citrus_##_m_##_iconv_init_context, \ + /* io_uninit_context */ &_citrus_##_m_##_iconv_uninit_context, \ + /* io_convert */ &_citrus_##_m_##_iconv_convert \ +} + +typedef _CITRUS_ICONV_GETOPS_FUNC_BASE((*_citrus_iconv_getops_t)); +typedef int (*_citrus_iconv_init_shared_t) + (struct _citrus_iconv_shared * __restrict, + const char * __restrict, const char * __restrict); +typedef void (*_citrus_iconv_uninit_shared_t) + (struct _citrus_iconv_shared *); +typedef int (*_citrus_iconv_convert_t) + (struct _citrus_iconv * __restrict, + char *__restrict* __restrict, size_t * __restrict, + char * __restrict * __restrict, size_t * __restrict, uint32_t, + size_t * __restrict); +typedef int (*_citrus_iconv_init_context_t)(struct _citrus_iconv *); +typedef void (*_citrus_iconv_uninit_context_t)(struct _citrus_iconv *); + +struct _citrus_iconv_ops { + _citrus_iconv_init_shared_t io_init_shared; + _citrus_iconv_uninit_shared_t io_uninit_shared; + _citrus_iconv_init_context_t io_init_context; + _citrus_iconv_uninit_context_t io_uninit_context; + _citrus_iconv_convert_t io_convert; +}; + +struct _citrus_iconv_shared { + struct _citrus_iconv_ops *ci_ops; + void *ci_closure; + _CITRUS_HASH_ENTRY(_citrus_iconv_shared) ci_hash_entry; + TAILQ_ENTRY(_citrus_iconv_shared) ci_tailq_entry; + _citrus_module_t ci_module; + unsigned int ci_used_count; + char *ci_convname; + bool ci_discard_ilseq; + struct iconv_hooks *ci_hooks; +}; + +struct _citrus_iconv { + struct _citrus_iconv_shared *cv_shared; + void *cv_closure; +}; + +#endif diff --git a/lib/libc/iconv/citrus_lock.h b/lib/libc/iconv/citrus_lock.h new file mode 100644 index 0000000..ad9443a --- /dev/null +++ b/lib/libc/iconv/citrus_lock.h @@ -0,0 +1,35 @@ +/* $FreeBSD$ */ +/*- + * Copyright (C) 2010 Gabor Kovesdan <gabor@FreeBSD.org> + * 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 <pthread.h> + +static pthread_rwlock_t lock; + +#define WLOCK if (__isthreaded) \ + pthread_rwlock_wrlock(&lock); +#define UNLOCK if (__isthreaded) \ + pthread_rwlock_unlock(&lock); diff --git a/lib/libc/iconv/citrus_lookup.c b/lib/libc/iconv/citrus_lookup.c new file mode 100644 index 0000000..09b1298 --- /dev/null +++ b/lib/libc/iconv/citrus_lookup.c @@ -0,0 +1,362 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_lookup.c,v 1.6 2009/02/03 04:58:38 lukem 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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_ignore_case; + 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); + if (cl->cl_ignore_case) + _bcs_convert_to_lower(cl->cl_key); + cl->cl_keylen = strlen(cl->cl_key); + _db_locator_init(&cl->cl_dblocator); + return (_db_lookup_by_s(cl->cl_db, cl->cl_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) +{ + struct _region r; + char path[PATH_MAX]; + int ret; + + 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 && ((size_t)(q - p) != cl->cl_keylen || + memcmp(p, cl->cl_key, (size_t)(q - p)) != 0)) + goto retry; + + /* found a entry */ + if (key) + _region_init(key, __DECONST(void *, p), (size_t)(q - p)); + p = _bcs_skip_ws_len(q, &len); + if (data) + _region_init(data, len ? __DECONST(void *, 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; + free(cl->cl_key); + cl->cl_key = strdup(key); + if (cl->cl_ignore_case) + _bcs_convert_to_lower(cl->cl_key); + cl->cl_keylen = strlen(cl->cl_key); + _memstream_bind(&cl->cl_plainms, &cl->cl_plainr); + p = _memstream_matchline(&cl->cl_plainms, cl->cl_key, &len, 0); + if (p == NULL) + return (ENOENT); + if (data) + _region_init(data, __DECONST(void *, 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 ignore_case) +{ + int ret; + struct _citrus_lookup *cl; + + cl = malloc(sizeof(*cl)); + if (cl == NULL) + return (errno); + + cl->cl_key = NULL; + cl->cl_keylen = 0; + cl->cl_ignore_case = ignore_case; + 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); + free(cl); +} + +char * +_citrus_lookup_simple(const char *name, const char *key, + char *linebuf, size_t linebufsize, int ignore_case) +{ + struct _citrus_lookup *cl; + struct _region data; + int ret; + + ret = _citrus_lookup_seq_open(&cl, name, ignore_case); + 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/iconv/citrus_lookup.h b/lib/libc/iconv/citrus_lookup.h new file mode 100644 index 0000000..e7a7150 --- /dev/null +++ b/lib/libc/iconv/citrus_lookup.h @@ -0,0 +1,64 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_lookup.h,v 1.2 2004/07/21 14:16: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_LOOKUP_H_ +#define _CITRUS_LOOKUP_H_ + +#define _CITRUS_LOOKUP_CASE_SENSITIVE 0 +#define _CITRUS_LOOKUP_CASE_IGNORE 1 + +struct _citrus_lookup; +__BEGIN_DECLS +char *_citrus_lookup_simple(const char *, const char *, char *, + size_t, int); +int _citrus_lookup_seq_open(struct _citrus_lookup **, + const char *, int); +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, + int ignore_case) +{ + const char *ret; + + ret = _citrus_lookup_simple(path, key, buf, n, ignore_case); + if (ret == NULL) + ret = key; + + return (ret); +} + +#endif diff --git a/lib/libc/iconv/citrus_lookup_factory.c b/lib/libc/iconv/citrus_lookup_factory.c new file mode 100644 index 0000000..ec5a5d6 --- /dev/null +++ b/lib/libc/iconv/citrus_lookup_factory.c @@ -0,0 +1,121 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_lookup_factory.c,v 1.4 2003/10/27 00:12:42 lukem 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 <sys/cdefs.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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 data[LINE_MAX], key[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); + _bcs_convert_to_lower(key); + + /* 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) +{ + void *ptr; + size_t size; + + 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/iconv/citrus_lookup_factory.h b/lib/libc/iconv/citrus_lookup_factory.h new file mode 100644 index 0000000..9016de5 --- /dev/null +++ b/lib/libc/iconv/citrus_lookup_factory.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $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/iconv/citrus_lookup_file.h b/lib/libc/iconv/citrus_lookup_file.h new file mode 100644 index 0000000..43944b3 --- /dev/null +++ b/lib/libc/iconv/citrus_lookup_file.h @@ -0,0 +1,35 @@ +/* $FreeBSD$ */ +/* $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/iconv/citrus_mapper.c b/lib/libc/iconv/citrus_mapper.c new file mode 100644 index 0000000..a788a9d9 --- /dev/null +++ b/lib/libc/iconv/citrus_mapper.c @@ -0,0 +1,397 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos 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 <sys/cdefs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_region.h" +#include "citrus_lock.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 + +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 _citrus_mapper_area *ma; + struct stat st; + char path[PATH_MAX]; + int ret; + + WLOCK; + + if (*rma != NULL) { + ret = 0; + goto quit; + } + + snprintf(path, (size_t)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: + UNLOCK; + + 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; + const char *cp, *cq; + char *p; + char path[PATH_MAX]; + size_t len; + int ret; + + /* create mapper.dir path */ + snprintf(path, (size_t)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_close: + * simply close a mapper. (without handling hash) + */ +static void +mapper_close(struct _citrus_mapper *cm) +{ + 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_traits); + free(cm); +} + +/* + * mapper_open: + * simply open a mapper. (without handling hash) + */ +static int +mapper_open(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper * __restrict * __restrict rcm, + const char * __restrict module, + const char * __restrict variable) +{ + struct _citrus_mapper *cm; + _citrus_mapper_getops_t getops; + int ret; + + /* 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); + 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: + 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) +{ + struct _citrus_mapper *cm; + char linebuf[PATH_MAX]; + const char *module, *variable; + int hashval, ret; + + variable = NULL; + + WLOCK; + + /* 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, + (size_t)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; + _mapper_close(cm); + goto quit; + } + + /* insert to the cache */ + cm->cm_refcount = 1; + _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval); + + *rcm = cm; + ret = 0; +quit: + UNLOCK; + + return (ret); +} + +/* + * _citrus_mapper_close: + * close the specified mapper. + */ +void +_citrus_mapper_close(struct _citrus_mapper *cm) +{ + + if (cm) { + WLOCK; + if (cm->cm_refcount == REFCOUNT_PERSISTENT) + goto quit; + if (cm->cm_refcount > 0) { + if (--cm->cm_refcount > 0) + goto quit; + _CITRUS_HASH_REMOVE(cm, cm_entry); + free(cm->cm_key); + } + mapper_close(cm); +quit: + UNLOCK; + } +} + +/* + * _citrus_mapper_set_persistent: + * set persistent count. + */ +void +_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm) +{ + + WLOCK; + cm->cm_refcount = REFCOUNT_PERSISTENT; + UNLOCK; +} diff --git a/lib/libc/iconv/citrus_mapper.h b/lib/libc/iconv/citrus_mapper.h new file mode 100644 index 0000000..429b2a1 --- /dev/null +++ b/lib/libc/iconv/citrus_mapper.h @@ -0,0 +1,131 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper.h,v 1.3 2003/07/12 15:39:19 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_NONIDENTICAL (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) +{ + + 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) +{ + + (*cm->cm_ops->mo_init_state)(); +} + +/* + * _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) +{ + + 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) +{ + + 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) +{ + + return (cm->cm_traits->mt_dst_max); +} + +#endif diff --git a/lib/libc/iconv/citrus_mapper_local.h b/lib/libc/iconv/citrus_mapper_local.h new file mode 100644 index 0000000..887a35d --- /dev/null +++ b/lib/libc/iconv/citrus_mapper_local.h @@ -0,0 +1,96 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_local.h,v 1.2 2008/02/09 14:56:20 junyoung 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 *) +#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 \ + (void); + +#define _CITRUS_MAPPER_DEF_OPS(_m_) \ +struct _citrus_mapper_ops _citrus_##_m_##_mapper_ops = { \ + /* 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)(void); + +struct _citrus_mapper_ops { + _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/iconv/citrus_memstream.c b/lib/libc/iconv/citrus_memstream.c new file mode 100644 index 0000000..d7ad4fd --- /dev/null +++ b/lib/libc/iconv/citrus_memstream.c @@ -0,0 +1,148 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_memstream.c,v 1.4 2009/02/03 05:02:12 lukem 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 <sys/cdefs.h> + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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) +{ + const uint8_t *h, *p; + size_t ret; + int i; + + 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 keylen, len; + + keylen = strlen(key); + for(;;) { + 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 ((size_t)(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 *chr, *head; + 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/iconv/citrus_memstream.h b/lib/libc/iconv/citrus_memstream.h new file mode 100644 index 0000000..cd5ef13 --- /dev/null +++ b/lib/libc/iconv/citrus_memstream.h @@ -0,0 +1,226 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_memstream.h,v 1.3 2005/05/14 17:55:42 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_bind_ptr(struct _citrus_memory_stream * __restrict ms, + void *ptr, size_t sz) +{ + struct _citrus_region r; + + _citrus_region_init(&r, ptr, sz); + _citrus_memory_stream_bind(ms, &r); +} + +static __inline void +_citrus_memory_stream_rewind(struct _citrus_memory_stream *ms) +{ + + ms->ms_pos = 0; +} + +static __inline size_t +_citrus_memory_stream_tell(struct _citrus_memory_stream *ms) +{ + + return (ms->ms_pos); +} + +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) +{ + size_t 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 += (ssize_t)ms->ms_pos; + if (pos >= sz) + return (-1); + ms->ms_pos = pos; + break; + case SEEK_END: + if (sz < pos) + return (-1); + ms->ms_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 void +_citrus_memory_stream_ungetc(struct _citrus_memory_stream *ms, int ch) +{ + + if (ch != EOF && ms->ms_pos > 0) + 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); +} + +static __inline int +_citrus_memory_stream_getln_region(struct _citrus_memory_stream *ms, + struct _citrus_region *r) +{ + const char *ptr; + size_t sz; + + ptr = _citrus_memory_stream_getln(ms, &sz); + if (ptr) + _citrus_region_init(r, __DECONST(void *, ptr), sz); + + return (ptr == NULL); +} + +#endif diff --git a/lib/libc/iconv/citrus_mmap.c b/lib/libc/iconv/citrus_mmap.c new file mode 100644 index 0000000..dd5d059 --- /dev/null +++ b/lib/libc/iconv/citrus_mmap.c @@ -0,0 +1,97 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft 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 <sys/cdefs.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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) +{ + struct stat st; + void *head; + int fd, ret; + + ret = 0; + + _region_init(r, NULL, 0); + + if ((fd = open(path, O_RDONLY)) == -1) + return (errno); + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + ret = errno; + goto error; + } + + if (fstat(fd, &st) == -1) { + ret = errno; + goto error; + } + if (!S_ISREG(st.st_mode)) { + ret = EOPNOTSUPP; + goto error; + } + + head = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE, + fd, (off_t)0); + if (head == MAP_FAILED) { + ret = errno; + goto error; + } + _region_init(r, head, (size_t)st.st_size); + +error: + (void)close(fd); + return (ret); +} + +void +_citrus_unmap_file(struct _citrus_region *r) +{ + + if (_region_head(r) != NULL) { + (void)munmap(_region_head(r), _region_size(r)); + _region_init(r, NULL, 0); + } +} diff --git a/lib/libc/iconv/citrus_mmap.h b/lib/libc/iconv/citrus_mmap.h new file mode 100644 index 0000000..590e7fb --- /dev/null +++ b/lib/libc/iconv/citrus_mmap.h @@ -0,0 +1,40 @@ +/* $FreeBSD$ */ +/* $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/iconv/citrus_module.c b/lib/libc/iconv/citrus_module.c new file mode 100644 index 0000000..aa96aba --- /dev/null +++ b/lib/libc/iconv/citrus_module.c @@ -0,0 +1,314 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_module.c,v 1.9 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c)1999, 2000, 2001, 2002 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. + */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Borman at Krystal Technologies. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <dirent.h> +#include <dlfcn.h> +#include <errno.h> +#include <limits.h> +#include <paths.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define I18NMODULE_MAJOR 4 + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_module.h" + +static int _getdewey(int[], char *); +static int _cmpndewey(int[], int, int[], int); +static const char *_findshlib(char *, int *, int *); + +static const char *_pathI18nModule = NULL; + +/* from libexec/ld.aout_so/shlib.c */ +#undef major +#undef minor +#define MAXDEWEY 3 /*ELF*/ + +static int +_getdewey(int dewey[], char *cp) +{ + int i, n; + + for (n = 0, i = 0; i < MAXDEWEY; i++) { + if (*cp == '\0') + break; + + if (*cp == '.') cp++; + if (*cp < '0' || '9' < *cp) + return (0); + + dewey[n++] = (int)_bcs_strtol(cp, &cp, 10); + } + + return (n); +} + +/* + * Compare two dewey arrays. + * Return -1 if `d1' represents a smaller value than `d2'. + * Return 1 if `d1' represents a greater value than `d2'. + * Return 0 if equal. + */ +static int +_cmpndewey(int d1[], int n1, int d2[], int n2) +{ + int i; + + for (i = 0; i < n1 && i < n2; i++) { + if (d1[i] < d2[i]) + return (-1); + if (d1[i] > d2[i]) + return (1); + } + + if (n1 == n2) + return (0); + + if (i == n1) + return (-1); + + if (i == n2) + return (1); + + /* cannot happen */ + return (0); +} + +static const char * +_findshlib(char *name, int *majorp, int *minorp) +{ + char *lname; + const char *search_dirs[1]; + static char path[PATH_MAX]; + int dewey[MAXDEWEY], tmp[MAXDEWEY]; + int i, len, major, minor, ndewey, n_search_dirs; + + n_search_dirs = 1; + major = *majorp; + minor = *minorp; + path[0] = '\0'; + search_dirs[0] = _pathI18nModule; + len = strlen(name); + lname = name; + + ndewey = 0; + + for (i = 0; i < n_search_dirs; i++) { + struct dirent *dp; + DIR *dd = opendir(search_dirs[i]); + int found_dot_a = 0, found_dot_so = 0; + + if (dd == NULL) + break; + + while ((dp = readdir(dd)) != NULL) { + int n; + + if (dp->d_namlen < len + 4) + continue; + if (strncmp(dp->d_name, lname, (size_t)len) != 0) + continue; + if (strncmp(dp->d_name+len, ".so.", 4) != 0) + continue; + + if ((n = _getdewey(tmp, dp->d_name+len+4)) == 0) + continue; + + if (major != -1 && found_dot_a) + found_dot_a = 0; + + /* XXX should verify the library is a.out/ELF? */ + + if (major == -1 && minor == -1) + goto compare_version; + else if (major != -1 && minor == -1) { + if (tmp[0] == major) + goto compare_version; + } else if (major != -1 && minor != -1) { + if (tmp[0] == major) { + if (n == 1 || tmp[1] >= minor) + goto compare_version; + } + } + + /* else, this file does not qualify */ + continue; + + compare_version: + if (_cmpndewey(tmp, n, dewey, ndewey) <= 0) + continue; + + /* We have a better version */ + found_dot_so = 1; + snprintf(path, sizeof(path), "%s/%s", search_dirs[i], + dp->d_name); + found_dot_a = 0; + bcopy(tmp, dewey, sizeof(dewey)); + ndewey = n; + *majorp = dewey[0]; + *minorp = dewey[1]; + } + closedir(dd); + + if (found_dot_a || found_dot_so) + /* + * There's a lib in this dir; take it. + */ + return (path[0] ? path : NULL); + } + + return (path[0] ? path : NULL); +} + +void * +_citrus_find_getops(_citrus_module_t handle, const char *modname, + const char *ifname) +{ + char name[PATH_MAX]; + void *p; + + snprintf(name, sizeof(name), "_citrus_%s_%s_getops", + modname, ifname); + p = dlsym((void *)handle, name); + return (p); +} + +int +_citrus_load_module(_citrus_module_t *rhandle, const char *encname) +{ + const char *p; + char path[PATH_MAX]; + void *handle; + int maj, min; + + if (_pathI18nModule == NULL) { + p = getenv("PATH_I18NMODULE"); + if (p != NULL && !issetugid()) { + _pathI18nModule = strdup(p); + if (_pathI18nModule == NULL) + return (ENOMEM); + } else + _pathI18nModule = _PATH_I18NMODULE; + } + + (void)snprintf(path, sizeof(path), "lib%s", encname); + maj = I18NMODULE_MAJOR; + min = -1; + p = _findshlib(path, &maj, &min); + if (!p) + return (EINVAL); + handle = dlopen(p, RTLD_LAZY); + if (!handle) { + printf("%s", dlerror()); + return (EINVAL); + } + + *rhandle = (_citrus_module_t)handle; + + return (0); +} + +void +_citrus_unload_module(_citrus_module_t handle) +{ + + if (handle) + dlclose((void *)handle); +} diff --git a/lib/libc/iconv/citrus_module.h b/lib/libc/iconv/citrus_module.h new file mode 100644 index 0000000..b004b87 --- /dev/null +++ b/lib/libc/iconv/citrus_module.h @@ -0,0 +1,54 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_module.h,v 1.1 2002/03/17 22:14:20 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 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_MODULE_H_ +#define _CITRUS_MODULE_H_ + +#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 (0) + +typedef struct _citrus_module_rec *_citrus_module_t; + +__BEGIN_DECLS +void *_citrus_find_getops(_citrus_module_t __restrict, + const char * __restrict, const char * __restrict); +int _citrus_load_module(_citrus_module_t * __restrict, + const char * __restrict); +void _citrus_unload_module(_citrus_module_t); +__END_DECLS + +#endif diff --git a/lib/libc/iconv/citrus_namespace.h b/lib/libc/iconv/citrus_namespace.h new file mode 100644 index 0000000..6e9ffe0 --- /dev/null +++ b/lib/libc/iconv/citrus_namespace.h @@ -0,0 +1,241 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_namespace.h,v 1.8 2009/01/11 02:46:24 christos 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 "citrus_bcs.h" + +#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 +#define _bcs_strtol _citrus_bcs_strtol +#define _bcs_strtoul _citrus_bcs_strtoul +#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_CASE_SENSITIVE _CITRUS_LOOKUP_CASE_SENSITIVE +#define _LOOKUP_CASE_IGNORE _CITRUS_LOOKUP_CASE_IGNORE +#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_NONIDENTICAL _CITRUS_MAPPER_CONVERT_NONIDENTICAL +#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_bind_ptr _citrus_memory_stream_bind_ptr +#define _memstream_seek _citrus_memory_stream_seek +#define _memstream_rewind _citrus_memory_stream_rewind +#define _memstream_tell _citrus_memory_stream_tell +#define _memstream_remainder _citrus_memory_stream_remainder +#define _memstream_getc _citrus_memory_stream_getc +#define _memstream_ungetc _citrus_memory_stream_ungetc +#define _memstream_peek _citrus_memory_stream_peek +#define _memstream_getregion _citrus_memory_stream_getregion +#define _memstream_getln_region _citrus_memory_stream_getln_region +#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 +#define _region_get_subregion _citrus_region_get_subregion +#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_state_desc _citrus_stdenc_state_desc +#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_put_state_reset _citrus_stdenc_put_state_reset +#define _stdenc_get_state_size _citrus_stdenc_get_state_size +#define _stdenc_get_mb_cur_max _citrus_stdenc_get_mb_cur_max +#define _stdenc_get_state_desc _citrus_stdenc_get_state_desc +#define _STDENC_SDID_GENERIC _CITRUS_STDENC_SDID_GENERIC +#define _STDENC_SDGEN_UNKNOWN _CITRUS_STDENC_SDGEN_UNKNOWN +#define _STDENC_SDGEN_INITIAL _CITRUS_STDENC_SDGEN_INITIAL +#define _STDENC_SDGEN_STABLE _CITRUS_STDENC_SDGEN_STABLE +#define _STDENC_SDGEN_INCOMPLETE_CHAR _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR +#define _STDENC_SDGEN_INCOMPLETE_SHIFT _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT +#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/iconv/citrus_none.c b/lib/libc/iconv/citrus_none.c new file mode 100644 index 0000000..1f77ad0 --- /dev/null +++ b/lib/libc/iconv/citrus_none.c @@ -0,0 +1,238 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c) 2002 Citrus Project, + * Copyright (c) 2010 Gabor Kovesdan <gabor@FreeBSD.org>, + * 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 <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <iconv.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_none.h" +#include "citrus_stdenc.h" + +_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 +_citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce, + const void *var __unused, size_t lenvar __unused, + 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 +_citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused) +{ + +} + +static int +_citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused, + void * __restrict ps __unused) +{ + + return (0); +} + +static int +_citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused, + _csid_t *csid, _index_t *idx, char **s, size_t n, + void *ps __unused, size_t *nresult, struct iconv_hooks *hooks) +{ + + if (n < 1) { + *nresult = (size_t)-2; + return (0); + } + + *csid = 0; + *idx = (_index_t)(unsigned char)*(*s)++; + *nresult = *idx == 0 ? 0 : 1; + + if ((hooks != NULL) && (hooks->uc_hook != NULL)) + hooks->uc_hook((unsigned int)*idx, hooks->data); + + return (0); +} + +static int +_citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused, + char *s, size_t n, _csid_t csid, _index_t idx, void *ps __unused, + size_t *nresult, struct iconv_hooks *hooks __unused) +{ + + if (csid == _CITRUS_CSID_INVALID) { + *nresult = 0; + return (0); + } + if (csid != 0) + return (EILSEQ); + + if ((idx & 0x000000FF) == idx) { + if (n < 1) { + *nresult = (size_t)-1; + return (E2BIG); + } + *s = (char)idx; + *nresult = 1; + } else if ((idx & 0x0000FFFF) == idx) { + if (n < 2) { + *nresult = (size_t)-1; + return (E2BIG); + } + s[0] = (char)idx; + /* XXX: might be endian dependent */ + s[1] = (char)(idx >> 8); + *nresult = 2; + } else if ((idx & 0x00FFFFFF) == idx) { + if (n < 3) { + *nresult = (size_t)-1; + return (E2BIG); + } + s[0] = (char)idx; + /* XXX: might be endian dependent */ + s[1] = (char)(idx >> 8); + s[2] = (char)(idx >> 16); + *nresult = 3; + } else { + if (n < 3) { + *nresult = (size_t)-1; + return (E2BIG); + } + s[0] = (char)idx; + /* XXX: might be endian dependent */ + s[1] = (char)(idx >> 8); + s[2] = (char)(idx >> 16); + s[3] = (char)(idx >> 24); + *nresult = 4; + } + + return (0); +} + +static int +_citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused, + _wc_t * __restrict pwc, char ** __restrict s, size_t n, + void * __restrict pspriv __unused, size_t * __restrict nresult, + struct iconv_hooks *hooks) +{ + + 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; + + if ((hooks != NULL) && (hooks->wc_hook != NULL)) + hooks->wc_hook(*pwc, hooks->data); + + return (0); +} + +static int +_citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused, + char * __restrict s, size_t n, _wc_t wc, + void * __restrict pspriv __unused, size_t * __restrict nresult, + struct iconv_hooks *hooks __unused) +{ + int ret; + + if ((wc & ~0xFFU) != 0) { + *nresult = (size_t)-1; + return (EILSEQ); + } + if (n == 0) { + *nresult = (size_t)-1; + ret = E2BIG; + } + + *nresult = 1; + if (s != NULL && n > 0) + *s = (char)wc; + + return (0); +} + +static int +_citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused, + char * __restrict s __unused, size_t n __unused, + void * __restrict pspriv __unused, size_t * __restrict nresult) +{ + + *nresult = 0; + + return (0); +} + +static int +_citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused, + void * __restrict ps __unused, int id, + struct _stdenc_state_desc * __restrict d) +{ + int ret = 0; + + switch (id) { + case _STDENC_SDID_GENERIC: + d->u.generic.state = _STDENC_SDGEN_INITIAL; + break; + default: + ret = EOPNOTSUPP; + } + + return (ret); +} diff --git a/lib/libc/iconv/citrus_none.h b/lib/libc/iconv/citrus_none.h new file mode 100644 index 0000000..20d2791 --- /dev/null +++ b/lib/libc/iconv/citrus_none.h @@ -0,0 +1,36 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 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_NONE_H_ +#define _CITRUS_NONE_H_ + +extern struct _citrus_stdenc_ops _citrus_NONE_stdenc_ops; +extern struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits; + +#endif diff --git a/lib/libc/iconv/citrus_pivot_factory.c b/lib/libc/iconv/citrus_pivot_factory.c new file mode 100644 index 0000000..0f279b1 --- /dev/null +++ b/lib/libc/iconv/citrus_pivot_factory.c @@ -0,0 +1,225 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_pivot_factory.c,v 1.7 2009/04/12 14:20:19 lukem 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 <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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; + STAILQ_ENTRY(src_entry) se_entry; +}; +STAILQ_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; + + STAILQ_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); + } + STAILQ_INSERT_TAIL(sh, se, se_entry); + *rse = se; + + return (0); +} + +static void +free_src(struct src_head *sh) +{ + struct src_entry *se; + + while ((se = STAILQ_FIRST(sh)) != NULL) { + STAILQ_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) +{ + struct src_entry *se; + const char *p; + char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX]; + char *ep; + uint32_t val; + int ret; + + se = NULL; + + /* 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); + val = strtoul(data, &ep, 0); + if (*ep != '\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) +{ + struct _db_factory *df; + struct src_entry *se; + struct _region subr; + void *ptr; + size_t size; + int ret; + + ret = _db_factory_create(&df, &_db_hash_std, NULL); + if (ret) + return (ret); + + STAILQ_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; + + STAILQ_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/iconv/citrus_pivot_factory.h b/lib/libc/iconv/citrus_pivot_factory.h new file mode 100644 index 0000000..76f0f70 --- /dev/null +++ b/lib/libc/iconv/citrus_pivot_factory.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $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/iconv/citrus_pivot_file.h b/lib/libc/iconv/citrus_pivot_file.h new file mode 100644 index 0000000..454e93a --- /dev/null +++ b/lib/libc/iconv/citrus_pivot_file.h @@ -0,0 +1,36 @@ +/* $FreeBSD$ */ +/* $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/iconv/citrus_prop.c b/lib/libc/iconv/citrus_prop.c new file mode 100644 index 0000000..c2d4829 --- /dev/null +++ b/lib/libc/iconv/citrus_prop.c @@ -0,0 +1,444 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_prop.c,v 1.3 2006/11/22 23:47:21 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 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 <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_prop.h" + +typedef struct { + _citrus_prop_type_t type; + union { + const char *str; + int chr; + bool boolean; + uint64_t num; + } u; +} _citrus_prop_object_t; + +static __inline void +_citrus_prop_object_init(_citrus_prop_object_t *obj, _citrus_prop_type_t type) +{ + + obj->type = type; + memset(&obj->u, 0, sizeof(obj->u)); +} + +static __inline void +_citrus_prop_object_uninit(_citrus_prop_object_t *obj) +{ + + if (obj->type == _CITRUS_PROP_STR) + free(__DECONST(void *, obj->u.str)); +} + +static const char *xdigit = "0123456789ABCDEF"; + +#define _CITRUS_PROP_READ_UINT_COMMON(_func_, _type_, _max_) \ +static int \ +_citrus_prop_read_##_func_##_common(struct _memstream * __restrict ms, \ + _type_ * __restrict result, int base) \ +{ \ + _type_ acc, cutoff; \ + int ch, cutlim, n; \ + char *p; \ + \ + acc = (_type_)0; \ + cutoff = _max_ / base; \ + cutlim = _max_ % base; \ + for (;;) { \ + ch = _memstream_getc(ms); \ + p = strchr(xdigit, _bcs_toupper(ch)); \ + if (p == NULL || (n = (p - xdigit)) >= base) \ + break; \ + if (acc > cutoff || (acc == cutoff && n > cutlim)) \ + break; \ + acc *= base; \ + acc += n; \ + } \ + _memstream_ungetc(ms, ch); \ + *result = acc; \ + return (0); \ +} +_CITRUS_PROP_READ_UINT_COMMON(chr, int, UCHAR_MAX) +_CITRUS_PROP_READ_UINT_COMMON(num, uint64_t, UINT64_MAX) +#undef _CITRUS_PROP_READ_UINT_COMMON + +#define _CITRUS_PROP_READ_INT(_func_, _type_) \ +static int \ +_citrus_prop_read_##_func_(struct _memstream * __restrict ms, \ + _citrus_prop_object_t * __restrict obj) \ +{ \ + int base, ch, neg; \ + \ + _memstream_skip_ws(ms); \ + ch = _memstream_getc(ms); \ + neg = 0; \ + switch (ch) { \ + case '-': \ + neg = 1; \ + case '+': \ + ch = _memstream_getc(ms); \ + } \ + base = 10; \ + if (ch == '0') { \ + base -= 2; \ + ch = _memstream_getc(ms); \ + if (ch == 'x' || ch == 'X') { \ + ch = _memstream_getc(ms); \ + if (_bcs_isxdigit(ch) == 0) { \ + _memstream_ungetc(ms, ch); \ + obj->u._func_ = 0; \ + return (0); \ + } \ + base += 8; \ + } \ + } else if (_bcs_isdigit(ch) == 0) \ + return (EINVAL); \ + _memstream_ungetc(ms, ch); \ + return (_citrus_prop_read_##_func_##_common \ + (ms, &obj->u._func_, base)); \ +} +_CITRUS_PROP_READ_INT(chr, int) +_CITRUS_PROP_READ_INT(num, uint64_t) +#undef _CITRUS_PROP_READ_INT + +static int +_citrus_prop_read_character_common(struct _memstream * __restrict ms, + int * __restrict result) +{ + int base, ch; + + ch = _memstream_getc(ms); + if (ch != '\\') + *result = ch; + else { + ch = _memstream_getc(ms); + base = 16; + switch (ch) { + case 'a': + *result = '\a'; + break; + case 'b': + *result = '\b'; + break; + case 'f': + *result = '\f'; + break; + case 'n': + *result = '\n'; + break; + case 'r': + *result = '\r'; + break; + case 't': + *result = '\t'; + break; + case 'v': + *result = '\v'; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + _memstream_ungetc(ms, ch); + base -= 8; + /*FALLTHROUGH*/ + case 'x': + return (_citrus_prop_read_chr_common(ms, result, base)); + /*NOTREACHED*/ + default: + /* unknown escape */ + *result = ch; + } + } + return (0); +} + +static int +_citrus_prop_read_character(struct _memstream * __restrict ms, + _citrus_prop_object_t * __restrict obj) +{ + int ch, errnum; + + _memstream_skip_ws(ms); + ch = _memstream_getc(ms); + if (ch != '\'') { + _memstream_ungetc(ms, ch); + return (_citrus_prop_read_chr(ms, obj)); + } + errnum = _citrus_prop_read_character_common(ms, &ch); + if (errnum != 0) + return (errnum); + obj->u.chr = ch; + ch = _memstream_getc(ms); + if (ch != '\'') + return (EINVAL); + return (0); +} + +static int +_citrus_prop_read_bool(struct _memstream * __restrict ms, + _citrus_prop_object_t * __restrict obj) +{ + + _memstream_skip_ws(ms); + switch (_bcs_tolower(_memstream_getc(ms))) { + case 't': + if (_bcs_tolower(_memstream_getc(ms)) == 'r' && + _bcs_tolower(_memstream_getc(ms)) == 'u' && + _bcs_tolower(_memstream_getc(ms)) == 'e') { + obj->u.boolean = true; + return (0); + } + break; + case 'f': + if (_bcs_tolower(_memstream_getc(ms)) == 'a' && + _bcs_tolower(_memstream_getc(ms)) == 'l' && + _bcs_tolower(_memstream_getc(ms)) == 's' && + _bcs_tolower(_memstream_getc(ms)) == 'e') { + obj->u.boolean = false; + return (0); + } + } + return (EINVAL); +} + +static int +_citrus_prop_read_str(struct _memstream * __restrict ms, + _citrus_prop_object_t * __restrict obj) +{ + int ch, errnum, quot; + char *s, *t; +#define _CITRUS_PROP_STR_BUFSIZ 512 + size_t m, n; + + m = _CITRUS_PROP_STR_BUFSIZ; + s = malloc(m); + if (s == NULL) + return (ENOMEM); + n = 0; + _memstream_skip_ws(ms); + quot = _memstream_getc(ms); + switch (quot) { + case EOF: + goto done; + /*NOTREACHED*/ + case '\\': + _memstream_ungetc(ms, quot); + quot = EOF; + /*FALLTHROUGH*/ + case '\"': case '\'': + break; + default: + s[n] = quot; + ++n, --m; + quot = EOF; + } + for (;;) { + if (m < 1) { + m = _CITRUS_PROP_STR_BUFSIZ; + t = realloc(s, n + m); + if (t == NULL) { + free(s); + return (ENOMEM); + } + s = t; + } + ch = _memstream_getc(ms); + if (quot == ch || (quot == EOF && + (ch == ';' || _bcs_isspace(ch)))) { +done: + s[n] = '\0'; + obj->u.str = (const char *)s; + return (0); + } + _memstream_ungetc(ms, ch); + errnum = _citrus_prop_read_character_common(ms, &ch); + if (errnum != 0) + return (errnum); + s[n] = ch; + ++n, --m; + } + free(s); + return (EINVAL); +#undef _CITRUS_PROP_STR_BUFSIZ +} + +typedef int (*_citrus_prop_read_type_t)(struct _memstream * __restrict, + _citrus_prop_object_t * __restrict); + +static const _citrus_prop_read_type_t readers[] = { + _citrus_prop_read_bool, + _citrus_prop_read_str, + _citrus_prop_read_character, + _citrus_prop_read_num, +}; + +static __inline int +_citrus_prop_read_symbol(struct _memstream * __restrict ms, + char * __restrict s, size_t n) +{ + int ch; + size_t m; + + for (m = 0; m < n; ++m) { + ch = _memstream_getc(ms); + if (ch != '_' && _bcs_isalnum(ch) == 0) + goto name_found; + s[m] = ch; + } + ch = _memstream_getc(ms); + if (ch == '_' || _bcs_isalnum(ch) != 0) + return (EINVAL); + +name_found: + _memstream_ungetc(ms, ch); + s[m] = '\0'; + + return (0); +} + +static int +_citrus_prop_parse_element(struct _memstream * __restrict ms, + const _citrus_prop_hint_t * __restrict hints, void ** __restrict context) +{ + int ch, errnum; +#define _CITRUS_PROP_HINT_NAME_LEN_MAX 255 + char name[_CITRUS_PROP_HINT_NAME_LEN_MAX + 1]; + const _citrus_prop_hint_t *hint; + _citrus_prop_object_t ostart, oend; + + errnum = _citrus_prop_read_symbol(ms, name, sizeof(name)); + if (errnum != 0) + return (errnum); + for (hint = hints; hint->name != NULL; ++hint) + if (_citrus_bcs_strcasecmp(name, hint->name) == 0) + goto hint_found; + return (EINVAL); + +hint_found: + _memstream_skip_ws(ms); + ch = _memstream_getc(ms); + if (ch != '=' && ch != ':') + _memstream_ungetc(ms, ch); + do { + _citrus_prop_object_init(&ostart, hint->type); + _citrus_prop_object_init(&oend, hint->type); + errnum = (*readers[hint->type])(ms, &ostart); + if (errnum != 0) + return (errnum); + _memstream_skip_ws(ms); + ch = _memstream_getc(ms); + switch (hint->type) { + case _CITRUS_PROP_BOOL: + /*FALLTHROUGH*/ + case _CITRUS_PROP_STR: + break; + default: + if (ch != '-') + break; + errnum = (*readers[hint->type])(ms, &oend); + if (errnum != 0) + return (errnum); + _memstream_skip_ws(ms); + ch = _memstream_getc(ms); + } +#define CALL0(_func_) \ +do { \ + errnum = (*hint->cb._func_.func)(context, \ + hint->name, ostart.u._func_); \ +} while (0) +#define CALL1(_func_) \ +do { \ + errnum = (*hint->cb._func_.func)(context, \ + hint->name, ostart.u._func_, oend.u._func_);\ +} while (0) + switch (hint->type) { + case _CITRUS_PROP_BOOL: + CALL0(boolean); + break; + case _CITRUS_PROP_STR: + CALL0(str); + break; + case _CITRUS_PROP_CHR: + CALL1(chr); + break; + case _CITRUS_PROP_NUM: + CALL1(num); + break; + default: + abort(); + /*NOTREACHED*/ + } +#undef CALL0 +#undef CALL1 + _citrus_prop_object_uninit(&ostart); + _citrus_prop_object_uninit(&oend); + if (errnum != 0) + return (errnum); + } while (ch == ','); + if (ch != ';') + _memstream_ungetc(ms, ch); + return (0); +} + +int +_citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict hints, + void * __restrict context, const void *var, size_t lenvar) +{ + struct _memstream ms; + int ch, errnum; + + _memstream_bind_ptr(&ms, __DECONST(void *, var), lenvar); + for (;;) { + _memstream_skip_ws(&ms); + ch = _memstream_getc(&ms); + if (ch == EOF || ch == '\0') + break; + _memstream_ungetc(&ms, ch); + errnum = _citrus_prop_parse_element( + &ms, hints, (void ** __restrict)context); + if (errnum != 0) + return (errnum); + } + return (0); +} diff --git a/lib/libc/iconv/citrus_prop.h b/lib/libc/iconv/citrus_prop.h new file mode 100644 index 0000000..db087a4 --- /dev/null +++ b/lib/libc/iconv/citrus_prop.h @@ -0,0 +1,92 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_prop.h,v 1.3 2006/11/23 13:59:03 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 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_PROP_H_ +#define _CITRUS_PROP_H_ + +typedef enum { + _CITRUS_PROP_BOOL = 0, + _CITRUS_PROP_STR = 1, + _CITRUS_PROP_CHR = 2, + _CITRUS_PROP_NUM = 3, +} _citrus_prop_type_t; + +typedef struct _citrus_prop_hint_t _citrus_prop_hint_t; + +#define _CITRUS_PROP_CB0_T(_func_, _type_) \ +typedef int (*_citrus_prop_##_func_##_cb_func_t) \ + (void ** __restrict, const char *, _type_); \ +typedef struct { \ + _citrus_prop_##_func_##_cb_func_t func; \ +} _citrus_prop_##_func_##_cb_t; +_CITRUS_PROP_CB0_T(boolean, int) +_CITRUS_PROP_CB0_T(str, const char *) +#undef _CITRUS_PROP_CB0_T + +#define _CITRUS_PROP_CB1_T(_func_, _type_) \ +typedef int (*_citrus_prop_##_func_##_cb_func_t) \ + (void ** __restrict, const char *, _type_, _type_); \ +typedef struct { \ + _citrus_prop_##_func_##_cb_func_t func; \ +} _citrus_prop_##_func_##_cb_t; +_CITRUS_PROP_CB1_T(chr, int) +_CITRUS_PROP_CB1_T(num, uint64_t) +#undef _CITRUS_PROP_CB1_T + +struct _citrus_prop_hint_t { + const char *name; + _citrus_prop_type_t type; +#define _CITRUS_PROP_CB_T_OPS(_name_) \ + _citrus_prop_##_name_##_cb_t _name_ + union { + _CITRUS_PROP_CB_T_OPS(boolean); + _CITRUS_PROP_CB_T_OPS(str); + _CITRUS_PROP_CB_T_OPS(chr); + _CITRUS_PROP_CB_T_OPS(num); + } cb; +}; + +#define _CITRUS_PROP_HINT_BOOL(name, cb) \ + { name, _CITRUS_PROP_BOOL, { .boolean = { cb } } } +#define _CITRUS_PROP_HINT_STR(name, cb) \ + { name, _CITRUS_PROP_STR, { .str = { cb } } } +#define _CITRUS_PROP_HINT_CHR(name, cb) \ + { name, _CITRUS_PROP_CHR, { .chr = { cb } } } +#define _CITRUS_PROP_HINT_NUM(name, cb) \ + { name, _CITRUS_PROP_NUM, { .num = { cb } } } +#define _CITRUS_PROP_HINT_END \ + { NULL, _CITRUS_PROP_NUM, { .num = { 0 } } } + +__BEGIN_DECLS +int _citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict, + void * __restrict, const void *, size_t); +__END_DECLS + +#endif /* !_CITRUS_PROP_H_ */ diff --git a/lib/libc/iconv/citrus_region.h b/lib/libc/iconv/citrus_region.h new file mode 100644 index 0000000..8cecb40 --- /dev/null +++ b/lib/libc/iconv/citrus_region.h @@ -0,0 +1,113 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_region.h,v 1.7 2008/02/09 14:56:20 junyoung 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_ + +#include <sys/types.h> + +struct _citrus_region { + void *r_head; + size_t r_size; +}; + +static __inline void +_citrus_region_init(struct _citrus_region *r, void *h, size_t sz) +{ + + 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), (size_t)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), (size_t)4); + return (val); +} + +static __inline int +_citrus_region_get_subregion(struct _citrus_region *subr, + const struct _citrus_region *r, size_t ofs, size_t sz) +{ + + if (_citrus_region_check(r, ofs, sz)) + return (-1); + _citrus_region_init(subr, _citrus_region_offset(r, ofs), sz); + return (0); +} + +#endif diff --git a/lib/libc/iconv/citrus_stdenc.c b/lib/libc/iconv/citrus_stdenc.c new file mode 100644 index 0000000..b6562f8 --- /dev/null +++ b/lib/libc/iconv/citrus_stdenc.c @@ -0,0 +1,145 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 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 <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_none.h" +#include "citrus_stdenc.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 */ +}; + +int +_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce, + char const * __restrict encname, const void * __restrict variable, + size_t lenvar) +{ + struct _citrus_stdenc *ce; + _citrus_module_t handle; + _citrus_stdenc_getops_t getops; + int ret; + + 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)); + if (ret) + goto bad; + + /* 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 || + ce->ce_ops->eo_get_state_desc == 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) +{ + + 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); +} diff --git a/lib/libc/iconv/citrus_stdenc.h b/lib/libc/iconv/citrus_stdenc.h new file mode 100644 index 0000000..50f4dff --- /dev/null +++ b/lib/libc/iconv/citrus_stdenc.h @@ -0,0 +1,124 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_stdenc.h,v 1.4 2005/10/29 18:02:04 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; + +#define _CITRUS_STDENC_SDID_GENERIC 0 +struct _citrus_stdenc_state_desc +{ + union { + struct { + int state; +#define _CITRUS_STDENC_SDGEN_UNKNOWN 0 +#define _CITRUS_STDENC_SDGEN_INITIAL 1 +#define _CITRUS_STDENC_SDGEN_STABLE 2 +#define _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR 3 +#define _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT 4 + } generic; + } u; +}; + +#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) +{ + + 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, + char ** __restrict s, size_t n, void * __restrict ps, + size_t * __restrict nresult, struct iconv_hooks *hooks) +{ + + return ((*ce->ce_ops->eo_mbtocs)(ce, csid, idx, s, n, ps, nresult, + hooks)); +} + +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, + struct iconv_hooks *hooks) +{ + + return ((*ce->ce_ops->eo_cstomb)(ce, s, n, csid, idx, ps, nresult, + hooks)); +} + +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, struct iconv_hooks *hooks) +{ + + return ((*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult, hooks)); +} + +static __inline int +_citrus_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce, + char * __restrict s, size_t n, void * __restrict ps, + size_t * __restrict nresult) +{ + + return ((*ce->ce_ops->eo_put_state_reset)(ce, s, n, ps, nresult)); +} + +static __inline size_t +_citrus_stdenc_get_state_size(struct _citrus_stdenc *ce) +{ + + return (ce->ce_traits->et_state_size); +} + +static __inline int +_citrus_stdenc_get_state_desc(struct _citrus_stdenc * __restrict ce, + void * __restrict ps, int id, + struct _citrus_stdenc_state_desc * __restrict d) +{ + + return ((*ce->ce_ops->eo_get_state_desc)(ce, ps, id, d)); +} +#endif diff --git a/lib/libc/iconv/citrus_stdenc_local.h b/lib/libc/iconv/citrus_stdenc_local.h new file mode 100644 index 0000000..c55387a --- /dev/null +++ b/lib/libc/iconv/citrus_stdenc_local.h @@ -0,0 +1,161 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_stdenc_local.h,v 1.4 2008/02/09 14:56:20 junyoung 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_ + +#include <iconv.h> + +#include "citrus_module.h" + +#define _CITRUS_STDENC_GETOPS_FUNC_BASE(n) \ + int n(struct _citrus_stdenc_ops *, size_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, \ + char ** __restrict, size_t, \ + void * __restrict, size_t * __restrict, \ + struct iconv_hooks *); \ +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, struct iconv_hooks *); \ +static int _citrus_##_e_##_stdenc_mbtowc \ + (struct _citrus_stdenc * __restrict, \ + _citrus_wc_t * __restrict, \ + char ** __restrict, size_t, \ + void * __restrict, size_t * __restrict, \ + struct iconv_hooks *); \ +static int _citrus_##_e_##_stdenc_wctomb \ + (struct _citrus_stdenc * __restrict, \ + char * __restrict, size_t, _citrus_wc_t, \ + void * __restrict, size_t * __restrict, \ + struct iconv_hooks *); \ +static int _citrus_##_e_##_stdenc_put_state_reset \ + (struct _citrus_stdenc * __restrict, \ + char * __restrict, size_t, void * __restrict, \ + size_t * __restrict); \ +static int _citrus_##_e_##_stdenc_get_state_desc \ + (struct _citrus_stdenc * __restrict, \ + void * __restrict, int, \ + struct _citrus_stdenc_state_desc * __restrict) + +#define _CITRUS_STDENC_DEF_OPS(_e_) \ +struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \ + /* 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, \ + /* eo_put_state_reset */&_citrus_##_e_##_stdenc_put_state_reset,\ + /* eo_get_state_desc */ &_citrus_##_e_##_stdenc_get_state_desc \ +} + +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, + char ** __restrict, size_t, + void * __restrict, size_t * __restrict, + struct iconv_hooks *); +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, struct iconv_hooks *); +typedef int (*_citrus_stdenc_mbtowc_t) + (struct _citrus_stdenc * __restrict, + _citrus_wc_t * __restrict, + char ** __restrict, size_t, + void * __restrict, size_t * __restrict, + struct iconv_hooks *); +typedef int (*_citrus_stdenc_wctomb_t) + (struct _citrus_stdenc *__restrict, char * __restrict, size_t, + _citrus_wc_t, void * __restrict, size_t * __restrict, + struct iconv_hooks *); +typedef int (*_citrus_stdenc_put_state_reset_t) + (struct _citrus_stdenc *__restrict, char * __restrict, size_t, + void * __restrict, size_t * __restrict); +typedef int (*_citrus_stdenc_get_state_desc_t) + (struct _citrus_stdenc * __restrict, void * __restrict, int, + struct _citrus_stdenc_state_desc * __restrict); + +struct _citrus_stdenc_ops { + _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; + _citrus_stdenc_put_state_reset_t eo_put_state_reset; + /* version 0x00000002 */ + _citrus_stdenc_get_state_desc_t eo_get_state_desc; +}; + +struct _citrus_stdenc_traits { + /* version 0x00000001 */ + size_t et_state_size; + size_t et_mb_cur_max; +}; + +struct _citrus_stdenc { + /* version 0x00000001 */ + struct _citrus_stdenc_ops *ce_ops; + void *ce_closure; + _citrus_module_t ce_module; + struct _citrus_stdenc_traits *ce_traits; +}; + +#define _CITRUS_DEFAULT_STDENC_NAME "NONE" + +#endif diff --git a/lib/libc/iconv/citrus_stdenc_template.h b/lib/libc/iconv/citrus_stdenc_template.h new file mode 100644 index 0000000..9a05fa7 --- /dev/null +++ b/lib/libc/iconv/citrus_stdenc_template.h @@ -0,0 +1,211 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_stdenc_template.h,v 1.4 2008/02/09 14:56:20 junyoung 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 <iconv.h> + +/* + * 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 __unused) +{ + + memcpy(ops, &_FUNCNAME(stdenc_ops), sizeof(_FUNCNAME(stdenc_ops))); + + return (0); +} + +static int +_FUNCNAME(stdenc_init)(struct _citrus_stdenc * __restrict ce, + const void * __restrict var, size_t lenvar, + struct _citrus_stdenc_traits * __restrict et) +{ + _ENCODING_INFO *ei; + int ret; + + ei = NULL; + if (sizeof(_ENCODING_INFO) > 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, + char ** __restrict s, size_t n, void * __restrict ps, + size_t * __restrict nresult, struct iconv_hooks *hooks) +{ + wchar_t wc; + int ret; + + ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), &wc, s, n, + _TO_STATE(ps), nresult); + + if ((ret == 0) && *nresult != (size_t)-2) + ret = _FUNCNAME(stdenc_wctocs)(_CE_TO_EI(ce), csid, idx, wc); + + if ((ret == 0) && (hooks != NULL) && (hooks->uc_hook != NULL)) + hooks->uc_hook((unsigned int)*idx, hooks->data); + 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, + struct iconv_hooks *hooks __unused) +{ + wchar_t wc; + int ret; + + wc = ret = 0; + + if (csid != _CITRUS_CSID_INVALID) + ret = _FUNCNAME(stdenc_cstowc)(_CE_TO_EI(ce), &wc, csid, idx); + + if (ret == 0) + ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, + _TO_STATE(ps), nresult); + return (ret); +} + +static int +_FUNCNAME(stdenc_mbtowc)(struct _citrus_stdenc * __restrict ce, + _citrus_wc_t * __restrict wc, char ** __restrict s, size_t n, + void * __restrict ps, size_t * __restrict nresult, + struct iconv_hooks *hooks) +{ + int ret; + + ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), wc, s, n, + _TO_STATE(ps), nresult); + if ((ret == 0) && (hooks != NULL) && (hooks->wc_hook != NULL)) + hooks->wc_hook(*wc, hooks->data); + return (ret); +} + +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, struct iconv_hooks *hooks __unused) +{ + int ret; + + ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps), + nresult); + return (ret); +} + +static int +_FUNCNAME(stdenc_put_state_reset)(struct _citrus_stdenc * __restrict ce __unused, + char * __restrict s __unused, size_t n __unused, + void * __restrict ps __unused, size_t * __restrict nresult) +{ + +#if _ENCODING_IS_STATE_DEPENDENT + return ((_FUNCNAME(put_state_reset)(_CE_TO_EI(ce), s, n, _TO_STATE(ps), + nresult))); +#else + *nresult = 0; + return (0); +#endif +} + +static int +_FUNCNAME(stdenc_get_state_desc)(struct _citrus_stdenc * __restrict ce, + void * __restrict ps, int id, + struct _citrus_stdenc_state_desc * __restrict d) +{ + int ret; + + switch (id) { + case _STDENC_SDID_GENERIC: + ret = _FUNCNAME(stdenc_get_state_desc_generic)( + _CE_TO_EI(ce), _TO_STATE(ps), &d->u.generic.state); + break; + default: + ret = EOPNOTSUPP; + } + + return (ret); +} diff --git a/lib/libc/iconv/citrus_types.h b/lib/libc/iconv/citrus_types.h new file mode 100644 index 0000000..5f9c4e3 --- /dev/null +++ b/lib/libc/iconv/citrus_types.h @@ -0,0 +1,40 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_types.h,v 1.3 2003/10/27 00:12:42 lukem 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 <sys/types.h> + +#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/iconv/iconv.3 b/lib/libc/iconv/iconv.3 new file mode 100644 index 0000000..9b658e9 --- /dev/null +++ b/lib/libc/iconv/iconv.3 @@ -0,0 +1,305 @@ +.\" $FreeBSD$ +.\" $NetBSD: iconv.3,v 1.12 2004/08/02 13:38:21 tshiozak Exp $ +.\" +.\" Copyright (c) 2003 Citrus Project, +.\" Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>, +.\" 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. +.\" +.Dd Juny 16, 2010 +.Dt ICONV 3 +.Os +.Sh NAME +.Nm iconv_open , +.Nm iconv_open_into , +.Nm iconv_close , +.Nm iconv +.Nd codeset conversion functions +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In iconv.h +.Ft iconv_t +.Fn iconv_open "const char *dstname" "const char *srcname" +.Ft int +.Fn iconv_open_into "const char *dstname" "const char *srcname" "iconv_allocation_t *ptr" +.Ft int +.Fn iconv_close "iconv_t cd" +.Ft size_t +.Fn iconv "iconv_t cd" "char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" +.Ft size_t +.Fn __iconv "iconv_t cd" "const char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" "uint32_t flags" "size_t invalids" +.Sh DESCRIPTION +The +.Fn iconv_open +function opens a converter from the codeset +.Fa srcname +to the codeset +.Fa dstname +and returns its descriptor. +The arguments +.Fa srcname +and +.Fa dstname +accept "" and "char", which refer to the current locale encoding. +.Pp +The +.Fn iconv_open_into +creates a conversion descriptor on a preallocated space. +The +.Ft iconv_allocation_t +is used as a spaceholder type when allocating such space. +The +.Fa dstname +and +.Fa srcname +arguments are the same as in the case of +.Fn iconv_open . +The +.Fa ptr +argument is a pointer of +.Ft iconv_allocation_t +to the preallocated space. +.Pp +The +.Fn iconv_close +function closes the specified converter +.Fa cd . +.Pp +The +.Fn iconv +function converts the string in the buffer +.Fa *src +of length +.Fa *srcleft +bytes and stores the converted string in the buffer +.Fa *dst +of size +.Fa *dstleft +bytes. +After calling +.Fn iconv , +the values pointed to by +.Fa src , +.Fa srcleft , +.Fa dst , +and +.Fa dstleft +are updated as follows: +.Bl -tag -width 01234567 +.It *src +Pointer to the byte just after the last character fetched. +.It *srcleft +Number of remaining bytes in the source buffer. +.It *dst +Pointer to the byte just after the last character stored. +.It *dstleft +Number of remainder bytes in the destination buffer. +.El +.Pp +If the string pointed to by +.Fa *src +contains a byte sequence which is not a valid character in the source +codeset, the conversion stops just after the last successful conversion. +If the output buffer is too small to store the converted +character, the conversion also stops in the same way. +In these cases, the values pointed to by +.Fa src , +.Fa srcleft , +.Fa dst , +and +.Fa dstleft +are updated to the state just after the last successful conversion. +.Pp +If the string pointed to by +.Fa *src +contains a character which is valid under the source codeset but +can not be converted to the destination codeset, +the character is replaced by an +.Dq invalid character +which depends on the destination codeset, e.g., +.Sq \&? , +and the conversion is continued. +.Fn iconv +returns the number of such +.Dq invalid conversions . +.Pp +There are two special cases of +.Fn iconv : +.Bl -tag -width 0123 +.It "src == NULL || *src == NULL" +If the source and/or destination codesets are stateful, +.Fn iconv +places these into their initial state. +.Pp +If both +.Fa dst +and +.Fa *dst +are +.No non- Ns Dv NULL , +.Fn iconv +stores the shift sequence for the destination switching to the initial state +in the buffer pointed to by +.Fa *dst . +The buffer size is specified by the value pointed to by +.Fa dstleft +as above. +.Fn iconv +will fail if the buffer is too small to store the shift sequence. +.Pp +On the other hand, +.Fa dst +or +.Fa *dst +may be +.Dv NULL . +In this case, the shift sequence for the destination switching +to the initial state is discarded. +.Pp +.El +The +.Fn __iconv +function works just like +.Fn iconv +but if +.Fn iconv +fails, the invalid character count is lost there. +This is a not bug rather a limitation of +.St -p1003.1-2008 , +so +.Fn __iconv +is provided as an alternative but non-standard interface. +It also has a flags argument, where currently the following +flags can be passed: +.Bl -tag -width 0123 +.It __ICONV_F_HIDE_INVALID +Skip invalid characters, instead of returning with an error. +.El +.Sh RETURN VALUES +Upon successful completion of +.Fn iconv_open , +it returns a conversion descriptor. +Otherwise, +.Fn iconv_open +returns (iconv_t)\-1 and sets errno to indicate the error. +.Pp +Upon successful completion of +.Fn iconv_open_into , +it returns 0. +Otherwise, +.Fn iconv_open_into +returns \-1, and sets errno to indicate the error. +.Pp +Upon successful completion of +.Fn iconv_close , +it returns 0. +Otherwise, +.Fn iconv_close +returns \-1 and sets errno to indicate the error. +.Pp +Upon successful completion of +.Fn iconv , +it returns the number of +.Dq invalid +conversions. +Otherwise, +.Fn iconv +returns (size_t)\-1 and sets errno to indicate the error. +.Sh ERRORS +The +.Fn iconv_open +function may cause an error in the following cases: +.Bl -tag -width Er +.It Bq Er ENOMEM +Memory is exhausted. +.It Bq Er EINVAL +There is no converter specified by +.Fa srcname +and +.Fa dstname . +.El +The +.Fn iconv_open_into +function may cause an error in the following cases: +.Bl -tag -width Er +.It Bq Er EINVAL +There is no converter specified by +.Fa srcname +and +.Fa dstname . +.El +.Pp +The +.Fn iconv_close +function may cause an error in the following case: +.Bl -tag -width Er +.It Bq Er EBADF +The conversion descriptor specified by +.Fa cd +is invalid. +.El +.Pp +The +.Fn iconv +function may cause an error in the following cases: +.Bl -tag -width Er +.It Bq Er EBADF +The conversion descriptor specified by +.Fa cd +is invalid. +.It Bq Er EILSEQ +The string pointed to by +.Fa *src +contains a byte sequence which does not describe a valid character of +the source codeset. +.It Bq Er E2BIG +The output buffer pointed to by +.Fa *dst +is too small to store the result string. +.It Bq Er EINVAL +The string pointed to by +.Fa *src +terminates with an incomplete character or shift sequence. +.El +.Sh SEE ALSO +.Xr iconv 1 , +.Xr mkcsmapper 1 , +.Xr mkesdb 1 +.Sh STANDARDS +The +.Fn iconv_open , +.Fn iconv_close , +and +.Fn iconv +functions conform to +.St -p1003.1-2008 . +.Pp +The +.Fn iconv_open_into +function is a GNU-specific extension and it is not part of any standard, +thus its use may break portability. +The +.Fn __iconv +function is an own extension and it is not part of any standard, +thus its use may break portability. diff --git a/lib/libc/iconv/iconv.c b/lib/libc/iconv/iconv.c new file mode 100644 index 0000000..2cd38df --- /dev/null +++ b/lib/libc/iconv/iconv.c @@ -0,0 +1,332 @@ +/* $FreeBSD$ */ +/* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */ + +/*- + * Copyright (c) 2003 Citrus Project, + * Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>, + * 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 <sys/cdefs.h> +#include <sys/queue.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <iconv.h> +#include <limits.h> +#include <paths.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_esdb.h" +#include "citrus_hash.h" +#include "citrus_iconv.h" + +#ifdef __weak_alias +__weak_alias(libiconv, _iconv) +__weak_alias(libiconv_open, _iconv_open) +__weak_alias(libiconv_open_into, _iconv_open_into) +__weak_alias(libiconv_close, _iconv_close) +__weak_alias(libiconvlist, _iconvlist) +__weak_alias(libiconvctl, _iconvctl) +__weak_alias(libiconv_set_relocation_prefix, _iconv_set_relocation_prefix) +__weak_alias(iconv_canonicalize, _iconv_canonicalize) +#endif + +#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1) + +int _libiconv_version = _LIBICONV_VERSION; + +iconv_t _iconv_open(const char *out, const char *in, + struct _citrus_iconv *prealloc); + +iconv_t +_iconv_open(const char *out, const char *in, struct _citrus_iconv *prealloc) +{ + struct _citrus_iconv *handle; + char *out_truncated, *p; + int ret; + + handle = prealloc; + + /* + * Remove anything following a //, as these are options (like + * //ignore, //translate, etc) and we just don't handle them. + * This is for compatibilty with software that uses thees + * blindly. + */ + out_truncated = strdup(out); + if (out_truncated == NULL) { + errno = ENOMEM; + return ((iconv_t)-1); + } + + p = out_truncated; + while (*p != 0) { + if (p[0] == '/' && p[1] == '/') { + *p = '\0'; + break; + } + p++; + } + + ret = _citrus_iconv_open(&handle, in, out_truncated); + free(out_truncated); + if (ret) { + errno = ret == ENOENT ? EINVAL : ret; + return ((iconv_t)-1); + } + + handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE"); + handle->cv_shared->ci_hooks = NULL; + + return ((iconv_t)(void *)handle); +} + +iconv_t +libiconv_open(const char *out, const char *in) +{ + + return (_iconv_open(out, in, NULL)); +} + +int +libiconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr) +{ + struct _citrus_iconv *handle; + + handle = (struct _citrus_iconv *)ptr; + return ((_iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0); +} + +int +libiconv_close(iconv_t handle) +{ + + if (ISBADF(handle)) { + errno = EBADF; + return (-1); + } + + _citrus_iconv_close((struct _citrus_iconv *)(void *)handle); + + return (0); +} + +size_t +libiconv(iconv_t handle, char **in, size_t *szin, char **out, size_t *szout) +{ + size_t ret; + int err; + + if (ISBADF(handle)) { + errno = EBADF; + return ((size_t)-1); + } + + err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, + in, szin, out, szout, 0, &ret); + if (err) { + errno = err; + ret = (size_t)-1; + } + + return (ret); +} + +size_t +__iconv(iconv_t handle, char **in, size_t *szin, char **out, + size_t *szout, uint32_t flags, size_t *invalids) +{ + size_t ret; + int err; + + if (ISBADF(handle)) { + errno = EBADF; + return ((size_t)-1); + } + + err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle, + in, szin, out, szout, flags, &ret); + if (invalids) + *invalids = ret; + if (err) { + errno = err; + ret = (size_t)-1; + } + + return (ret); +} + +int +__iconv_get_list(char ***rlist, size_t *rsz, bool sorted) +{ + int ret; + + ret = _citrus_esdb_get_list(rlist, rsz, sorted); + if (ret) { + errno = ret; + return (-1); + } + + return (0); +} + +void +__iconv_free_list(char **list, size_t sz) +{ + + _citrus_esdb_free_list(list, sz); +} + +/* + * GNU-compatibile non-standard interfaces. + */ +static int +qsort_helper(const void *first, const void *second) +{ + const char * const *s1; + const char * const *s2; + + s1 = first; + s2 = second; + return (strcmp(*s1, *s2)); +} + +void +libiconvlist(int (*do_one) (unsigned int, const char * const *, + void *), void *data) +{ + char **list, **names; + const char * const *np; + char *curitem, *curkey, *slashpos; + size_t sz; + unsigned int i, j; + + i = 0; + + if (__iconv_get_list(&list, &sz, true)) + list = NULL; + qsort((void *)list, sz, sizeof(char *), qsort_helper); + while (i < sz) { + j = 0; + slashpos = strchr(list[i], '/'); + curkey = (char *)malloc(slashpos - list[i] + 2); + names = (char **)malloc(sz * sizeof(char *)); + if ((curkey == NULL) || (names == NULL)) { + __iconv_free_list(list, sz); + return; + } + strlcpy(curkey, list[i], slashpos - list[i] + 1); + names[j++] = strdup(curkey); + for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) { + slashpos = strchr(list[i], '/'); + curitem = (char *)malloc(strlen(slashpos) + 1); + if (curitem == NULL) { + __iconv_free_list(list, sz); + return; + } + strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1); + if (strcmp(curkey, curitem) == 0) { + continue; + } + names[j++] = strdup(curitem); + } + np = (const char * const *)names; + do_one(j, np, data); + free(names); + } + + __iconv_free_list(list, sz); +} + +__inline const char +*iconv_canonicalize(const char *name) +{ + + return (_citrus_iconv_canonicalize(name)); +} + +int +libiconvctl(iconv_t cd, int request, void *argument) +{ + struct _citrus_iconv *cv; + struct iconv_hooks *hooks; + const char *convname; + char src[PATH_MAX], *dst; + int *i; + + cv = (struct _citrus_iconv *)(void *)cd; + hooks = (struct iconv_hooks *)argument; + i = (int *)argument; + + if (ISBADF(cd)) { + errno = EBADF; + return (-1); + } + + switch (request) { + case ICONV_TRIVIALP: + convname = cv->cv_shared->ci_convname; + dst = strchr(convname, '/'); + + strlcpy(src, convname, dst - convname + 1); + dst++; + if ((convname == NULL) || (src == NULL) || (dst == NULL)) + return (-1); + *i = strcmp(src, dst) == 0 ? 1 : 0; + return (0); + case ICONV_GET_TRANSLITERATE: + *i = 1; + return (0); + case ICONV_SET_TRANSLITERATE: + return ((*i == 1) ? 0 : -1); + case ICONV_GET_DISCARD_ILSEQ: + *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0; + return (0); + case ICONV_SET_DISCARD_ILSEQ: + cv->cv_shared->ci_discard_ilseq = *i; + return (0); + case ICONV_SET_HOOKS: + cv->cv_shared->ci_hooks = hooks; + return (0); + case ICONV_SET_FALLBACKS: + errno = EOPNOTSUPP; + return (-1); + default: + errno = EINVAL; + return (-1); + } +} + +void +libiconv_set_relocation_prefix(const char *orig_prefix __unused, + const char *curr_prefix __unused) +{ + +} diff --git a/lib/libc/iconv/iconv_canonicalize.3 b/lib/libc/iconv/iconv_canonicalize.3 new file mode 100644 index 0000000..3c52ae2 --- /dev/null +++ b/lib/libc/iconv/iconv_canonicalize.3 @@ -0,0 +1,74 @@ +.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org> +.\" 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. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD$ +.\" +.Dd October 20, 2009 +.Dt ICONV_CANONICALIZE 3 +.Os +.Sh NAME +.Nm iconv_canonicalize +.Nd resolving character encoding names to canonical form +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In iconv.h +.Ft const char * +.Fn iconv_canonicalize "const char *name" +.Sh DESCRIPTION +The +.Fn iconv_canonicalize +function resolves the character encoding name specified by the +.Fa name +argument to its canonical form. +.Sh RETURN VALUES +Upon successful completion +.Fn iconv_canonicalize , +returns the canonical name of the given encoding. +If the specified name is already a canonical name, the same +value is returned. +If the specified name is not an existing character encoding +name, NULL is returned. +.Sh SEE ALSO +.Xr iconv 3 +.Sh STANDARDS +The +.Nm +function is a non-standard extension, which appeared in +the GNU implementation and was adopted in +.Fx 9 +for compatibility's sake. +.Sh AUTHORS +This manual page was written by +.An Gabor Kovesdan Aq gabor@FreeBSD.org . diff --git a/lib/libc/iconv/iconvctl.3 b/lib/libc/iconv/iconvctl.3 new file mode 100644 index 0000000..29007c1 --- /dev/null +++ b/lib/libc/iconv/iconvctl.3 @@ -0,0 +1,162 @@ +.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org> +.\" 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. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD$ +.\" +.Dd November 7, 2009 +.Dt ICONVCTL 3 +.Os +.Sh NAME +.Nm iconvctl +.Nd controlling and diagnostical facility for +.Xr iconv 3 +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In iconv.h +.Ft int +.Fn iconvctl "iconv_t cd" "int request" "void *argument" +.Sh DESCRIPTION +The +.Fn iconvctl +function can retrieve or set specific conversion +setting from the +.Fa cd +conversion descriptor. +The +.Fa request +parameter specifies the operation to accomplish and +.Fa argument +is an operation-specific argument. +.Pp +The possible operations are the following: +.Bl -tag -width -indent +.It ICONV_TRIVIALP +In this case +.Fa argument +is an +.Ft int * +variable, which is set to 1 if the encoding is trivial one, i.e. +the input and output encodings are the same. +Otherwise, the variable will be 0. +.It ICONV_GET_TRANSLITERATE +Determines if transliteration is enabled. +The answer is stored in +.Fa argument , +which is of +.Ft int * . +It will be set to 1 if this feature is enabled or set to 0 otherwise. +.It ICONV_SET_TRANSLITERATE +Enables transliteration if +.Fa argument , +which is of +.Ft int * +set to 1 or disables it if +.Fa argument +is set to 0. +.It ICONV_GET_DISCARD_ILSEQ +Determines if illegal sequences are discarded or not. +The answer is stored in +.Fa argument , +which is of +.Ft int * . +It will be set to 1 if this feature is enabled or set to 0 otherwise. +.It ICONV_SET_DISCARD_ILSEQ +Sets whether illegal sequences are discarded or not. +.Fa argument , +which is of +.Ft int * +set to 1 or disables it if +.Fa argument +is set to 0. +.It ICONV_SET_HOOKS +Sets callback functions, which will be called back after successful +conversions. +The callback functions are stored in a +.Ft struct iconv_hooks +variable, which is passed to +.Nm +via +.Fa argument +by its address. +.\" XXX: fallbacks are unimplemented and trying to set them will always +.\" return EOPNOTSUPP but definitions are provided for source-level +.\" compatibility. +.\".It ICONV_SET_FALLBACKS +.\"Sets callback functions, which will be called back after failed +.\"conversions. +.\"The callback functions are stored in a +.\".Ft struct iconv_fallbacks +.\"variable, which is passed to +.\".Nm +.\"via +.\".Fa argument +.\"by its address. +.Sh RETURN VALUES +Upon successful completion +.Fn iconvctl , +returns 0. +Otherwise, \-1 is returned and errno is set to +specify the kind of error. +.Sh ERRORS +The +.Fn iconvctl +function may cause an error in the following cases: +.Bl -tag -width Er +.It Bq Er EINVAL +Unknown or unimplemented operation. +.It Bq Er EBADF +The conversion descriptor specified by +.Fa cd +is invalid. +.Sh SEE ALSO +.Xr iconv 1 , +.Xr iconv 3 +.Sh STANDARDS +The +.Nm +facility is a non-standard extension, which appeared in +the GNU implementation and was adopted in +.Fx 9 +for compatibility's sake. +.Sh BUGS +Transliteration is enabled in this implementation by default, so it +is impossible by design to turn it off. +Accordingly, trying to turn it off will always fail and \-1 will be +returned. +Getting the transliteration state will always succeed and indicate +that it is turned on, though. +.Sh AUTHORS +This manual page was written by +.An Gabor Kovesdan Aq gabor@FreeBSD.org . diff --git a/lib/libc/iconv/iconvlist.3 b/lib/libc/iconv/iconvlist.3 new file mode 100644 index 0000000..e3fc43c --- /dev/null +++ b/lib/libc/iconv/iconvlist.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org> +.\" 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. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD$ +.\" +.Dd October 20, 2009 +.Dt ICONVLIST 3 +.Os +.Sh NAME +.Nm iconvlist +.Nd retrieving a list of character encodings supported by +.Xr iconv 3 +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In iconv.h +.Ft void +.Fo iconvlist "char ***names" "size_t count" "bool paired" +.Fa "int \*[lp]*do_one\*[rp]\*[lp]unsigned int *count, const char * const *names, void *arg\*[rp]" +.Fa "void *arg" +.Fc +.Sh DESCRIPTION +The +.Fn iconvlist +function obtains a list of character encodings that are supported by the +.Xr iconv 3 +call. +The +.Fn do_one +callback function will be called, where the +.Fa count +argument will be set to the number of the encoding names found, the +.Fa names +argument will be the list of the supported encoding names and the +.Fa arg +argument will be the \"outer\" +.Fa arg +argument of the +.Fn iconvlist +function. +This argument can be used to interchange custom data between the caller of +.Fn iconvlist +and the callback function. +.Pp +If an error occurs, +.Fa names +will be NULL when calling +.Fn do_one . +.Sh SEE ALSO +.Xr iconv 3 , +.Xr __iconv_get_list 3 , +.Xr __iconv_free_list 3 +.Sh STANDARDS +The +.Nm +function is a non-standard extension, which appeared in +the GNU implementation and was adopted in +.Fx 9 +for compatibility's sake. +.Sh AUTHORS +This manual page was written by +.An Gabor Kovesdan Aq gabor@FreeBSD.org . |