Add the BSD-licensed Citrus iconv to the base system with default off

setting. It can be built by setting the WITH_ICONV knob. While this
knob is unset, the library part, the binaries, the header file and
the metadata files will not be built or installed so it makes no impact
on the system if left turned off.

This work is based on the iconv implementation in NetBSD but a great
number of improvements and feature additions have been included:

- Some utilities have been added. There is a conversion table generator,
  which can compare conversion tables to reference data generated by
  GNU libiconv. This helps ensuring conversion compatibility.
- UTF-16 surrogate support and some endianness issues have been fixed.
- The rather chaotic Makefiles to build metadata have been refactored
  and cleaned up, now it is easy to read and it is also easier to add
  support for new encodings.
- A bunch of new encodings and encoding aliases have been added.
- Support for 1->2, 1->3 and 1->4 mappings, which is needed for
  transliterating with flying accents as GNU does, like "u.
- Lots of warnings have been fixed, the major part of the code is
  now WARNS=6 clean.
- New section 1 and section 5 manual pages have been added.
- Some GNU-specific calls have been implemented:
  iconvlist(), iconvctl(), iconv_canonicalize(), iconv_open_into()
- Support for GNU's //IGNORE suffix has been added.
- The "-" argument for stdin is now recognized in iconv(1) as per POSIX.
- The Big5 conversion module has been fixed.
- The iconv.h header files is supposed to be compatible with the
  GNU version, i.e. sources should build with base iconv.h and
  GNU libiconv. It also includes a macro magic to deal with the
  char ** and const char ** incompatibility.
- GNU compatibility: "" or "char" means the current local
  encoding in use
- Various cleanups and style(9) fixes.

Approved by:	delphij (mentor)
Obtained from:	The NetBSD Project
Sponsored by:	Google Summer of Code 2009
This commit is contained in:
Gabor Kovesdan 2011-02-25 00:04:39 +00:00
parent 95d068b14b
commit ad30f8e79b
1032 changed files with 2289190 additions and 9 deletions

View File

@ -452,7 +452,7 @@ build32:
@echo "--------------------------------------------------------------"
@echo ">>> stage 5.1: building 32 bit shim libraries"
@echo "--------------------------------------------------------------"
mkdir -p ${LIB32TMP}/usr/lib32
mkdir -p ${LIB32TMP}/usr/include
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${LIB32TMP}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
@ -496,13 +496,6 @@ build32:
.endfor
distribute32 install32:
.if make(distribute32)
mkdir -p ${DISTDIR}/${DISTRIBUTION}/usr/lib32 # XXX add to mtree
mkdir -p ${DISTDIR}/${DISTRIBUTION}/usr/lib32/dtrace # XXX add to mtree
.else
mkdir -p ${DESTDIR}/usr/lib32 # XXX add to mtree
mkdir -p ${DESTDIR}/usr/lib32/dtrace # XXX add to mtree
.endif
cd ${.CURDIR}/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
.if ${MK_CDDL} != "no"
cd ${.CURDIR}/cddl/lib; ${LIB32IMAKE} ${.TARGET:S/32$//}
@ -1048,7 +1041,9 @@ build-tools:
${_aicasm} \
usr.bin/awk \
lib/libmagic \
usr.sbin/sysinstall
usr.sbin/sysinstall \
usr.bin/mkesdb_static \
usr.bin/mkcsmapper_static
${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \

View File

@ -22,6 +22,14 @@
..
engines
..
i18n
..
..
lib32
dtrace
..
i18n
..
..
libdata
gcc
@ -311,6 +319,78 @@
..
..
info
..
i18n
csmapper
APPLE
..
AST
..
BIG5
..
CNS
..
CP
..
EBCDIC
..
GB
..
GEORGIAN
..
ISO-8859
..
ISO646
..
JIS
..
KAZAKH
..
KOI
..
KS
..
MISC
..
TCVN
..
..
esdb
APPLE
..
AST
..
BIG5
..
CP
..
DEC
..
EBCDIC
..
EUC
..
GB
..
GEORGIAN
..
ISO-2022
..
ISO-8859
..
ISO646
..
KAZAKH
..
KOI
..
MISC
..
TCVN
..
UTF
..
..
..
locale
UTF-8

View File

@ -68,6 +68,10 @@ _dev_ieee488= dev/ieee488
INCS+= hesiod.h
.endif
.if ${MK_ICONV} != "no"
INCS+= iconv.h
.endif
.if ${MK_BLUETOOTH} != "no"
LSUBSUBDIRS+= netgraph/bluetooth/include
.endif

138
include/iconv.h Normal file
View File

@ -0,0 +1,138 @@
/* $FreeBSD$ */
/* $NetBSD: iconv.h,v 1.6 2005/02/03 04:39:32 perry 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.
*
*/
#ifndef _ICONV_H_
#define _ICONV_H_
#include <sys/cdefs.h>
#include <sys/types.h>
#include <stdbool.h>
#include <wchar.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#define iconv_open libiconv_open
#define iconv_close libiconv_close
#define iconv(cd, in, insize, out, outsize) libiconv(cd, __DECONST(char **, in), insize, out, outsize)
#define iconv_t libiconv_t
struct __tag_iconv_t;
typedef struct __tag_iconv_t *iconv_t;
__BEGIN_DECLS
iconv_t libiconv_open(const char *, const char *);
size_t libiconv(iconv_t, char ** __restrict,
size_t * __restrict, char ** __restrict,
size_t * __restrict);
int libiconv_close(iconv_t);
/*
* non-portable interfaces for iconv
*/
int __iconv_get_list(char ***, size_t *, bool);
void __iconv_free_list(char **, size_t);
size_t __iconv(iconv_t, char **, size_t *, char **,
size_t *, __uint32_t, size_t *);
#define __ICONV_F_HIDE_INVALID 0x0001
/*
* GNU interfaces for iconv
*/
#define iconv_open_into libiconv_open_into
#define iconvctl libiconvctl
#define iconvlist libiconvlist
/* We have iconvctl() */
#define _LIBICONV_VERSION 0x0108
extern int _libiconv_version;
typedef struct {
void *spaceholder[64];
} iconv_allocation_t;
int iconv_open_into(const char *, const char *, iconv_allocation_t *);
void libiconv_set_relocation_prefix (const char *orig_prefix,
const char *curr_prefix);
/*
* iconvctl() request macros
*/
#define ICONV_TRIVIALP 0
#define ICONV_GET_TRANSLITERATE 1
#define ICONV_SET_TRANSLITERATE 2
#define ICONV_GET_DISCARD_ILSEQ 3
#define ICONV_SET_DISCARD_ILSEQ 4
#define ICONV_SET_HOOKS 5
#define ICONV_SET_FALLBACKS 6
typedef void (*iconv_unicode_char_hook) (unsigned int mbr, void *data);
typedef void (*iconv_wide_char_hook) (wchar_t wc, void *data);
struct iconv_hooks {
iconv_unicode_char_hook uc_hook;
iconv_wide_char_hook wc_hook;
void *data;
};
/*
* Fallbacks aren't supported but type definitions are provided for
* source compatibility.
*/
typedef void (*iconv_unicode_mb_to_uc_fallback) (const char*,
size_t, void (*write_replacement) (const unsigned int *,
size_t, void*), void*, void*);
typedef void (*iconv_unicode_uc_to_mb_fallback) (unsigned int,
void (*write_replacement) (const char *, size_t, void*),
void*, void*);
typedef void (*iconv_wchar_mb_to_wc_fallback) (const char*, size_t,
void (*write_replacement) (const wchar_t *, size_t, void*),
void*, void*);
typedef void (*iconv_wchar_wc_to_mb_fallback) (wchar_t,
void (*write_replacement) (const char *, size_t, void*),
void*, void*);
struct iconv_fallbacks {
iconv_unicode_mb_to_uc_fallback mb_to_uc_fallback;
iconv_unicode_uc_to_mb_fallback uc_to_mb_fallback;
iconv_wchar_mb_to_wc_fallback mb_to_wc_fallback;
iconv_wchar_wc_to_mb_fallback wc_to_mb_fallback;
void *data;
};
void iconvlist(int (*do_one) (unsigned int, const char * const *,
void *), void *);
const char *iconv_canonicalize(const char *);
int iconvctl(iconv_t, int, void *);
__END_DECLS
#endif /* !_ICONV_H_ */

View File

@ -49,14 +49,21 @@
#define _PATH_CONSOLE "/dev/console"
#define _PATH_CP "/bin/cp"
#define _PATH_CSHELL "/bin/csh"
#define _PATH_CSMAPPER "/usr/share/i18n/csmapper"
#define _PATH_DEFTAPE "/dev/sa0"
#define _PATH_DEVNULL "/dev/null"
#define _PATH_DEVZERO "/dev/zero"
#define _PATH_DRUM "/dev/drum"
#define _PATH_ESDB "/usr/share/i18n/esdb"
#define _PATH_ETC "/etc"
#define _PATH_FTPUSERS "/etc/ftpusers"
#define _PATH_FWMEM "/dev/fwmem"
#define _PATH_HALT "/sbin/halt"
#ifdef COMPAT_32BIT
#define _PATH_I18NMODULE "/usr/lib32/i18n"
#else
#define _PATH_I18NMODULE "/usr/lib/i18n"
#endif
#define _PATH_IFCONFIG "/sbin/ifconfig"
#define _PATH_KMEM "/dev/kmem"
#define _PATH_LIBMAP_CONF "/etc/libmap.conf"

View File

@ -37,6 +37,7 @@ SUBDIR_ORDERED= ${_csu} \
libcompiler_rt \
libcrypt \
libelf \
${_libiconv_modules} \
libkvm \
msun \
libmd \
@ -156,6 +157,10 @@ _libgssapi= libgssapi
_librpcsec_gss= librpcsec_gss
.endif
.if ${MK_ICONV} != "no"
_libiconv_modules= libiconv_modules
.endif
.if ${MK_IPX} != "no"
_libipx= libipx
.endif

View File

@ -57,6 +57,9 @@ NOASM=
.include "${.CURDIR}/gdtoa/Makefile.inc"
.include "${.CURDIR}/gen/Makefile.inc"
.include "${.CURDIR}/gmon/Makefile.inc"
.if ${MK_ICONV} != "no"
.include "${.CURDIR}/iconv/Makefile.inc"
.endif
.include "${.CURDIR}/inet/Makefile.inc"
.include "${.CURDIR}/isc/Makefile.inc"
.include "${.CURDIR}/locale/Makefile.inc"

View File

@ -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

101
lib/libc/iconv/Symbol.map Normal file
View File

@ -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;
};

View File

@ -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 .

167
lib/libc/iconv/_strtol.h Normal file
View File

@ -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);
}

126
lib/libc/iconv/_strtoul.h Normal file
View File

@ -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);
}

View File

@ -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_*/

168
lib/libc/iconv/citrus_bcs.c Normal file
View File

@ -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++;
}
}

102
lib/libc/iconv/citrus_bcs.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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);
}

View File

@ -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

331
lib/libc/iconv/citrus_db.c Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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_*/

View File

@ -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));
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

305
lib/libc/iconv/iconv.3 Normal file
View File

@ -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.

332
lib/libc/iconv/iconv.c Normal file
View File

@ -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)
{
}

View File

@ -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 .

162
lib/libc/iconv/iconvctl.3 Normal file
View File

@ -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 .

View File

@ -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 .

25
lib/libiconv/Makefile Normal file
View File

@ -0,0 +1,25 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libc/iconv
LIB= iconv
SHLIB_MAJOR= 4
MAN= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 \
__iconv_get_list.3
MLNKS= 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
WARNS?= 6
CFLAGS+= --param max-inline-insns-single=128 -I ${.CURDIR}/../../include -I${.CURDIR}/../libc/include
.include <bsd.lib.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= BIG5
SRCS+= citrus_big5.c
CFLAGS+= --param max-inline-insns-single=32
.include <bsd.lib.mk>

View File

@ -0,0 +1,457 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_big5.c,v 1.12 2008/06/14 16:01:07 tnozaki Exp $ */
/*-
* Copyright (c)2002, 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.
*/
/*-
* 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/queue.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_prop.h"
#include "citrus_types.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_big5.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
int chlen;
char ch[2];
} _BIG5State;
typedef struct _BIG5Exclude {
TAILQ_ENTRY(_BIG5Exclude) entry;
wint_t end;
wint_t start;
} _BIG5Exclude;
typedef TAILQ_HEAD(_BIG5ExcludeList, _BIG5Exclude) _BIG5ExcludeList;
typedef struct {
_BIG5ExcludeList excludes;
int cell[0x100];
} _BIG5EncodingInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_BIG5_##m
#define _ENCODING_INFO _BIG5EncodingInfo
#define _ENCODING_STATE _BIG5State
#define _ENCODING_MB_CUR_MAX(_ei_) 2
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline void
/*ARGSUSED*/
_citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei __unused,
_BIG5State * __restrict s)
{
memset(s, 0, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei __unused,
void * __restrict pspriv,
const _BIG5State * __restrict s)
{
memcpy(pspriv, (const void *)s, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei __unused,
_BIG5State * __restrict s,
const void * __restrict pspriv)
{
memcpy((void *)s, pspriv, sizeof(*s));
}
static __inline int
_citrus_BIG5_check(_BIG5EncodingInfo *ei, unsigned int c)
{
return ((ei->cell[c & 0xFF] & 0x1) ? 2 : 1);
}
static __inline int
_citrus_BIG5_check2(_BIG5EncodingInfo *ei, unsigned int c)
{
return ((ei->cell[c & 0xFF] & 0x2) ? 1 : 0);
}
static __inline int
_citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c)
{
_BIG5Exclude *exclude;
TAILQ_FOREACH(exclude, &ei->excludes, entry) {
if (c >= exclude->start && c <= exclude->end)
return (EILSEQ);
}
return (0);
}
static int
_citrus_BIG5_fill_rowcol(void ** __restrict ctx, const char * __restrict s,
uint64_t start, uint64_t end)
{
_BIG5EncodingInfo *ei;
uint64_t n;
int i;
if (start > 0xFF || end > 0xFF)
return (EINVAL);
ei = (_BIG5EncodingInfo *)ctx;
i = strcmp("row", s) ? 1 : 0;
i = 1 << i;
for (n = start; n <= end; ++n)
ei->cell[n & 0xFF] |= i;
return (0);
}
static int
/*ARGSUSED*/
_citrus_BIG5_fill_excludes(void ** __restrict ctx,
const char * __restrict s __unused, uint64_t start, uint64_t end)
{
_BIG5EncodingInfo *ei;
_BIG5Exclude *exclude;
if (start > 0xFFFF || end > 0xFFFF)
return (EINVAL);
ei = (_BIG5EncodingInfo *)ctx;
exclude = TAILQ_LAST(&ei->excludes, _BIG5ExcludeList);
if (exclude != NULL && (wint_t)start <= exclude->end)
return (EINVAL);
exclude = (void *)malloc(sizeof(*exclude));
if (exclude == NULL)
return (ENOMEM);
exclude->start = (wint_t)start;
exclude->end = (wint_t)end;
TAILQ_INSERT_TAIL(&ei->excludes, exclude, entry);
return (0);
}
static const _citrus_prop_hint_t root_hints[] = {
_CITRUS_PROP_HINT_NUM("row", &_citrus_BIG5_fill_rowcol),
_CITRUS_PROP_HINT_NUM("col", &_citrus_BIG5_fill_rowcol),
_CITRUS_PROP_HINT_NUM("excludes", &_citrus_BIG5_fill_excludes),
_CITRUS_PROP_HINT_END
};
static void
/*ARGSUSED*/
_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei)
{
_BIG5Exclude *exclude;
while ((exclude = TAILQ_FIRST(&ei->excludes)) != NULL) {
TAILQ_REMOVE(&ei->excludes, exclude, entry);
free(exclude);
}
}
static int
/*ARGSUSED*/
_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
const void * __restrict var, size_t lenvar)
{
void *ctx = (void *)ei;
const char *s;
int err;
memset((void *)ei, 0, sizeof(*ei));
TAILQ_INIT(&ei->excludes);
if (lenvar > 0 && var != NULL) {
s = _bcs_skip_ws_len((const char *)var, &lenvar);
if (lenvar > 0 && *s != '\0') {
err = _citrus_prop_parse_variable(
root_hints, (void *)ei, s, lenvar);
if (err == 0)
return (0);
_citrus_BIG5_encoding_module_uninit(ei);
memset((void *)ei, 0, sizeof(*ei));
TAILQ_INIT(&ei->excludes);
}
}
/* fallback Big5-1984, for backward compatibility. */
_citrus_BIG5_fill_rowcol((void **)&ctx, "row", 0xA1, 0xFE);
_citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0x40, 0x7E);
_citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0xA1, 0xFE);
return (0);
}
static int
/*ARGSUSED*/
_citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei,
wchar_t * __restrict pwc,
char ** __restrict s, size_t n,
_BIG5State * __restrict psenc,
size_t * __restrict nresult)
{
wchar_t wchar;
char *s0;
int c, chlenbak;
s0 = *s;
if (s0 == NULL) {
_citrus_BIG5_init_state(ei, psenc);
*nresult = 0;
return (0);
}
chlenbak = psenc->chlen;
/* make sure we have the first byte in the buffer */
switch (psenc->chlen) {
case 0:
if (n < 1)
goto restart;
psenc->ch[0] = *s0++;
psenc->chlen = 1;
n--;
break;
case 1:
break;
default:
/* illegal state */
goto ilseq;
}
c = _citrus_BIG5_check(ei, psenc->ch[0] & 0xff);
if (c == 0)
goto ilseq;
while (psenc->chlen < c) {
if (n < 1) {
goto restart;
}
psenc->ch[psenc->chlen] = *s0++;
psenc->chlen++;
n--;
}
switch (c) {
case 1:
wchar = psenc->ch[0] & 0xff;
break;
case 2:
if (!_citrus_BIG5_check2(ei, psenc->ch[1] & 0xff))
goto ilseq;
wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
break;
default:
/* illegal state */
goto ilseq;
}
if (_citrus_BIG5_check_excludes(ei, (wint_t)wchar) != 0)
goto ilseq;
*s = s0;
psenc->chlen = 0;
if (pwc)
*pwc = wchar;
*nresult = wchar ? c - chlenbak : 0;
return (0);
ilseq:
psenc->chlen = 0;
*nresult = (size_t)-1;
return (EILSEQ);
restart:
*s = s0;
*nresult = (size_t)-2;
return (0);
}
static int
/*ARGSUSED*/
_citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei,
char * __restrict s,
size_t n, wchar_t wc, _BIG5State * __restrict psenc __unused,
size_t * __restrict nresult)
{
unsigned char l;
int ret;
/* check invalid sequence */
if (wc & ~0xffff ||
_citrus_BIG5_check_excludes(ei, (wint_t)wc) != 0) {
ret = EILSEQ;
goto err;
}
if (wc & 0x8000) {
if (_citrus_BIG5_check(ei, (wc >> 8) & 0xff) != 2 ||
!_citrus_BIG5_check2(ei, wc & 0xff)) {
ret = EILSEQ;
goto err;
}
l = 2;
} else {
if (wc & ~0xff || !_citrus_BIG5_check(ei, wc & 0xff)) {
ret = EILSEQ;
goto err;
}
l = 1;
}
if (n < l) {
/* bound check failure */
ret = E2BIG;
goto err;
}
if (l == 2) {
s[0] = (wc >> 8) & 0xff;
s[1] = wc & 0xff;
} else
s[0] = wc & 0xff;
*nresult = l;
return (0);
err:
*nresult = (size_t)-1;
return (ret);
}
static __inline int
/*ARGSUSED*/
_citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid,
_index_t * __restrict idx, wchar_t wc)
{
*csid = (wc < 0x100) ? 0 : 1;
*idx = (_index_t)wc;
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei __unused,
wchar_t * __restrict wc,
_csid_t csid, _index_t idx)
{
switch (csid) {
case 0:
case 1:
*wc = (wchar_t)idx;
break;
default:
return (EILSEQ);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_BIG5_stdenc_get_state_desc_generic(_BIG5EncodingInfo * __restrict ei __unused,
_BIG5State * __restrict psenc,
int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(BIG5);
_CITRUS_STDENC_DEF_OPS(BIG5);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_big5.h,v 1.2 2003/06/25 09:51:41 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_BIG5_H_
#define _CITRUS_BIG5_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(BIG5);
__END_DECLS
#endif

View File

@ -0,0 +1,6 @@
# $FreeBSD$
SHLIB= DECHanyu
SRCS+= citrus_dechanyu.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,392 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_dechanyu.c,v 1.3 2008/06/14 16:01:07 tnozaki Exp $ */
/*-
* Copyright (c)2007 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_types.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_dechanyu.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
size_t chlen;
char ch[4];
} _DECHanyuState;
typedef struct {
int dummy;
} _DECHanyuEncodingInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.__CONCAT(s_,_func_)
#define _FUNCNAME(m) __CONCAT(_citrus_DECHanyu_,m)
#define _ENCODING_INFO _DECHanyuEncodingInfo
#define _ENCODING_STATE _DECHanyuState
#define _ENCODING_MB_CUR_MAX(_ei_) 4
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline void
/*ARGSUSED*/
_citrus_DECHanyu_init_state(_DECHanyuEncodingInfo * __restrict ei __unused,
_DECHanyuState * __restrict psenc)
{
psenc->chlen = 0;
}
static __inline void
/*ARGSUSED*/
_citrus_DECHanyu_pack_state(_DECHanyuEncodingInfo * __restrict ei __unused,
void * __restrict pspriv, const _DECHanyuState * __restrict psenc)
{
memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
}
static __inline void
/*ARGSUSED*/
_citrus_DECHanyu_unpack_state(_DECHanyuEncodingInfo * __restrict ei __unused,
_DECHanyuState * __restrict psenc,
const void * __restrict pspriv)
{
memcpy((void *)psenc, pspriv, sizeof(*psenc));
}
static void
/*ARGSUSED*/
_citrus_DECHanyu_encoding_module_uninit(_DECHanyuEncodingInfo *ei __unused)
{
/* ei may be null */
}
static int
/*ARGSUSED*/
_citrus_DECHanyu_encoding_module_init(_DECHanyuEncodingInfo * __restrict ei __unused,
const void * __restrict var __unused, size_t lenvar __unused)
{
/* ei may be null */
return (0);
}
static __inline bool
is_singlebyte(int c)
{
return (c <= 0x7F);
}
static __inline bool
is_leadbyte(int c)
{
return (c >= 0xA1 && c <= 0xFE);
}
static __inline bool
is_trailbyte(int c)
{
c &= ~0x80;
return (c >= 0x21 && c <= 0x7E);
}
static __inline bool
is_hanyu1(int c)
{
return (c == 0xC2);
}
static __inline bool
is_hanyu2(int c)
{
return (c == 0xCB);
}
#define HANYUBIT 0xC2CB0000
static __inline bool
is_94charset(int c)
{
return (c >= 0x21 && c <= 0x7E);
}
static int
/*ARGSUSED*/
_citrus_DECHanyu_mbrtowc_priv(_DECHanyuEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s, size_t n,
_DECHanyuState * __restrict psenc, size_t * __restrict nresult)
{
char *s0;
wchar_t wc;
int ch;
if (*s == NULL) {
_citrus_DECHanyu_init_state(ei, psenc);
*nresult = _ENCODING_IS_STATE_DEPENDENT;
return (0);
}
s0 = *s;
wc = (wchar_t)0;
switch (psenc->chlen) {
case 0:
if (n-- < 1)
goto restart;
ch = *s0++ & 0xFF;
if (is_singlebyte(ch)) {
if (pwc != NULL)
*pwc = (wchar_t)ch;
*nresult = (size_t)((ch == 0) ? 0 : 1);
*s = s0;
return (0);
}
if (!is_leadbyte(ch))
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
break;
case 1:
ch = psenc->ch[0] & 0xFF;
if (!is_leadbyte(ch))
return (EINVAL);
break;
case 2: case 3:
ch = psenc->ch[0] & 0xFF;
if (is_hanyu1(ch)) {
ch = psenc->ch[1] & 0xFF;
if (is_hanyu2(ch)) {
wc |= (wchar_t)HANYUBIT;
break;
}
}
/*FALLTHROUGH*/
default:
return (EINVAL);
}
switch (psenc->chlen) {
case 1:
if (is_hanyu1(ch)) {
if (n-- < 1)
goto restart;
ch = *s0++ & 0xFF;
if (!is_hanyu2(ch))
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
wc |= (wchar_t)HANYUBIT;
if (n-- < 1)
goto restart;
ch = *s0++ & 0xFF;
if (!is_leadbyte(ch))
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
}
break;
case 2:
if (n-- < 1)
goto restart;
ch = *s0++ & 0xFF;
if (!is_leadbyte(ch))
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
break;
case 3:
ch = psenc->ch[2] & 0xFF;
if (!is_leadbyte(ch))
return (EINVAL);
}
if (n-- < 1)
goto restart;
wc |= (wchar_t)(ch << 8);
ch = *s0++ & 0xFF;
if (!is_trailbyte(ch))
goto ilseq;
wc |= (wchar_t)ch;
if (pwc != NULL)
*pwc = wc;
*nresult = (size_t)(s0 - *s);
*s = s0;
psenc->chlen = 0;
return (0);
restart:
*nresult = (size_t)-2;
*s = s0;
return (0);
ilseq:
*nresult = (size_t)-1;
return (EILSEQ);
}
static int
/*ARGSUSED*/
_citrus_DECHanyu_wcrtomb_priv(_DECHanyuEncodingInfo * __restrict ei __unused,
char * __restrict s, size_t n, wchar_t wc,
_DECHanyuState * __restrict psenc, size_t * __restrict nresult)
{
int ch;
if (psenc->chlen != 0)
return (EINVAL);
/* XXX: assume wchar_t as int */
if ((uint32_t)wc <= 0x7F) {
ch = wc & 0xFF;
} else {
if ((uint32_t)wc > 0xFFFF) {
if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT)
goto ilseq;
psenc->ch[psenc->chlen++] = (wc >> 24) & 0xFF;
psenc->ch[psenc->chlen++] = (wc >> 16) & 0xFF;
wc &= 0xFFFF;
}
ch = (wc >> 8) & 0xFF;
if (!is_leadbyte(ch))
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
ch = wc & 0xFF;
if (!is_trailbyte(ch))
goto ilseq;
}
psenc->ch[psenc->chlen++] = ch;
if (n < psenc->chlen) {
*nresult = (size_t)-1;
return (E2BIG);
}
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
psenc->chlen = 0;
return (0);
ilseq:
*nresult = (size_t)-1;
return (EILSEQ);
}
static __inline int
/*ARGSUSED*/
_citrus_DECHanyu_stdenc_wctocs(_DECHanyuEncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
wchar_t mask;
int plane;
plane = 0;
mask = 0x7F;
/* XXX: assume wchar_t as int */
if ((uint32_t)wc > 0x7F) {
if ((uint32_t)wc > 0xFFFF) {
if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT)
return (EILSEQ);
plane += 2;
}
if (!is_leadbyte((wc >> 8) & 0xFF) ||
!is_trailbyte(wc & 0xFF))
return (EILSEQ);
plane += (wc & 0x80) ? 1 : 2;
mask |= 0x7F00;
}
*csid = plane;
*idx = (_index_t)(wc & mask);
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_DECHanyu_stdenc_cstowc(_DECHanyuEncodingInfo * __restrict ei __unused,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
if (csid == 0) {
if (idx > 0x7F)
return (EILSEQ);
} else if (csid <= 4) {
if (!is_94charset(idx >> 8))
return (EILSEQ);
if (!is_94charset(idx & 0xFF))
return (EILSEQ);
if (csid % 2)
idx |= 0x80;
idx |= 0x8000;
if (csid > 2)
idx |= HANYUBIT;
} else
return (EILSEQ);
*wc = (wchar_t)idx;
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_DECHanyu_stdenc_get_state_desc_generic(
_DECHanyuEncodingInfo * __restrict ei __unused,
_DECHanyuState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0)
? _STDENC_SDGEN_INITIAL
: _STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(DECHanyu);
_CITRUS_STDENC_DEF_OPS(DECHanyu);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_dechanyu.h,v 1.1 2007/04/01 18:52:32 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_DECHANYU_H_
#define _CITRUS_DECHANYU_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(DECHanyu);
__END_DECLS
#endif

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= EUC
SRCS+= citrus_euc.c
CFLAGS+= --param max-inline-insns-single=32
.include <bsd.lib.mk>

View File

@ -0,0 +1,385 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos 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.
*/
/*-
* 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 <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_bcs.h"
#include "citrus_types.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_euc.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
int chlen;
char ch[3];
} _EUCState;
typedef struct {
wchar_t bits[4];
wchar_t mask;
unsigned count[4];
unsigned mb_cur_max;
} _EUCEncodingInfo;
#define _SS2 0x008e
#define _SS3 0x008f
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_EUC_##m
#define _ENCODING_INFO _EUCEncodingInfo
#define _ENCODING_STATE _EUCState
#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline int
_citrus_EUC_cs(unsigned int c)
{
c &= 0xff;
return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
}
static __inline int
_citrus_EUC_parse_variable(_EUCEncodingInfo *ei, const void *var,
size_t lenvar __unused)
{
char *e;
const char *v;
int x;
/* parse variable string */
if (!var)
return (EFTYPE);
v = (const char *)var;
while (*v == ' ' || *v == '\t')
++v;
ei->mb_cur_max = 1;
for (x = 0; x < 4; ++x) {
ei->count[x] = (int)_bcs_strtol(v, (char **)&e, 0);
if (v == e || !(v = e) || ei->count[x] < 1 || ei->count[x] > 4) {
return (EFTYPE);
}
if (ei->mb_cur_max < ei->count[x])
ei->mb_cur_max = ei->count[x];
while (*v == ' ' || *v == '\t')
++v;
ei->bits[x] = (int)_bcs_strtol(v, (char **)&e, 0);
if (v == e || !(v = e)) {
return (EFTYPE);
}
while (*v == ' ' || *v == '\t')
++v;
}
ei->mask = (int)_bcs_strtol(v, (char **)&e, 0);
if (v == e || !(v = e)) {
return (EFTYPE);
}
return (0);
}
static __inline void
/*ARGSUSED*/
_citrus_EUC_init_state(_EUCEncodingInfo *ei __unused, _EUCState *s)
{
memset(s, 0, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_EUC_pack_state(_EUCEncodingInfo *ei __unused, void *pspriv,
const _EUCState *s)
{
memcpy(pspriv, (const void *)s, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_EUC_unpack_state(_EUCEncodingInfo *ei __unused, _EUCState *s,
const void *pspriv)
{
memcpy((void *)s, pspriv, sizeof(*s));
}
static int
_citrus_EUC_mbrtowc_priv(_EUCEncodingInfo *ei, wchar_t *pwc, char **s,
size_t n, _EUCState *psenc, size_t *nresult)
{
wchar_t wchar;
int c, chlenbak, cs, len;
char *s0, *s1 = NULL;
s0 = *s;
if (s0 == NULL) {
_citrus_EUC_init_state(ei, psenc);
*nresult = 0; /* state independent */
return (0);
}
chlenbak = psenc->chlen;
/* make sure we have the first byte in the buffer */
switch (psenc->chlen) {
case 0:
if (n < 1)
goto restart;
psenc->ch[0] = *s0++;
psenc->chlen = 1;
n--;
break;
case 1:
case 2:
break;
default:
/* illgeal state */
goto encoding_error;
}
c = ei->count[cs = _citrus_EUC_cs(psenc->ch[0] & 0xff)];
if (c == 0)
goto encoding_error;
while (psenc->chlen < c) {
if (n < 1)
goto restart;
psenc->ch[psenc->chlen] = *s0++;
psenc->chlen++;
n--;
}
*s = s0;
switch (cs) {
case 3:
case 2:
/* skip SS2/SS3 */
len = c - 1;
s1 = &psenc->ch[1];
break;
case 1:
case 0:
len = c;
s1 = &psenc->ch[0];
break;
default:
goto encoding_error;
}
wchar = 0;
while (len-- > 0)
wchar = (wchar << 8) | (*s1++ & 0xff);
wchar = (wchar & ~ei->mask) | ei->bits[cs];
psenc->chlen = 0;
if (pwc)
*pwc = wchar;
*nresult = wchar ? (size_t)(c - chlenbak) : 0;
return (0);
encoding_error:
psenc->chlen = 0;
*nresult = (size_t)-1;
return (EILSEQ);
restart:
*nresult = (size_t)-2;
*s = s0;
return (0);
}
static int
_citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc,
_EUCState *psenc __unused, size_t *nresult)
{
wchar_t m, nm;
unsigned int cs;
int ret;
short i;
m = wc & ei->mask;
nm = wc & ~m;
for (cs = 0; cs < sizeof(ei->count) / sizeof(ei->count[0]); cs++)
if (m == ei->bits[cs])
break;
/* fallback case - not sure if it is necessary */
if (cs == sizeof(ei->count) / sizeof(ei->count[0]))
cs = 1;
i = ei->count[cs];
if (n < (unsigned)i) {
ret = E2BIG;
goto err;
}
m = (cs) ? 0x80 : 0x00;
switch (cs) {
case 2:
*s++ = _SS2;
i--;
break;
case 3:
*s++ = _SS3;
i--;
break;
}
while (i-- > 0)
*s++ = ((nm >> (i << 3)) & 0xff) | m;
*nresult = (size_t)ei->count[cs];
return (0);
err:
*nresult = (size_t)-1;
return (ret);
}
static __inline int
/*ARGSUSED*/
_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * __restrict ei,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
wchar_t m, nm;
m = wc & ei->mask;
nm = wc & ~m;
*csid = (_citrus_csid_t)m;
*idx = (_citrus_index_t)nm;
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * __restrict ei,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0)
return (EINVAL);
*wc = (wchar_t)csid | (wchar_t)idx;
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_EUC_stdenc_get_state_desc_generic(_EUCEncodingInfo * __restrict ei __unused,
_EUCState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
static int
/*ARGSUSED*/
_citrus_EUC_encoding_module_init(_EUCEncodingInfo * __restrict ei,
const void * __restrict var, size_t lenvar)
{
return (_citrus_EUC_parse_variable(ei, var, lenvar));
}
static void
/*ARGSUSED*/
_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * __restrict ei __unused)
{
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(EUC);
_CITRUS_STDENC_DEF_OPS(EUC);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_euc.h,v 1.2 2003/06/25 09:51:42 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_EUC_H_
#define _CITRUS_EUC_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(EUC);
__END_DECLS
#endif

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= EUCTW
SRCS+= citrus_euctw.c
CFLAGS+= --param max-inline-insns-single=32
.include <bsd.lib.mk>

View File

@ -0,0 +1,377 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki 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.
*/
/*-
* Copyright (c)1999 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.
*
* $Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <limits.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_stdenc.h"
#include "citrus_euctw.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
int chlen;
char ch[4];
} _EUCTWState;
typedef struct {
int dummy;
} _EUCTWEncodingInfo;
#define _SS2 0x008e
#define _SS3 0x008f
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_EUCTW_##m
#define _ENCODING_INFO _EUCTWEncodingInfo
#define _ENCODING_STATE _EUCTWState
#define _ENCODING_MB_CUR_MAX(_ei_) 4
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline int
_citrus_EUCTW_cs(unsigned int c)
{
c &= 0xff;
return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0);
}
static __inline int
_citrus_EUCTW_count(int cs)
{
switch (cs) {
case 0:
/*FALLTHROUGH*/
case 1:
/*FALLTHROUGH*/
case 2:
return (2^cs);
case 3:
abort();
/*NOTREACHED*/
}
return (0);
}
static __inline void
/*ARGSUSED*/
_citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei __unused,
_EUCTWState * __restrict s)
{
memset(s, 0, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei __unused,
void * __restrict pspriv, const _EUCTWState * __restrict s)
{
memcpy(pspriv, (const void *)s, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei __unused,
_EUCTWState * __restrict s, const void * __restrict pspriv)
{
memcpy((void *)s, pspriv, sizeof(*s));
}
static int
/*ARGSUSED*/
_citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei,
const void * __restrict var __unused, size_t lenvar __unused)
{
memset((void *)ei, 0, sizeof(*ei));
return (0);
}
static void
/*ARGSUSED*/
_citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei __unused)
{
}
static int
_citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s,
size_t n, _EUCTWState * __restrict psenc, size_t * __restrict nresult)
{
char *s0;
wchar_t wchar;
int c, chlenbak, cs;
s0 = *s;
if (s0 == NULL) {
_citrus_EUCTW_init_state(ei, psenc);
*nresult = 0; /* state independent */
return (0);
}
chlenbak = psenc->chlen;
/* make sure we have the first byte in the buffer */
switch (psenc->chlen) {
case 0:
if (n < 1)
goto restart;
psenc->ch[0] = *s0++;
psenc->chlen = 1;
n--;
break;
case 1:
case 2:
break;
default:
/* illgeal state */
goto ilseq;
}
c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff));
if (c == 0)
goto ilseq;
while (psenc->chlen < c) {
if (n < 1)
goto ilseq;
psenc->ch[psenc->chlen] = *s0++;
psenc->chlen++;
n--;
}
wchar = 0;
switch (cs) {
case 0:
if (psenc->ch[0] & 0x80)
goto ilseq;
wchar = psenc->ch[0] & 0xff;
break;
case 1:
if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80))
goto ilseq;
wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
wchar |= 'G' << 24;
break;
case 2:
if ((unsigned char)psenc->ch[1] < 0xa1 ||
0xa7 < (unsigned char)psenc->ch[1])
goto ilseq;
if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80))
goto ilseq;
wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff);
wchar |= ('G' + psenc->ch[1] - 0xa1) << 24;
break;
default:
goto ilseq;
}
*s = s0;
psenc->chlen = 0;
if (pwc)
*pwc = wchar;
*nresult = wchar ? c - chlenbak : 0;
return (0);
ilseq:
psenc->chlen = 0;
*nresult = (size_t)-1;
return (EILSEQ);
restart:
*s = s0;
*nresult = (size_t)-1;
return (0);
}
static int
_citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei __unused,
char * __restrict s, size_t n, wchar_t wc,
_EUCTWState * __restrict psenc __unused, size_t * __restrict nresult)
{
wchar_t cs, v;
int clen, i, ret;
size_t len;
cs = wc & 0x7f000080;
clen = 1;
if (wc & 0x00007f00)
clen = 2;
if ((wc & 0x007f0000) && !(wc & 0x00800000))
clen = 3;
if (clen == 1 && cs == 0x00000000) {
/* ASCII */
len = 1;
if (n < len) {
ret = E2BIG;
goto err;
}
v = wc & 0x0000007f;
} else if (clen == 2 && cs == ('G' << 24)) {
/* CNS-11643-1 */
len = 2;
if (n < len) {
ret = E2BIG;
goto err;
}
v = wc & 0x00007f7f;
v |= 0x00008080;
} else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') {
/* CNS-11643-[2-7] */
len = 4;
if (n < len) {
ret = E2BIG;
goto err;
}
*s++ = _SS2;
*s++ = (cs >> 24) - 'H' + 0xa2;
v = wc & 0x00007f7f;
v |= 0x00008080;
} else {
ret = EILSEQ;
goto err;
}
i = clen;
while (i-- > 0)
*s++ = (v >> (i << 3)) & 0xff;
*nresult = len;
return (0);
err:
*nresult = (size_t)-1;
return (ret);
}
static __inline int
/*ARGSUSED*/
_citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
*csid = (_csid_t)(wc >> 24) & 0xFF;
*idx = (_index_t)(wc & 0x7F7F);
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei __unused,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
if (csid == 0) {
if ((idx & ~0x7F) != 0)
return (EINVAL);
*wc = (wchar_t)idx;
} else {
if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0)
return (EINVAL);
*wc = (wchar_t)idx | ((wchar_t)csid << 24);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei __unused,
_EUCTWState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(EUCTW);
_CITRUS_STDENC_DEF_OPS(EUCTW);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_euctw.h,v 1.2 2003/06/25 09:51:42 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_EUCTW_H_
#define _CITRUS_EUCTW_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(EUCTW);
__END_DECLS
#endif

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= GBK2K
SRCS+= citrus_gbk2k.c
CFLAGS+= --param max-inline-insns-single=16
.include <bsd.lib.mk>

View File

@ -0,0 +1,417 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki 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 <stdbool.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_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_gbk2k.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct _GBK2KState {
int chlen;
char ch[4];
} _GBK2KState;
typedef struct {
int mb_cur_max;
} _GBK2KEncodingInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_GBK2K_##m
#define _ENCODING_INFO _GBK2KEncodingInfo
#define _ENCODING_STATE _GBK2KState
#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline void
/*ARGSUSED*/
_citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei __unused,
_GBK2KState * __restrict s)
{
memset(s, 0, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei __unused,
void * __restrict pspriv, const _GBK2KState * __restrict s)
{
memcpy(pspriv, (const void *)s, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei __unused,
_GBK2KState * __restrict s, const void * __restrict pspriv)
{
memcpy((void *)s, pspriv, sizeof(*s));
}
static __inline bool
_mb_singlebyte(int c)
{
return ((c & 0xff) <= 0x7f);
}
static __inline bool
_mb_leadbyte(int c)
{
c &= 0xff;
return (0x81 <= c && c <= 0xfe);
}
static __inline bool
_mb_trailbyte(int c)
{
c &= 0xff;
return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe));
}
static __inline bool
_mb_surrogate(int c)
{
c &= 0xff;
return (0x30 <= c && c <= 0x39);
}
static __inline int
_mb_count(wchar_t v)
{
uint32_t c;
c = (uint32_t)v; /* XXX */
if (!(c & 0xffffff00))
return (1);
if (!(c & 0xffff0000))
return (2);
return (4);
}
#define _PSENC (psenc->ch[psenc->chlen - 1])
#define _PUSH_PSENC(c) (psenc->ch[psenc->chlen++] = (c))
static int
_citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s, size_t n,
_GBK2KState * __restrict psenc, size_t * __restrict nresult)
{
char *s0, *s1;
wchar_t wc;
int chlenbak, len;
s0 = *s;
if (s0 == NULL) {
/* _citrus_GBK2K_init_state(ei, psenc); */
psenc->chlen = 0;
*nresult = 0;
return (0);
}
chlenbak = psenc->chlen;
switch (psenc->chlen) {
case 3:
if (!_mb_leadbyte (_PSENC))
goto invalid;
/* FALLTHROUGH */
case 2:
if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC))
goto invalid;
/* FALLTHROUGH */
case 1:
if (!_mb_leadbyte (_PSENC))
goto invalid;
/* FALLTHOROUGH */
case 0:
break;
default:
goto invalid;
}
for (;;) {
if (n-- < 1)
goto restart;
_PUSH_PSENC(*s0++);
switch (psenc->chlen) {
case 1:
if (_mb_singlebyte(_PSENC))
goto convert;
if (_mb_leadbyte (_PSENC))
continue;
goto ilseq;
case 2:
if (_mb_trailbyte (_PSENC))
goto convert;
if (ei->mb_cur_max == 4 &&
_mb_surrogate (_PSENC))
continue;
goto ilseq;
case 3:
if (_mb_leadbyte (_PSENC))
continue;
goto ilseq;
case 4:
if (_mb_surrogate (_PSENC))
goto convert;
goto ilseq;
}
}
convert:
len = psenc->chlen;
s1 = &psenc->ch[0];
wc = 0;
while (len-- > 0)
wc = (wc << 8) | (*s1++ & 0xff);
if (pwc != NULL)
*pwc = wc;
*s = s0;
*nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak;
/* _citrus_GBK2K_init_state(ei, psenc); */
psenc->chlen = 0;
return (0);
restart:
*s = s0;
*nresult = (size_t)-2;
return (0);
invalid:
return (EINVAL);
ilseq:
*nresult = (size_t)-1;
return (EILSEQ);
}
static int
_citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
char * __restrict s, size_t n, wchar_t wc, _GBK2KState * __restrict psenc,
size_t * __restrict nresult)
{
size_t len;
int ret;
if (psenc->chlen != 0) {
ret = EINVAL;
goto err;
}
len = _mb_count(wc);
if (n < len) {
ret = E2BIG;
goto err;
}
switch (len) {
case 1:
if (!_mb_singlebyte(_PUSH_PSENC(wc ))) {
ret = EILSEQ;
goto err;
}
break;
case 2:
if (!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
!_mb_trailbyte (_PUSH_PSENC(wc))) {
ret = EILSEQ;
goto err;
}
break;
case 4:
if (ei->mb_cur_max != 4 ||
!_mb_leadbyte (_PUSH_PSENC(wc >> 24)) ||
!_mb_surrogate (_PUSH_PSENC(wc >> 16)) ||
!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
!_mb_surrogate (_PUSH_PSENC(wc))) {
ret = EILSEQ;
goto err;
}
break;
}
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
/* _citrus_GBK2K_init_state(ei, psenc); */
psenc->chlen = 0;
return (0);
err:
*nresult = (size_t)-1;
return (ret);
}
static __inline int
/*ARGSUSED*/
_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
uint8_t ch, cl;
if ((uint32_t)wc < 0x80) {
/* ISO646 */
*csid = 0;
*idx = (_index_t)wc;
} else if ((uint32_t)wc >= 0x10000) {
/* GBKUCS : XXX */
*csid = 3;
*idx = (_index_t)wc;
} else {
ch = (uint8_t)(wc >> 8);
cl = (uint8_t)wc;
if (ch >= 0xA1 && cl >= 0xA1) {
/* EUC G1 */
*csid = 1;
*idx = (_index_t)wc & 0x7F7FU;
} else {
/* extended area (0x8140-) */
*csid = 2;
*idx = (_index_t)wc;
}
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
switch (csid) {
case 0:
/* ISO646 */
*wc = (wchar_t)idx;
break;
case 1:
/* EUC G1 */
*wc = (wchar_t)idx | 0x8080U;
break;
case 2:
/* extended area */
*wc = (wchar_t)idx;
break;
case 3:
/* GBKUCS : XXX */
if (ei->mb_cur_max != 4)
return (EINVAL);
*wc = (wchar_t)idx;
break;
default:
return (EILSEQ);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei __unused,
_GBK2KState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
static int
/*ARGSUSED*/
_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,
const void * __restrict var, size_t lenvar)
{
const char *p;
p = var;
memset((void *)ei, 0, sizeof(*ei));
ei->mb_cur_max = 4;
while (lenvar > 0) {
switch (_bcs_tolower(*p)) {
case '2':
MATCH("2byte", ei->mb_cur_max = 2);
break;
}
p++;
lenvar--;
}
return (0);
}
static void
/*ARGSUSED*/
_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei __unused)
{
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(GBK2K);
_CITRUS_STDENC_DEF_OPS(GBK2K);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_gbk2k.h,v 1.2 2003/06/25 09:51:43 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _CITRUS_GBK2K_H_
#define _CITRUS_GBK2K_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(GBK2K);
__END_DECLS
#endif

View File

@ -0,0 +1,6 @@
# $FreeBSD$
SHLIB= HZ
SRCS+= citrus_hz.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,648 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp $ */
/*-
* Copyright (c)2004, 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 <sys/queue.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_types.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_hz.h"
#include "citrus_prop.h"
/*
* wchar_t mapping:
*
* CTRL/ASCII 00000000 00000000 00000000 gxxxxxxx
* GB2312 00000000 00000000 0xxxxxxx gxxxxxxx
* 94/96*n (~M) 0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx
*/
#define ESCAPE_CHAR '~'
typedef enum {
CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4
} charset_t;
typedef struct {
int end;
int start;
int width;
} range_t;
static const range_t ranges[] = {
#define RANGE(start, end) { start, end, (end - start) + 1 }
/* CTRL */ RANGE(0x00, 0x1F),
/* ASCII */ RANGE(0x20, 0x7F),
/* GB2312 */ RANGE(0x21, 0x7E),
/* CS94 */ RANGE(0x21, 0x7E),
/* CS96 */ RANGE(0x20, 0x7F),
#undef RANGE
};
typedef struct escape_t escape_t;
typedef struct {
charset_t charset;
escape_t *escape;
ssize_t length;
#define ROWCOL_MAX 3
} graphic_t;
typedef TAILQ_HEAD(escape_list, escape_t) escape_list;
struct escape_t {
TAILQ_ENTRY(escape_t) entry;
escape_list *set;
graphic_t *left;
graphic_t *right;
int ch;
};
#define GL(escape) ((escape)->left)
#define GR(escape) ((escape)->right)
#define SET(escape) ((escape)->set)
#define ESC(escape) ((escape)->ch)
#define INIT(escape) (TAILQ_FIRST(SET(escape)))
static __inline escape_t *
find_escape(escape_list *set, int ch)
{
escape_t *escape;
TAILQ_FOREACH(escape, set, entry) {
if (ESC(escape) == ch)
break;
}
return (escape);
}
typedef struct {
escape_list e0;
escape_list e1;
graphic_t *ascii;
graphic_t *gb2312;
} _HZEncodingInfo;
#define E0SET(ei) (&(ei)->e0)
#define E1SET(ei) (&(ei)->e1)
#define INIT0(ei) (TAILQ_FIRST(E0SET(ei)))
#define INIT1(ei) (TAILQ_FIRST(E1SET(ei)))
typedef struct {
escape_t *inuse;
int chlen;
char ch[ROWCOL_MAX];
} _HZState;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_HZ_##m
#define _ENCODING_INFO _HZEncodingInfo
#define _ENCODING_STATE _HZState
#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
#define _ENCODING_IS_STATE_DEPENDENT 1
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->inuse == NULL)
static __inline void
_citrus_HZ_init_state(_HZEncodingInfo * __restrict ei,
_HZState * __restrict psenc)
{
psenc->chlen = 0;
psenc->inuse = INIT0(ei);
}
static __inline void
/*ARGSUSED*/
_citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei __unused,
void *__restrict pspriv, const _HZState * __restrict psenc)
{
memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
}
static __inline void
/*ARGSUSED*/
_citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei __unused,
_HZState * __restrict psenc, const void * __restrict pspriv)
{
memcpy((void *)psenc, pspriv, sizeof(*psenc));
}
static int
_citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s, size_t n,
_HZState * __restrict psenc, size_t * __restrict nresult)
{
escape_t *candidate, *init;
graphic_t *graphic;
const range_t *range;
char *s0;
wchar_t wc;
int bit, ch, head, len, tail;
if (*s == NULL) {
_citrus_HZ_init_state(ei, psenc);
*nresult = 1;
return (0);
}
s0 = *s;
if (psenc->chlen < 0 || psenc->inuse == NULL)
return (EINVAL);
wc = (wchar_t)0;
bit = head = tail = 0;
graphic = NULL;
for (len = 0; len <= MB_LEN_MAX;) {
if (psenc->chlen == tail) {
if (n-- < 1) {
*s = s0;
*nresult = (size_t)-2;
return (0);
}
psenc->ch[psenc->chlen++] = *s0++;
++len;
}
ch = (unsigned char)psenc->ch[tail++];
if (tail == 1) {
if ((ch & ~0x80) <= 0x1F) {
if (psenc->inuse != INIT0(ei))
break;
wc = (wchar_t)ch;
goto done;
}
if (ch & 0x80) {
graphic = GR(psenc->inuse);
bit = 0x80;
ch &= ~0x80;
} else {
graphic = GL(psenc->inuse);
if (ch == ESCAPE_CHAR)
continue;
bit = 0x0;
}
if (graphic == NULL)
break;
} else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) {
if (tail < psenc->chlen)
return (EINVAL);
if (ch == ESCAPE_CHAR) {
++head;
} else if (ch == '\n') {
if (psenc->inuse != INIT0(ei))
break;
tail = psenc->chlen = 0;
continue;
} else {
candidate = NULL;
init = INIT0(ei);
if (psenc->inuse == init) {
init = INIT1(ei);
} else if (INIT(psenc->inuse) == init) {
if (ESC(init) != ch)
break;
candidate = init;
}
if (candidate == NULL) {
candidate = find_escape(
SET(psenc->inuse), ch);
if (candidate == NULL) {
if (init == NULL ||
ESC(init) != ch)
break;
candidate = init;
}
}
psenc->inuse = candidate;
tail = psenc->chlen = 0;
continue;
}
} else if (ch & 0x80) {
if (graphic != GR(psenc->inuse))
break;
ch &= ~0x80;
} else {
if (graphic != GL(psenc->inuse))
break;
}
range = &ranges[(size_t)graphic->charset];
if (range->start > ch || range->end < ch)
break;
wc <<= 8;
wc |= ch;
if (graphic->length == (tail - head)) {
if (graphic->charset > GB2312)
bit |= ESC(psenc->inuse) << 24;
wc |= bit;
goto done;
}
}
*nresult = (size_t)-1;
return (EILSEQ);
done:
if (tail < psenc->chlen)
return (EINVAL);
*s = s0;
if (pwc != NULL)
*pwc = wc;
psenc->chlen = 0;
*nresult = (wc == 0) ? 0 : len;
return (0);
}
static int
_citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei,
char * __restrict s, size_t n, wchar_t wc,
_HZState * __restrict psenc, size_t * __restrict nresult)
{
escape_t *candidate, *init;
graphic_t *graphic;
const range_t *range;
size_t len;
int bit, ch;
if (psenc->chlen != 0 || psenc->inuse == NULL)
return (EINVAL);
if (wc & 0x80) {
bit = 0x80;
wc &= ~0x80;
} else {
bit = 0x0;
}
if ((uint32_t)wc <= 0x1F) {
candidate = INIT0(ei);
graphic = (bit == 0) ? candidate->left : candidate->right;
if (graphic == NULL)
goto ilseq;
range = &ranges[(size_t)CTRL];
len = 1;
} else if ((uint32_t)wc <= 0x7F) {
graphic = ei->ascii;
if (graphic == NULL)
goto ilseq;
candidate = graphic->escape;
range = &ranges[(size_t)graphic->charset];
len = graphic->length;
} else if ((uint32_t)wc <= 0x7F7F) {
graphic = ei->gb2312;
if (graphic == NULL)
goto ilseq;
candidate = graphic->escape;
range = &ranges[(size_t)graphic->charset];
len = graphic->length;
} else {
ch = (wc >> 24) & 0xFF;
candidate = find_escape(E0SET(ei), ch);
if (candidate == NULL) {
candidate = find_escape(E1SET(ei), ch);
if (candidate == NULL)
goto ilseq;
}
wc &= ~0xFF000000;
graphic = (bit == 0) ? candidate->left : candidate->right;
if (graphic == NULL)
goto ilseq;
range = &ranges[(size_t)graphic->charset];
len = graphic->length;
}
if (psenc->inuse != candidate) {
init = INIT0(ei);
if (SET(psenc->inuse) == SET(candidate)) {
if (INIT(psenc->inuse) != init ||
psenc->inuse == init || candidate == init)
init = NULL;
} else if (candidate == (init = INIT(candidate))) {
init = NULL;
}
if (init != NULL) {
if (n < 2)
return (E2BIG);
n -= 2;
psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
psenc->ch[psenc->chlen++] = ESC(init);
}
if (n < 2)
return (E2BIG);
n -= 2;
psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
psenc->ch[psenc->chlen++] = ESC(candidate);
psenc->inuse = candidate;
}
if (n < len)
return (E2BIG);
while (len-- > 0) {
ch = (wc >> (len * 8)) & 0xFF;
if (range->start > ch || range->end < ch)
goto ilseq;
psenc->ch[psenc->chlen++] = ch | bit;
}
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
psenc->chlen = 0;
return (0);
ilseq:
*nresult = (size_t)-1;
return (EILSEQ);
}
static __inline int
_citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei,
char * __restrict s, size_t n, _HZState * __restrict psenc,
size_t * __restrict nresult)
{
escape_t *candidate;
if (psenc->chlen != 0 || psenc->inuse == NULL)
return (EINVAL);
candidate = INIT0(ei);
if (psenc->inuse != candidate) {
if (n < 2)
return (E2BIG);
n -= 2;
psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
psenc->ch[psenc->chlen++] = ESC(candidate);
}
if (n < 1)
return (E2BIG);
if (psenc->chlen > 0)
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
_citrus_HZ_init_state(ei, psenc);
return (0);
}
static __inline int
_citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei,
_HZState * __restrict psenc, int * __restrict rstate)
{
if (psenc->chlen < 0 || psenc->inuse == NULL)
return (EINVAL);
*rstate = (psenc->chlen == 0)
? ((psenc->inuse == INIT0(ei))
? _STDENC_SDGEN_INITIAL
: _STDENC_SDGEN_STABLE)
: ((psenc->ch[0] == ESCAPE_CHAR)
? _STDENC_SDGEN_INCOMPLETE_SHIFT
: _STDENC_SDGEN_INCOMPLETE_CHAR);
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
int bit;
if (wc & 0x80) {
bit = 0x80;
wc &= ~0x80;
} else
bit = 0x0;
if ((uint32_t)wc <= 0x7F) {
*csid = (_csid_t)bit;
*idx = (_index_t)wc;
} else if ((uint32_t)wc <= 0x7F7F) {
*csid = (_csid_t)(bit | 0x8000);
*idx = (_index_t)wc;
} else {
*csid = (_index_t)(wc & ~0x00FFFF7F);
*idx = (_csid_t)(wc & 0x00FFFF7F);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei __unused,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
*wc = (wchar_t)idx;
switch (csid) {
case 0x80:
case 0x8080:
*wc |= (wchar_t)0x80;
/*FALLTHROUGH*/
case 0x0:
case 0x8000:
break;
default:
*wc |= (wchar_t)csid;
}
return (0);
}
static void
_citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei)
{
escape_t *escape;
while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) {
TAILQ_REMOVE(E0SET(ei), escape, entry);
free(GL(escape));
free(GR(escape));
free(escape);
}
while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) {
TAILQ_REMOVE(E1SET(ei), escape, entry);
free(GL(escape));
free(GR(escape));
free(escape);
}
}
static int
_citrus_HZ_parse_char(void **context, const char *name __unused, const char *s)
{
escape_t *escape;
void **p;
p = (void **)*context;
escape = (escape_t *)p[0];
if (escape->ch != '\0')
return (EINVAL);
escape->ch = *s++;
if (escape->ch == ESCAPE_CHAR || *s != '\0')
return (EINVAL);
return (0);
}
static int
_citrus_HZ_parse_graphic(void **context, const char *name, const char *s)
{
_HZEncodingInfo *ei;
escape_t *escape;
graphic_t *graphic;
void **p;
p = (void **)*context;
escape = (escape_t *)p[0];
ei = (_HZEncodingInfo *)p[1];
graphic = malloc(sizeof(*graphic));
if (graphic == NULL)
return (ENOMEM);
memset(graphic, 0, sizeof(*graphic));
if (strcmp("GL", name) == 0) {
if (GL(escape) != NULL)
goto release;
GL(escape) = graphic;
} else if (strcmp("GR", name) == 0) {
if (GR(escape) != NULL)
goto release;
GR(escape) = graphic;
} else {
release:
free(graphic);
return (EINVAL);
}
graphic->escape = escape;
if (_bcs_strncasecmp("ASCII", s, 5) == 0) {
if (s[5] != '\0')
return (EINVAL);
graphic->charset = ASCII;
graphic->length = 1;
ei->ascii = graphic;
return (0);
} else if (_bcs_strncasecmp("GB2312", s, 6) == 0) {
if (s[6] != '\0')
return (EINVAL);
graphic->charset = GB2312;
graphic->length = 2;
ei->gb2312 = graphic;
return (0);
} else if (strncmp("94*", s, 3) == 0)
graphic->charset = CS94;
else if (strncmp("96*", s, 3) == 0)
graphic->charset = CS96;
else
return (EINVAL);
s += 3;
switch(*s) {
case '1': case '2': case '3':
graphic->length = (size_t)(*s - '0');
if (*++s == '\0')
break;
/*FALLTHROUGH*/
default:
return (EINVAL);
}
return (0);
}
static const _citrus_prop_hint_t escape_hints[] = {
_CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char),
_CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic),
_CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic),
_CITRUS_PROP_HINT_END
};
static int
_citrus_HZ_parse_escape(void **context, const char *name, const char *s)
{
_HZEncodingInfo *ei;
escape_t *escape;
void *p[2];
ei = (_HZEncodingInfo *)*context;
escape = malloc(sizeof(*escape));
if (escape == NULL)
return (EINVAL);
memset(escape, 0, sizeof(*escape));
if (strcmp("0", name) == 0) {
escape->set = E0SET(ei);
TAILQ_INSERT_TAIL(E0SET(ei), escape, entry);
} else if (strcmp("1", name) == 0) {
escape->set = E1SET(ei);
TAILQ_INSERT_TAIL(E1SET(ei), escape, entry);
} else {
free(escape);
return (EINVAL);
}
p[0] = (void *)escape;
p[1] = (void *)ei;
return (_citrus_prop_parse_variable(
escape_hints, (void *)&p[0], s, strlen(s)));
}
static const _citrus_prop_hint_t root_hints[] = {
_CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape),
_CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape),
_CITRUS_PROP_HINT_END
};
static int
_citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei,
const void * __restrict var, size_t lenvar)
{
int errnum;
memset(ei, 0, sizeof(*ei));
TAILQ_INIT(E0SET(ei));
TAILQ_INIT(E1SET(ei));
errnum = _citrus_prop_parse_variable(
root_hints, (void *)ei, var, lenvar);
if (errnum != 0)
_citrus_HZ_encoding_module_uninit(ei);
return (errnum);
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(HZ);
_CITRUS_STDENC_DEF_OPS(HZ);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_hz.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */
/*-
* Copyright (c)2004, 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_HZ_H_
#define _CITRUS_HZ_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(HZ);
__END_DECLS
#endif

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= ISO2022
SRCS+= citrus_iso2022.c
CFLAGS+= --param max-inline-insns-single=128
.include <bsd.lib.mk>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_iso2022.h,v 1.2 2003/06/25 09:51:44 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_ISO2022_H_
#define _CITRUS_ISO2022_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(ISO2022);
__END_DECLS
#endif

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= JOHAB
SRCS+= citrus_johab.c
CFLAGS+= --param max-inline-insns-single=16
.include <bsd.lib.mk>

View File

@ -0,0 +1,333 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 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 <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_types.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_johab.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
int chlen;
char ch[2];
} _JOHABState;
typedef struct {
int dummy;
} _JOHABEncodingInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_JOHAB_##m
#define _ENCODING_INFO _JOHABEncodingInfo
#define _ENCODING_STATE _JOHABState
#define _ENCODING_MB_CUR_MAX(_ei_) 2
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static __inline void
/*ARGSUSED*/
_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,
_JOHABState * __restrict psenc)
{
psenc->chlen = 0;
}
static __inline void
/*ARGSUSED*/
_citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei __unused,
void * __restrict pspriv, const _JOHABState * __restrict psenc)
{
memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
}
static __inline void
/*ARGSUSED*/
_citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei __unused,
_JOHABState * __restrict psenc, const void * __restrict pspriv)
{
memcpy((void *)psenc, pspriv, sizeof(*psenc));
}
static void
/*ARGSUSED*/
_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused)
{
/* ei may be null */
}
static int
/*ARGSUSED*/
_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,
const void * __restrict var __unused, size_t lenvar __unused)
{
/* ei may be null */
return (0);
}
static __inline bool
ishangul(int l, int t)
{
return ((l >= 0x84 && l <= 0xD3) &&
((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE)));
}
static __inline bool
isuda(int l, int t)
{
return ((l == 0xD8) &&
((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
}
static __inline bool
ishanja(int l, int t)
{
return (((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
}
static int
/*ARGSUSED*/
_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s, size_t n,
_JOHABState * __restrict psenc, size_t * __restrict nresult)
{
char *s0;
int l, t;
if (*s == NULL) {
_citrus_JOHAB_init_state(ei, psenc);
*nresult = _ENCODING_IS_STATE_DEPENDENT;
return (0);
}
s0 = *s;
switch (psenc->chlen) {
case 0:
if (n-- < 1)
goto restart;
l = *s0++ & 0xFF;
if (l <= 0x7F) {
if (pwc != NULL)
*pwc = (wchar_t)l;
*nresult = (l == 0) ? 0 : 1;
*s = s0;
return (0);
}
psenc->ch[psenc->chlen++] = l;
break;
case 1:
l = psenc->ch[0] & 0xFF;
break;
default:
return (EINVAL);
}
if (n-- < 1) {
restart:
*nresult = (size_t)-2;
*s = s0;
return (0);
}
t = *s0++ & 0xFF;
if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
*nresult = (size_t)-1;
return (EILSEQ);
}
if (pwc != NULL)
*pwc = (wchar_t)(l << 8 | t);
*nresult = s0 - *s;
*s = s0;
psenc->chlen = 0;
return (0);
}
static int
/*ARGSUSED*/
_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,
char * __restrict s, size_t n, wchar_t wc,
_JOHABState * __restrict psenc, size_t * __restrict nresult)
{
int l, t;
if (psenc->chlen != 0)
return (EINVAL);
/* XXX assume wchar_t as int */
if ((uint32_t)wc <= 0x7F) {
if (n < 1)
goto e2big;
*s = wc & 0xFF;
*nresult = 1;
} else if ((uint32_t)wc <= 0xFFFF) {
if (n < 2) {
e2big:
*nresult = (size_t)-1;
return (E2BIG);
}
l = (wc >> 8) & 0xFF;
t = wc & 0xFF;
if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
goto ilseq;
*s++ = l;
*s = t;
*nresult = 2;
} else {
ilseq:
*nresult = (size_t)-1;
return (EILSEQ);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
int m, l, linear, t;
/* XXX assume wchar_t as int */
if ((uint32_t)wc <= 0x7F) {
*idx = (_index_t)wc;
*csid = 0;
} else if ((uint32_t)wc <= 0xFFFF) {
l = (wc >> 8) & 0xFF;
t = wc & 0xFF;
if (ishangul(l, t) || isuda(l, t)) {
*idx = (_index_t)wc;
*csid = 1;
} else {
if (l >= 0xD9 && l <= 0xDE) {
linear = l - 0xD9;
m = 0x21;
} else if (l >= 0xE0 && l <= 0xF9) {
linear = l - 0xE0;
m = 0x4A;
} else
return (EILSEQ);
linear *= 188;
if (t >= 0x31 && t <= 0x7E)
linear += t - 0x31;
else if (t >= 0x91 && t <= 0xFE)
linear += t - 0x43;
else
return (EILSEQ);
l = (linear / 94) + m;
t = (linear % 94) + 0x21;
*idx = (_index_t)((l << 8) | t);
*csid = 2;
}
} else
return (EILSEQ);
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
int m, n, l, linear, t;
switch (csid) {
case 0:
case 1:
*wc = (wchar_t)idx;
break;
case 2:
if (idx >= 0x2121 && idx <= 0x2C71) {
m = 0xD9;
n = 0x21;
} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
m = 0xE0;
n = 0x4A;
} else
return (EILSEQ);
l = ((idx >> 8) & 0xFF) - n;
t = (idx & 0xFF) - 0x21;
linear = (l * 94) + t;
l = (linear / 188) + m;
t = linear % 188;
t += (t <= 0x4D) ? 0x31 : 0x43;
break;
default:
return (EILSEQ);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,
_JOHABState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(JOHAB);
_CITRUS_STDENC_DEF_OPS(JOHAB);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_johab.h,v 1.1 2006/10/18 17:54:55 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_JOHAB_H_
#define _CITRUS_JOHAB_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(JOHAB);
__END_DECLS
#endif

View File

@ -0,0 +1,6 @@
# $FreeBSD$
SHLIB= MSKanji
SRCS+= citrus_mskanji.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,473 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki 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.
*/
/*
* ja_JP.SJIS locale table for BSD4.4/rune
* version 1.0
* (C) Sin'ichiro MIYATANI / Phase One, Inc
* May 12, 1995
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Phase One, Inc.
* 4. The name of Phase One, Inc. 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 <errno.h>
#include <limits.h>
#include <stdbool.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_bcs.h"
#include "citrus_module.h"
#include "citrus_stdenc.h"
#include "citrus_mskanji.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct _MSKanjiState {
int chlen;
char ch[2];
} _MSKanjiState;
typedef struct {
int mode;
#define MODE_JIS2004 1
} _MSKanjiEncodingInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_MSKanji_##m
#define _ENCODING_INFO _MSKanjiEncodingInfo
#define _ENCODING_STATE _MSKanjiState
#define _ENCODING_MB_CUR_MAX(_ei_) 2
#define _ENCODING_IS_STATE_DEPENDENT 0
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
static bool
_mskanji1(int c)
{
return ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc));
}
static bool
_mskanji2(int c)
{
return ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc));
}
static __inline void
/*ARGSUSED*/
_citrus_MSKanji_init_state(_MSKanjiEncodingInfo * __restrict ei __unused,
_MSKanjiState * __restrict s)
{
s->chlen = 0;
}
static __inline void
/*ARGSUSED*/
_citrus_MSKanji_pack_state(_MSKanjiEncodingInfo * __restrict ei __unused,
void * __restrict pspriv, const _MSKanjiState * __restrict s)
{
memcpy(pspriv, (const void *)s, sizeof(*s));
}
static __inline void
/*ARGSUSED*/
_citrus_MSKanji_unpack_state(_MSKanjiEncodingInfo * __restrict ei __unused,
_MSKanjiState * __restrict s, const void * __restrict pspriv)
{
memcpy((void *)s, pspriv, sizeof(*s));
}
static int
/*ARGSUSED*/
_citrus_MSKanji_mbrtowc_priv(_MSKanjiEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, char ** __restrict s, size_t n,
_MSKanjiState * __restrict psenc, size_t * __restrict nresult)
{
char *s0;
wchar_t wchar;
int chlenbak, len;
s0 = *s;
if (s0 == NULL) {
_citrus_MSKanji_init_state(ei, psenc);
*nresult = 0; /* state independent */
return (0);
}
chlenbak = psenc->chlen;
/* make sure we have the first byte in the buffer */
switch (psenc->chlen) {
case 0:
if (n < 1)
goto restart;
psenc->ch[0] = *s0++;
psenc->chlen = 1;
n--;
break;
case 1:
break;
default:
/* illegal state */
goto encoding_error;
}
len = _mskanji1(psenc->ch[0] & 0xff) ? 2 : 1;
while (psenc->chlen < len) {
if (n < 1)
goto restart;
psenc->ch[psenc->chlen] = *s0++;
psenc->chlen++;
n--;
}
*s = s0;
switch (len) {
case 1:
wchar = psenc->ch[0] & 0xff;
break;
case 2:
if (!_mskanji2(psenc->ch[1] & 0xff))
goto encoding_error;
wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
break;
default:
/* illegal state */
goto encoding_error;
}
psenc->chlen = 0;
if (pwc)
*pwc = wchar;
*nresult = wchar ? len - chlenbak : 0;
return (0);
encoding_error:
psenc->chlen = 0;
*nresult = (size_t)-1;
return (EILSEQ);
restart:
*nresult = (size_t)-2;
*s = s0;
return (0);
}
static int
_citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei __unused,
char * __restrict s, size_t n, wchar_t wc,
_MSKanjiState * __restrict psenc __unused, size_t * __restrict nresult)
{
int ret;
/* check invalid sequence */
if (wc & ~0xffff) {
ret = EILSEQ;
goto err;
}
if (wc & 0xff00) {
if (n < 2) {
ret = E2BIG;
goto err;
}
s[0] = (wc >> 8) & 0xff;
s[1] = wc & 0xff;
if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) {
ret = EILSEQ;
goto err;
}
*nresult = 2;
return (0);
} else {
if (n < 1) {
ret = E2BIG;
goto err;
}
s[0] = wc & 0xff;
if (_mskanji1(s[0] & 0xff)) {
ret = EILSEQ;
goto err;
}
*nresult = 1;
return (0);
}
err:
*nresult = (size_t)-1;
return (ret);
}
static __inline int
/*ARGSUSED*/
_citrus_MSKanji_stdenc_wctocs(_MSKanjiEncodingInfo * __restrict ei,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
_index_t col, row;
int offset;
if ((_wc_t)wc < 0x80) {
/* ISO-646 */
*csid = 0;
*idx = (_index_t)wc;
} else if ((_wc_t)wc < 0x100) {
/* KANA */
*csid = 1;
*idx = (_index_t)wc & 0x7F;
} else {
/* Kanji (containing Gaiji zone) */
/*
* 94^2 zone (contains a part of Gaiji (0xED40 - 0xEEFC)):
* 0x8140 - 0x817E -> 0x2121 - 0x215F
* 0x8180 - 0x819E -> 0x2160 - 0x217E
* 0x819F - 0x81FC -> 0x2221 - 0x227E
*
* 0x8240 - 0x827E -> 0x2321 - 0x235F
* ...
* 0x9F9F - 0x9FFc -> 0x5E21 - 0x5E7E
*
* 0xE040 - 0xE07E -> 0x5F21 - 0x5F5F
* ...
* 0xEF9F - 0xEFFC -> 0x7E21 - 0x7E7E
*
* extended Gaiji zone:
* 0xF040 - 0xFCFC
*
* JIS X0213-plane2:
* 0xF040 - 0xF09E -> 0x2121 - 0x217E
* 0xF140 - 0xF19E -> 0x2321 - 0x237E
* ...
* 0xF240 - 0xF29E -> 0x2521 - 0x257E
*
* 0xF09F - 0xF0FC -> 0x2821 - 0x287E
* 0xF29F - 0xF2FC -> 0x2C21 - 0x2C7E
* ...
* 0xF44F - 0xF49E -> 0x2F21 - 0x2F7E
*
* 0xF49F - 0xF4FC -> 0x6E21 - 0x6E7E
* ...
* 0xFC9F - 0xFCFC -> 0x7E21 - 0x7E7E
*/
row = ((_wc_t)wc >> 8) & 0xFF;
col = (_wc_t)wc & 0xFF;
if (!_mskanji1(row) || !_mskanji2(col))
return (EILSEQ);
if ((ei->mode & MODE_JIS2004) == 0 || row < 0xF0) {
*csid = 2;
offset = 0x81;
} else {
*csid = 3;
if ((_wc_t)wc <= 0xF49E) {
offset = (_wc_t)wc >= 0xF29F ||
((_wc_t)wc >= 0xF09F &&
(_wc_t)wc <= 0xF0FC) ? 0xED : 0xF0;
} else
offset = 0xCE;
}
row -= offset;
if (row >= 0x5F)
row -= 0x40;
row = row * 2 + 0x21;
col -= 0x1F;
if (col >= 0x61)
col -= 1;
if (col > 0x7E) {
row += 1;
col -= 0x5E;
}
*idx = ((_index_t)row << 8) | col;
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_MSKanji_stdenc_cstowc(_MSKanjiEncodingInfo * __restrict ei,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
uint32_t col, row;
int offset;
switch (csid) {
case 0:
/* ISO-646 */
if (idx >= 0x80)
return (EILSEQ);
*wc = (wchar_t)idx;
break;
case 1:
/* kana */
if (idx >= 0x80)
return (EILSEQ);
*wc = (wchar_t)idx + 0x80;
break;
case 3:
if ((ei->mode & MODE_JIS2004) == 0)
return (EILSEQ);
/*FALLTHROUGH*/
case 2:
/* kanji */
row = (idx >> 8);
if (row < 0x21)
return (EILSEQ);
if (csid == 3) {
if (row <= 0x2F)
offset = (row == 0x22 || row >= 0x26) ?
0xED : 0xF0;
else if (row >= 0x4D && row <= 0x7E)
offset = 0xCE;
else
return (EILSEQ);
} else {
if (row > 0x97)
return (EILSEQ);
offset = (row < 0x5F) ? 0x81 : 0xC1;
}
col = idx & 0xFF;
if (col < 0x21 || col > 0x7E)
return (EILSEQ);
row -= 0x21; col -= 0x21;
if ((row & 1) == 0) {
col += 0x40;
if (col >= 0x7F)
col += 1;
} else
col += 0x9F;
row = row / 2 + offset;
*wc = ((wchar_t)row << 8) | col;
break;
default:
return (EILSEQ);
}
return (0);
}
static __inline int
/*ARGSUSED*/
_citrus_MSKanji_stdenc_get_state_desc_generic(_MSKanjiEncodingInfo * __restrict ei __unused,
_MSKanjiState * __restrict psenc, int * __restrict rstate)
{
*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
_STDENC_SDGEN_INCOMPLETE_CHAR;
return (0);
}
static int
/*ARGSUSED*/
_citrus_MSKanji_encoding_module_init(_MSKanjiEncodingInfo * __restrict ei,
const void * __restrict var, size_t lenvar)
{
const char *p;
p = var;
memset((void *)ei, 0, sizeof(*ei));
while (lenvar > 0) {
switch (_bcs_toupper(*p)) {
case 'J':
MATCH(JIS2004, ei->mode |= MODE_JIS2004);
break;
}
++p;
--lenvar;
}
return (0);
}
static void
_citrus_MSKanji_encoding_module_uninit(_MSKanjiEncodingInfo *ei __unused)
{
}
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(MSKanji);
_CITRUS_STDENC_DEF_OPS(MSKanji);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $FreeBSD$ */
/* $NetBSD: citrus_mskanji.h,v 1.2 2003/06/25 09:51:48 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_MSKANJI_H_
#define _CITRUS_MSKANJI_H_
__BEGIN_DECLS
_CITRUS_STDENC_GETOPS_FUNC(MSKanji);
__END_DECLS
#endif

View File

@ -0,0 +1,9 @@
# $FreeBSD$
.include <bsd.own.mk>
SUBDIR= BIG5 DECHanyu EUC EUCTW GBK2K HZ ISO2022 JOHAB MSKanji UES UTF1632 \
UTF7 UTF8 VIQR ZW iconv_none iconv_std mapper_646 mapper_none \
mapper_parallel mapper_serial mapper_std mapper_zone
.include <bsd.subdir.mk>

View File

@ -0,0 +1,14 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../libc/iconv
SHLIB_MAJOR= 4
WARNS?= 6
CFLAGS+= -I${.CURDIR}/../../libc/iconv
.if !defined(COMPAT_32BIT)
SHLIBDIR= /usr/lib/i18n
.else
SHLIBDIR= /usr/lib32/i18n
.endif
LIBDIR= ${SHLIBDIR}
NO_PROFILE=

View File

@ -0,0 +1,7 @@
# $FreeBSD$
SHLIB= UES
SRCS+= citrus_ues.c
CFLAGS+= --param max-inline-insns-single=64
.include <bsd.lib.mk>

Some files were not shown because too many files have changed in this diff Show More