1. add iconv support for following encodings:

Chinese Simplefied
        HZ, HZ8 - 7/8bit stateful encoding, see RFC1842,1843. (libHZ)
        zW      - 7bit stateful encoding, see RFC1842. (libZW)
2. add citrus_prop.[ch] - parser for encoding module's init parameter strings.
This commit is contained in:
tnozaki 2006-11-22 23:38:25 +00:00
parent ec21dc99eb
commit 8033a5b008
21 changed files with 1942 additions and 217 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.673 2006/11/13 15:16:28 tnozaki Exp $
# $NetBSD: mi,v 1.674 2006/11/22 23:38:25 tnozaki Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -2038,6 +2038,8 @@
./usr/share/i18n/esdb/MISC/GB18030.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/GBK.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/HP-ROMAN8.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/HZ.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/HZ8.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/JAVA.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/JOHAB.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/KOI8-R.esdb base-obsolete obsolete
@ -2045,6 +2047,7 @@
./usr/share/i18n/esdb/MISC/NEXTSTEP.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/PTCP154.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/Shift_JIS.esdb base-sysutil-share nls
./usr/share/i18n/esdb/MISC/ZW.esdb base-sysutil-share nls
./usr/share/i18n/esdb/TCVN base-sysutil-share
./usr/share/i18n/esdb/TCVN/TCVN5712-1.esdb base-sysutil-share nls
./usr/share/i18n/esdb/TCVN/VIQR.esdb base-sysutil-share nls

View File

@ -1,4 +1,4 @@
# $NetBSD: shl.elf,v 1.124 2006/11/13 15:16:28 tnozaki Exp $
# $NetBSD: shl.elf,v 1.125 2006/11/22 23:38:25 tnozaki Exp $
# Note: libtermcap and libtermlib are hardlinked and share the same version.
./lib/libc.so base-sys-shlib
./lib/libc.so.12 base-sys-shlib
@ -39,6 +39,8 @@
./usr/lib/i18n/libEUCTW.so.4 base-i18n-shlib
./usr/lib/i18n/libGBK2K.so base-i18n-shlib
./usr/lib/i18n/libGBK2K.so.4 base-i18n-shlib
./usr/lib/i18n/libHZ.so base-i18n-shlib
./usr/lib/i18n/libHZ.so.4 base-i18n-shlib
./usr/lib/i18n/libISO2022.so base-i18n-shlib
./usr/lib/i18n/libISO2022.so.4 base-i18n-shlib
./usr/lib/i18n/libJOHAB.so base-i18n-shlib
@ -55,6 +57,8 @@
./usr/lib/i18n/libUTF8.so.4 base-i18n-shlib
./usr/lib/i18n/libVIQR.so base-i18n-shlib
./usr/lib/i18n/libVIQR.so.4 base-i18n-shlib
./usr/lib/i18n/libZW.so base-i18n-shlib
./usr/lib/i18n/libZW.so.4 base-i18n-shlib
./usr/lib/i18n/libiconv_none.so base-i18n-shlib
./usr/lib/i18n/libiconv_none.so.4 base-i18n-shlib
./usr/lib/i18n/libiconv_std.so base-i18n-shlib

View File

@ -1,4 +1,4 @@
# $NetBSD: shl.mi,v 1.379 2006/11/17 22:13:58 christos Exp $
# $NetBSD: shl.mi,v 1.380 2006/11/22 23:38:26 tnozaki Exp $
# Note: libtermcap and libtermlib are hardlinked and share the same version.
./lib/libc.so.12.149 base-sys-shlib
./lib/libcrypt.so.0.2 base-sys-shlib
@ -19,6 +19,7 @@
./usr/lib/i18n/libEUC.so.4.4 base-i18n-shlib
./usr/lib/i18n/libEUCTW.so.4.4 base-i18n-shlib
./usr/lib/i18n/libGBK2K.so.4.4 base-i18n-shlib
./usr/lib/i18n/libHZ.so.4.4 base-i18n-shlib
./usr/lib/i18n/libISO2022.so.4.4 base-i18n-shlib
./usr/lib/i18n/libJOHAB.so.4.4 base-i18n-shlib
./usr/lib/i18n/libMSKanji.so.4.4 base-i18n-shlib
@ -27,6 +28,7 @@
./usr/lib/i18n/libUTF7.so.4.4 base-i18n-shlib
./usr/lib/i18n/libUTF8.so.4.4 base-i18n-shlib
./usr/lib/i18n/libVIQR.so.4.4 base-i18n-shlib
./usr/lib/i18n/libZW.so.4.4 base-i18n-shlib
./usr/lib/i18n/libiconv_none.so.4.4 base-i18n-shlib
./usr/lib/i18n/libiconv_std.so.4.4 base-i18n-shlib
./usr/lib/i18n/libmapper_646.so.4.4 base-i18n-shlib

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.978 2006/11/22 17:23:24 christos Exp $
# $NetBSD: mi,v 1.979 2006/11/22 23:38:26 tnozaki Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -2009,6 +2009,7 @@
./usr/lib/i18n/libEUC.a comp-i18n-lib
./usr/lib/i18n/libEUCTW.a comp-i18n-lib
./usr/lib/i18n/libGBK2K.a comp-i18n-lib
./usr/lib/i18n/libHZ.a comp-i18n-lib
./usr/lib/i18n/libISO2022.a comp-i18n-lib
./usr/lib/i18n/libJOHAB.a comp-i18n-lib
./usr/lib/i18n/libMSKanji.a comp-i18n-lib
@ -2017,6 +2018,7 @@
./usr/lib/i18n/libUTF7.a comp-i18n-lib
./usr/lib/i18n/libUTF8.a comp-i18n-lib
./usr/lib/i18n/libVIQR.a comp-i18n-lib
./usr/lib/i18n/libZW.a comp-i18n-lib
./usr/lib/i18n/libiconv_none.a comp-i18n-lib
./usr/lib/i18n/libiconv_std.a comp-i18n-lib
./usr/lib/i18n/libmapper_646.a comp-i18n-lib

View File

@ -1,4 +1,5 @@
# $NetBSD: Makefile,v 1.1 2002/03/17 22:14:14 tshiozak Exp $
# $NetBSD: Makefile,v 1.2 2006/11/22 23:38:27 tnozaki Exp $
SRCS= citrus_big5.c citrus_prop.c
SRCPRE=citrus_
.include <bsd.lib.mk>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
SRCS= citrus_hz.c citrus_prop.c
.include <bsd.lib.mk>

View File

@ -1,6 +1,6 @@
# $NetBSD: Makefile,v 1.6 2006/11/13 15:16:30 tnozaki Exp $
# $NetBSD: Makefile,v 1.7 2006/11/22 23:38:27 tnozaki Exp $
SUBDIR= BIG5 EUC EUCTW GBK2K ISO2022 JOHAB MSKanji UES UTF1632 UTF8 UTF7 VIQR
SUBDIR= BIG5 EUC EUCTW GBK2K HZ ISO2022 JOHAB MSKanji UES UTF1632 UTF8 UTF7 VIQR ZW
SUBDIR+=iconv_none iconv_std
SUBDIR+=mapper_646 mapper_none mapper_serial mapper_parallel mapper_std \
mapper_zone

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.8 2004/05/17 05:49:54 lukem Exp $
# $NetBSD: Makefile.inc,v 1.9 2006/11/22 23:38:27 tnozaki Exp $
NOLINT= # defined
NOPICINSTALL= # defined
@ -17,4 +17,4 @@ BASENAME= ${.CURDIR:T}
LIB= ${BASENAME}
SRCS?= ${SRCPRE:tl}${BASENAME:tl}.c
.PATH: ${NETBSDSRCDIR}/lib/libc/citrus/modules
.PATH: ${NETBSDSRCDIR}/lib/libc/citrus ${NETBSDSRCDIR}/lib/libc/citrus/modules

View File

@ -0,0 +1,4 @@
# $NetBSD: Makefile,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
SRCPRE=citrus_
.include <bsd.lib.mk>

View File

@ -0,0 +1,447 @@
/* $NetBSD: citrus_prop.c,v 1.1 2006/11/22 23:38:27 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 <assert.h>
#include <limits.h>
#include <errno.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 bool, chr;
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)
{
_DIAGASSERT(obj != NULL);
obj->type = type;
memset(&obj->u, 0, sizeof(obj->u));
}
static __inline void
_citrus_prop_object_uninit(_citrus_prop_object_t *obj)
{
_DIAGASSERT(obj != NULL);
if (obj->type == _CITRUS_PROP_STR)
free(__UNCONST(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 n, ch, cutlim; \
char *p; \
\
_DIAGASSERT(ms != NULL); \
_DIAGASSERT(result != NULL); \
\
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 ch, neg, base; \
\
_DIAGASSERT(ms != NULL); \
_DIAGASSERT(obj != NULL); \
\
_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 ch, base;
_DIAGASSERT(ms != NULL);
_DIAGASSERT(result != NULL);
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;
/*FALLTHROUGH*/
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
_memstream_ungetc(ms, ch);
base -= 8;
case 'x':
return _citrus_prop_read_chr_common(ms, result, base);
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;
_DIAGASSERT(ms != NULL);
_DIAGASSERT(obj != NULL);
_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)
{
_DIAGASSERT(ms != NULL);
_DIAGASSERT(obj != NULL);
_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.bool = 1;
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.bool = 0;
return 0;
}
}
return EINVAL;
}
static int
_citrus_prop_read_str(struct _memstream * __restrict ms,
_citrus_prop_object_t * __restrict obj)
{
int errnum, quot, ch;
char *s, *t;
#define _CITRUS_PROP_STR_BUFSIZ 512
size_t n, m;
_DIAGASSERT(ms != NULL);
_DIAGASSERT(obj != NULL);
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;
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[] = {
NULL, /*dummy*/
_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;
_DIAGASSERT(ms != NULL);
_DIAGASSERT(s != NULL);
_DIAGASSERT(n > 0);
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;
_DIAGASSERT(ms != NULL);
_DIAGASSERT(hints != NULL);
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:
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 { \
_DIAGASSERT(hint->cb._func_.func != NULL); \
errnum = (*hint->cb._func_.func)(context, \
hint->name, ostart.u._func_); \
} while (/*CONSTCOND*/0)
#define CALL1(_func_) \
do { \
_DIAGASSERT(hint->cb._func_.func != NULL); \
errnum = (*hint->cb._func_.func)(context, \
hint->name, ostart.u._func_, oend.u._func_);\
} while (/*CONSTCOND*/0)
switch (hint->type) {
case _CITRUS_PROP_BOOL: CALL0(bool); 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 errnum, ch;
_DIAGASSERT(hints != NULL);
_memstream_bind_ptr(&ms, __UNCONST(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 **)&context);
if (errnum != 0)
return errnum;
}
return 0;
}

View File

@ -0,0 +1,91 @@
/* $NetBSD: citrus_prop.h,v 1.1 2006/11/22 23:38:27 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_SEC = 0,
_CITRUS_PROP_BOOL = 1,
_CITRUS_PROP_STR = 2,
_CITRUS_PROP_CHR = 3,
_CITRUS_PROP_NUM = 4,
} _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(bool, 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(bool);
_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, { bool: { 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 }
__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

@ -1,4 +1,4 @@
/* $NetBSD: citrus_big5.c,v 1.10 2006/06/19 17:28:24 tnozaki Exp $ */
/* $NetBSD: citrus_big5.c,v 1.11 2006/11/22 23:38:27 tnozaki Exp $ */
/*-
* Copyright (c)2002, 2006 Citrus Project,
@ -60,7 +60,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_big5.c,v 1.10 2006/06/19 17:28:24 tnozaki Exp $");
__RCSID("$NetBSD: citrus_big5.c,v 1.11 2006/11/22 23:38:27 tnozaki Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/queue.h>
@ -84,6 +84,8 @@ __RCSID("$NetBSD: citrus_big5.c,v 1.10 2006/06/19 17:28:24 tnozaki Exp $");
#include "citrus_stdenc.h"
#include "citrus_big5.h"
#include "citrus_prop.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
@ -188,202 +190,19 @@ _citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c)
return 0;
}
#define _STRTOL_LEN(_func_, _type_, _limit_) \
static int \
_prop_##_func_##_len(const char *s, size_t *n, \
char **endptr, int base, _type_ *result) \
{ \
const char *ptr; \
char buf[_limit_ + 1], *tail; \
size_t siz; \
int save_errno, err; \
\
_DIAGASSERT(s != NULL); \
_DIAGASSERT(n != NULL); \
/* endptr may be null */ \
_DIAGASSERT(result != NULL); \
\
ptr = _bcs_skip_ws_len(s, n); \
if (*n < 1) { \
*result = 0; \
if (endptr != NULL) \
*endptr = __UNCONST(s); \
return 0; \
} \
siz = _limit_ < *n ? _limit_ : *n; \
memcpy(buf, ptr, siz); \
buf[siz] = '\0'; \
\
save_errno = errno; \
errno = 0; \
*result = _func_(buf, &tail, base); \
err = errno; \
errno = save_errno; \
if (err == 0) { \
siz = (size_t)(tail - buf); \
if (endptr != NULL) \
*endptr = __UNCONST(ptr + siz); \
*n -= siz; \
} \
return (err); \
}
_STRTOL_LEN(strtoul, unsigned long, 13)
#define _PROP_READ_UINT(_func_, _type_, _max_) \
static int \
_prop_read_##_func_(const char **s, size_t *n, _type_ *result) \
{ \
const char *s0; \
char *t; \
size_t n0; \
unsigned long l; \
\
_DIAGASSERT(s != NULL); \
_DIAGASSERT(n != NULL); \
_DIAGASSERT(result != NULL); \
\
s0 = *s; \
n0 = *n; \
if (_prop_strtoul_len(s0, &n0, &t, 0, &l) != 0 || \
s0 == t) \
return EINVAL; \
if (l > _max_) \
return ERANGE; \
*result = (_type_)l; \
*s = (const char *)t; \
*n = n0; \
\
return 0; \
}
_PROP_READ_UINT( u8, uint8_t, UINT8_MAX)
_PROP_READ_UINT(u16, uint16_t, UINT16_MAX)
#define _PROP_HANDLE_TYPE_T(_func_, _type_) \
typedef int (*_prop_handle_##_func_##_t) \
(void *, const char *, _type_, _type_);
_PROP_HANDLE_TYPE_T( u8, uint8_t)
_PROP_HANDLE_TYPE_T(u16, uint16_t)
typedef struct _prop_key_t _prop_key_t;
typedef union {
#define _PROP_HANDLE_TYPE_OPS(_func_) \
_prop_handle_##_func_##_t _func_
_PROP_HANDLE_TYPE_OPS( u8);
_PROP_HANDLE_TYPE_OPS(u16);
} _prop_handler_t;
typedef enum {
_PROP_U8, _PROP_U16,
} _prop_type_t;
struct _prop_key_t {
const char *name;
_prop_type_t type;
_prop_handler_t handler;
};
static int
_prop_parse_variable(void *ctx, const char **s, size_t *n,
const _prop_key_t *keys)
{
const char *s0, *s1;
size_t n0, n1, nlen;
const _prop_key_t *key;
const _prop_handler_t *ptr;
int ch0, ret;
s0 = *s;
n0 = *n;
#define PARSE(_func_, _type_) \
do { \
_type_ x, y; \
if (ptr->_func_ == NULL) \
return EINVAL; \
for (ch0 = 0; ch0 != ';';) { \
ret = _prop_read_##_func_(&s0, &n0, &x); \
if (ret != 0) \
return ret; \
s0 = _bcs_skip_ws_len(s0, &n0); \
if (n0 < 1 || (ch0 = (int)*s0) == '\0') \
return EINVAL; \
if(ch0 == '-') { \
++s0, --n0; \
ret = _prop_read_##_func_(&s0, &n0, &y);\
if (ret != 0) \
return ret; \
if (x >= y) \
return EINVAL; \
} else \
y = x; \
s0 = _bcs_skip_ws_len(s0, &n0); \
if (n0 < 1) \
return EINVAL; \
ch0 = (int)*s0; \
if (ch0 != ',' && ch0 != ';') \
return EINVAL; \
++s0, --n0; \
_DIAGASSERT(ctx != NULL); \
ret = (*ptr->_func_)(ctx, key->name, x, y); \
if (ret != 0) \
return ret; \
} \
} while (/*CONSTCOND*/0)
for (;;) {
s0 = _bcs_skip_ws_len(s0, &n0);
if (n0 < 1 || *s0 == '\0')
break;
for (key = keys; key->name != NULL; ++key) {
s1 = s0, n1 = n0;
nlen = strlen(key->name);
if (n1 <= nlen || strncmp(s1, key->name, nlen) != 0)
continue;
s1 += nlen, n1 -= nlen;
s1 = _bcs_skip_ws_len(s1, &n1);
if (n1 < 1)
continue;
ptr = (const _prop_handler_t *)&key->handler;
if (*s1 == '=') {
s0 = ++s1, n0 = --n1;
switch (key->type) {
case _PROP_U8:
PARSE( u8, uint8_t);
break;
case _PROP_U16:
PARSE(u16, uint16_t);
break;
default:
goto invalid;
}
break;
}
}
if (key->name == NULL)
goto invalid;
}
*s = s0;
*n = n0;
return 0;
invalid:
return EINVAL;
}
static int
_citrus_BIG5_fill_rowcol(void * __restrict ctx, const char * __restrict s,
uint8_t start, uint8_t end)
_citrus_BIG5_fill_rowcol(void ** __restrict ctx, const char * __restrict s,
uint64_t start, uint64_t end)
{
_BIG5EncodingInfo *ei;
int i;
uint8_t n;
uint64_t n;
_DIAGASSERT(ctx != NULL);
_DIAGASSERT(ctx != NULL && *ctx != NULL);
ei = (_BIG5EncodingInfo *)ctx;
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)
@ -393,15 +212,17 @@ _citrus_BIG5_fill_rowcol(void * __restrict ctx, const char * __restrict s,
static int
/*ARGSUSED*/
_citrus_BIG5_fill_excludes(void * __restrict ctx, const char * __restrict s,
uint16_t start, uint16_t end)
_citrus_BIG5_fill_excludes(void ** __restrict ctx, const char * __restrict s,
uint64_t start, uint64_t end)
{
_BIG5EncodingInfo *ei;
_BIG5Exclude *exclude;
_DIAGASSERT(ctx != NULL);
_DIAGASSERT(ctx != NULL && *ctx != NULL);
ei = (_BIG5EncodingInfo *)ctx;
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;
@ -415,11 +236,11 @@ _citrus_BIG5_fill_excludes(void * __restrict ctx, const char * __restrict s,
return 0;
}
static const _prop_key_t rootkeys[] = {
{ "row", _PROP_U8, { u8: &_citrus_BIG5_fill_rowcol } },
{ "col", _PROP_U8, { u8: &_citrus_BIG5_fill_rowcol } },
{ "excludes", _PROP_U16, { u16: &_citrus_BIG5_fill_excludes } },
{ NULL },
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
@ -452,7 +273,8 @@ _citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
if (lenvar > 0 && var != NULL) {
s = _bcs_skip_ws_len((const char *)var, &lenvar);
if (lenvar > 0 && *s != '\0') {
err = _prop_parse_variable(ei, &s, &lenvar, rootkeys);
err = _citrus_prop_parse_variable(
root_hints, (void *)ei, s, lenvar);
if (err == 0)
return 0;
@ -463,9 +285,9 @@ _citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
}
/* fallback Big5-1984, for backward compatibility. */
_citrus_BIG5_fill_rowcol(ei, "row", 0xA1, 0xFE);
_citrus_BIG5_fill_rowcol(ei, "col", 0x40, 0x7E);
_citrus_BIG5_fill_rowcol(ei, "col", 0xA1, 0xFE);
_citrus_BIG5_fill_rowcol((void **)&ei, "row", 0xA1, 0xFE);
_citrus_BIG5_fill_rowcol((void **)&ei, "col", 0x40, 0x7E);
_citrus_BIG5_fill_rowcol((void **)&ei, "col", 0xA1, 0xFE);
return 0;
}

View File

@ -0,0 +1,727 @@
/* $NetBSD: citrus_hz.c,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.
*
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_hz.c,v 1.1 2006/11/22 23:38:27 tnozaki Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/queue.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <locale.h>
#include <limits.h>
#include <wchar.h>
#include "citrus_namespace.h"
#include "citrus_types.h"
#include "citrus_bcs.h"
#include "citrus_module.h"
#include "citrus_ctype.h"
#include "citrus_stdenc.h"
#include "citrus_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 start, end, 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;
size_t length;
#define ROWCOL_MAX 3
escape_t *escape;
} graphic_t;
typedef TAILQ_HEAD(escape_list, escape_t) escape_list;
struct escape_t {
TAILQ_ENTRY(escape_t) entry;
int ch;
graphic_t *left, *right;
escape_list *set;
};
#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;
_DIAGASSERT(set != NULL);
TAILQ_FOREACH(escape, set, entry) {
if (ESC(escape) == ch)
break;
}
return escape;
}
typedef struct {
escape_list e0, e1;
graphic_t *ascii, *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 {
int chlen;
char ch[ROWCOL_MAX];
escape_t *inuse;
} _HZState;
typedef struct {
_HZEncodingInfo ei;
struct {
/* for future multi-locale facility */
_HZState s_mblen;
_HZState s_mbrlen;
_HZState s_mbrtowc;
_HZState s_mbtowc;
_HZState s_mbsrtowcs;
_HZState s_wcrtomb;
_HZState s_wcsrtombs;
_HZState s_wctomb;
} states;
} _HZCTypeInfo;
#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 _CTYPE_INFO _HZCTypeInfo
#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)
{
_DIAGASSERT(ei != NULL);
_DIAGASSERT(psenc != NULL);
psenc->chlen = 0;
psenc->inuse = INIT0(ei);
}
static __inline void
/*ARGSUSED*/
_citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei,
void *__restrict pspriv, const _HZState * __restrict psenc)
{
/* ei may be unused */
_DIAGASSERT(pspriv != NULL);
_DIAGASSERT(psenc != NULL);
memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
}
static __inline void
/*ARGSUSED*/
_citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei,
_HZState * __restrict psenc, const void * __restrict pspriv)
{
/* ei may be unused */
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(pspriv != NULL);
memcpy((void *)psenc, pspriv, sizeof(*psenc));
}
static int
_citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
_HZState * __restrict psenc, size_t * __restrict nresult)
{
const char *s0;
wchar_t wc;
int bit, head, tail, len, ch;
graphic_t *graphic;
escape_t *candidate, *init;
const range_t *range;
_DIAGASSERT(ei != NULL);
/* pwc may be null */
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
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);
_DIAGASSERT(init != NULL);
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;
}
_DIAGASSERT(graphic != NULL);
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)
{
int bit, ch;
escape_t *candidate, *init;
graphic_t *graphic;
size_t len;
const range_t *range;
_DIAGASSERT(ei != NULL);
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
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;
_DIAGASSERT(ei != NULL);
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
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)
{
_DIAGASSERT(ei != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(rstate != NULL);
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,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
int bit;
_DIAGASSERT(csid != NULL);
_DIAGASSERT(idx != NULL);
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,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
_DIAGASSERT(ei != NULL);
_DIAGASSERT(wc != NULL);
*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;
_DIAGASSERT(ei != NULL);
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, const char *s)
{
void **p;
escape_t *escape;
_DIAGASSERT(context != NULL && *context != NULL);
_DIAGASSERT(name != NULL);
_DIAGASSERT(s != NULL);
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)
{
void **p;
_HZEncodingInfo *ei;
escape_t *escape;
graphic_t *graphic;
_DIAGASSERT(context != NULL && *context != NULL);
_DIAGASSERT(name != NULL);
_DIAGASSERT(s != NULL);
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];
_DIAGASSERT(context != NULL);
_DIAGASSERT(name != NULL);
_DIAGASSERT(s != NULL);
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;
_DIAGASSERT(ei != NULL);
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 ctype
*/
_CITRUS_CTYPE_DECLS(HZ);
_CITRUS_CTYPE_DEF_OPS(HZ);
#include "citrus_ctype_template.h"
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(HZ);
_CITRUS_STDENC_DEF_OPS(HZ);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $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_CTYPE_GETOPS_FUNC(HZ);
_CITRUS_STDENC_GETOPS_FUNC(HZ);
__END_DECLS
#endif

View File

@ -0,0 +1,514 @@
/* $NetBSD: citrus_zw.c,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.
*
*/
#include <sys/cdefs.h>
#if defined(LIB_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_zw.c,v 1.1 2006/11/22 23:38:27 tnozaki Exp $");
#endif /* LIB_SCCS and not lint */
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <locale.h>
#include <wchar.h>
#include <limits.h>
#include "citrus_namespace.h"
#include "citrus_types.h"
#include "citrus_module.h"
#include "citrus_ctype.h"
#include "citrus_stdenc.h"
#include "citrus_zw.h"
/* ----------------------------------------------------------------------
* private stuffs used by templates
*/
typedef struct {
int dummy;
} _ZWEncodingInfo;
typedef enum {
NONE, AMBIGIOUS, ASCII, GB2312
} _ZWCharset;
typedef struct {
int chlen;
char ch[4];
_ZWCharset charset;
} _ZWState;
typedef struct {
_ZWEncodingInfo ei;
struct {
/* for future multi-locale facility */
_ZWState s_mblen;
_ZWState s_mbrlen;
_ZWState s_mbrtowc;
_ZWState s_mbtowc;
_ZWState s_mbsrtowcs;
_ZWState s_wcrtomb;
_ZWState s_wcsrtombs;
_ZWState s_wctomb;
} states;
} _ZWCTypeInfo;
#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
#define _FUNCNAME(m) _citrus_ZW_##m
#define _ENCODING_INFO _ZWEncodingInfo
#define _CTYPE_INFO _ZWCTypeInfo
#define _ENCODING_STATE _ZWState
#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
#define _ENCODING_IS_STATE_DEPENDENT 1
#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->charset != NONE)
static __inline void
/*ARGSUSED*/
_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,
_ZWState * __restrict psenc)
{
/* ei my be unused */
_DIAGASSERT(psenc != NULL);
psenc->chlen = 0;
psenc->charset = NONE;
}
static __inline void
/*ARGSUSED*/
_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,
void *__restrict pspriv, const _ZWState * __restrict psenc)
{
/* ei may be unused */
_DIAGASSERT(pspriv != NULL);
_DIAGASSERT(psenc != NULL);
memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
}
static __inline void
/*ARGSUSED*/
_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,
_ZWState * __restrict psenc, const void * __restrict pspriv)
{
/* ei may be unused */
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(pspriv != NULL);
memcpy((void *)psenc, pspriv, sizeof(*psenc));
}
static int
_citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,
wchar_t * __restrict pwc, const char **__restrict s, size_t n,
_ZWState * __restrict psenc, size_t * __restrict nresult)
{
const char *s0;
int ch;
wchar_t wc;
/* ei may be unused */
/* pwc may be null */
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
if (*s == NULL) {
_citrus_ZW_init_state(ei, psenc);
*nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
return 0;
}
s0 = *s;
#define STORE \
do { \
if (n-- < 1) { \
*nresult = (size_t)-2; \
*s = s0; \
return 0; \
} \
ch = (unsigned char)*s0++; \
if (ch > 0x7F) \
goto ilseq; \
psenc->ch[psenc->chlen++] = ch; \
} while (/*CONSTCOND*/0)
loop:
switch (psenc->charset) {
case ASCII:
switch (psenc->chlen) {
case 0:
STORE;
switch (psenc->ch[0]) {
case '\0': case '\n':
psenc->charset = NONE;
}
/*FALLTHROUGH*/
case 1:
break;
default:
return EINVAL;
}
ch = (unsigned char)psenc->ch[0];
if (ch > 0x7F)
goto ilseq;
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
case NONE:
if (psenc->chlen != 0)
return EINVAL;
STORE;
ch = (unsigned char)psenc->ch[0];
if (ch != 'z') {
if (ch != '\n' && ch != '\0')
psenc->charset = ASCII;
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
}
psenc->charset = AMBIGIOUS;
psenc->chlen = 0;
/* FALLTHROUGH */
case AMBIGIOUS:
if (psenc->chlen != 0)
return EINVAL;
STORE;
if (psenc->ch[0] != 'W') {
psenc->charset = ASCII;
wc = L'z';
break;
}
psenc->charset = GB2312;
psenc->chlen = 0;
/* FALLTHROUGH */
case GB2312:
switch (psenc->chlen) {
case 0:
STORE;
ch = (unsigned char)psenc->ch[0];
if (ch == '\0') {
psenc->charset = NONE;
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
} else if (ch == '\n') {
psenc->charset = NONE;
psenc->chlen = 0;
goto loop;
}
/*FALLTHROUGH*/
case 1:
STORE;
if (psenc->ch[0] == ' ') {
ch = (unsigned char)psenc->ch[1];
if (ch == ' ')
goto ilseq;
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
} else if (psenc->ch[0] == '#') {
ch = (unsigned char)psenc->ch[1];
if (ch == '\n') {
psenc->charset = NONE;
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
} else if (ch == ' ') {
wc = (wchar_t)ch;
psenc->chlen = 0;
break;
}
}
ch = (unsigned char)psenc->ch[0];
if (ch < 0x21 || ch > 0x7E)
goto ilseq;
wc = (wchar_t)(ch << 8);
ch = (unsigned char)psenc->ch[1];
if (ch < 0x21 || ch > 0x7E) {
ilseq:
*nresult = (size_t)-1;
return EILSEQ;
}
wc |= (wchar_t)ch;
psenc->chlen = 0;
break;
default:
return EINVAL;
}
break;
default:
return EINVAL;
}
if (pwc != NULL)
*pwc = wc;
*nresult = (size_t)(wc == 0 ? 0 : s0 - *s);
*s = s0;
return 0;
}
static int
/*ARGSUSED*/
_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,
char *__restrict s, size_t n, wchar_t wc,
_ZWState * __restrict psenc, size_t * __restrict nresult)
{
int ch;
/* ei may be null */
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
if (psenc->chlen != 0)
return EINVAL;
if ((uint32_t)wc <= 0x7F) {
ch = (unsigned char)wc;
switch (psenc->charset) {
case NONE:
if (ch == '\0' || ch == '\n') {
psenc->ch[psenc->chlen++] = ch;
} else {
if (n < 4)
return E2BIG;
n -= 4;
psenc->ch[psenc->chlen++] = 'z';
psenc->ch[psenc->chlen++] = 'W';
psenc->ch[psenc->chlen++] = ' ';
psenc->ch[psenc->chlen++] = ch;
psenc->charset = GB2312;
}
break;
case GB2312:
if (n < 2)
return E2BIG;
n -= 2;
if (ch == '\0') {
psenc->ch[psenc->chlen++] = '\n';
psenc->ch[psenc->chlen++] = '\0';
psenc->charset = NONE;
} else if (ch == '\n') {
psenc->ch[psenc->chlen++] = '#';
psenc->ch[psenc->chlen++] = '\n';
psenc->charset = NONE;
} else {
psenc->ch[psenc->chlen++] = ' ';
psenc->ch[psenc->chlen++] = ch;
}
break;
default:
return EINVAL;
}
} else if ((uint32_t)wc <= 0x7E7E) {
switch (psenc->charset) {
case NONE:
if (n < 2)
return E2BIG;
n -= 2;
psenc->ch[psenc->chlen++] = 'z';
psenc->ch[psenc->chlen++] = 'W';
psenc->charset = GB2312;
/* FALLTHROUGH*/
case GB2312:
if (n < 2)
return E2BIG;
n -= 2;
ch = (wc >> 8) & 0xFF;
if (ch < 0x21 || ch > 0x7E)
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
ch = wc & 0xFF;
if (ch < 0x21 || ch > 0x7E)
goto ilseq;
psenc->ch[psenc->chlen++] = ch;
break;
default:
return EINVAL;
}
} else {
ilseq:
*nresult = (size_t)-1;
return EILSEQ;
}
memcpy(s, psenc->ch, psenc->chlen);
*nresult = psenc->chlen;
psenc->chlen = 0;
return 0;
}
static int
/*ARGSUSED*/
_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,
char * __restrict s, size_t n,
_ZWState * __restrict psenc, size_t * __restrict nresult)
{
/* ei may be unused */
_DIAGASSERT(s != NULL);
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(nresult != NULL);
if (psenc->chlen != 0)
return EINVAL;
switch (psenc->charset) {
case GB2312:
if (n-- < 1)
return E2BIG;
psenc->ch[psenc->chlen++] = '\n';
psenc->charset = NONE;
/*FALLTHROUGH*/
case NONE:
*nresult = psenc->chlen;
if (psenc->chlen > 0) {
memcpy(s, psenc->ch, psenc->chlen);
psenc->chlen = 0;
}
break;
default:
return EINVAL;
}
return 0;
}
static __inline int
/*ARGSUSED*/
_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,
_ZWState * __restrict psenc, int * __restrict rstate)
{
/* ei may be unused */
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(rstate != NULL);
switch (psenc->charset) {
case NONE:
if (psenc->chlen != 0)
return EINVAL;
*rstate = _STDENC_SDGEN_INITIAL;
break;
case AMBIGIOUS:
if (psenc->chlen != 0)
return EINVAL;
*rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
break;
case ASCII:
case GB2312:
switch (psenc->chlen) {
case 0:
*rstate = _STDENC_SDGEN_STABLE;
break;
case 1:
*rstate = (psenc->ch[0] == '#')
? _STDENC_SDGEN_INCOMPLETE_SHIFT
: _STDENC_SDGEN_INCOMPLETE_CHAR;
break;
default:
return EINVAL;
}
break;
default:
return EINVAL;
}
return 0;
}
static __inline int
/*ARGSUSED*/
_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,
_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
{
/* ei seems to be unused */
_DIAGASSERT(csid != NULL);
_DIAGASSERT(idx != NULL);
*csid = (_csid_t)(wc <= 0x7FU) ? 0 : 1;
*idx = (_index_t)wc;
return 0;
}
static __inline int
/*ARGSUSED*/
_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,
wchar_t * __restrict wc, _csid_t csid, _index_t idx)
{
/* ei seems to be unused */
_DIAGASSERT(wc != NULL);
switch (csid) {
case 0: case 1:
break;
default:
return EINVAL;
}
*wc = (wchar_t)idx;
return 0;
}
static void
/*ARGSUSED*/
_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei)
{
}
static int
/*ARGSUSED*/
_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,
const void *__restrict var, size_t lenvar)
{
return 0;
}
/* ----------------------------------------------------------------------
* public interface for ctype
*/
_CITRUS_CTYPE_DECLS(ZW);
_CITRUS_CTYPE_DEF_OPS(ZW);
#include "citrus_ctype_template.h"
/* ----------------------------------------------------------------------
* public interface for stdenc
*/
_CITRUS_STDENC_DECLS(ZW);
_CITRUS_STDENC_DEF_OPS(ZW);
#include "citrus_stdenc_template.h"

View File

@ -0,0 +1,37 @@
/* $NetBSD: citrus_zw.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_ZW_H_
#define _CITRUS_ZW_H_
__BEGIN_DECLS
_CITRUS_CTYPE_GETOPS_FUNC(ZW);
_CITRUS_STDENC_GETOPS_FUNC(ZW);
__END_DECLS
#endif

View File

@ -0,0 +1,8 @@
# $NetBSD: HZ.src,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
NAME "HZ"
ENCODING "HZ"
VARIABLE "0='CH:};GL:ASCII','CH:{;GL:GB2312'"
DEFCSID "ISO646-US" 0x0
DEFCSID "GB2312" 0x8000
INVALID 0x3F # '?'

View File

@ -0,0 +1,9 @@
# $NetBSD: HZ8.src,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
NAME "HZ8"
ENCODING "HZ"
VARIABLE "0='CH:};GL:ASCII','CH:{;GR:GB2312'"
DEFCSID "ISO646-US" 0x0
DEFCSID "ISO-8859-1:GR" 0x80
DEFCSID "GB2312" 0x8080
INVALID 0x3F # '?'

View File

@ -0,0 +1,8 @@
# $NetBSD: ZW.src,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
NAME "ZW"
ENCODING "ZW"
VARIABLE ""
DEFCSID "ISO646-US" 0
DEFCSID "GB2312" 1
INVALID 0x3F # '?'

View File

@ -1,9 +1,10 @@
# $NetBSD: esdb.alias.MISC.src,v 1.11 2006/11/13 15:16:30 tnozaki Exp $
# $NetBSD: esdb.alias.MISC.src,v 1.12 2006/11/22 23:38:27 tnozaki Exp $
c99 C99
ctext CTEXT
gb18030 GB18030
gbk GBK
HZ-GB2312 HZ
java JAVA
CP1361 JOHAB
csPTCP154 PTCP154

View File

@ -1,4 +1,4 @@
# $NetBSD: esdb.dir.MISC.src,v 1.11 2006/11/13 15:16:30 tnozaki Exp $
# $NetBSD: esdb.dir.MISC.src,v 1.12 2006/11/22 23:38:27 tnozaki Exp $
ATARIST MISC/ATARIST.esdb
C99 MISC/C99.esdb
@ -6,8 +6,11 @@ CTEXT MISC/CTEXT.esdb
GB18030 MISC/GB18030.esdb
GBK MISC/GBK.esdb
HP-ROMAN8 MISC/HP-ROMAN8.esdb
HZ MISC/HZ.esdb
HZ8 MISC/HZ8.esdb
JAVA MISC/JAVA.esdb
JOHAB MISC/JOHAB.esdb
NEXTSTEP MISC/NEXTSTEP.esdb
PTCP154 MISC/PTCP154.esdb
Shift_JIS MISC/Shift_JIS.esdb
ZW MISC/ZW.esdb