From 85a67e61f75c076ff4d0b497160a3065fe39fc5c Mon Sep 17 00:00:00 2001 From: joerg Date: Tue, 28 May 2013 16:57:56 +0000 Subject: [PATCH] Add mbsnrtowcs and wcsnrtombs. Approved by core. --- distrib/sets/lists/debug/mi | 3 +- distrib/sets/lists/tests/mi | 3 +- include/wchar.h | 11 +- lib/libc/citrus/citrus_ctype.c | 8 +- lib/libc/citrus/citrus_ctype.h | 22 ++- lib/libc/citrus/citrus_ctype_fallback.c | 123 ++++++++++++++- lib/libc/citrus/citrus_ctype_fallback.h | 14 +- lib/libc/citrus/citrus_ctype_local.h | 36 ++++- lib/libc/citrus/citrus_ctype_template.h | 177 +++++++++++++++++++++- lib/libc/citrus/citrus_none.c | 87 ++++++++++- lib/libc/citrus/modules/citrus_big5.c | 6 +- lib/libc/citrus/modules/citrus_dechanyu.c | 6 +- lib/libc/citrus/modules/citrus_euc.c | 6 +- lib/libc/citrus/modules/citrus_euctw.c | 6 +- lib/libc/citrus/modules/citrus_gbk2k.c | 6 +- lib/libc/citrus/modules/citrus_hz.c | 6 +- lib/libc/citrus/modules/citrus_iso2022.c | 6 +- lib/libc/citrus/modules/citrus_johab.c | 6 +- lib/libc/citrus/modules/citrus_mskanji.c | 6 +- lib/libc/citrus/modules/citrus_ues.c | 6 +- lib/libc/citrus/modules/citrus_utf7.c | 6 +- lib/libc/citrus/modules/citrus_utf8.c | 6 +- lib/libc/citrus/modules/citrus_viqr.c | 6 +- lib/libc/citrus/modules/citrus_zw.c | 6 +- lib/libc/locale/multibyte_amd1.c | 27 +++- lib/libc/locale/multibyte_c90.c | 31 +++- tests/lib/libc/locale/Makefile | 3 +- tests/lib/libc/locale/t_mbsnrtowcs.c | 97 ++++++++++++ 28 files changed, 672 insertions(+), 54 deletions(-) create mode 100644 tests/lib/libc/locale/t_mbsnrtowcs.c diff --git a/distrib/sets/lists/debug/mi b/distrib/sets/lists/debug/mi index 93aa653e6d0b..e032c560a27f 100644 --- a/distrib/sets/lists/debug/mi +++ b/distrib/sets/lists/debug/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.22 2013/05/08 17:41:31 christos Exp $ +# $NetBSD: mi,v 1.23 2013/05/28 16:57:56 joerg Exp $ ./etc/mtree/set.debug comp-sys-root ./usr/libdata/debug/bin/cat.debug comp-util-debug debug ./usr/libdata/debug/bin/chio.debug comp-util-debug debug @@ -1543,6 +1543,7 @@ ./usr/libdata/debug/usr/tests/lib/libc/locale/t_io.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbrtowc.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbstowcs.debug tests-lib-debug debug,atf +./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbsnrtowcs.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbtowc.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcscspn.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcspbrk.debug tests-lib-debug debug,atf diff --git a/distrib/sets/lists/tests/mi b/distrib/sets/lists/tests/mi index a1049e0106b3..45c0bb275b28 100644 --- a/distrib/sets/lists/tests/mi +++ b/distrib/sets/lists/tests/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.535 2013/04/22 21:06:28 christos Exp $ +# $NetBSD: mi,v 1.536 2013/05/28 16:57:56 joerg Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -1942,6 +1942,7 @@ ./usr/tests/lib/libc/locale/t_io tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbrtowc tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbstowcs tests-lib-tests atf +./usr/tests/lib/libc/locale/t_mbsnrtowcs tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbtowc tests-lib-tests atf ./usr/tests/lib/libc/locale/t_wcscspn tests-lib-tests atf ./usr/tests/lib/libc/locale/t_wcspbrk tests-lib-tests atf diff --git a/include/wchar.h b/include/wchar.h index 28c8181dc19d..541be87e3c3c 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wchar.h,v 1.37 2013/04/19 23:45:15 joerg Exp $ */ +/* $NetBSD: wchar.h,v 1.38 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)1999 Citrus Project, @@ -212,6 +212,11 @@ typedef struct _locale *locale_t; # define __LOCALE_T_DECLARED # endif __BEGIN_DECLS +size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, + size_t, mbstate_t * __restrict); +size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t, + size_t, mbstate_t * __restrict); + int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t); int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t); @@ -246,9 +251,13 @@ size_t mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t, int mbsinit_l(const mbstate_t *, locale_t); size_t mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, + size_t, mbstate_t * __restrict, locale_t); size_t wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t); size_t wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, + size_t, mbstate_t * __restrict, locale_t); int wctob_l(wint_t, locale_t); int fwprintf_l(FILE * __restrict, locale_t, const wchar_t * __restrict, ...); diff --git a/lib/libc/citrus/citrus_ctype.c b/lib/libc/citrus/citrus_ctype.c index 5155dfcfef4e..0cac1411748e 100644 --- a/lib/libc/citrus/citrus_ctype.c +++ b/lib/libc/citrus/citrus_ctype.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype.c,v 1.6 2011/11/19 18:34:21 tnozaki Exp $ */ +/* $NetBSD: citrus_ctype.c,v 1.7 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)1999, 2000, 2001, 2002 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_ctype.c,v 1.6 2011/11/19 18:34:21 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_ctype.c,v 1.7 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -92,6 +92,8 @@ _initctypemodule(_citrus_ctype_t cc, char const *modname, cc->cc_ops->co_wctob = &_citrus_ctype_wctob_fallback; /* FALLTHROUGH */ case 0x00000002: + cc->cc_ops->co_mbsnrtowcs = &_citrus_ctype_mbsnrtowcs_fallback; + cc->cc_ops->co_wcsnrtombs = &_citrus_ctype_wcsnrtombs_fallback; /* FALLTHROUGH */ default: break; @@ -106,10 +108,12 @@ _initctypemodule(_citrus_ctype_t cc, char const *modname, cc->cc_ops->co_mbrtowc == NULL || cc->cc_ops->co_mbsinit == NULL || cc->cc_ops->co_mbsrtowcs == NULL || + cc->cc_ops->co_mbsnrtowcs == NULL || cc->cc_ops->co_mbstowcs == NULL || cc->cc_ops->co_mbtowc == NULL || cc->cc_ops->co_wcrtomb == NULL || cc->cc_ops->co_wcsrtombs == NULL || + cc->cc_ops->co_wcsnrtombs == NULL || cc->cc_ops->co_wcstombs == NULL || cc->cc_ops->co_wctomb == NULL || cc->cc_ops->co_btowc == NULL || diff --git a/lib/libc/citrus/citrus_ctype.h b/lib/libc/citrus/citrus_ctype.h index aeb0a2beaeef..3ece364879f7 100644 --- a/lib/libc/citrus/citrus_ctype.h +++ b/lib/libc/citrus/citrus_ctype.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $ */ +/* $NetBSD: citrus_ctype.h,v 1.3 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -94,6 +94,16 @@ _citrus_ctype_mbsrtowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char **s, nresult); } +static __inline int +_citrus_ctype_mbsnrtowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char **s, + size_t in, size_t n, void *pspriv, size_t *nresult) +{ + + _DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbsnrtowcs && nresult); + return (*cc->cc_ops->co_mbsnrtowcs)(cc, pwcs, s, in, n, + pspriv, nresult); +} + static __inline int _citrus_ctype_mbstowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char *s, size_t n, size_t *nresult) @@ -132,6 +142,16 @@ _citrus_ctype_wcsrtombs(_citrus_ctype_t cc, char *s, const wchar_t **ppwcs, pspriv, nresult); } +static __inline int +_citrus_ctype_wcsnrtombs(_citrus_ctype_t cc, char *s, const wchar_t **ppwcs, + size_t in, size_t n, void *pspriv, size_t *nresult) +{ + + _DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wcsnrtombs && nresult); + return (*cc->cc_ops->co_wcsnrtombs)(cc, s, ppwcs, in, n, + pspriv, nresult); +} + static __inline int _citrus_ctype_wcstombs(_citrus_ctype_t cc, char *s, const wchar_t *wcs, size_t n, size_t *nresult) diff --git a/lib/libc/citrus/citrus_ctype_fallback.c b/lib/libc/citrus/citrus_ctype_fallback.c index 2adbb8b3b45f..860fa55d2fab 100644 --- a/lib/libc/citrus/citrus_ctype_fallback.c +++ b/lib/libc/citrus/citrus_ctype_fallback.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype_fallback.c,v 1.2 2003/06/27 14:52:25 yamt Exp $ */ +/* $NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2003 Citrus Project, @@ -28,13 +28,14 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_ctype_fallback.c,v 1.2 2003/06/27 14:52:25 yamt Exp $"); +__RCSID("$NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" #include #include +#include #include #include #include @@ -108,3 +109,121 @@ _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict cc, return 0; } + +/* + * for ABI version >= 0x00000003 + */ + +int +_citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict cc, + wchar_t * __restrict pwcs, const char ** __restrict s, size_t in, + size_t n, void * __restrict psenc, size_t * __restrict nresult) +{ + int err; + size_t cnt, siz; + const char *s0, *se; + + _DIAGASSERT(nresult != 0); + _DIAGASSERT(psenc != NULL); + _DIAGASSERT(s != NULL); + _DIAGASSERT(*s != NULL); + + /* if pwcs is NULL, ignore n */ + if (pwcs == NULL) + n = 1; /* arbitrary >0 value */ + + err = 0; + cnt = 0; + se = *s + in; + s0 = *s; /* to keep *s unchanged for now, use copy instead. */ + while (s0 < se && n > 0) { + err = _citrus_ctype_mbrtowc(cc, pwcs, s0, (size_t)(se - s0), + psenc, &siz); + if (err) { + cnt = (size_t)-1; + goto bye; + } + if (siz == (size_t)-2) { + s0 = se; + goto bye; + } + switch (siz) { + case 0: + if (pwcs) { + size_t dum; + _citrus_ctype_mbrtowc(cc, NULL, NULL, 0, psenc, + &dum); + } + s0 = 0; + goto bye; + default: + if (pwcs) { + pwcs++; + n--; + } + s0 += siz; + cnt++; + break; + } + } +bye: + if (pwcs) + *s = s0; + + *nresult = cnt; + + return err; +} + +int +_citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict cc, + char * __restrict s, const wchar_t ** __restrict pwcs, size_t in, + size_t n, void * __restrict psenc, size_t * __restrict nresult) +{ + size_t cnt = 0; + int err; + char buf[MB_LEN_MAX]; + size_t siz; + const wchar_t* pwcs0; + mbstate_t state; + + pwcs0 = *pwcs; + + if (!s) + n = 1; + + while (in > 0 && n > 0) { + memcpy(&state, psenc, sizeof(state)); + err = _citrus_ctype_wcrtomb(cc, buf, *pwcs0, psenc, &siz); + if (siz == (size_t)-1) { + *nresult = siz; + return (err); + } + + if (s) { + if (n < siz) { + memcpy(psenc, &state, sizeof(state)); + break; + } + memcpy(s, buf, siz); + s += siz; + n -= siz; + } + cnt += siz; + if (!*pwcs0) { + if (s) { + memset(psenc, 0, sizeof(state)); + } + pwcs0 = 0; + cnt--; /* don't include terminating null */ + break; + } + pwcs0++; + --in; + } + if (s) + *pwcs = pwcs0; + + *nresult = cnt; + return (0); +} diff --git a/lib/libc/citrus/citrus_ctype_fallback.h b/lib/libc/citrus/citrus_ctype_fallback.h index 81a20c79a3cb..e760cef3c7ae 100644 --- a/lib/libc/citrus/citrus_ctype_fallback.h +++ b/lib/libc/citrus/citrus_ctype_fallback.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype_fallback.h,v 1.1 2003/03/05 20:18:15 tshiozak Exp $ */ +/* $NetBSD: citrus_ctype_fallback.h,v 1.2 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2003 Citrus Project, @@ -35,4 +35,16 @@ int _citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict, int _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict, wint_t, int * __restrict); +/* fallback functions for 0x00000003 */ +int _citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict, + wchar_t * __restrict, + const char ** __restrict, size_t, + size_t, void * __restrict, + size_t * __restrict); +int _citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict, + char * __restrict, + const wchar_t ** __restrict, size_t, + size_t, void * __restrict, + size_t * __restrict); + #endif diff --git a/lib/libc/citrus/citrus_ctype_local.h b/lib/libc/citrus/citrus_ctype_local.h index 496994619a4c..cd3e76afbd0f 100644 --- a/lib/libc/citrus/citrus_ctype_local.h +++ b/lib/libc/citrus/citrus_ctype_local.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype_local.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */ +/* $NetBSD: citrus_ctype_local.h,v 1.4 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -60,6 +60,11 @@ static int _citrus_##_e_##_ctype_mbsrtowcs(void * __restrict, \ const char ** __restrict, \ size_t, void * __restrict, \ size_t * __restrict); \ +static int _citrus_##_e_##_ctype_mbsnrtowcs(_citrus_ctype_rec_t * __restrict, \ + wchar_t * __restrict, \ + const char ** __restrict, \ + size_t, size_t, void * __restrict, \ + size_t * __restrict); \ static int _citrus_##_e_##_ctype_mbstowcs(void * __restrict, \ wchar_t * __restrict, \ const char * __restrict, \ @@ -77,6 +82,11 @@ static int _citrus_##_e_##_ctype_wcsrtombs(void * __restrict, \ const wchar_t ** __restrict, \ size_t, void * __restrict, \ size_t * __restrict); \ +static int _citrus_##_e_##_ctype_wcsnrtombs(_citrus_ctype_rec_t * __restrict, \ + char * __restrict, \ + const wchar_t ** __restrict, \ + size_t, size_t, void * __restrict, \ + size_t * __restrict); \ static int _citrus_##_e_##_ctype_wcstombs(void * __restrict, \ char * __restrict, \ const wchar_t * __restrict, \ @@ -107,7 +117,9 @@ _citrus_ctype_ops_rec_t _citrus_##_e_##_ctype_ops = { \ /* co_wcstombs */ &_citrus_##_e_##_ctype_wcstombs, \ /* co_wctomb */ &_citrus_##_e_##_ctype_wctomb, \ /* co_btowc */ &_citrus_##_e_##_ctype_btowc, \ - /* co_wctob */ &_citrus_##_e_##_ctype_wctob \ + /* co_wctob */ &_citrus_##_e_##_ctype_wctob, \ + /* co_mbsnrtowcs */ &_citrus_##_e_##_ctype_mbsnrtowcs, \ + /* co_wcsnrtombs */ &_citrus_##_e_##_ctype_wcsnrtombs, \ } typedef struct _citrus_ctype_ops_rec _citrus_ctype_ops_rec_t; @@ -129,7 +141,10 @@ typedef int (*_citrus_ctype_mbsinit_t) (void * __restrict, const void * __restrict, int * __restrict); typedef int (*_citrus_ctype_mbsrtowcs_t) (void * __restrict, wchar_t * __restrict, const char ** __restrict, - size_t, void * __restrict, + size_t, void * __restrict, size_t * __restrict); +typedef int (*_citrus_ctype_mbsnrtowcs_t) + (_citrus_ctype_rec_t * __restrict, wchar_t * __restrict, + const char ** __restrict, size_t, size_t, void * __restrict, size_t * __restrict); typedef int (*_citrus_ctype_mbstowcs_t) (void * __restrict, wchar_t * __restrict, const char * __restrict, @@ -143,6 +158,10 @@ typedef int (*_citrus_ctype_wcrtomb_t) typedef int (*_citrus_ctype_wcsrtombs_t) (void * __restrict, char * __restrict, const wchar_t ** __restrict, size_t, void * __restrict, size_t * __restrict); +typedef int (*_citrus_ctype_wcsnrtombs_t) + (_citrus_ctype_rec_t * __restrict, char * __restrict, + const wchar_t ** __restrict, size_t, size_t, void * __restrict, + size_t * __restrict); typedef int (*_citrus_ctype_wcstombs_t) (void * __restrict, char * __restrict, const wchar_t * __restrict, size_t, size_t * __restrict); @@ -152,16 +171,20 @@ typedef int (*_citrus_ctype_btowc_t) (_citrus_ctype_rec_t * __restrict, int, wint_t * __restrict); typedef int (*_citrus_ctype_wctob_t) (_citrus_ctype_rec_t * __restrict, wint_t, int * __restrict); +#include "citrus_ctype_fallback.h" /* * ABI Version change log: * 0x00000001 * initial version * 0x00000002 - * ops record: btowc and wctob are added. + * ops record: btowc and wctob added. + * ctype record: unchanged. + * 0x00000003 + * ops record: mbsnrtowcs and wcsnrtombs added. * ctype record: unchanged. */ -#define _CITRUS_CTYPE_ABI_VERSION 0x00000002 +#define _CITRUS_CTYPE_ABI_VERSION 0x00000003 struct _citrus_ctype_ops_rec { uint32_t co_abi_version; /* version 0x00000001 */ @@ -182,6 +205,9 @@ struct _citrus_ctype_ops_rec { /* version 0x00000002 */ _citrus_ctype_btowc_t co_btowc; _citrus_ctype_wctob_t co_wctob; + /* version 0x00000003 */ + _citrus_ctype_mbsnrtowcs_t co_mbsnrtowcs; + _citrus_ctype_wcsnrtombs_t co_wcsnrtombs; }; #define _CITRUS_DEFAULT_CTYPE_NAME "NONE" diff --git a/lib/libc/citrus/citrus_ctype_template.h b/lib/libc/citrus/citrus_ctype_template.h index c61dedf89493..1f0c6ecd9f9e 100644 --- a/lib/libc/citrus/citrus_ctype_template.h +++ b/lib/libc/citrus/citrus_ctype_template.h @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ctype_template.h,v 1.35 2008/02/09 14:56:20 junyoung Exp $ */ +/* $NetBSD: citrus_ctype_template.h,v 1.36 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -85,8 +85,10 @@ * mbrtowc * mbtowc * mbsrtowcs + * mbsnrtowcs * wcrtomb * wcsrtombs + * wcsnrtombs * wctomb * These need to be keeped in the ctype encoding information structure, * pointed by "cei". @@ -238,8 +240,8 @@ _FUNCNAME(mbsrtowcs_priv)(_ENCODING_INFO * __restrict ei, _DIAGASSERT(nresult != 0); _DIAGASSERT(ei != NULL); _DIAGASSERT(psenc != NULL); - _DIAGASSERT(s == NULL); - _DIAGASSERT(*s == NULL); + _DIAGASSERT(s != NULL); + _DIAGASSERT(*s != NULL); /* if pwcs is NULL, ignore n */ if (pwcs == NULL) @@ -282,6 +284,66 @@ bye: return err; } +static int +_FUNCNAME(mbsnrtowcs_priv)(_ENCODING_INFO * __restrict ei, + wchar_t * __restrict pwcs, + const char ** __restrict s, size_t in, + size_t n, _ENCODING_STATE * __restrict psenc, + size_t * __restrict nresult) +{ + int err; + size_t cnt, siz; + const char *s0, *se; + + _DIAGASSERT(nresult != 0); + _DIAGASSERT(ei != NULL); + _DIAGASSERT(psenc != NULL); + _DIAGASSERT(s != NULL); + _DIAGASSERT(*s != NULL); + + /* if pwcs is NULL, ignore n */ + if (pwcs == NULL) + n = 1; /* arbitrary >0 value */ + + err = 0; + cnt = 0; + se = *s + in; + s0 = *s; /* to keep *s unchanged for now, use copy instead. */ + while (s0 < se && n > 0) { + err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, se - s0, + psenc, &siz); + if (err) { + cnt = (size_t)-1; + goto bye; + } + if (siz == (size_t)-2) { + s0 = se; + goto bye; + } + switch (siz) { + case 0: + if (pwcs) { + _FUNCNAME(init_state)(ei, psenc); + } + s0 = 0; + goto bye; + default: + if (pwcs) { + pwcs++; + n--; + } + cnt++; + break; + } + } +bye: + if (pwcs) + *s = s0; + + *nresult = cnt; + + return err; +} static int _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, @@ -289,9 +351,9 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, size_t n, _ENCODING_STATE * __restrict psenc, size_t * __restrict nresult) { - int cnt = 0, err; + int err; char buf[MB_LEN_MAX]; - size_t siz; + size_t cnt, siz; const wchar_t* pwcs0; #if _ENCODING_IS_STATE_DEPENDENT _ENCODING_STATE state; @@ -299,6 +361,7 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, pwcs0 = *pwcs; + cnt = 0; if (!s) n = 1; @@ -338,6 +401,66 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, if (s) *pwcs = pwcs0; + *nresult = cnt; + return (0); +} + +static int +_FUNCNAME(wcsnrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, + const wchar_t ** __restrict pwcs, size_t in, + size_t n, _ENCODING_STATE * __restrict psenc, + size_t * __restrict nresult) +{ + int cnt = 0, err; + char buf[MB_LEN_MAX]; + size_t siz; + const wchar_t* pwcs0; +#if _ENCODING_IS_STATE_DEPENDENT + _ENCODING_STATE state; +#endif + + pwcs0 = *pwcs; + + if (!s) + n = 1; + + while (in > 0 && n > 0) { +#if _ENCODING_IS_STATE_DEPENDENT + state = *psenc; +#endif + err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf), + *pwcs0, psenc, &siz); + if (siz == (size_t)-1) { + *nresult = siz; + return (err); + } + + if (s) { + if (n < siz) { +#if _ENCODING_IS_STATE_DEPENDENT + *psenc = state; +#endif + break; + } + memcpy(s, buf, siz); + s += siz; + n -= siz; + } + cnt += siz; + if (!*pwcs0) { + if (s) { + _FUNCNAME(init_state)(ei, psenc); + } + pwcs0 = 0; + cnt--; /* don't include terminating null */ + break; + } + pwcs0++; + --in; + } + if (s) + *pwcs = pwcs0; + *nresult = (size_t)cnt; return (0); } @@ -525,6 +648,27 @@ _FUNCNAME(ctype_mbsrtowcs)(void * __restrict cl, wchar_t * __restrict pwcs, return (err); } +static int __used +_FUNCNAME(ctype_mbsnrtowcs)(_citrus_ctype_rec_t * __restrict cc, wchar_t * __restrict pwcs, + const char ** __restrict s, size_t in, size_t n, + void * __restrict pspriv, + size_t * __restrict nresult) +{ + void *cl = cc->cc_closure; + _ENCODING_STATE *psenc; + _ENCODING_INFO *ei; + int err = 0; + + _DIAGASSERT(cl != NULL); + + ei = _CEI_TO_EI(_TO_CEI(cl)); + _RESTART_BEGIN(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc); + err = _FUNCNAME(mbsnrtowcs_priv)(ei, pwcs, s, in, n, psenc, nresult); + _RESTART_END(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc); + + return (err); +} + static int _FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs, const char * __restrict s, size_t n, @@ -637,6 +781,29 @@ _FUNCNAME(ctype_wcsrtombs)(void * __restrict cl, char * __restrict s, return err; } +static int __used +/*ARGSUSED*/ +_FUNCNAME(ctype_wcsnrtombs)(_citrus_ctype_rec_t * __restrict cc, + char * __restrict s, + const wchar_t ** __restrict pwcs, size_t in, + size_t n, void * __restrict pspriv, + size_t * __restrict nresult) +{ + void *cl = cc->cc_closure; + _ENCODING_STATE *psenc; + _ENCODING_INFO *ei; + int err = 0; + + _DIAGASSERT(cl != NULL); + + ei = _CEI_TO_EI(_TO_CEI(cl)); + _RESTART_BEGIN(wcsnrtombs, _TO_CEI(cl), pspriv, psenc); + err = _FUNCNAME(wcsnrtombs_priv)(ei, s, pwcs, in, n, psenc, nresult); + _RESTART_END(wcsnrtombs, _TO_CEI(cl), pspriv, psenc); + + return err; +} + static int /*ARGSUSED*/ _FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s, diff --git a/lib/libc/citrus/citrus_none.c b/lib/libc/citrus/citrus_none.c index 047219732aad..381e7434069a 100644 --- a/lib/libc/citrus/citrus_none.c +++ b/lib/libc/citrus/citrus_none.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */ +/* $NetBSD: citrus_none.c,v 1.19 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_none.c,v 1.19 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -184,6 +184,47 @@ _citrus_NONE_ctype_mbsrtowcs(void * __restrict cl, wchar_t * __restrict pwcs, return (0); } +static int +/*ARGSUSED*/ +_citrus_NONE_ctype_mbsnrtowcs(_citrus_ctype_rec_t * __restrict cc, + wchar_t * __restrict pwcs, + const char ** __restrict s, size_t in, size_t n, + void * __restrict pspriv, + size_t * __restrict nresult) +{ + int cnt; + const char *s0; + + /* if pwcs is NULL, ignore n */ + if (pwcs == NULL) + n = 1; /* arbitrary >0 value */ + + cnt = 0; + s0 = *s; /* to keep *s unchanged for now, use copy instead. */ + while (in > 0 && n > 0) { + if (pwcs != NULL) { + *pwcs = (wchar_t)(unsigned char)*s0; + } + if (*s0 == '\0') { + s0 = NULL; + break; + } + s0++; + --in; + if (pwcs != NULL) { + pwcs++; + n--; + } + cnt++; + } + if (pwcs) + *s = s0; + + *nresult = (size_t)cnt; + + return (0); +} + static int _citrus_NONE_ctype_mbstowcs(void * __restrict cl, wchar_t * __restrict wcs, const char * __restrict s, size_t n, @@ -281,6 +322,48 @@ _citrus_NONE_ctype_wcsrtombs(void * __restrict cl, char * __restrict s, return (0); } +static int +/*ARGSUSED*/ +_citrus_NONE_ctype_wcsnrtombs(_citrus_ctype_rec_t * __restrict cc, + char * __restrict s, + const wchar_t ** __restrict pwcs, size_t in, + size_t n, void * __restrict pspriv, + size_t * __restrict nresult) +{ + size_t count; + const wchar_t *pwcs0; + + pwcs0 = *pwcs; + count = 0; + + if (s == NULL) + n = 1; + + while (in > 0 && n > 0) { + if ((*pwcs0 & ~0xFFU) != 0) { + *nresult = (size_t)-1; + return (EILSEQ); + } + if (s != NULL) { + *s++ = (char)*pwcs0; + n--; + } + if (*pwcs0 == L'\0') { + pwcs0 = NULL; + break; + } + count++; + pwcs0++; + --in; + } + if (s != NULL) + *pwcs = pwcs0; + + *nresult = count; + + return (0); +} + static int _citrus_NONE_ctype_wcstombs(void * __restrict cl, char * __restrict s, const wchar_t * __restrict pwcs, size_t n, diff --git a/lib/libc/citrus/modules/citrus_big5.c b/lib/libc/citrus/modules/citrus_big5.c index f42a9300689f..e53a684a9759 100644 --- a/lib/libc/citrus/modules/citrus_big5.c +++ b/lib/libc/citrus/modules/citrus_big5.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_big5.c,v 1.13 2011/05/23 14:53:46 joerg Exp $ */ +/* $NetBSD: citrus_big5.c,v 1.14 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002, 2006 Citrus Project, @@ -60,7 +60,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_big5.c,v 1.13 2011/05/23 14:53:46 joerg Exp $"); +__RCSID("$NetBSD: citrus_big5.c,v 1.14 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -115,8 +115,10 @@ typedef struct { _BIG5State s_mbrtowc; _BIG5State s_mbtowc; _BIG5State s_mbsrtowcs; + _BIG5State s_mbsnrtowcs; _BIG5State s_wcrtomb; _BIG5State s_wcsrtombs; + _BIG5State s_wcsnrtombs; _BIG5State s_wctomb; } states; } _BIG5CTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_dechanyu.c b/lib/libc/citrus/modules/citrus_dechanyu.c index 6e480f6e2c83..0db33eb45dbe 100644 --- a/lib/libc/citrus/modules/citrus_dechanyu.c +++ b/lib/libc/citrus/modules/citrus_dechanyu.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_dechanyu.c,v 1.4 2011/11/19 18:20:13 tnozaki Exp $ */ +/* $NetBSD: citrus_dechanyu.c,v 1.5 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2007 Citrus Project, @@ -27,7 +27,7 @@ */ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_dechanyu.c,v 1.4 2011/11/19 18:20:13 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_dechanyu.c,v 1.5 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -71,8 +71,10 @@ typedef struct { _DECHanyuState s_mbrtowc; _DECHanyuState s_mbtowc; _DECHanyuState s_mbsrtowcs; + _DECHanyuState s_mbsnrtowcs; _DECHanyuState s_wcrtomb; _DECHanyuState s_wcsrtombs; + _DECHanyuState s_wcsnrtombs; _DECHanyuState s_wctomb; } states; } _DECHanyuCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_euc.c b/lib/libc/citrus/modules/citrus_euc.c index 32292f894053..4d5426e948a7 100644 --- a/lib/libc/citrus/modules/citrus_euc.c +++ b/lib/libc/citrus/modules/citrus_euc.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp $ */ +/* $NetBSD: citrus_euc.c,v 1.15 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -60,7 +60,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp $"); +__RCSID("$NetBSD: citrus_euc.c,v 1.15 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -107,8 +107,10 @@ typedef struct { _EUCState s_mbrtowc; _EUCState s_mbtowc; _EUCState s_mbsrtowcs; + _EUCState s_mbsnrtowcs; _EUCState s_wcrtomb; _EUCState s_wcsrtombs; + _EUCState s_wcsnrtombs; _EUCState s_wctomb; } states; } _EUCCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_euctw.c b/lib/libc/citrus/modules/citrus_euctw.c index 7ab35e8857d3..9d6738f557b0 100644 --- a/lib/libc/citrus/modules/citrus_euctw.c +++ b/lib/libc/citrus/modules/citrus_euctw.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp $ */ +/* $NetBSD: citrus_euctw.c,v 1.12 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -56,7 +56,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_euctw.c,v 1.12 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -98,8 +98,10 @@ typedef struct { _EUCTWState s_mbrtowc; _EUCTWState s_mbtowc; _EUCTWState s_mbsrtowcs; + _EUCTWState s_mbsnrtowcs; _EUCTWState s_wcrtomb; _EUCTWState s_wcsrtombs; + _EUCTWState s_wcsnrtombs; _EUCTWState s_wctomb; } states; } _EUCTWCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_gbk2k.c b/lib/libc/citrus/modules/citrus_gbk2k.c index 77d7dd2b30fe..9223e0354151 100644 --- a/lib/libc/citrus/modules/citrus_gbk2k.c +++ b/lib/libc/citrus/modules/citrus_gbk2k.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp $ */ +/* $NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2003 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -72,8 +72,10 @@ typedef struct { _GBK2KState s_mbrtowc; _GBK2KState s_mbtowc; _GBK2KState s_mbsrtowcs; + _GBK2KState s_mbsnrtowcs; _GBK2KState s_wcrtomb; _GBK2KState s_wcsrtombs; + _GBK2KState s_wcsnrtombs; _GBK2KState s_wctomb; } states; } _GBK2KCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_hz.c b/lib/libc/citrus/modules/citrus_hz.c index caebd2f50ba3..0797cf762e9e 100644 --- a/lib/libc/citrus/modules/citrus_hz.c +++ b/lib/libc/citrus/modules/citrus_hz.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp $ */ +/* $NetBSD: citrus_hz.c,v 1.3 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2004, 2006 Citrus Project, @@ -29,7 +29,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_hz.c,v 1.3 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -143,8 +143,10 @@ typedef struct { _HZState s_mbrtowc; _HZState s_mbtowc; _HZState s_mbsrtowcs; + _HZState s_mbsnrtowcs; _HZState s_wcrtomb; _HZState s_wcsrtombs; + _HZState s_wcsnrtombs; _HZState s_wctomb; } states; } _HZCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_iso2022.c b/lib/libc/citrus/modules/citrus_iso2022.c index c31449a6afe4..0b3a0a8012b0 100644 --- a/lib/libc/citrus/modules/citrus_iso2022.c +++ b/lib/libc/citrus/modules/citrus_iso2022.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_iso2022.c,v 1.22 2011/10/10 22:45:45 tnozaki Exp $ */ +/* $NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)1999, 2002 Citrus Project, @@ -30,7 +30,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_iso2022.c,v 1.22 2011/10/10 22:45:45 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -133,8 +133,10 @@ typedef struct { _ISO2022State s_mbrtowc; _ISO2022State s_mbtowc; _ISO2022State s_mbsrtowcs; + _ISO2022State s_mbsnrtowcs; _ISO2022State s_wcrtomb; _ISO2022State s_wcsrtombs; + _ISO2022State s_wcsnrtombs; _ISO2022State s_wctomb; } states; } _ISO2022CTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_johab.c b/lib/libc/citrus/modules/citrus_johab.c index bebf939a5b69..57761e4fed4c 100644 --- a/lib/libc/citrus/modules/citrus_johab.c +++ b/lib/libc/citrus/modules/citrus_johab.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */ +/* $NetBSD: citrus_johab.c,v 1.5 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2006 Citrus Project, @@ -27,7 +27,7 @@ */ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_johab.c,v 1.5 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -71,8 +71,10 @@ typedef struct { _JOHABState s_mbrtowc; _JOHABState s_mbtowc; _JOHABState s_mbsrtowcs; + _JOHABState s_mbsnrtowcs; _JOHABState s_wcrtomb; _JOHABState s_wcsrtombs; + _JOHABState s_wcsnrtombs; _JOHABState s_wctomb; } states; } _JOHABCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_mskanji.c b/lib/libc/citrus/modules/citrus_mskanji.c index c6011c4410a9..808ca35e8c8b 100644 --- a/lib/libc/citrus/modules/citrus_mskanji.c +++ b/lib/libc/citrus/modules/citrus_mskanji.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp $ */ +/* $NetBSD: citrus_mskanji.c,v 1.14 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -62,7 +62,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_mskanji.c,v 1.14 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -107,8 +107,10 @@ typedef struct { _MSKanjiState s_mbrtowc; _MSKanjiState s_mbtowc; _MSKanjiState s_mbsrtowcs; + _MSKanjiState s_mbsnrtowcs; _MSKanjiState s_wcrtomb; _MSKanjiState s_wcsrtombs; + _MSKanjiState s_wcsnrtombs; _MSKanjiState s_wctomb; } states; } _MSKanjiCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_ues.c b/lib/libc/citrus/modules/citrus_ues.c index f31e83d7cb7f..fa818e1f5ea3 100644 --- a/lib/libc/citrus/modules/citrus_ues.c +++ b/lib/libc/citrus/modules/citrus_ues.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_ues.c,v 1.3 2012/02/12 13:51:29 wiz Exp $ */ +/* $NetBSD: citrus_ues.c,v 1.4 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2006 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_ues.c,v 1.3 2012/02/12 13:51:29 wiz Exp $"); +__RCSID("$NetBSD: citrus_ues.c,v 1.4 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -68,8 +68,10 @@ typedef struct { _UESState s_mbrtowc; _UESState s_mbtowc; _UESState s_mbsrtowcs; + _UESState s_mbsnrtowcs; _UESState s_wcrtomb; _UESState s_wcsrtombs; + _UESState s_wcsnrtombs; _UESState s_wctomb; } states; } _UESCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_utf7.c b/lib/libc/citrus/modules/citrus_utf7.c index fabb048b0c0f..eae0ee3eb66b 100644 --- a/lib/libc/citrus/modules/citrus_utf7.c +++ b/lib/libc/citrus/modules/citrus_utf7.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp $ */ +/* $NetBSD: citrus_utf7.c,v 1.6 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2004, 2005 Citrus Project, @@ -29,7 +29,7 @@ #include #if defined(LIB_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_utf7.c,v 1.6 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIB_SCCS and not lint */ #include @@ -79,8 +79,10 @@ typedef struct { _UTF7State s_mbrtowc; _UTF7State s_mbtowc; _UTF7State s_mbsrtowcs; + _UTF7State s_mbsnrtowcs; _UTF7State s_wcrtomb; _UTF7State s_wcsrtombs; + _UTF7State s_wcsnrtombs; _UTF7State s_wctomb; } states; } _UTF7CTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_utf8.c b/lib/libc/citrus/modules/citrus_utf8.c index de22faeaabfd..0b7df8865581 100644 --- a/lib/libc/citrus/modules/citrus_utf8.c +++ b/lib/libc/citrus/modules/citrus_utf8.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp $ */ +/* $NetBSD: citrus_utf8.c,v 1.18 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002 Citrus Project, @@ -60,7 +60,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_utf8.c,v 1.18 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -111,8 +111,10 @@ typedef struct { _UTF8State s_mbrtowc; _UTF8State s_mbtowc; _UTF8State s_mbsrtowcs; + _UTF8State s_mbsnrtowcs; _UTF8State s_wcrtomb; _UTF8State s_wcsrtombs; + _UTF8State s_wcsnrtombs; _UTF8State s_wctomb; } states; } _UTF8CTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_viqr.c b/lib/libc/citrus/modules/citrus_viqr.c index 5d340a13028d..06e744f0658a 100644 --- a/lib/libc/citrus/modules/citrus_viqr.c +++ b/lib/libc/citrus/modules/citrus_viqr.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_viqr.c,v 1.5 2011/11/19 18:20:13 tnozaki Exp $ */ +/* $NetBSD: citrus_viqr.c,v 1.6 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2006 Citrus Project, @@ -29,7 +29,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_viqr.c,v 1.5 2011/11/19 18:20:13 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_viqr.c,v 1.6 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -234,8 +234,10 @@ typedef struct { _VIQRState s_mbrtowc; _VIQRState s_mbtowc; _VIQRState s_mbsrtowcs; + _VIQRState s_mbsnrtowcs; _VIQRState s_wcrtomb; _VIQRState s_wcsrtombs; + _VIQRState s_wcsnrtombs; _VIQRState s_wctomb; } states; } _VIQRCTypeInfo; diff --git a/lib/libc/citrus/modules/citrus_zw.c b/lib/libc/citrus/modules/citrus_zw.c index 485d53a6cbf3..e60f244397b9 100644 --- a/lib/libc/citrus/modules/citrus_zw.c +++ b/lib/libc/citrus/modules/citrus_zw.c @@ -1,4 +1,4 @@ -/* $NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $ */ +/* $NetBSD: citrus_zw.c,v 1.5 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2004, 2006 Citrus Project, @@ -29,7 +29,7 @@ #include #if defined(LIB_SCCS) && !defined(lint) -__RCSID("$NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $"); +__RCSID("$NetBSD: citrus_zw.c,v 1.5 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIB_SCCS and not lint */ #include @@ -77,8 +77,10 @@ typedef struct { _ZWState s_mbrtowc; _ZWState s_mbtowc; _ZWState s_mbsrtowcs; + _ZWState s_mbsnrtowcs; _ZWState s_wcrtomb; _ZWState s_wcsrtombs; + _ZWState s_wcsnrtombs; _ZWState s_wctomb; } states; } _ZWCTypeInfo; diff --git a/lib/libc/locale/multibyte_amd1.c b/lib/libc/locale/multibyte_amd1.c index 67649714b068..723f6ff76095 100644 --- a/lib/libc/locale/multibyte_amd1.c +++ b/lib/libc/locale/multibyte_amd1.c @@ -1,4 +1,4 @@ -/* $NetBSD: multibyte_amd1.c,v 1.12 2013/05/17 12:55:57 joerg Exp $ */ +/* $NetBSD: multibyte_amd1.c,v 1.13 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002, 2008 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: multibyte_amd1.c,v 1.12 2013/05/17 12:55:57 joerg Exp $"); +__RCSID("$NetBSD: multibyte_amd1.c,v 1.13 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -150,6 +150,29 @@ mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps) return mbsrtowcs_l(pwcs, s, n, ps, _current_locale()); } +size_t +mbsnrtowcs_l(wchar_t *pwcs, const char **s, size_t in, size_t n, mbstate_t *ps, + locale_t loc) +{ + size_t ret; + int err0; + + _fixup_ps(_RUNE_LOCALE(loc), ps, s == NULL); + + err0 = _citrus_ctype_mbsnrtowcs(_ps_to_ctype(ps), pwcs, s, in, n, + _ps_to_private(ps), &ret); + if (err0) + errno = err0; + + return ret; +} + +size_t +mbsnrtowcs(wchar_t *pwcs, const char **s, size_t in, size_t n, mbstate_t *ps) +{ + return mbsnrtowcs_l(pwcs, s, in, n, ps, _current_locale()); +} + size_t wcrtomb_l(char *s, wchar_t wc, mbstate_t *ps, locale_t loc) { diff --git a/lib/libc/locale/multibyte_c90.c b/lib/libc/locale/multibyte_c90.c index e5ec03e6dded..5d0d7d0ca6de 100644 --- a/lib/libc/locale/multibyte_c90.c +++ b/lib/libc/locale/multibyte_c90.c @@ -1,4 +1,4 @@ -/* $NetBSD: multibyte_c90.c,v 1.10 2013/05/17 12:55:57 joerg Exp $ */ +/* $NetBSD: multibyte_c90.c,v 1.11 2013/05/28 16:57:56 joerg Exp $ */ /*- * Copyright (c)2002, 2008 Citrus Project, @@ -28,7 +28,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: multibyte_c90.c,v 1.10 2013/05/17 12:55:57 joerg Exp $"); +__RCSID("$NetBSD: multibyte_c90.c,v 1.11 2013/05/28 16:57:56 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -45,6 +45,10 @@ __RCSID("$NetBSD: multibyte_c90.c,v 1.10 2013/05/17 12:55:57 joerg Exp $"); #include "citrus_module.h" #include "citrus_ctype.h" #include "runetype_local.h" +#include "multibyte.h" + +#define _RUNE_LOCALE(loc) \ + ((_RuneLocale *)((loc)->part_impl[(size_t)LC_CTYPE])) #define _CITRUS_CTYPE(loc) \ (((_RuneLocale *)((loc)->part_impl[(size_t)LC_CTYPE]))->rl_citrus_ctype) @@ -126,6 +130,29 @@ wcstombs(char *s, const wchar_t *wcs, size_t n) return wcstombs_l(s, wcs, n, _current_locale()); } +size_t +wcsnrtombs_l(char *s, const wchar_t **ppwcs, size_t in, size_t n, mbstate_t *ps, + locale_t loc) +{ + size_t ret; + int err0; + + _fixup_ps(_RUNE_LOCALE(loc), ps, s == NULL); + + err0 = _citrus_ctype_wcsnrtombs(_ps_to_ctype(ps), s, ppwcs, in, n, + _ps_to_private(ps), &ret); + if (err0) + errno = err0; + + return ret; +} + +size_t +wcsnrtombs(char *s, const wchar_t **ppwcs, size_t in, size_t n, mbstate_t *ps) +{ + return wcsnrtombs_l(s, ppwcs, in, n, ps, _current_locale()); +} + int wctomb_l(char *s, wchar_t wc, locale_t loc) { diff --git a/tests/lib/libc/locale/Makefile b/tests/lib/libc/locale/Makefile index c47925756bcb..cf20e3baf934 100644 --- a/tests/lib/libc/locale/Makefile +++ b/tests/lib/libc/locale/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.5 2013/02/28 21:52:02 christos Exp $ +# $NetBSD: Makefile,v 1.6 2013/05/28 16:57:56 joerg Exp $ .include @@ -6,6 +6,7 @@ TESTSDIR= ${TESTSBASE}/lib/libc/locale TESTS_C+= t_mbrtowc TESTS_C+= t_mbstowcs +TESTS_C+= t_mbsnrtowcs TESTS_C+= t_mbtowc TESTS_C+= t_wcscspn TESTS_C+= t_wcspbrk diff --git a/tests/lib/libc/locale/t_mbsnrtowcs.c b/tests/lib/libc/locale/t_mbsnrtowcs.c new file mode 100644 index 000000000000..4631dc73067f --- /dev/null +++ b/tests/lib/libc/locale/t_mbsnrtowcs.c @@ -0,0 +1,97 @@ +/* $NetBSD: t_mbsnrtowcs.c,v 1.1 2013/05/28 16:57:56 joerg Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__RCSID("$NetBSD: t_mbsnrtowcs.c,v 1.1 2013/05/28 16:57:56 joerg Exp $"); + +#include +#include + +#include + +static const struct test { + const char *locale; + const char *data; + size_t limit; + const wchar_t output1[64]; + size_t output1_len; + const wchar_t output2[64]; + size_t output2_len; +} tests[] = { + { "C", "ABCD0123", 4, { 0x41, 0x42, 0x43, 0x44 }, 4, + { 0x30, 0x31, 0x32, 0x33, 0x0 }, 5 }, + { "en_US.UTF-8", "ABCD0123", 4, { 0x41, 0x42, 0x43, 0x44 }, 4, + { 0x30, 0x31, 0x32, 0x33, 0x0 }, 5 }, + { "en_US.UTF-8", "ABC\303\2440123", 4, { 0x41, 0x42, 0x43, }, 3, + { 0xe4, 0x30, 0x31, 0x32, 0x33, 0x0 }, 6 }, +}; + +ATF_TC(mbsnrtowcs); +ATF_TC_HEAD(mbsnrtowcs, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks mbsnrtowc(3) with different locales"); +} +ATF_TC_BODY(mbsnrtowcs, tc) +{ + size_t i; + const struct test *t; + mbstate_t state; + wchar_t buf[64]; + const char *src; + size_t len; + + for (i = 0; i < __arraycount(tests); ++i) { + t = &tests[i]; + ATF_REQUIRE_STREQ(setlocale(LC_ALL, "C"), "C"); + ATF_REQUIRE(setlocale(LC_CTYPE, t->locale) != NULL); + memset(&state, 0, sizeof(state)); + src = t->data; + len = mbsnrtowcs(buf, &src, t->limit, + __arraycount(buf), &state); + ATF_REQUIRE_EQ(src, t->data + t->limit); + ATF_REQUIRE_EQ(len, t->output1_len); + ATF_REQUIRE(wmemcmp(t->output1, buf, len) == 0); + len = mbsnrtowcs(buf, &src, strlen(src) + 1, + __arraycount(buf), &state); + ATF_REQUIRE_EQ(len, strlen(t->data) - t->limit); + ATF_REQUIRE(wmemcmp(t->output2, buf, len + 1) == 0); + ATF_REQUIRE_EQ(src, NULL); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, mbsnrtowcs); + + return atf_no_error(); +}