correct wcrtomb(3) - it is not conforming to standard on handling L'\0'.

This change also affects Citrus iconv engine.
This commit is contained in:
tshiozak 2003-06-26 12:09:56 +00:00
parent 537ec5768d
commit f3995f1ad3
15 changed files with 167 additions and 85 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_ctype_template.h,v 1.22 2003/06/25 09:51:28 tshiozak Exp $ */
/* $NetBSD: citrus_ctype_template.h,v 1.23 2003/06/26 12:09:56 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -71,7 +71,7 @@
* you need to define the macros below:
*
* _FUNCNAME(method) :
* It should convine the real function name for the method.
* It should convine the real function name for the method.
* e.g. _FUNCNAME(mbrtowc) should be expanded to
* _EUC_ctype_mbrtowc
* for EUC locale.
@ -132,7 +132,12 @@ static void _FUNCNAME(pack_state)(_ENCODING_INFO * __restrict,
static void _FUNCNAME(unpack_state)(_ENCODING_INFO * __restrict,
_ENCODING_STATE * __restrict,
const void * __restrict);
#if _ENCODING_IS_STATE_DEPENDENT
static int _FUNCNAME(put_state_reset)(_ENCODING_INFO * __restrict,
char * __restrict, size_t,
_ENCODING_STATE * __restrict,
size_t * __restrict);
#endif
/*
* standard form of mbrtowc_priv.
@ -537,7 +542,8 @@ _FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
ei = _CEI_TO_EI(_TO_CEI(cl));
_FUNCNAME(init_state)(ei, &state);
err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, n, &state, nresult);
err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, n,
&state, nresult);
if (*nresult == (size_t)-2) {
err = EILSEQ;
*nresult = (size_t)-1;
@ -570,6 +576,7 @@ _FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
_ENCODING_STATE *psenc;
char buf[MB_LEN_MAX];
int err = 0;
size_t sz;
_DIAGASSERT(cl != NULL);
@ -582,9 +589,24 @@ _FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
}
_RESTART_BEGIN(wcrtomb, _TO_CEI(cl), pspriv, psenc);
err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s,
_ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))),
wc, psenc, nresult);
sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
#if _ENCODING_IS_STATE_DEPENDENT
if (wc == L'\0') {
size_t rsz;
/* reset state */
err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
sz, psenc, &rsz);
if (err)
goto quit;
s += rsz;
sz -= rsz;
}
#endif
err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, sz,
wc, psenc, nresult);
#if _ENCODING_IS_STATE_DEPENDENT
quit:
#endif
if (err == E2BIG)
err = EINVAL;
_RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc);
@ -639,7 +661,7 @@ _FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
{
_ENCODING_STATE *psenc;
_ENCODING_INFO *ei;
size_t nr;
size_t nr, sz;
int err = 0;
_DIAGASSERT(cl != NULL);
@ -653,9 +675,22 @@ _FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
*nresult = _ENCODING_IS_STATE_DEPENDENT;
return 0;
}
err = _FUNCNAME(wcrtomb_priv)(ei, s, _ENCODING_MB_CUR_MAX(ei), wc,
psenc, &nr);
sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
#if _ENCODING_IS_STATE_DEPENDENT
if (wc == L'\0') {
size_t rsz;
/* reset state */
err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
sz, psenc, &rsz);
if (err) {
*nresult = -1;
return err;
}
s += rsz;
sz -= rsz;
}
#endif
err = _FUNCNAME(wcrtomb_priv)(ei, s, sz, wc, psenc, &nr);
*nresult = (int)nr;
return 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_namespace.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $ */
/* $NetBSD: citrus_namespace.h,v 1.2 2003/06/26 12:09:56 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -206,6 +206,7 @@
#define _stdenc_cstomb _citrus_stdenc_cstomb
#define _stdenc_mbtowc _citrus_stdenc_mbtowc
#define _stdenc_wctomb _citrus_stdenc_wctomb
#define _stdenc_put_state_reset _citrus_stdenc_put_state_reset
#define _stdenc_get_state_size _citrus_stdenc_get_state_size
#define _stdenc_get_mb_cur_max _citrus_stdenc_get_mb_cur_max
#endif /* _CITRUS_STDENC_NO_NAMESPACE */

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_none.c,v 1.9 2003/06/25 09:51:38 tshiozak Exp $ */
/* $NetBSD: citrus_none.c,v 1.10 2003/06/26 12:09:56 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_none.c,v 1.9 2003/06/25 09:51:38 tshiozak Exp $");
__RCSID("$NetBSD: citrus_none.c,v 1.10 2003/06/26 12:09:56 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -465,3 +465,16 @@ _citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce,
return (0);
}
static int
/*ARGSUSED*/
_citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce,
char * __restrict s, size_t n,
void * __restrict pspriv,
size_t * __restrict nresult)
{
*nresult = 0;
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_stdenc.h,v 1.1 2003/06/25 09:51:40 tshiozak Exp $ */
/* $NetBSD: citrus_stdenc.h,v 1.2 2003/06/26 12:09:56 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -91,6 +91,16 @@ _citrus_stdenc_wctomb(struct _citrus_stdenc * __restrict ce,
return (*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult);
}
static __inline int
_citrus_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce,
char * __restrict s, size_t n,
void * __restrict ps,
size_t * __restrict nresult)
{
_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_put_state_reset);
return (*ce->ce_ops->eo_put_state_reset)(ce, s, n, ps, nresult);
}
static __inline size_t
_citrus_stdenc_get_state_size(struct _citrus_stdenc *ce)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_stdenc_local.h,v 1.1 2003/06/25 09:51:40 tshiozak Exp $ */
/* $NetBSD: citrus_stdenc_local.h,v 1.2 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -60,7 +60,10 @@ static int _citrus_##_e_##_stdenc_mbtowc \
void * __restrict, size_t * __restrict); \
static int _citrus_##_e_##_stdenc_wctomb \
(struct _citrus_stdenc * __restrict, char * __restrict, size_t, \
_citrus_wc_t, void * __restrict, size_t * __restrict)
_citrus_wc_t, void * __restrict, size_t * __restrict); \
static int _citrus_##_e_##_stdenc_put_state_reset \
(struct _citrus_stdenc * __restrict, char * __restrict, size_t, \
void * __restrict, size_t * __restrict)
#define _CITRUS_STDENC_DEF_OPS(_e_) \
struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \
@ -72,6 +75,7 @@ struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \
/* eo_cstomb */ &_citrus_##_e_##_stdenc_cstomb, \
/* eo_mbtowc */ &_citrus_##_e_##_stdenc_mbtowc, \
/* eo_wctomb */ &_citrus_##_e_##_stdenc_wctomb, \
/* eo_put_state_reset */&_citrus_##_e_##_stdenc_put_state_reset \
}
typedef int (*_citrus_stdenc_init_t)
@ -97,6 +101,9 @@ typedef int (*_citrus_stdenc_mbtowc_t)
typedef int (*_citrus_stdenc_wctomb_t)
(struct _citrus_stdenc *__restrict, char * __restrict, size_t,
_citrus_wc_t, void * __restrict, size_t * __restrict);
typedef int (*_citrus_stdenc_put_state_reset_t)
(struct _citrus_stdenc *__restrict, char * __restrict, size_t,
void * __restrict, size_t * __restrict);
/*
* ABI version change log
@ -114,6 +121,7 @@ struct _citrus_stdenc_ops {
_citrus_stdenc_cstomb_t eo_cstomb;
_citrus_stdenc_mbtowc_t eo_mbtowc;
_citrus_stdenc_wctomb_t eo_wctomb;
_citrus_stdenc_put_state_reset_t eo_put_state_reset;
};
struct _citrus_stdenc_traits {

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_stdenc_template.h,v 1.1 2003/06/25 09:51:41 tshiozak Exp $ */
/* $NetBSD: citrus_stdenc_template.h,v 1.2 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -169,3 +169,18 @@ _FUNCNAME(stdenc_wctomb)(struct _citrus_stdenc * __restrict ce,
return _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps),
nresult);
}
static int
_FUNCNAME(stdenc_put_state_reset)(struct _citrus_stdenc * __restrict ce,
char * __restrict s, size_t n,
void * __restrict ps,
size_t * __restrict nresult)
{
#if _ENCODING_IS_STATE_DEPENDENT
return _FUNCNAME(put_state_reset)(_CE_TO_EI(ce), s, n, _TO_STATE(ps),
nresult);
#else
*nresult = 0;
return 0;
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $ */
/* $NetBSD: citrus_big5.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -64,7 +64,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $");
__RCSID("$NetBSD: citrus_big5.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -291,12 +291,6 @@ _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei,
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
/* check invalid sequence */
if (wc & ~0xffff) {
ret = EILSEQ;

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_euc.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $ */
/* $NetBSD: citrus_euc.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -64,7 +64,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_euc.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $");
__RCSID("$NetBSD: citrus_euc.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -309,12 +309,6 @@ _citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc,
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
m = wc & ei->mask;
nm = wc & ~m;

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_euctw.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $ */
/* $NetBSD: citrus_euctw.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -56,7 +56,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_euctw.c,v 1.6 2003/06/25 09:51:42 tshiozak Exp $");
__RCSID("$NetBSD: citrus_euctw.c,v 1.7 2003/06/26 12:09:57 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -305,12 +305,6 @@ _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei,
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
clen = 1;
if (wc & 0x00007f00)
clen = 2;

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_gbk2k.c,v 1.3 2003/06/25 09:51:42 tshiozak Exp $ */
/* $NetBSD: citrus_gbk2k.c,v 1.4 2003/06/26 12:09:57 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_gbk2k.c,v 1.3 2003/06/25 09:51:42 tshiozak Exp $");
__RCSID("$NetBSD: citrus_gbk2k.c,v 1.4 2003/06/26 12:09:57 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -285,12 +285,6 @@ _citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
goto err;
}
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
len = _mb_count(wc);
if (n < len) {
ret = E2BIG;

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_iconv_std.c,v 1.1 2003/06/25 09:51:43 tshiozak Exp $ */
/* $NetBSD: citrus_iconv_std.c,v 1.2 2003/06/26 12:09:58 tshiozak Exp $ */
/*-
* Copyright (c)2003 Citrus Project,
@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_iconv_std.c,v 1.1 2003/06/25 09:51:43 tshiozak Exp $");
__RCSID("$NetBSD: citrus_iconv_std.c,v 1.2 2003/06/26 12:09:58 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -127,6 +127,13 @@ wctombx(struct _citrus_iconv_std_encoding *se,
return _stdenc_wctomb(se->se_handle, s, n, wc, se->se_ps, nresult);
}
static __inline int
put_state_resetx(struct _citrus_iconv_std_encoding *se,
char *s, size_t n, size_t *nresult)
{
return _stdenc_put_state_reset(se->se_handle, s, n, se->se_ps, nresult);
}
/*
* open/close an encoding.
@ -442,11 +449,10 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict ci,
save_encoding_state(&is->is_src_encoding);
save_encoding_state(&is->is_dst_encoding);
szrout = 0;
ret = cstombx(&is->is_dst_encoding,
*out, *outbytes,
_CITRUS_CSID_INVALID,
0, &szrout);
ret = put_state_resetx(&is->is_dst_encoding,
*out, *outbytes,
&szrout);
if (ret)
goto err;
@ -487,6 +493,7 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict ci,
if (ret) {
if (ret == E_NO_CORRESPONDING_CHAR) {
inval ++;
szrout = 0;
if ((flags&_CITRUS_ICONV_F_HIDE_INVALID)==0 &&
is->is_use_invalid) {
ret = wctombx(&is->is_dst_encoding,

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_iso2022.c,v 1.7 2003/06/25 09:51:44 tshiozak Exp $ */
/* $NetBSD: citrus_iso2022.c,v 1.8 2003/06/26 12:09:58 tshiozak Exp $ */
/*-
* Copyright (c)1999, 2002 Citrus Project,
@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_iso2022.c,v 1.7 2003/06/25 09:51:44 tshiozak Exp $");
__RCSID("$NetBSD: citrus_iso2022.c,v 1.8 2003/06/26 12:09:58 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -1150,9 +1150,8 @@ sideok:
i = isthree(cs.final) ? 3 : 2;
break;
}
if (wc != 0)
while (i-- > 0)
*p++ = ((wc >> (i << 3)) & 0x7f) | mask;
while (i-- > 0)
*p++ = ((wc >> (i << 3)) & 0x7f) | mask;
/* reset single shift state */
psenc->singlegl = psenc->singlegr = -1;
@ -1169,6 +1168,42 @@ sideok:
return len;
}
static int
_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
char * __restrict s, size_t n,
_ISO2022State * __restrict psenc,
size_t * __restrict nresult)
{
char buf[MB_LEN_MAX];
char *result;
int len, ret;
_DIAGASSERT(ei != NULL);
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* XXX state will be modified after this operation... */
len = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc);
if (len==0) {
ret = EINVAL;
goto err;
}
if (sizeof(buf) < len || n < len-1) {
/* XXX should recover state? */
ret = E2BIG;
goto err;
}
memcpy(s, buf, len-1);
*nresult = (size_t)(len-1);
return (0);
err:
/* bound check failure */
*nresult = (size_t)-1;
return ret;
}
static int
_citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
char * __restrict s, size_t n, wchar_t wc,

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_mskanji.c,v 1.6 2003/06/25 09:51:48 tshiozak Exp $ */
/* $NetBSD: citrus_mskanji.c,v 1.7 2003/06/26 12:09:58 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -62,7 +62,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_mskanji.c,v 1.6 2003/06/25 09:51:48 tshiozak Exp $");
__RCSID("$NetBSD: citrus_mskanji.c,v 1.7 2003/06/26 12:09:58 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -275,12 +275,6 @@ _citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei,
_DIAGASSERT(psenc != NULL);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
/* check invalid sequence */
if (wc & ~0xffff) {
ret = EILSEQ;

View File

@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_utf1632.c,v 1.1 2003/06/25 09:51:49 tshiozak Exp $");
__RCSID("$NetBSD: citrus_utf1632.c,v 1.2 2003/06/26 12:09:58 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -249,12 +249,6 @@ _citrus_UTF1632_wcrtomb_priv(_UTF1632EncodingInfo *ei, char *s, size_t n,
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
wc2 = 0;
if ((ei->mode & _MODE_UTF32)==0) {
/* UTF16 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: citrus_utf8.c,v 1.8 2003/06/25 09:51:49 tshiozak Exp $ */
/* $NetBSD: citrus_utf8.c,v 1.9 2003/06/26 12:09:58 tshiozak Exp $ */
/*-
* Copyright (c)2002 Citrus Project,
@ -64,7 +64,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: citrus_utf8.c,v 1.8 2003/06/25 09:51:49 tshiozak Exp $");
__RCSID("$NetBSD: citrus_utf8.c,v 1.9 2003/06/26 12:09:58 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
@ -301,12 +301,6 @@ _citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei, char *s, size_t n, wchar_t wc,
_DIAGASSERT(nresult != 0);
_DIAGASSERT(s != NULL);
/* reset state */
if (wc == 0) {
*nresult = 0; /* stateless */
return 0;
}
cnt = _UTF8_findlen(wc);
if (cnt <= 0 || cnt > 6) {
/* invalid UCS4 value */