Diff below adds mbsnrtowcs() and wcsnrtombs(), which are new POSIX
2008 functions.  I'd appreciate if someone could run this through a
bulk build and let me know if anything breaks or misbehaves.

Thanks!


Index: include/wchar.h
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/include/wchar.h,v
retrieving revision 1.22
diff -u -p -r1.22 wchar.h
--- include/wchar.h     5 Jan 2012 20:37:50 -0000       1.22
+++ include/wchar.h     25 May 2012 06:01:50 -0000
@@ -158,6 +158,11 @@ unsigned long int wcstoul(const wchar_t 
 wchar_t        *wcsdup(const wchar_t *);
 int wcscasecmp(const wchar_t *, const wchar_t *);
 int wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
+
+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);
 #endif
 
 #if __ISO_C_VISIBLE >= 1999
Index: lib/libc/locale/multibyte_citrus.c
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/lib/libc/locale/multibyte_citrus.c,v
retrieving revision 1.1
diff -u -p -r1.1 multibyte_citrus.c
--- lib/libc/locale/multibyte_citrus.c  27 Jul 2010 16:59:04 -0000      1.1
+++ lib/libc/locale/multibyte_citrus.c  25 May 2012 16:45:00 -0000
@@ -30,6 +30,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <errno.h>
+#include <limits.h>
 #include <wchar.h>
 
 #include "citrus_ctype.h"
@@ -65,7 +66,19 @@ mbrtowc(wchar_t *pwc, const char *s, siz
 }
 
 size_t
-mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps)
+mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps)
+{
+       static mbstate_t mbs;
+       struct _citrus_ctype_rec *cc;
+
+       if (ps == NULL)
+               ps = &mbs;
+       return (mbsnrtowcs(dst, src, SIZE_MAX, len, ps));
+}
+
+size_t
+mbsnrtowcs(wchar_t *dst, const char **src, size_t nmc, size_t len,
+    mbstate_t *ps)
 {
        static mbstate_t mbs;
        struct _citrus_ctype_rec *cc;
@@ -73,7 +86,8 @@ mbsrtowcs(wchar_t *pwcs, const char **s,
        if (ps == NULL)
                ps = &mbs;
        cc = _CurrentRuneLocale->rl_citrus_ctype;
-       return (*cc->cc_ops->co_mbsrtowcs)(pwcs, s, n, _ps_to_private(ps));
+       return (*cc->cc_ops->co_mbsnrtowcs)(dst, src, nmc, len,
+           _ps_to_private(ps));
 }
 
 size_t
@@ -89,7 +103,18 @@ wcrtomb(char *s, wchar_t wc, mbstate_t *
 }
 
 size_t
-wcsrtombs(char *s, const wchar_t **ppwcs, size_t n, mbstate_t *ps)
+wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps)
+{
+       static mbstate_t mbs;
+
+       if (ps == NULL)
+               ps = &mbs;
+       return (wcsnrtombs(dst, src, SIZE_MAX, len, ps));
+}
+
+size_t
+wcsnrtombs(char *dst, const wchar_t **src, size_t nwc, size_t len,
+    mbstate_t *ps)
 {
        static mbstate_t mbs;
        struct _citrus_ctype_rec *cc;
@@ -97,5 +122,6 @@ wcsrtombs(char *s, const wchar_t **ppwcs
        if (ps == NULL)
                ps = &mbs;
        cc = _CurrentRuneLocale->rl_citrus_ctype;
-       return (*cc->cc_ops->co_wcsrtombs)(s, ppwcs, n, _ps_to_private(ps));
+       return (*cc->cc_ops->co_wcsnrtombs)(dst, src, nwc, len,
+           _ps_to_private(ps));
 }
Index: lib/libc/citrus/citrus_ctype_local.h
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/lib/libc/citrus/citrus_ctype_local.h,v
retrieving revision 1.2
diff -u -p -r1.2 citrus_ctype_local.h
--- lib/libc/citrus/citrus_ctype_local.h        27 Jul 2010 16:59:03 -0000      
1.2
+++ lib/libc/citrus/citrus_ctype_local.h        25 May 2012 01:36:32 -0000
@@ -36,43 +36,45 @@ size_t      _citrus_##_e_##_ctype_mbrtowc(wch
                                      const char * __restrict, size_t,  \
                                      void * __restrict);               \
 int    _citrus_##_e_##_ctype_mbsinit(const void * __restrict);         \
-size_t _citrus_##_e_##_ctype_mbsrtowcs(wchar_t * __restrict,           \
-                                       const char ** __restrict,       \
-                                       size_t, void * __restrict);     \
+size_t _citrus_##_e_##_ctype_mbsnrtowcs(wchar_t * __restrict,          \
+                                        const char ** __restrict,      \
+                                        size_t, size_t,                \
+                                        void * __restrict);            \
 size_t _citrus_##_e_##_ctype_wcrtomb(char * __restrict, wchar_t,       \
                                      void * __restrict);               \
-size_t _citrus_##_e_##_ctype_wcsrtombs(char * __restrict,              \
-                                       const wchar_t ** __restrict,    \
-                                       size_t, void * __restrict);     \
+size_t _citrus_##_e_##_ctype_wcsnrtombs(char * __restrict,             \
+                                        const wchar_t ** __restrict,   \
+                                        size_t, size_t,                \
+                                        void * __restrict);            \
 
 #define _CITRUS_CTYPE_DEF_OPS(_e_)                                     \
 struct _citrus_ctype_ops_rec _citrus_##_e_##_ctype_ops = {             \
        /* co_mbrtowc */        &_citrus_##_e_##_ctype_mbrtowc,         \
        /* co_mbsinit */        &_citrus_##_e_##_ctype_mbsinit,         \
-       /* co_mbsrtowcs */      &_citrus_##_e_##_ctype_mbsrtowcs,       \
+       /* co_mbsnrtowcs */     &_citrus_##_e_##_ctype_mbsnrtowcs,      \
        /* co_wcrtomb */        &_citrus_##_e_##_ctype_wcrtomb,         \
-       /* co_wcsrtombs */      &_citrus_##_e_##_ctype_wcsrtombs,       \
+       /* co_wcsnrtombs */     &_citrus_##_e_##_ctype_wcsnrtombs,      \
 }
 
 typedef size_t (*_citrus_ctype_mbrtowc_t)
        (wchar_t * __restrict, const char * __restrict,
        size_t, void * __restrict);
 typedef int    (*_citrus_ctype_mbsinit_t) (const void * __restrict);
-typedef size_t (*_citrus_ctype_mbsrtowcs_t)
+typedef size_t (*_citrus_ctype_mbsnrtowcs_t)
        (wchar_t * __restrict, const char ** __restrict,
-        size_t, void * __restrict);
+        size_t, size_t, void * __restrict);
 typedef size_t (*_citrus_ctype_wcrtomb_t)
        (char * __restrict, wchar_t, void * __restrict);
-typedef size_t (*_citrus_ctype_wcsrtombs_t)
+typedef size_t (*_citrus_ctype_wcsnrtombs_t)
        (char * __restrict, const wchar_t ** __restrict,
-        size_t, void * __restrict);
+        size_t, size_t, void * __restrict);
 
 struct _citrus_ctype_ops_rec {
        _citrus_ctype_mbrtowc_t         co_mbrtowc;
        _citrus_ctype_mbsinit_t         co_mbsinit;
-       _citrus_ctype_mbsrtowcs_t       co_mbsrtowcs;
+       _citrus_ctype_mbsnrtowcs_t      co_mbsnrtowcs;
        _citrus_ctype_wcrtomb_t         co_wcrtomb;
-       _citrus_ctype_wcsrtombs_t       co_wcsrtombs;
+       _citrus_ctype_wcsnrtombs_t      co_wcsnrtombs;
 };
 
 #define _CITRUS_DEFAULT_CTYPE_NAME     "NONE"
Index: lib/libc/citrus/citrus_none.c
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/lib/libc/citrus/citrus_none.c,v
retrieving revision 1.2
diff -u -p -r1.2 citrus_none.c
--- lib/libc/citrus/citrus_none.c       3 Aug 2010 11:23:37 -0000       1.2
+++ lib/libc/citrus/citrus_none.c       25 May 2012 16:37:39 -0000
@@ -31,6 +31,7 @@
 #include <sys/types.h>
 
 #include <errno.h>
+#include <limits.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,6 +43,19 @@
 
 _CITRUS_CTYPE_DEF_OPS(none);
 
+/*
+ * Convert an unsigned char value into a char value without relying on
+ * signed overflow behavior.
+ */
+static inline char
+wrapv(unsigned char ch)
+{
+       if (ch >= 0x80)
+               return ((int)ch - 0x100);
+       else
+               return (ch);
+}
+
 size_t
 /*ARGSUSED*/
 _citrus_none_ctype_mbrtowc(wchar_t * __restrict pwc,
@@ -70,30 +84,27 @@ _citrus_none_ctype_mbsinit(const void * 
 
 size_t
 /*ARGSUSED*/
-_citrus_none_ctype_mbsrtowcs(wchar_t * __restrict pwcs,
-                            const char ** __restrict s, size_t n,
-                            void * __restrict pspriv)
+_citrus_none_ctype_mbsnrtowcs(wchar_t * __restrict dst,
+                             const char ** __restrict src,
+                             size_t nmc, size_t len,
+                             void * __restrict pspriv)
 {
-       int count = 0;
+       size_t i;
 
-       /* pwcs may be NULL */
-       /* s may be NULL */
+       /* dst may be NULL */
        /* pspriv appears to be unused */
 
-       if (!s || !*s)
-               return 0;
+       if (dst == NULL)
+               return strnlen(*src, nmc);
 
-       if (pwcs == NULL)
-               return strlen(*s);
+       for (i = 0; i < nmc && i < len; i++)
+               if ((dst[i] = (wchar_t)(unsigned char)(*src)[i]) == L'\0') {
+                       *src = NULL;
+                       return (i);
+               }
 
-       while (n > 0) {
-               if ((*pwcs++ = (wchar_t)(unsigned char)*(*s)++) == 0)
-                       break;
-               count++;
-               n--;
-       }
-       
-       return count;
+       *src += i;
+       return (i);
 }
 
 size_t
@@ -105,40 +116,55 @@ _citrus_none_ctype_wcrtomb(char * __rest
        /* ps appears to be unused */
 
        if (s == NULL)
-               return 0;
+               return (0);
+
+       if (wc < 0 || wc > 0xff) {
+               errno = EILSEQ;
+               return (-1);
+       }
 
-       *s = (char) wc;
-       return 1;
+       *s = wrapv(wc);
+       return (1);
 }
 
 size_t
 /*ARGSUSED*/
-_citrus_none_ctype_wcsrtombs(char * __restrict s,
-                            const wchar_t ** __restrict pwcs, size_t n,
-                            void * __restrict pspriv)
+_citrus_none_ctype_wcsnrtombs(char * __restrict dst,
+                             const wchar_t ** __restrict src,
+                             size_t nwc, size_t len,
+                             void * __restrict pspriv)
 {
-       int count = 0;
+       size_t i;
 
-       /* s may be NULL */
-       /* pwcs may be NULL */
+       /* dst may be NULL */
        /* pspriv appears to be unused */
 
-       if (pwcs == NULL || *pwcs == NULL)
-               return (0);
-
-       if (s == NULL) {
-               while (*(*pwcs)++ != 0)
-                       count++;
-               return(count);
+       if (dst == NULL) {
+               for (i = 0; i < nwc; i++) {
+                       wchar_t wc = (*src)[i];
+                       if (wc < 0 || wc > 0xff) {
+                               errno = EILSEQ;
+                               return (-1);
+                       }
+                       if (wc == L'\0')
+                               return (i);
+               }
+               return (i);
        }
 
-       if (n != 0) {
-               do {
-                       if ((*s++ = (char) *(*pwcs)++) == 0)
-                               break;
-                       count++;
-               } while (--n != 0);
+       for (i = 0; i < nwc && i < len; i++) {
+               wchar_t wc = (*src)[i];
+               if (wc < 0 || wc > 0xff) {
+                       *src += i;
+                       errno = EILSEQ;
+                       return (-1);
+               }
+               dst[i] = wrapv(wc);
+               if (wc == L'\0') {
+                       *src = NULL;
+                       return (i);
+               }
        }
-
-       return count;
+       *src += i;
+       return (i);
 }
Index: lib/libc/citrus/citrus_utf8.c
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/lib/libc/citrus/citrus_utf8.c,v
retrieving revision 1.4
diff -u -p -r1.4 citrus_utf8.c
--- lib/libc/citrus/citrus_utf8.c       21 Apr 2011 00:16:06 -0000      1.4
+++ lib/libc/citrus/citrus_utf8.c       25 May 2012 17:03:00 -0000
@@ -186,53 +186,44 @@ _citrus_utf8_ctype_mbsinit(const void * 
 
 size_t
 /*ARGSUSED*/
-_citrus_utf8_ctype_mbsrtowcs(wchar_t * __restrict pwcs,
-                            const char ** __restrict s, size_t n,
-                            void * __restrict pspriv)
+_citrus_utf8_ctype_mbsnrtowcs(wchar_t * __restrict dst,
+                             const char ** __restrict src,
+                             size_t nmc, size_t len,
+                             void * __restrict pspriv)
 {
        struct _utf8_state *us;
-       const char *src;
-       size_t nchr;
-       wchar_t wc;
-       size_t nb;
+       size_t i, o, r;
 
        us = (struct _utf8_state *)pspriv;
-       src = *s;
-       nchr = 0;
 
-       if (pwcs == NULL) {
+       if (dst == NULL) {
                /*
                 * The fast path in the loop below is not safe if an ASCII
                 * character appears as anything but the first byte of a
                 * multibyte sequence. Check now to avoid doing it in the loop.
                 */
-               if (us->want > 0 && (signed char)*src > 0) {
+               if (nmc > 0 && us->want > 0 && (unsigned char)(*src)[0] < 0x80) 
{
                        errno = EILSEQ;
                        return ((size_t)-1);
                }
-               for (;;) {
-                       if ((signed char)*src > 0) {
-                               /*
-                                * Fast path for plain ASCII characters
-                                * excluding NUL.
-                                */
-                               nb = 1;
+               for (i = o = 0; i < nmc; i += r, o++) {
+                       if ((unsigned char)(*src)[i] < 0x80) {
+                               /* Fast path for plain ASCII characters. */
+                               if ((*src)[i] == '\0')
+                                       return (o);
+                               r = 1;
                        } else {
-                               nb = _citrus_utf8_ctype_mbrtowc(&wc, src,
-                                   _CITRUS_UTF8_MB_CUR_MAX, us);
-                               if (nb == (size_t)-1) {
-                                       /* Invalid sequence. */
-                                       return (nb);
-                               }
-                               if (nb == 0 || nb == (size_t)-2) {
-                                       return (nchr);
-                               }
+                               r = _citrus_utf8_ctype_mbrtowc(NULL, *src + i,
+                                   nmc - i, us);
+                               if (r == (size_t)-1)
+                                       return (r);
+                               if (r == (size_t)-2)
+                                       return (o);
+                               if (r == 0)
+                                       return (o);
                        }
-
-                       src += nb;
-                       nchr++;
                }
-               /*NOTREACHED*/
+               return (o);
        }
 
        /*
@@ -240,40 +231,38 @@ _citrus_utf8_ctype_mbsrtowcs(wchar_t * _
         * character appears as anything but the first byte of a
         * multibyte sequence. Check now to avoid doing it in the loop.
         */
-       if (n > 0 && us->want > 0 && (signed char)*src > 0) {
+       if (len > 0 && nmc > 0 && us->want > 0 && (unsigned char)(*src)[0] < 
0x80) {
                errno = EILSEQ;
                return ((size_t)-1);
        }
-       while (n-- > 0) {
-               if ((signed char)*src > 0) {
-                       /*
-                        * Fast path for plain ASCII characters
-                        * excluding NUL.
-                        */
-                       *pwcs = (wchar_t)*src;
-                       nb = 1;
+       for (i = o = 0; i < nmc && o < len; i += r, o++) {
+               if ((unsigned char)(*src)[i] < 0x80) {
+                       /* Fast path for plain ASCII characters. */
+                       dst[o] = (wchar_t)(unsigned char)(*src)[i];
+                       if ((*src)[i] == '\0') {
+                               *src = NULL;
+                               return (o);
+                       }
+                       r = 1;
                } else {
-                       nb = _citrus_utf8_ctype_mbrtowc(pwcs, src,
-                           _CITRUS_UTF8_MB_CUR_MAX, us);
-                       if (nb == (size_t)-1) {
-                               *s = src;
-                               return (nb);
-                       }
-                       if (nb == (size_t)-2) {
-                               *s = src;
-                               return (nchr);
-                       }
-                       if (nb == 0) {
-                               *s = NULL;
-                               return (nchr);
+                       r = _citrus_utf8_ctype_mbrtowc(dst + o, *src + i,
+                           nmc - i, us);
+                       if (r == (size_t)-1) {
+                               *src += i;
+                               return (r);
+                       }
+                       if (r == (size_t)-2) {
+                               *src += nmc;
+                               return (o);
+                       }
+                       if (r == 0) {
+                               *src = NULL;
+                               return (o);
                        }
                }
-               src += nb;
-               nchr++;
-               pwcs++;
        }
-       *s = src;
-       return (nchr);
+       *src += i;
+       return (o);
 }
 
 size_t
@@ -343,15 +332,14 @@ _citrus_utf8_ctype_wcrtomb(char * __rest
 
 size_t
 /*ARGSUSED*/
-_citrus_utf8_ctype_wcsrtombs(char * __restrict s,
-                            const wchar_t ** __restrict pwcs, size_t n,
-                            void * __restrict pspriv)
+_citrus_utf8_ctype_wcsnrtombs(char * __restrict dst,
+                             const wchar_t ** __restrict src,
+                             size_t nwc, size_t len,
+                             void * __restrict pspriv)
 {
        struct _utf8_state *us;
        char buf[_CITRUS_UTF8_MB_CUR_MAX];
-       const wchar_t *src;
-       size_t nbytes;
-       size_t nb;
+       size_t i, o, r;
 
        us = (struct _utf8_state *)pspriv;
 
@@ -360,65 +348,52 @@ _citrus_utf8_ctype_wcsrtombs(char * __re
                return ((size_t)-1);
        }
 
-       src = *pwcs;
-       nbytes = 0;
-
-       if (s == NULL) {
-               for (;;) {
-                       if (0 <= *src && *src < 0x80)
+       if (dst == NULL) {
+               for (i = o = 0; i < nwc; i++, o += r) {
+                       wchar_t wc = (*src)[i];
+                       if (wc >= 0 && wc < 0x80) {
                                /* Fast path for plain ASCII characters. */
-                               nb = 1;
-                       else {
-                               nb = _citrus_utf8_ctype_wcrtomb(buf, *src, us);
-                               if (nb == (size_t)-1) {
-                                       /* Invalid character */
-                                       return (nb);
-                               }
-                       }
-                       if (*src == L'\0') {
-                               return (nbytes + nb - 1);
+                               if (wc == 0)
+                                       return (o);
+                               r = 1;
+                       } else {
+                               r = _citrus_utf8_ctype_wcrtomb(buf, wc, us);
+                               if (r == (size_t)-1)
+                                       return (r);
                        }
-                       src++;
-                       nbytes += nb;
                }
-               /*NOTREACHED*/
+               return (o);
        }
 
-       while (n > 0) {
-               if (0 <= *src && *src < 0x80) {
+       for (i = o = 0; i < nwc && o < len; i++, o += r) {
+               wchar_t wc = (*src)[i];
+               if (wc >= 0 && wc < 0x80) {
                        /* Fast path for plain ASCII characters. */
-                       nb = 1;
-                       *s = *src;
-               } else if (n > (size_t)_CITRUS_UTF8_MB_CUR_MAX) {
+                       dst[o] = (wchar_t)wc;
+                       if (wc == 0) {
+                               *src = NULL;
+                               return (o);
+                       }
+                       r = 1;
+               } else if (len - o >= _CITRUS_UTF8_MB_CUR_MAX) {
                        /* Enough space to translate in-place. */
-                       nb = _citrus_utf8_ctype_wcrtomb(s, *src, us);
-                       if (nb == (size_t)-1) {
-                               *pwcs = src;
-                               return (nb);
+                       r = _citrus_utf8_ctype_wcrtomb(dst + o, wc, us);
+                       if (r == (size_t)-1) {
+                               *src += i;
+                               return (r);
                        }
                } else {
-                       /*
-                        * May not be enough space; use temp. buffer.
-                        */
-                       nb = _citrus_utf8_ctype_wcrtomb(buf, *src, us);
-                       if (nb == (size_t)-1) {
-                               *pwcs = src;
-                               return (nb);
+                       /* May not be enough space; use temp buffer. */
+                       r = _citrus_utf8_ctype_wcrtomb(buf, wc, us);
+                       if (r == (size_t)-1) {
+                               *src += i;
+                               return (r);
                        }
-                       if (nb > n)
-                               /* MB sequence for character won't fit. */
+                       if (r > len - o)
                                break;
-                       memcpy(s, buf, nb);
-               }
-               if (*src == L'\0') {
-                       *pwcs = NULL;
-                       return (nbytes + nb - 1);
+                       memcpy(dst + o, buf, r);
                }
-               src++;
-               s += nb;
-               n -= nb;
-               nbytes += nb;
        }
-       *pwcs = src;
-       return (nbytes);
+       *src += i;
+       return (o);
 }

----- End forwarded message -----

Reply via email to