Module Name:    src
Committed By:   joerg
Date:           Tue May 28 16:57:57 UTC 2013

Modified Files:
        src/distrib/sets/lists/debug: mi
        src/distrib/sets/lists/tests: mi
        src/include: wchar.h
        src/lib/libc/citrus: citrus_ctype.c citrus_ctype.h
            citrus_ctype_fallback.c citrus_ctype_fallback.h
            citrus_ctype_local.h citrus_ctype_template.h citrus_none.c
        src/lib/libc/citrus/modules: citrus_big5.c citrus_dechanyu.c
            citrus_euc.c citrus_euctw.c citrus_gbk2k.c citrus_hz.c
            citrus_iso2022.c citrus_johab.c citrus_mskanji.c citrus_ues.c
            citrus_utf7.c citrus_utf8.c citrus_viqr.c citrus_zw.c
        src/lib/libc/locale: multibyte_amd1.c multibyte_c90.c
        src/tests/lib/libc/locale: Makefile
Added Files:
        src/tests/lib/libc/locale: t_mbsnrtowcs.c

Log Message:
Add mbsnrtowcs and wcsnrtombs. Approved by core.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.535 -r1.536 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.37 -r1.38 src/include/wchar.h
cvs rdiff -u -r1.6 -r1.7 src/lib/libc/citrus/citrus_ctype.c
cvs rdiff -u -r1.2 -r1.3 src/lib/libc/citrus/citrus_ctype.h \
    src/lib/libc/citrus/citrus_ctype_fallback.c
cvs rdiff -u -r1.1 -r1.2 src/lib/libc/citrus/citrus_ctype_fallback.h
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/citrus/citrus_ctype_local.h
cvs rdiff -u -r1.35 -r1.36 src/lib/libc/citrus/citrus_ctype_template.h
cvs rdiff -u -r1.18 -r1.19 src/lib/libc/citrus/citrus_none.c
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/citrus/modules/citrus_big5.c \
    src/lib/libc/citrus/modules/citrus_mskanji.c
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/citrus/modules/citrus_dechanyu.c \
    src/lib/libc/citrus/modules/citrus_johab.c \
    src/lib/libc/citrus/modules/citrus_zw.c
cvs rdiff -u -r1.14 -r1.15 src/lib/libc/citrus/modules/citrus_euc.c
cvs rdiff -u -r1.11 -r1.12 src/lib/libc/citrus/modules/citrus_euctw.c
cvs rdiff -u -r1.7 -r1.8 src/lib/libc/citrus/modules/citrus_gbk2k.c
cvs rdiff -u -r1.2 -r1.3 src/lib/libc/citrus/modules/citrus_hz.c
cvs rdiff -u -r1.22 -r1.23 src/lib/libc/citrus/modules/citrus_iso2022.c
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/citrus/modules/citrus_ues.c
cvs rdiff -u -r1.5 -r1.6 src/lib/libc/citrus/modules/citrus_utf7.c \
    src/lib/libc/citrus/modules/citrus_viqr.c
cvs rdiff -u -r1.17 -r1.18 src/lib/libc/citrus/modules/citrus_utf8.c
cvs rdiff -u -r1.12 -r1.13 src/lib/libc/locale/multibyte_amd1.c
cvs rdiff -u -r1.10 -r1.11 src/lib/libc/locale/multibyte_c90.c
cvs rdiff -u -r1.5 -r1.6 src/tests/lib/libc/locale/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/locale/t_mbsnrtowcs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/debug/mi
diff -u src/distrib/sets/lists/debug/mi:1.22 src/distrib/sets/lists/debug/mi:1.23
--- src/distrib/sets/lists/debug/mi:1.22	Wed May  8 17:41:31 2013
+++ src/distrib/sets/lists/debug/mi	Tue May 28 16:57:56 2013
@@ -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

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.535 src/distrib/sets/lists/tests/mi:1.536
--- src/distrib/sets/lists/tests/mi:1.535	Mon Apr 22 21:06:28 2013
+++ src/distrib/sets/lists/tests/mi	Tue May 28 16:57:56 2013
@@ -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

Index: src/include/wchar.h
diff -u src/include/wchar.h:1.37 src/include/wchar.h:1.38
--- src/include/wchar.h:1.37	Fri Apr 19 23:45:15 2013
+++ src/include/wchar.h	Tue May 28 16:57:56 2013
@@ -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, c
 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, ...);

Index: src/lib/libc/citrus/citrus_ctype.c
diff -u src/lib/libc/citrus/citrus_ctype.c:1.6 src/lib/libc/citrus/citrus_ctype.c:1.7
--- src/lib/libc/citrus/citrus_ctype.c:1.6	Sat Nov 19 18:34:21 2011
+++ src/lib/libc/citrus/citrus_ctype.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -92,6 +92,8 @@ _initctypemodule(_citrus_ctype_t cc, cha
 		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, cha
 	    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 ||

Index: src/lib/libc/citrus/citrus_ctype.h
diff -u src/lib/libc/citrus/citrus_ctype.h:1.2 src/lib/libc/citrus/citrus_ctype.h:1.3
--- src/lib/libc/citrus/citrus_ctype.h:1.2	Wed Mar  5 20:18:15 2003
+++ src/lib/libc/citrus/citrus_ctype.h	Tue May 28 16:57:56 2013
@@ -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,
@@ -95,6 +95,16 @@ _citrus_ctype_mbsrtowcs(_citrus_ctype_t 
 }
 
 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)
 {
@@ -133,6 +143,16 @@ _citrus_ctype_wcsrtombs(_citrus_ctype_t 
 }
 
 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)
 {
Index: src/lib/libc/citrus/citrus_ctype_fallback.c
diff -u src/lib/libc/citrus/citrus_ctype_fallback.c:1.2 src/lib/libc/citrus/citrus_ctype_fallback.c:1.3
--- src/lib/libc/citrus/citrus_ctype_fallback.c:1.2	Fri Jun 27 14:52:25 2003
+++ src/lib/libc/citrus/citrus_ctype_fallback.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
 #include <assert.h>
+#include <errno.h>
 #include <wchar.h>
 #include <stdio.h>
 #include <string.h>
@@ -108,3 +109,121 @@ _citrus_ctype_wctob_fallback(_citrus_cty
 
 	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);
+}

Index: src/lib/libc/citrus/citrus_ctype_fallback.h
diff -u src/lib/libc/citrus/citrus_ctype_fallback.h:1.1 src/lib/libc/citrus/citrus_ctype_fallback.h:1.2
--- src/lib/libc/citrus/citrus_ctype_fallback.h:1.1	Wed Mar  5 20:18:15 2003
+++ src/lib/libc/citrus/citrus_ctype_fallback.h	Tue May 28 16:57:56 2013
@@ -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
 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

Index: src/lib/libc/citrus/citrus_ctype_local.h
diff -u src/lib/libc/citrus/citrus_ctype_local.h:1.3 src/lib/libc/citrus/citrus_ctype_local.h:1.4
--- src/lib/libc/citrus/citrus_ctype_local.h:1.3	Sat Feb  9 14:56:20 2008
+++ src/lib/libc/citrus/citrus_ctype_local.h	Tue May 28 16:57:56 2013
@@ -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_mbsrtow
 					 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_wcsrtom
 					 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_##_
 	/* 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"

Index: src/lib/libc/citrus/citrus_ctype_template.h
diff -u src/lib/libc/citrus/citrus_ctype_template.h:1.35 src/lib/libc/citrus/citrus_ctype_template.h:1.36
--- src/lib/libc/citrus/citrus_ctype_template.h:1.35	Sat Feb  9 14:56:20 2008
+++ src/lib/libc/citrus/citrus_ctype_template.h	Tue May 28 16:57:56 2013
@@ -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
 	_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,6 +351,66 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
 			  size_t n, _ENCODING_STATE * __restrict psenc,
 			  size_t * __restrict nresult)
 {
+	int err;
+	char buf[MB_LEN_MAX];
+	size_t cnt, siz;
+	const wchar_t* pwcs0;
+#if _ENCODING_IS_STATE_DEPENDENT
+	_ENCODING_STATE state;
+#endif
+
+	pwcs0 = *pwcs;
+
+	cnt = 0;
+	if (!s)
+		n = 1;
+
+	while (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++;
+	}
+	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;
@@ -302,7 +424,7 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
 	if (!s)
 		n = 1;
 
-	while (n > 0) {
+	while (in > 0 && n > 0) {
 #if _ENCODING_IS_STATE_DEPENDENT
 		state = *psenc;
 #endif
@@ -334,6 +456,7 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
 			break;
 		}
 		pwcs0++;
+		--in;
 	}
 	if (s)
 		*pwcs = pwcs0;
@@ -525,6 +648,27 @@ _FUNCNAME(ctype_mbsrtowcs)(void * __rest
 	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 * __rest
 	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,

Index: src/lib/libc/citrus/citrus_none.c
diff -u src/lib/libc/citrus/citrus_none.c:1.18 src/lib/libc/citrus/citrus_none.c:1.19
--- src/lib/libc/citrus/citrus_none.c:1.18	Sat Jun 14 16:01:07 2008
+++ src/lib/libc/citrus/citrus_none.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -185,6 +185,47 @@ _citrus_NONE_ctype_mbsrtowcs(void * __re
 }
 
 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,
 			    size_t * __restrict nresult)
@@ -282,6 +323,48 @@ _citrus_NONE_ctype_wcsrtombs(void * __re
 }
 
 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,
 			    size_t * __restrict nresult)

Index: src/lib/libc/citrus/modules/citrus_big5.c
diff -u src/lib/libc/citrus/modules/citrus_big5.c:1.13 src/lib/libc/citrus/modules/citrus_big5.c:1.14
--- src/lib/libc/citrus/modules/citrus_big5.c:1.13	Mon May 23 14:53:46 2011
+++ src/lib/libc/citrus/modules/citrus_big5.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/queue.h>
@@ -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;
Index: src/lib/libc/citrus/modules/citrus_mskanji.c
diff -u src/lib/libc/citrus/modules/citrus_mskanji.c:1.13 src/lib/libc/citrus/modules/citrus_mskanji.c:1.14
--- src/lib/libc/citrus/modules/citrus_mskanji.c:1.13	Sat Jun 14 16:01:08 2008
+++ src/lib/libc/citrus/modules/citrus_mskanji.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_dechanyu.c
diff -u src/lib/libc/citrus/modules/citrus_dechanyu.c:1.4 src/lib/libc/citrus/modules/citrus_dechanyu.c:1.5
--- src/lib/libc/citrus/modules/citrus_dechanyu.c:1.4	Sat Nov 19 18:20:13 2011
+++ src/lib/libc/citrus/modules/citrus_dechanyu.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -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;
Index: src/lib/libc/citrus/modules/citrus_johab.c
diff -u src/lib/libc/citrus/modules/citrus_johab.c:1.4 src/lib/libc/citrus/modules/citrus_johab.c:1.5
--- src/lib/libc/citrus/modules/citrus_johab.c:1.4	Sat Jun 14 16:01:07 2008
+++ src/lib/libc/citrus/modules/citrus_johab.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -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;
Index: src/lib/libc/citrus/modules/citrus_zw.c
diff -u src/lib/libc/citrus/modules/citrus_zw.c:1.4 src/lib/libc/citrus/modules/citrus_zw.c:1.5
--- src/lib/libc/citrus/modules/citrus_zw.c:1.4	Sat Jun 14 16:01:08 2008
+++ src/lib/libc/citrus/modules/citrus_zw.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_euc.c
diff -u src/lib/libc/citrus/modules/citrus_euc.c:1.14 src/lib/libc/citrus/modules/citrus_euc.c:1.15
--- src/lib/libc/citrus/modules/citrus_euc.c:1.14	Sun Jan 11 02:46:24 2009
+++ src/lib/libc/citrus/modules/citrus_euc.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_euctw.c
diff -u src/lib/libc/citrus/modules/citrus_euctw.c:1.11 src/lib/libc/citrus/modules/citrus_euctw.c:1.12
--- src/lib/libc/citrus/modules/citrus_euctw.c:1.11	Sat Jun 14 16:01:07 2008
+++ src/lib/libc/citrus/modules/citrus_euctw.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_gbk2k.c
diff -u src/lib/libc/citrus/modules/citrus_gbk2k.c:1.7 src/lib/libc/citrus/modules/citrus_gbk2k.c:1.8
--- src/lib/libc/citrus/modules/citrus_gbk2k.c:1.7	Sat Jun 14 16:01:07 2008
+++ src/lib/libc/citrus/modules/citrus_gbk2k.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_hz.c
diff -u src/lib/libc/citrus/modules/citrus_hz.c:1.2 src/lib/libc/citrus/modules/citrus_hz.c:1.3
--- src/lib/libc/citrus/modules/citrus_hz.c:1.2	Sat Jun 14 16:01:07 2008
+++ src/lib/libc/citrus/modules/citrus_hz.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/queue.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_iso2022.c
diff -u src/lib/libc/citrus/modules/citrus_iso2022.c:1.22 src/lib/libc/citrus/modules/citrus_iso2022.c:1.23
--- src/lib/libc/citrus/modules/citrus_iso2022.c:1.22	Mon Oct 10 22:45:45 2011
+++ src/lib/libc/citrus/modules/citrus_iso2022.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_ues.c
diff -u src/lib/libc/citrus/modules/citrus_ues.c:1.3 src/lib/libc/citrus/modules/citrus_ues.c:1.4
--- src/lib/libc/citrus/modules/citrus_ues.c:1.3	Sun Feb 12 13:51:29 2012
+++ src/lib/libc/citrus/modules/citrus_ues.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_utf7.c
diff -u src/lib/libc/citrus/modules/citrus_utf7.c:1.5 src/lib/libc/citrus/modules/citrus_utf7.c:1.6
--- src/lib/libc/citrus/modules/citrus_utf7.c:1.5	Wed Aug 23 12:57:24 2006
+++ src/lib/libc/citrus/modules/citrus_utf7.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;
Index: src/lib/libc/citrus/modules/citrus_viqr.c
diff -u src/lib/libc/citrus/modules/citrus_viqr.c:1.5 src/lib/libc/citrus/modules/citrus_viqr.c:1.6
--- src/lib/libc/citrus/modules/citrus_viqr.c:1.5	Sat Nov 19 18:20:13 2011
+++ src/lib/libc/citrus/modules/citrus_viqr.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/queue.h>
@@ -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;

Index: src/lib/libc/citrus/modules/citrus_utf8.c
diff -u src/lib/libc/citrus/modules/citrus_utf8.c:1.17 src/lib/libc/citrus/modules/citrus_utf8.c:1.18
--- src/lib/libc/citrus/modules/citrus_utf8.c:1.17	Sat Jun 14 16:01:08 2008
+++ src/lib/libc/citrus/modules/citrus_utf8.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <assert.h>
@@ -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;

Index: src/lib/libc/locale/multibyte_amd1.c
diff -u src/lib/libc/locale/multibyte_amd1.c:1.12 src/lib/libc/locale/multibyte_amd1.c:1.13
--- src/lib/libc/locale/multibyte_amd1.c:1.12	Fri May 17 12:55:57 2013
+++ src/lib/libc/locale/multibyte_amd1.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -151,6 +151,29 @@ mbsrtowcs(wchar_t *pwcs, const char **s,
 }
 
 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)
 {
 	size_t ret;

Index: src/lib/libc/locale/multibyte_c90.c
diff -u src/lib/libc/locale/multibyte_c90.c:1.10 src/lib/libc/locale/multibyte_c90.c:1.11
--- src/lib/libc/locale/multibyte_c90.c:1.10	Fri May 17 12:55:57 2013
+++ src/lib/libc/locale/multibyte_c90.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
 #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 <sys/types.h>
@@ -45,6 +45,10 @@ __RCSID("$NetBSD: multibyte_c90.c,v 1.10
 #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, si
 	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)
 {

Index: src/tests/lib/libc/locale/Makefile
diff -u src/tests/lib/libc/locale/Makefile:1.5 src/tests/lib/libc/locale/Makefile:1.6
--- src/tests/lib/libc/locale/Makefile:1.5	Thu Feb 28 21:52:02 2013
+++ src/tests/lib/libc/locale/Makefile	Tue May 28 16:57:56 2013
@@ -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 <bsd.own.mk>
 
@@ -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

Added files:

Index: src/tests/lib/libc/locale/t_mbsnrtowcs.c
diff -u /dev/null src/tests/lib/libc/locale/t_mbsnrtowcs.c:1.1
--- /dev/null	Tue May 28 16:57:57 2013
+++ src/tests/lib/libc/locale/t_mbsnrtowcs.c	Tue May 28 16:57:56 2013
@@ -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 <sys/cdefs.h>
+__RCSID("$NetBSD: t_mbsnrtowcs.c,v 1.1 2013/05/28 16:57:56 joerg Exp $");
+
+#include <locale.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+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();
+}

Reply via email to