summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2012-06-06 16:58:03 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2012-06-06 16:58:03 +0000
commite6b7baa38b9c9d4730b74744f6795b2ae0941a06 (patch)
treeaac2a5956a548f193a19189cb947c38b617f1a90 /lib
parent64e66057c29657d2722c956cc3dbdd149aac406e (diff)
Add support for mbsnrtowcs() and wcsnrtombs() to libc.
Bulk build test by naddy.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/citrus/citrus_ctype_local.h32
-rw-r--r--lib/libc/citrus/citrus_none.c112
-rw-r--r--lib/libc/citrus/citrus_utf8.c197
-rw-r--r--lib/libc/locale/multibyte_citrus.c36
-rw-r--r--lib/libc/shlib_version2
5 files changed, 204 insertions, 175 deletions
diff --git a/lib/libc/citrus/citrus_ctype_local.h b/lib/libc/citrus/citrus_ctype_local.h
index 8ada0ef3d2c..4536261df12 100644
--- a/lib/libc/citrus/citrus_ctype_local.h
+++ b/lib/libc/citrus/citrus_ctype_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: citrus_ctype_local.h,v 1.2 2010/07/27 16:59:03 stsp Exp $ */
+/* $OpenBSD: citrus_ctype_local.h,v 1.3 2012/06/06 16:58:02 matthew Exp $ */
/* $NetBSD: citrus_ctype_local.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $ */
/*-
@@ -36,43 +36,45 @@ size_t _citrus_##_e_##_ctype_mbrtowc(wchar_t * __restrict, \
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"
diff --git a/lib/libc/citrus/citrus_none.c b/lib/libc/citrus/citrus_none.c
index e0dfafdecd0..9699bf88038 100644
--- a/lib/libc/citrus/citrus_none.c
+++ b/lib/libc/citrus/citrus_none.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: citrus_none.c,v 1.2 2010/08/03 11:23:37 stsp Exp $ */
+/* $OpenBSD: citrus_none.c,v 1.3 2012/06/06 16:58:02 matthew Exp $ */
/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */
/*-
@@ -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 * __restrict pspriv)
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 * __restrict s,
/* 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);
}
diff --git a/lib/libc/citrus/citrus_utf8.c b/lib/libc/citrus/citrus_utf8.c
index 895ca6a27fb..5b37b267e21 100644
--- a/lib/libc/citrus/citrus_utf8.c
+++ b/lib/libc/citrus/citrus_utf8.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: citrus_utf8.c,v 1.4 2011/04/21 00:16:06 yasuoka Exp $ */
+/* $OpenBSD: citrus_utf8.c,v 1.5 2012/06/06 16:58:02 matthew Exp $ */
/*-
* Copyright (c) 2002-2004 Tim J. Robbins
@@ -186,53 +186,44 @@ _citrus_utf8_ctype_mbsinit(const void * __restrict pspriv)
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 * __restrict pwcs,
* 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);
+ r = _citrus_utf8_ctype_mbrtowc(dst + o, *src + i,
+ nmc - i, us);
+ if (r == (size_t)-1) {
+ *src += i;
+ return (r);
}
- if (nb == (size_t)-2) {
- *s = src;
- return (nchr);
+ if (r == (size_t)-2) {
+ *src += nmc;
+ return (o);
}
- if (nb == 0) {
- *s = NULL;
- return (nchr);
+ 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 * __restrict s,
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 * __restrict s,
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);
}
diff --git a/lib/libc/locale/multibyte_citrus.c b/lib/libc/locale/multibyte_citrus.c
index 9993e67fe15..3352c7bdbc2 100644
--- a/lib/libc/locale/multibyte_citrus.c
+++ b/lib/libc/locale/multibyte_citrus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: multibyte_citrus.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/* $OpenBSD: multibyte_citrus.c,v 1.2 2012/06/06 16:58:02 matthew Exp $ */
/* $NetBSD: multibyte_amd1.c,v 1.7 2009/01/11 02:46:28 christos Exp $ */
/*-
@@ -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, size_t n, mbstate_t *ps)
}
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, size_t n, mbstate_t *ps)
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 *ps)
}
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, size_t n, mbstate_t *ps)
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));
}
diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version
index da350fdb8a2..56a8145c9df 100644
--- a/lib/libc/shlib_version
+++ b/lib/libc/shlib_version
@@ -1,4 +1,4 @@
major=64
-minor=1
+minor=2
# note: If changes were made to include/thread_private.h or if system
# calls were added/changed then libpthread must also be updated.