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:
parent
ec21dc99eb
commit
8033a5b008
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.1 2006/11/22 23:38:27 tnozaki Exp $
|
||||
|
||||
SRCPRE=citrus_
|
||||
.include <bsd.lib.mk>
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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 # '?'
|
|
@ -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 # '?'
|
|
@ -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 # '?'
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue