diff --git a/include/wchar.h b/include/wchar.h index c1aaf7812e71..39b74e8637ef 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -209,6 +209,10 @@ int wcwidth(wchar_t); #if __BSD_VISIBLE wchar_t *fgetwln(struct __sFILE * __restrict, size_t * __restrict); +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); size_t wcslcat(wchar_t *, const wchar_t *, size_t); size_t wcslcpy(wchar_t *, const wchar_t *, size_t); #endif diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc index 1e8a36322288..cf02a3fa5cbf 100644 --- a/lib/libc/locale/Makefile.inc +++ b/lib/libc/locale/Makefile.inc @@ -8,11 +8,13 @@ SRCS+= big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c frune.c \ gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ - mbrtowc.c mbrune.c mbsinit.c mbsrtowcs.c mbtowc.c mbstowcs.c \ + mbrtowc.c mbrune.c mbsinit.c mbsnrtowcs.c \ + mbsrtowcs.c mbtowc.c mbstowcs.c \ mskanji.c nextwctype.c nl_langinfo.c nomacros.c none.c rune.c \ runetype.c setinvalidrune.c setlocale.c setrunelocale.c srune.c \ table.c \ - tolower.c toupper.c utf2.c utf8.c wcrtomb.c wcsrtombs.c wcsftime.c \ + tolower.c toupper.c utf2.c utf8.c wcrtomb.c wcsnrtombs.c \ + wcsrtombs.c wcsftime.c \ wcstof.c wcstod.c \ wcstoimax.c wcstol.c wcstold.c wcstoll.c \ wcstombs.c \ @@ -47,9 +49,11 @@ MLINKS+=iswalnum.3 iswalpha.3 iswalnum.3 iswascii.3 iswalnum.3 iswblank.3 \ iswalnum.3 iswupper.3 iswalnum.3 iswxdigit.3 MLINKS+=isxdigit.3 ishexnumber.3 MLINKS+=mbrune.3 mbmb.3 mbrune.3 mbrrune.3 +MLINKS+=mbsrtowcs.3 mbsnrtowcs.3 MLINKS+=rune.3 fgetrune.3 rune.3 fputrune.3 rune.3 fungetrune.3 \ rune.3 setinvalidrune.3 rune.3 setrunelocale.3 rune.3 sgetrune.3 \ rune.3 sputrune.3 +MLINKS+=wcsrtombs.3 wcsnrtombs.3 MLINKS+=wcstod.3 wcstof.3 wcstod.3 wcstold.3 MLINKS+=wcstol.3 wcstoul.3 wcstol.3 wcstoll.3 wcstol.3 wcstoull.3 \ wcstol.3 wcstoimax.3 wcstol.3 wcstoumax.3 diff --git a/lib/libc/locale/mblocal.h b/lib/libc/locale/mblocal.h index 8e36ad5ea2a2..3727b72c0742 100644 --- a/lib/libc/locale/mblocal.h +++ b/lib/libc/locale/mblocal.h @@ -37,11 +37,11 @@ extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); extern int (*__mbsinit)(const mbstate_t *); -extern size_t (*__mbsrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, mbstate_t * __restrict); +extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, mbstate_t * __restrict); +extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); /* * Conversion functions for "NONE"/C/POSIX encoding. @@ -49,17 +49,17 @@ extern size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict, extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); extern int _none_mbsinit(const mbstate_t *); -extern size_t _none_mbsrtowcs(wchar_t * __restrict, const char ** __restrict, - size_t, mbstate_t * __restrict); +extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); extern size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t _none_wcsrtombs(char * __restrict, const wchar_t ** __restrict, - size_t, mbstate_t * __restrict); +extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); -extern size_t __mbsrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, mbstate_t * __restrict); -extern size_t __wcsrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, mbstate_t * __restrict); +extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict); +extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); /* * Rune emulation functions. diff --git a/lib/libc/locale/mbsnrtowcs.c b/lib/libc/locale/mbsnrtowcs.c new file mode 100644 index 000000000000..5284087fb4c1 --- /dev/null +++ b/lib/libc/locale/mbsnrtowcs.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "mblocal.h" + +size_t +mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + static mbstate_t mbs; + + if (ps == NULL) + ps = &mbs; + return (__mbsnrtowcs(dst, src, nms, len, ps)); +} + +size_t +__mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps) +{ + const char *s; + size_t nchr; + wchar_t wc; + size_t nb; + + s = *src; + nchr = 0; + + if (dst == NULL) { + for (;;) { + if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + /* Invalid sequence - mbrtowc() sets errno. */ + return ((size_t)-1); + else if (nb == 0 || nb == (size_t)-2) + return (nchr); + s += nb; + nms -= nb; + nchr++; + } + /*NOTREACHED*/ + } + + while (len-- > 0) { + if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + *src = s; + return ((size_t)-1); + } else if (nb == (size_t)-2) { + *src = s + nms; + return (nchr); + } else if (nb == 0) { + *src = NULL; + return (nchr); + } + s += nb; + nms -= nb; + nchr++; + dst++; + } + *src = s; + return (nchr); +} diff --git a/lib/libc/locale/mbsrtowcs.3 b/lib/libc/locale/mbsrtowcs.3 index 9963d8552088..f54e419139e2 100644 --- a/lib/libc/locale/mbsrtowcs.3 +++ b/lib/libc/locale/mbsrtowcs.3 @@ -23,11 +23,12 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd April 8, 2004 +.Dd July 21, 2004 .Dt MBSRTOWCS 3 .Os .Sh NAME -.Nm mbsrtowcs +.Nm mbsrtowcs , +.Nm mbsnrtowcs .Nd "convert a character string to a wide-character string (restartable)" .Sh LIBRARY .Lb libc @@ -38,6 +39,11 @@ .Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t len" .Fa "mbstate_t * restrict ps" .Fc +.Ft size_t +.Fo mbsnrtowcs +.Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t nms" +.Fa "size_t len" "mbstate_t * restrict ps" +.Fc .Sh DESCRIPTION The .Fn mbsrtowcs @@ -82,10 +88,21 @@ uses an internal, static .Vt mbstate_t object, which is initialized to the initial conversion state at program startup. +.Pp +The +.Fn mbsnrtowcs +function behaves identically to +.Fn mbsrtowcs , +except that conversion stops after reading at most +.Fa nms +bytes from the buffer pointed to by +.Fa src . .Sh RETURN VALUES The .Fn mbsrtowcs -function returns the number of wide characters stored in +and +.Fn mbsnrtowcs +functions return the number of wide characters stored in the array pointed to by .Fa dst if successful, otherwise it returns @@ -93,7 +110,9 @@ if successful, otherwise it returns .Sh ERRORS The .Fn mbsrtowcs -function will fail if: +and +.Fn mbsnrtowcs +functions will fail if: .Bl -tag -width Er .It Bq Er EILSEQ An invalid multibyte character sequence was encountered. @@ -110,3 +129,7 @@ The .Fn mbsrtowcs function conforms to .St -isoC-99 . +.Pp +The +.Fn mbsnrtowcs +function is an extension to the standard. diff --git a/lib/libc/locale/mbsrtowcs.c b/lib/libc/locale/mbsrtowcs.c index a90c65563f7a..1239c82c337f 100644 --- a/lib/libc/locale/mbsrtowcs.c +++ b/lib/libc/locale/mbsrtowcs.c @@ -41,46 +41,5 @@ mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, if (ps == NULL) ps = &mbs; - return (__mbsrtowcs(dst, src, len, ps)); -} - -size_t -__mbsrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src, - size_t len, mbstate_t * __restrict ps) -{ - const char *s; - size_t nchr; - wchar_t wc; - int nb; - - s = *src; - nchr = 0; - - if (dst == NULL) { - for (;;) { - if ((nb = (int)__mbrtowc(&wc, s, MB_CUR_MAX, ps)) < 0) - /* Invalid sequence - mbrtowc() sets errno. */ - return ((size_t)-1); - else if (nb == 0) - return (nchr); - s += nb; - nchr++; - } - /*NOTREACHED*/ - } - - while (len-- > 0) { - if ((nb = (int)__mbrtowc(dst, s, MB_CUR_MAX, ps)) < 0) { - *src = s; - return ((size_t)-1); - } else if (nb == 0) { - *src = NULL; - return (nchr); - } - s += nb; - nchr++; - dst++; - } - *src = s; - return (nchr); + return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); } diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c index 4623535457dd..ad259d84dab3 100644 --- a/lib/libc/locale/mbstowcs.c +++ b/lib/libc/locale/mbstowcs.c @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include "mblocal.h" @@ -38,5 +39,5 @@ mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) mbstate_t mbs; mbs = initial; - return (__mbsrtowcs(pwcs, &s, n, &mbs)); + return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs)); } diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c index 2a3ada6b3ee6..d964233e45e0 100644 --- a/lib/libc/locale/none.c +++ b/lib/libc/locale/none.c @@ -55,11 +55,12 @@ int _none_init(_RuneLocale *); size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); int _none_mbsinit(const mbstate_t *); -size_t _none_mbsrtowcs(wchar_t * __restrict, const char ** __restrict, - size_t, mbstate_t * __restrict); +size_t _none_mbsnrtowcs(wchar_t * __restrict dst, + const char ** __restrict src, size_t nms, size_t len, + mbstate_t * __restrict ps __unused); size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); -size_t _none_wcsrtombs(char * __restrict, const wchar_t ** __restrict, - size_t, mbstate_t * __restrict); +size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict); int _none_init(_RuneLocale *rl) @@ -67,9 +68,9 @@ _none_init(_RuneLocale *rl) __mbrtowc = _none_mbrtowc; __mbsinit = _none_mbsinit; - __mbsrtowcs = _none_mbsrtowcs; + __mbsnrtowcs = _none_mbsnrtowcs; __wcrtomb = _none_wcrtomb; - __wcsrtombs = _none_wcsrtombs; + __wcsnrtombs = _none_wcsnrtombs; _CurrentRuneLocale = rl; __mb_cur_max = 1; return(0); @@ -119,18 +120,20 @@ _none_wcrtomb(char * __restrict s, wchar_t wc, } size_t -_none_mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, - size_t len, mbstate_t * __restrict ps __unused) +_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps __unused) { const char *s; size_t nchr; - if (dst == NULL) - return (strlen(*src)); + if (dst == NULL) { + s = memchr(*src, '\0', nms); + return (s != NULL ? s - *src : nms); + } s = *src; nchr = 0; - while (len-- > 0) { + while (len-- > 0 && nms-- > 0) { if ((*dst++ = (unsigned char)*s++) == L'\0') { *src = NULL; return (nchr); @@ -142,14 +145,14 @@ _none_mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, } size_t -_none_wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, - size_t len, mbstate_t * __restrict ps __unused) +_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps __unused) { const wchar_t *s; size_t nchr; if (dst == NULL) { - for (s = *src; *s != L'\0'; s++) { + for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) { if (*s < 0 || *s > UCHAR_MAX) { errno = EILSEQ; return ((size_t)-1); @@ -160,7 +163,7 @@ _none_wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, s = *src; nchr = 0; - while (len-- > 0) { + while (len-- > 0 && nwc-- > 0) { if (*s < 0 || *s > UCHAR_MAX) { errno = EILSEQ; return ((size_t)-1); diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c index de3ee06d7c37..4c19ff76a178 100644 --- a/lib/libc/locale/setrunelocale.c +++ b/lib/libc/locale/setrunelocale.c @@ -100,10 +100,11 @@ __setrunelocale(const char *encoding) static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); static int (*Cached__mbsinit)(const mbstate_t *); - static size_t (*Cached__mbsrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcsrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, mbstate_t * __restrict); + static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict, + const char ** __restrict, size_t, size_t, mbstate_t * __restrict); + static size_t (*Cached__wcsnrtombs)(char * __restrict, + const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict); /* * The "C" and "POSIX" locale are always here. @@ -113,9 +114,9 @@ __setrunelocale(const char *encoding) __mb_cur_max = 1; __mbrtowc = _none_mbrtowc; __mbsinit = _none_mbsinit; - __mbsrtowcs = _none_mbsrtowcs; + __mbsnrtowcs = _none_mbsnrtowcs; __wcrtomb = _none_wcrtomb; - __wcsrtombs = _none_wcsrtombs; + __wcsnrtombs = _none_wcsnrtombs; return (0); } @@ -128,9 +129,9 @@ __setrunelocale(const char *encoding) __mb_cur_max = Cached__mb_cur_max; __mbrtowc = Cached__mbrtowc; __mbsinit = Cached__mbsinit; - __mbsrtowcs = Cached__mbsrtowcs; + __mbsnrtowcs = Cached__mbsnrtowcs; __wcrtomb = Cached__wcrtomb; - __wcsrtombs = Cached__wcsrtombs; + __wcsnrtombs = Cached__wcsnrtombs; return (0); } @@ -156,9 +157,9 @@ __setrunelocale(const char *encoding) __mbrtowc = NULL; __mbsinit = NULL; - __mbsrtowcs = __mbsrtowcs_std; + __mbsnrtowcs = __mbsnrtowcs_std; __wcrtomb = NULL; - __wcsrtombs = __wcsrtombs_std; + __wcsnrtombs = __wcsnrtombs_std; rl->__sputrune = __emulated_sputrune; rl->__sgetrune = __emulated_sgetrune; if (strcmp(rl->__encoding, "NONE") == 0) @@ -192,9 +193,9 @@ __setrunelocale(const char *encoding) Cached__mb_cur_max = __mb_cur_max; Cached__mbrtowc = __mbrtowc; Cached__mbsinit = __mbsinit; - Cached__mbsrtowcs = __mbsrtowcs; + Cached__mbsnrtowcs = __mbsnrtowcs; Cached__wcrtomb = __wcrtomb; - Cached__wcsrtombs = __wcsrtombs; + Cached__wcsnrtombs = __wcsnrtombs; (void)strcpy(ctype_encoding, encoding); } else free(rl); diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c index 4d72959505b3..de71a4b820b8 100644 --- a/lib/libc/locale/table.c +++ b/lib/libc/locale/table.c @@ -255,9 +255,9 @@ int __mb_cur_max = 1; size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict) = _none_mbrtowc; int (*__mbsinit)(const mbstate_t *) = _none_mbsinit; -size_t (*__mbsrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, mbstate_t * __restrict) = _none_mbsrtowcs; +size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, + size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs; size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) = _none_wcrtomb; -size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, mbstate_t * __restrict) = _none_wcsrtombs; +size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, + size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; diff --git a/lib/libc/locale/wcsnrtombs.c b/lib/libc/locale/wcsnrtombs.c new file mode 100644 index 000000000000..6f2d5b0c88c0 --- /dev/null +++ b/lib/libc/locale/wcsnrtombs.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "mblocal.h" + +size_t +wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, + size_t len, mbstate_t * __restrict ps) +{ + static mbstate_t mbs; + + if (ps == NULL) + ps = &mbs; + return (__wcsnrtombs(dst, src, nwc, len, ps)); +} + +size_t +__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps) +{ + mbstate_t mbsbak; + char buf[MB_LEN_MAX]; + const wchar_t *s; + size_t nbytes; + size_t nb; + + s = *src; + nbytes = 0; + + if (dst == NULL) { + while (nwc-- > 0) { + if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) + /* Invalid character - wcrtomb() sets errno. */ + return ((size_t)-1); + else if (*s == L'\0') + break; + s++; + nbytes += nb; + } + return (nbytes + nb - 1); + } + + while (len > 0 && nwc-- > 0) { + if (len > (size_t)MB_CUR_MAX) { + /* Enough space to translate in-place. */ + if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) { + *src = s; + return ((size_t)-1); + } + } else { + /* + * May not be enough space; use temp. buffer. + * + * We need to save a copy of the conversion state + * here so we can restore it if the multibyte + * character is too long for the buffer. + */ + mbsbak = *ps; + if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) { + *src = s; + return ((size_t)-1); + } + if (nb > (int)len) { + /* MB sequence for character won't fit. */ + *ps = mbsbak; + break; + } + memcpy(dst, buf, nb); + } + if (*s == L'\0') { + *src = NULL; + return (nbytes + nb - 1); + } + s++; + dst += nb; + len -= nb; + nbytes += nb; + } + *src = s; + return (nbytes); +} diff --git a/lib/libc/locale/wcsrtombs.3 b/lib/libc/locale/wcsrtombs.3 index 91e61fde5086..ff607c2dad11 100644 --- a/lib/libc/locale/wcsrtombs.3 +++ b/lib/libc/locale/wcsrtombs.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd April 8, 2004 +.Dd July 21, 2004 .Dt WCSRTOMBS 3 .Os .Sh NAME -.Nm wcsrtombs +.Nm wcsrtombs , +.Nm wcsnrtombs .Nd "convert a wide-character string to a character string (restartable)" .Sh LIBRARY .Lb libc @@ -39,6 +40,11 @@ .Fa "char * restrict dst" "const wchar_t ** restrict src" .Fa "size_t len" "mbstate_t * restrict ps" .Fc +.Ft size_t +.Fo wcsnrtombs +.Fa "char * restrict dst" "const wchar_t ** restrict src" "size_t nwc" +.Fa "size_t len" "mbstate_t * restrict ps" +.Fc .Sh DESCRIPTION The .Fn wcsrtombs @@ -82,10 +88,21 @@ uses an internal, static .Vt mbstate_t object, which is initialized to the initial conversion state at program startup. +.Pp +The +.Fn wcsnrtombs +function behaves identically to +.Fn wcsrtombs , +except that conversion stops after reading at most +.Fa nwc +characters from the buffer pointed to by +.Fa src . .Sh RETURN VALUES The .Fn wcsrtombs -function returns the number of bytes stored in +and +.Fn wcsnrtombs +functions return the number of bytes stored in the array pointed to by .Fa dst (not including any terminating null), if successful, otherwise it returns @@ -93,7 +110,9 @@ the array pointed to by .Sh ERRORS The .Fn wcsrtombs -function will fail if: +and +.Fn wcsnrtombs +functions will fail if: .Bl -tag -width Er .It Bq Er EILSEQ An invalid wide character was encountered. @@ -109,3 +128,7 @@ The .Fn wcsrtombs function conforms to .St -isoC-99 . +.Pp +The +.Fn wcsnrtombs +function is an extension to the standard. diff --git a/lib/libc/locale/wcsrtombs.c b/lib/libc/locale/wcsrtombs.c index a03f0d33f83d..f3b38b71c4d8 100644 --- a/lib/libc/locale/wcsrtombs.c +++ b/lib/libc/locale/wcsrtombs.c @@ -41,71 +41,5 @@ wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, if (ps == NULL) ps = &mbs; - return (__wcsrtombs(dst, src, len, ps)); -} - -size_t -__wcsrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, - size_t len, mbstate_t * __restrict ps) -{ - mbstate_t mbsbak; - char buf[MB_LEN_MAX]; - const wchar_t *s; - size_t nbytes; - int nb; - - s = *src; - nbytes = 0; - - if (dst == NULL) { - for (;;) { - if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) - /* Invalid character - wcrtomb() sets errno. */ - return ((size_t)-1); - else if (*s == L'\0') - return (nbytes + nb - 1); - s++; - nbytes += nb; - } - /*NOTREACHED*/ - } - - while (len > 0) { - if (len > (size_t)MB_CUR_MAX) { - /* Enough space to translate in-place. */ - if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) { - *src = s; - return ((size_t)-1); - } - } else { - /* - * May not be enough space; use temp. buffer. - * - * We need to save a copy of the conversion state - * here so we can restore it if the multibyte - * character is too long for the buffer. - */ - mbsbak = *ps; - if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) { - *src = s; - return ((size_t)-1); - } - if (nb > (int)len) { - /* MB sequence for character won't fit. */ - *ps = mbsbak; - break; - } - memcpy(dst, buf, nb); - } - if (*s == L'\0') { - *src = NULL; - return (nbytes + nb - 1); - } - s++; - dst += nb; - len -= nb; - nbytes += nb; - } - *src = s; - return (nbytes); + return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); } diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c index 5bb5954a7cde..acd0051463b3 100644 --- a/lib/libc/locale/wcstombs.c +++ b/lib/libc/locale/wcstombs.c @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include "mblocal.h" @@ -38,5 +39,5 @@ wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) mbstate_t mbs; mbs = initial; - return (__wcsrtombs(s, &pwcs, n, &mbs)); + return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs)); } diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c index b5be7317ba72..025e1c00d198 100644 --- a/lib/libc/stdio/fputws.c +++ b/lib/libc/stdio/fputws.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include +#include #include #include #include "un-namespace.h" @@ -53,7 +54,7 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp) uio.uio_iovcnt = 1; iov.iov_base = buf; do { - nbytes = __wcsrtombs(buf, &ws, sizeof(buf), + nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf), &fp->_extra->mbstate); if (nbytes == (size_t)-1) goto error;