summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2010-07-27 16:59:05 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2010-07-27 16:59:05 +0000
commitca2246f7206f312d3507d148d8fca7b5028c4088 (patch)
treece30da3359d783bea6fe127d1b15a6d9b6a52b33 /lib
parent357ef0a59acd38d0252d97a185411096ea76c5dd (diff)
Replace the single-byte placeholders for the multi-byte/wide-character
conversion interfaces of libc (mbrtowc(3) and friends) with new implementations that internally call an API based on NetBSD's citrus. This allows us to support locales with multi-byte character encodings. Provide two implementations of the citrus-based API: one based on the old single-byte placeholders for use with our existing single-byte character locales (C, ISO8859-*, KOI8, CP1251, etc.), and one that provides support for UTF-8 encoded characters (code based on FreeBSD's implementation). Install the en_US.UTF-8 ctype locale support file, and allow the UTF-8 ctype locale to be enabled via setlocale(3) (export LC_CTYPE='en_US.UTF-8'). A lot of programs, especially from ports, will now start using UTF-8 if the UTF-8 locale is enabled. Use at your own risk, and please report any breakage. Note that ncurses-based programs cannot display UTF-8 right now, this is being worked on. To prevent install media growth, add vfprintf(3) and mbrtowc(3) to libstubs. The mbrtowc stub was copied unchanged from its old single-byte placeholder. vfprintf.c doesn't need to be copied, just put in .PATH (hint by fgsch@). Testing by myself, naddy, sthen, nicm, espie, armani, Dmitrij D. Czarkoff. ok matthieu espie millert sthen nicm deraadt
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/Makefile.inc3
-rw-r--r--lib/libc/citrus/Makefile.inc7
-rw-r--r--lib/libc/citrus/citrus_ctype.c60
-rw-r--r--lib/libc/citrus/citrus_ctype.h4
-rw-r--r--lib/libc/citrus/citrus_ctype_local.h58
-rw-r--r--lib/libc/citrus/citrus_none.c (renamed from lib/libc/locale/multibyte_sb.c)156
-rw-r--r--lib/libc/citrus/citrus_none.h37
-rw-r--r--lib/libc/citrus/citrus_utf8.c416
-rw-r--r--lib/libc/citrus/citrus_utf8.h39
-rw-r--r--lib/libc/locale/Makefile.inc16
-rw-r--r--lib/libc/locale/btowc.c54
-rw-r--r--lib/libc/locale/mblen.c50
-rw-r--r--lib/libc/locale/mbrlen.c41
-rw-r--r--lib/libc/locale/mbstowcs.c45
-rw-r--r--lib/libc/locale/mbtowc.c51
-rw-r--r--lib/libc/locale/multibyte.h50
-rw-r--r--lib/libc/locale/multibyte_citrus.c101
-rw-r--r--lib/libc/locale/runetable.c4
-rw-r--r--lib/libc/locale/setrunelocale.c5
-rw-r--r--lib/libc/locale/wcscoll.c43
-rw-r--r--lib/libc/locale/wcstombs.c45
-rw-r--r--lib/libc/locale/wcsxfrm.c (renamed from lib/libc/locale/mbrtowc_sb.c)35
-rw-r--r--lib/libc/locale/wctob.c45
-rw-r--r--lib/libc/locale/wctomb.c49
24 files changed, 1259 insertions, 155 deletions
diff --git a/lib/libc/Makefile.inc b/lib/libc/Makefile.inc
index 28622a6da8e..170a44eeb5b 100644
--- a/lib/libc/Makefile.inc
+++ b/lib/libc/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.14 2010/02/03 20:49:00 miod Exp $
+# $OpenBSD: Makefile.inc,v 1.15 2010/07/27 16:59:03 stsp Exp $
#
# This file contains make rules used to build libc
#
@@ -30,6 +30,7 @@ AINC+= -nostdinc -idirafter ${DESTDIR}/usr/include
.include "${LIBCSRCDIR}/db/Makefile.inc"
.include "${LIBCSRCDIR}/dlfcn/Makefile.inc"
+.include "${LIBCSRCDIR}/citrus/Makefile.inc"
.include "${LIBCSRCDIR}/compat-43/Makefile.inc"
.include "${LIBCSRCDIR}/gen/Makefile.inc"
.include "${LIBCSRCDIR}/crypt/Makefile.inc"
diff --git a/lib/libc/citrus/Makefile.inc b/lib/libc/citrus/Makefile.inc
new file mode 100644
index 00000000000..b1466442dd9
--- /dev/null
+++ b/lib/libc/citrus/Makefile.inc
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile.inc,v 1.1 2010/07/27 16:59:03 stsp Exp $
+
+# citrus sources
+.PATH: ${LIBCSRCDIR}/citrus
+
+SRCS+= citrus_ctype.c citrus_none.c citrus_utf8.c
+CFLAGS+=-I${.CURDIR}
diff --git a/lib/libc/citrus/citrus_ctype.c b/lib/libc/citrus/citrus_ctype.c
new file mode 100644
index 00000000000..c869519bff7
--- /dev/null
+++ b/lib/libc/citrus/citrus_ctype.c
@@ -0,0 +1,60 @@
+/* $OpenBSD: citrus_ctype.c,v 1.1 2010/07/27 16:59:03 stsp Exp $ */
+/* $NetBSD: citrus_ctype.c,v 1.5 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)1999, 2000, 2001, 2002 Citrus Project,
+ * 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 <sys/cdefs.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "citrus_ctype.h"
+#include "citrus_none.h"
+#include "citrus_utf8.h"
+
+struct _citrus_ctype_rec _citrus_ctype_none = {
+ &_citrus_none_ctype_ops, /* cc_ops */
+};
+
+struct _citrus_ctype_rec _citrus_ctype_utf8 = {
+ &_citrus_utf8_ctype_ops, /* cc_ops */
+};
+
+_citrus_ctype_open(struct _citrus_ctype_rec **rcc, char const *encname)
+{
+ if (!strcmp(encname, "NONE")) {
+ *rcc = &_citrus_ctype_none;
+ __mb_cur_max = 1;
+ return (0);
+ } else if (!strcmp(encname, "UTF8")) {
+ *rcc = &_citrus_ctype_utf8;
+ __mb_cur_max = _CITRUS_UTF8_MB_CUR_MAX;
+ return (0);
+ }
+
+ return (-1);
+}
diff --git a/lib/libc/citrus/citrus_ctype.h b/lib/libc/citrus/citrus_ctype.h
index 28356ab079f..5e69b3e8076 100644
--- a/lib/libc/citrus/citrus_ctype.h
+++ b/lib/libc/citrus/citrus_ctype.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: citrus_ctype.h,v 1.1 2005/08/07 10:16:23 espie Exp $ */
+/* $OpenBSD: citrus_ctype.h,v 1.2 2010/07/27 16:59:03 stsp Exp $ */
/* $NetBSD: citrus_ctype.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $ */
/*-
@@ -33,4 +33,6 @@
#include "citrus_ctype_local.h"
+extern struct _citrus_ctype_rec _citrus_ctype_none;
+
#endif
diff --git a/lib/libc/citrus/citrus_ctype_local.h b/lib/libc/citrus/citrus_ctype_local.h
index e3bcd923be2..8ada0ef3d2c 100644
--- a/lib/libc/citrus/citrus_ctype_local.h
+++ b/lib/libc/citrus/citrus_ctype_local.h
@@ -1,6 +1,4 @@
-#ifndef _CITRUS_CTYPE_LOCAL_H_
-#define _CITRUS_CTYPE_LOCAL_H_
-/* $OpenBSD: citrus_ctype_local.h,v 1.1 2005/08/07 10:16:23 espie Exp $ */
+/* $OpenBSD: citrus_ctype_local.h,v 1.2 2010/07/27 16:59:03 stsp Exp $ */
/* $NetBSD: citrus_ctype_local.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $ */
/*-
@@ -30,7 +28,57 @@
*
*/
-#define _CITRUS_DEFAULT_CTYPE_NAME "NONE"
+#ifndef _CITRUS_CTYPE_LOCAL_H_
+#define _CITRUS_CTYPE_LOCAL_H_
+
+#define _CITRUS_CTYPE_DECLS(_e_) \
+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_wcrtomb(char * __restrict, wchar_t, \
+ void * __restrict); \
+size_t _citrus_##_e_##_ctype_wcsrtombs(char * __restrict, \
+ const wchar_t ** __restrict, \
+ size_t, void * __restrict); \
-#endif
+#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_wcrtomb */ &_citrus_##_e_##_ctype_wcrtomb, \
+ /* co_wcsrtombs */ &_citrus_##_e_##_ctype_wcsrtombs, \
+}
+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)
+ (wchar_t * __restrict, const char ** __restrict,
+ size_t, void * __restrict);
+typedef size_t (*_citrus_ctype_wcrtomb_t)
+ (char * __restrict, wchar_t, void * __restrict);
+typedef size_t (*_citrus_ctype_wcsrtombs_t)
+ (char * __restrict, const wchar_t ** __restrict,
+ 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_wcrtomb_t co_wcrtomb;
+ _citrus_ctype_wcsrtombs_t co_wcsrtombs;
+};
+
+#define _CITRUS_DEFAULT_CTYPE_NAME "NONE"
+
+struct _citrus_ctype_rec {
+ struct _citrus_ctype_ops_rec *cc_ops;
+};
+
+#endif
diff --git a/lib/libc/locale/multibyte_sb.c b/lib/libc/citrus/citrus_none.c
index 4067b154b02..b7b039ee773 100644
--- a/lib/libc/locale/multibyte_sb.c
+++ b/lib/libc/citrus/citrus_none.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: multibyte_sb.c,v 1.7 2008/08/23 07:51:35 djm Exp $ */
-/* $NetBSD: multibyte_sb.c,v 1.4 2003/08/07 16:43:04 agc Exp $ */
+/* $OpenBSD: citrus_none.c,v 1.1 2010/07/27 16:59:03 stsp Exp $ */
+/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */
-/*
- * Copyright (c) 1991 The Regents of the University of California.
+/*-
+ * Copyright (c)2002 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -13,14 +13,11 @@
* 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.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * 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)
@@ -30,80 +27,58 @@
* SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
#include <errno.h>
+#include <string.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <stddef.h>
#include <wchar.h>
-/*
- * Stub multibyte character functions.
- * This cheezy implementation is fixed to the native single-byte
- * character set.
- */
+#include "citrus_ctype.h"
+#include "citrus_none.h"
-/*ARGSUSED*/
-int
-mbsinit(const mbstate_t *ps)
-{
+_CITRUS_CTYPE_DEF_OPS(none);
- return 1;
-}
-
-/*ARGSUSED*/
size_t
-mbrlen(const char *s, size_t n, mbstate_t *ps)
-{
-
- /* ps appears to be unused */
-
- if (s == NULL || *s == '\0')
- return 0;
- if (n == 0)
- return (size_t)-1;
- return 1;
-}
-
-int
-mblen(const char *s, size_t n)
-{
-
- /* s may be NULL */
-
- return mbrlen(s, n, NULL);
-}
-
/*ARGSUSED*/
-size_t
-wcrtomb(char *s, wchar_t wchar, mbstate_t *ps)
+_citrus_none_ctype_mbrtowc(wchar_t * __restrict pwc,
+ const char * __restrict s, size_t n,
+ void * __restrict pspriv)
{
-
+ /* pwc may be NULL */
/* s may be NULL */
- /* ps appears to be unused */
+ /* pspriv appears to be unused */
if (s == NULL)
return 0;
-
- *s = (char) wchar;
- return 1;
+ if (n == 0)
+ return (size_t)-2;
+ if (pwc)
+ *pwc = (wchar_t)(unsigned char)*s;
+ return (*s != '\0');
}
int
-wctomb(char *s, wchar_t wchar)
+/*ARGSUSED*/
+_citrus_none_ctype_mbsinit(const void * __restrict pspriv)
{
-
- /* s may be NULL */
-
- return wcrtomb(s, wchar, NULL);
+ return (1); /* always initial state */
}
-/*ARGSUSED*/
size_t
-mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps)
+/*ARGSUSED*/
+_citrus_none_ctype_mbsrtowcs(wchar_t * __restrict pwcs,
+ const char ** __restrict s, size_t n,
+ void * __restrict pspriv)
{
int count = 0;
/* pwcs may be NULL */
/* s may be NULL */
- /* ps appears to be unused */
+ /* pspriv appears to be unused */
if (!s || !*s)
return 0;
@@ -128,25 +103,31 @@ mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps)
}
size_t
-mbstowcs(wchar_t *pwcs, const char *s, size_t n)
+/*ARGSUSED*/
+_citrus_none_ctype_wcrtomb(char * __restrict s,
+ wchar_t wc, void * __restrict pspriv)
{
+ /* s may be NULL */
+ /* ps appears to be unused */
- /* pwcs may be NULL */
- if (pwcs == NULL)
- return strlen(s);
+ if (s == NULL)
+ return 0;
- return mbsrtowcs(pwcs, &s, n, NULL);
+ *s = (char) wc;
+ return 1;
}
-/*ARGSUSED*/
size_t
-wcsrtombs(char *s, const wchar_t **pwcs, size_t n, mbstate_t *ps)
+/*ARGSUSED*/
+_citrus_none_ctype_wcsrtombs(char * __restrict s,
+ const wchar_t ** __restrict pwcs, size_t n,
+ void * __restrict pspriv)
{
int count = 0;
/* s may be NULL */
/* pwcs may be NULL */
- /* ps appears to be unused */
+ /* pspriv appears to be unused */
if (pwcs == NULL || *pwcs == NULL)
return (0);
@@ -167,46 +148,3 @@ wcsrtombs(char *s, const wchar_t **pwcs, size_t n, mbstate_t *ps)
return count;
}
-
-size_t
-wcstombs(char *s, const wchar_t *pwcs, size_t n)
-{
-
- /* s may be NULL */
- /* pwcs may be NULL */
-
- return wcsrtombs(s, &pwcs, n, NULL);
-}
-
-wint_t
-btowc(int c)
-{
- if (c == EOF || c & ~0xFF)
- return WEOF;
- return (wint_t)c;
-}
-
-int
-wctob(wint_t c)
-{
- if (c == WEOF || c & ~0xFF)
- return EOF;
- return (int)c;
-}
-
-int
-wcscoll(const wchar_t *s1, const wchar_t *s2)
-{
- while (*s1 == *s2++)
- if (*s1++ == 0)
- return (0);
- return ((unsigned char)(*s1) - (unsigned char)(*--s2));
-}
-
-size_t
-wcsxfrm(wchar_t *dest, const wchar_t *src, size_t n)
-{
- if (n == 0)
- return wcslen(src);
- return wcslcpy(dest, src, n);
-}
diff --git a/lib/libc/citrus/citrus_none.h b/lib/libc/citrus/citrus_none.h
new file mode 100644
index 00000000000..096e3794177
--- /dev/null
+++ b/lib/libc/citrus/citrus_none.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: citrus_none.h,v 1.1 2010/07/27 16:59:03 stsp Exp $ */
+/* $NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * 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.
+ */
+
+#ifndef _CITRUS_NONE_H_
+#define _CITRUS_NONE_H_
+
+extern struct _citrus_ctype_ops_rec _citrus_none_ctype_ops;
+
+_CITRUS_CTYPE_DECLS(none);
+
+#endif
diff --git a/lib/libc/citrus/citrus_utf8.c b/lib/libc/citrus/citrus_utf8.c
new file mode 100644
index 00000000000..d28670c9eb7
--- /dev/null
+++ b/lib/libc/citrus/citrus_utf8.c
@@ -0,0 +1,416 @@
+
+/* $OpenBSD: citrus_utf8.c,v 1.1 2010/07/27 16:59:03 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/limits.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_ctype.h"
+#include "citrus_utf8.h"
+
+_CITRUS_CTYPE_DEF_OPS(utf8);
+
+struct _utf8_state {
+ wchar_t ch;
+ int want;
+ wchar_t lbound;
+};
+
+size_t
+/*ARGSUSED*/
+_citrus_utf8_ctype_mbrtowc(wchar_t * __restrict pwc,
+ const char * __restrict s, size_t n,
+ void * __restrict pspriv)
+{
+ struct _utf8_state *us;
+ int ch, i, mask, want;
+ wchar_t lbound, wch;
+
+ us = (struct _utf8_state *)pspriv;
+
+ if (us->want < 0 || us->want > _CITRUS_UTF8_MB_CUR_MAX) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0) {
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+ }
+
+ if (us->want == 0 && ((ch = (unsigned char)*s) & ~0x7f) == 0) {
+ /* Fast path for plain ASCII characters. */
+ if (pwc != NULL)
+ *pwc = ch;
+ return (ch != '\0' ? 1 : 0);
+ }
+
+ if (us->want == 0) {
+ /*
+ * Determine the number of octets that make up this character
+ * from the first octet, and a mask that extracts the
+ * interesting bits of the first octet. We already know
+ * the character is at least two bytes long.
+ *
+ * We also specify a lower bound for the character code to
+ * detect redundant, non-"shortest form" encodings. For
+ * example, the sequence C0 80 is _not_ a legal representation
+ * of the null character. This enforces a 1-to-1 mapping
+ * between character codes and their multibyte representations.
+ */
+ ch = (unsigned char)*s;
+ if ((ch & 0x80) == 0) {
+ mask = 0x7f;
+ want = 1;
+ lbound = 0;
+ } else if ((ch & 0xe0) == 0xc0) {
+ mask = 0x1f;
+ want = 2;
+ lbound = 0x80;
+ } else if ((ch & 0xf0) == 0xe0) {
+ mask = 0x0f;
+ want = 3;
+ lbound = 0x800;
+ } else if ((ch & 0xf8) == 0xf0) {
+ mask = 0x07;
+ want = 4;
+ lbound = 0x10000;
+ } else {
+ /*
+ * Malformed input; input is not UTF-8.
+ * See RFC 3629.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ } else {
+ want = us->want;
+ lbound = us->lbound;
+ }
+
+ /*
+ * Decode the octet sequence representing the character in chunks
+ * of 6 bits, most significant first.
+ */
+ if (us->want == 0)
+ wch = (unsigned char)*s++ & mask;
+ else
+ wch = us->ch;
+ for (i = (us->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
+ if ((*s & 0xc0) != 0x80) {
+ /*
+ * Malformed input; bad characters in the middle
+ * of a character.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wch <<= 6;
+ wch |= *s++ & 0x3f;
+ }
+ if (i < want) {
+ /* Incomplete multibyte sequence. */
+ us->want = want - i;
+ us->lbound = lbound;
+ us->ch = wch;
+ return ((size_t)-2);
+ }
+ if (wch < lbound) {
+ /*
+ * Malformed input; redundant encoding.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if (pwc != NULL)
+ *pwc = wch;
+ us->want = 0;
+ return (wch == L'\0' ? 0 : want);
+}
+
+int
+/*ARGSUSED*/
+_citrus_utf8_ctype_mbsinit(const void * __restrict pspriv)
+{
+ return (pspriv == NULL ||
+ ((const struct _utf8_state *)pspriv)->want == 0);
+}
+
+size_t
+/*ARGSUSED*/
+_citrus_utf8_ctype_mbsrtowcs(wchar_t * __restrict pwcs,
+ const char ** __restrict s, size_t n,
+ void * __restrict pspriv)
+{
+ struct _utf8_state *us;
+ const char *src;
+ size_t nchr;
+ wchar_t wc;
+ size_t nb;
+
+ us = (struct _utf8_state *)pspriv;
+ src = *s;
+ nchr = 0;
+
+ if (pwcs == 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) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ for (;;) {
+ if ((signed char)*src > 0) {
+ /*
+ * Fast path for plain ASCII characters
+ * excluding NUL.
+ */
+ nb = 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);
+ }
+ }
+
+ src += nb;
+ nchr++;
+ }
+ /*NOTREACHED*/
+ }
+
+ /*
+ * 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 (n > 0 && us->want > 0 && (signed char)*src > 0) {
+ 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;
+ } else {
+ nb = _citrus_utf8_ctype_mbrtowc(pwcs, src, n, 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);
+ }
+ }
+ src += nb;
+ nchr++;
+ pwcs++;
+ }
+ *s = src;
+ return (nchr);
+}
+
+size_t
+/*ARGSUSED*/
+_citrus_utf8_ctype_wcrtomb(char * __restrict s,
+ wchar_t wc, void * __restrict pspriv)
+{
+ struct _utf8_state *us;
+ unsigned char lead;
+ int i, len;
+
+ us = (struct _utf8_state *)pspriv;
+
+ if (us->want != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ }
+
+ if ((wc & ~0x7f) == 0) {
+ /* Fast path for plain ASCII characters. */
+ *s = (char)wc;
+ return (1);
+ }
+
+ /*
+ * Determine the number of octets needed to represent this character.
+ * We always output the shortest sequence possible. Also specify the
+ * first few bits of the first octet, which contains the information
+ * about the sequence length.
+ */
+ if ((wc & ~0x7f) == 0) {
+ lead = 0;
+ len = 1;
+ } else if ((wc & ~0x7ff) == 0) {
+ lead = 0xc0;
+ len = 2;
+ } else if ((wc & ~0xffff) == 0) {
+ lead = 0xe0;
+ len = 3;
+ } else if ((wc & ~0x1fffff) == 0) {
+ lead = 0xf0;
+ len = 4;
+ } else {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+
+ /*
+ * Output the octets representing the character in chunks
+ * of 6 bits, least significant last. The first octet is
+ * a special case because it contains the sequence length
+ * information.
+ */
+ for (i = len - 1; i > 0; i--) {
+ s[i] = (wc & 0x3f) | 0x80;
+ wc >>= 6;
+ }
+ *s = (wc & 0xff) | lead;
+
+ return (len);
+}
+
+size_t
+/*ARGSUSED*/
+_citrus_utf8_ctype_wcsrtombs(char * __restrict s,
+ const wchar_t ** __restrict pwcs, size_t n,
+ void * __restrict pspriv)
+{
+ struct _utf8_state *us;
+ char buf[_CITRUS_UTF8_MB_CUR_MAX];
+ const wchar_t *src;
+ size_t nbytes;
+ size_t nb;
+
+ us = (struct _utf8_state *)pspriv;
+
+ if (us->want != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ src = *pwcs;
+ nbytes = 0;
+
+ if (s == NULL) {
+ for (;;) {
+ if (0 <= *src && *src < 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);
+ }
+ src++;
+ nbytes += nb;
+ }
+ /*NOTREACHED*/
+ }
+
+ while (n > 0) {
+ if (0 <= *src && *src < 0x80) {
+ /* Fast path for plain ASCII characters. */
+ nb = 1;
+ *s = *src;
+ } else if (n > (size_t)_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);
+ }
+ } 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);
+ }
+ if (nb > n)
+ /* MB sequence for character won't fit. */
+ break;
+ memcpy(s, buf, nb);
+ }
+ if (*src == L'\0') {
+ *pwcs = NULL;
+ return (nbytes + nb - 1);
+ }
+ src++;
+ s += nb;
+ n -= nb;
+ nbytes += nb;
+ }
+ *pwcs = src;
+ return (nbytes);
+}
diff --git a/lib/libc/citrus/citrus_utf8.h b/lib/libc/citrus/citrus_utf8.h
new file mode 100644
index 00000000000..d7a7bd87794
--- /dev/null
+++ b/lib/libc/citrus/citrus_utf8.h
@@ -0,0 +1,39 @@
+/* $OpenBSD */
+/* $NetBSD: citrus_utf8.h,v 1.2 2003/06/25 09:51:49 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * 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.
+ */
+
+#ifndef _CITRUS_UTF8_H_
+#define _CITRUS_UTF8_H_
+
+extern struct _citrus_ctype_ops_rec _citrus_utf8_ctype_ops;
+
+#define _CITRUS_UTF8_MB_CUR_MAX 4
+
+_CITRUS_CTYPE_DECLS(utf8);
+
+#endif
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc
index 8800b1433eb..987996b7269 100644
--- a/lib/libc/locale/Makefile.inc
+++ b/lib/libc/locale/Makefile.inc
@@ -1,15 +1,15 @@
-# $OpenBSD: Makefile.inc,v 1.15 2010/02/03 20:49:00 miod Exp $
+# $OpenBSD: Makefile.inc,v 1.16 2010/07/27 16:59:03 stsp Exp $
# locale sources
.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/locale ${LIBCSRCDIR}/locale
-SRCS+= _def_messages.c _def_monetary.c _def_numeric.c _def_time.c \
- localeconv.c nl_langinfo.c setlocale.c iswctype.c mbrtowc_sb.c \
- multibyte_sb.c __mb_cur_max.c \
- wcstof.c wcstod.c wcstold.c \
- wcstol.c wcstoul.c wcstoll.c wcstoull.c wcstoimax.c wcstoumax.c \
+SRCS+= btowc.c _def_messages.c _def_monetary.c _def_numeric.c _def_time.c \
+ localeconv.c nl_langinfo.c setlocale.c iswctype.c __mb_cur_max.c \
+ mblen.c mbrlen.c mbstowcs.c mbtowc.c multibyte_citrus.c wcscoll.c \
+ wcstombs.c wctob.c wctomb.c wcstof.c wcstod.c wcstold.c wcstol.c \
+ wcstoul.c wcstoll.c wcstoull.c wcstoimax.c wcstoumax.c \
setrunelocale.c runeglue.c rune.c runetable.c ___runetype_mb.c \
- _wctrans.c
+ _wctrans.c wcsxfrm.c
MAN+= nl_langinfo.3 setlocale.3 iswalnum.3 towlower.3 \
btowc.3 mblen.3 mbrlen.3 mbrtowc.3 mbsinit.3 mbsrtowcs.3 \
@@ -37,4 +37,4 @@ MLINKS+=setlocale.3 localeconv.3 \
wcstol.3 wcstoimax.3 \
wcstol.3 wcstoumax.3
-CFLAGS+=-I${.CURDIR}
+CFLAGS+=-I${.CURDIR} -I${LIBCSRCDIR}/citrus
diff --git a/lib/libc/locale/btowc.c b/lib/libc/locale/btowc.c
new file mode 100644
index 00000000000..e1c6893bca9
--- /dev/null
+++ b/lib/libc/locale/btowc.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: btowc.c,v 1.1 2010/07/27 16:59:03 stsp Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 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 <sys/cdefs.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+wint_t
+btowc(int c)
+{
+ mbstate_t mbs;
+ char cc;
+ wchar_t wc;
+
+ if (c == EOF)
+ return (WEOF);
+ /*
+ * We expect mbrtowc() to return 0 or 1, hence the check for n > 1
+ * which detects error return values as well as "impossible" byte
+ * counts.
+ */
+ memset(&mbs, 0, sizeof(mbs));
+ cc = (char)c;
+ if (mbrtowc(&wc, &cc, 1, &mbs) > 1)
+ return (WEOF);
+ return (wc);
+}
diff --git a/lib/libc/locale/mblen.c b/lib/libc/locale/mblen.c
new file mode 100644
index 00000000000..56d718e69f4
--- /dev/null
+++ b/lib/libc/locale/mblen.c
@@ -0,0 +1,50 @@
+/* $OpenBSD: mblen.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+mblen(const char *s, size_t n)
+{
+ static mbstate_t mbs;
+ size_t rval;
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ memset(&mbs, 0, sizeof(mbs));
+ return (0);
+ }
+ rval = mbrtowc(NULL, s, n, &mbs);
+ if (rval == (size_t)-1 || rval == (size_t)-2)
+ return (-1);
+ return ((int)rval);
+}
diff --git a/lib/libc/locale/mbrlen.c b/lib/libc/locale/mbrlen.c
new file mode 100644
index 00000000000..97c48d2d6ad
--- /dev/null
+++ b/lib/libc/locale/mbrlen.c
@@ -0,0 +1,41 @@
+/* $OpenBSD: mbrlen.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <wchar.h>
+
+size_t
+mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps)
+{
+ static mbstate_t mbs;
+
+ if (ps == NULL)
+ ps = &mbs;
+ return (mbrtowc(NULL, s, n, ps));
+}
diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c
new file mode 100644
index 00000000000..7ea97e4b614
--- /dev/null
+++ b/lib/libc/locale/mbstowcs.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: mbstowcs.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+size_t
+mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
+{
+ mbstate_t mbs;
+ const char *sp;
+
+ memset(&mbs, 0, sizeof(mbs));
+ sp = s;
+ return (mbsrtowcs(pwcs, &sp, n, &mbs));
+}
diff --git a/lib/libc/locale/mbtowc.c b/lib/libc/locale/mbtowc.c
new file mode 100644
index 00000000000..e0dcff0b915
--- /dev/null
+++ b/lib/libc/locale/mbtowc.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: mbtowc.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <errno.h>
+
+int
+mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n)
+{
+ static mbstate_t mbs;
+ size_t rval;
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ memset(&mbs, 0, sizeof(mbs));
+ return (0);
+ }
+ rval = mbrtowc(pwc, s, n, &mbs);
+ if (rval == (size_t)-1 || rval == (size_t)-2)
+ return (-1);
+ return ((int)rval);
+}
diff --git a/lib/libc/locale/multibyte.h b/lib/libc/locale/multibyte.h
new file mode 100644
index 00000000000..9a69ada2751
--- /dev/null
+++ b/lib/libc/locale/multibyte.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: multibyte.h,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/* $NetBSD: multibyte.h,v 1.5 2009/01/11 02:46:28 christos Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * 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.
+ */
+
+#ifndef _MULTIBYTE_H_
+#define _MULTIBYTE_H_
+
+typedef struct _RuneStatePriv {
+ _RuneLocale *__runelocale;
+ char __private __attribute__((__aligned__));
+} _RuneStatePriv;
+
+typedef union _RuneState {
+ mbstate_t __pad;
+ struct _RuneStatePriv __priv;
+#define rs_runelocale __priv.__runelocale
+#define rs_private __priv.__private
+} _RuneState;
+#define _RUNE_STATE_PRIVSIZE (sizeof(mbstate_t)-offsetof(_RuneStatePriv, __private))
+
+#define _ps_to_runestate(ps) ((_RuneState *)(void *)(ps))
+#define _ps_to_runelocale(ps) (_ps_to_runestate(ps)->rs_runelocale)
+#define _ps_to_private(ps) ((void *)&_ps_to_runestate(ps)->rs_private)
+
+#endif /*_MULTIBYTE_H_*/
diff --git a/lib/libc/locale/multibyte_citrus.c b/lib/libc/locale/multibyte_citrus.c
new file mode 100644
index 00000000000..9993e67fe15
--- /dev/null
+++ b/lib/libc/locale/multibyte_citrus.c
@@ -0,0 +1,101 @@
+/* $OpenBSD: multibyte_citrus.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/* $NetBSD: multibyte_amd1.c,v 1.7 2009/01/11 02:46:28 christos Exp $ */
+
+/*-
+ * Copyright (c)2002, 2008 Citrus Project,
+ * 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 <sys/cdefs.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <wchar.h>
+
+#include "citrus_ctype.h"
+#include "rune.h"
+#include "multibyte.h"
+
+int
+mbsinit(const mbstate_t *ps)
+{
+ struct _citrus_ctype_rec *cc;
+ _RuneLocale *rl;
+
+ if (ps == NULL)
+ return 1;
+
+ rl = _ps_to_runelocale(ps);
+ if (rl == NULL)
+ rl = _CurrentRuneLocale;
+ cc = rl->rl_citrus_ctype;
+ return (*cc->cc_ops->co_mbsinit)(ps);
+}
+
+size_t
+mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+{
+ static mbstate_t mbs;
+ struct _citrus_ctype_rec *cc;
+
+ if (ps == NULL)
+ ps = &mbs;
+ cc = _CurrentRuneLocale->rl_citrus_ctype;
+ return (*cc->cc_ops->co_mbrtowc)(pwc, s, n, _ps_to_private(ps));
+}
+
+size_t
+mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps)
+{
+ static mbstate_t mbs;
+ struct _citrus_ctype_rec *cc;
+
+ if (ps == NULL)
+ ps = &mbs;
+ cc = _CurrentRuneLocale->rl_citrus_ctype;
+ return (*cc->cc_ops->co_mbsrtowcs)(pwcs, s, n, _ps_to_private(ps));
+}
+
+size_t
+wcrtomb(char *s, wchar_t wc, mbstate_t *ps)
+{
+ static mbstate_t mbs;
+ struct _citrus_ctype_rec *cc;
+
+ if (ps == NULL)
+ ps = &mbs;
+ cc = _CurrentRuneLocale->rl_citrus_ctype;
+ return (*cc->cc_ops->co_wcrtomb)(s, wc, _ps_to_private(ps));
+}
+
+size_t
+wcsrtombs(char *s, const wchar_t **ppwcs, size_t n, mbstate_t *ps)
+{
+ static mbstate_t mbs;
+ struct _citrus_ctype_rec *cc;
+
+ if (ps == NULL)
+ ps = &mbs;
+ cc = _CurrentRuneLocale->rl_citrus_ctype;
+ return (*cc->cc_ops->co_wcsrtombs)(s, ppwcs, n, _ps_to_private(ps));
+}
diff --git a/lib/libc/locale/runetable.c b/lib/libc/locale/runetable.c
index 3324d1baa22..07dce4ba2b0 100644
--- a/lib/libc/locale/runetable.c
+++ b/lib/libc/locale/runetable.c
@@ -43,6 +43,8 @@
#include <wchar.h>
#include "rune.h"
#include "rune_local.h"
+#include "citrus_ctype.h"
+#include "citrus_none.h"
#include <stdlib.h>
_RuneLocale _DefaultRuneLocale = {
@@ -378,7 +380,7 @@ _RuneLocale _DefaultRuneLocale = {
{ 0, NULL },
NULL, 0,
"646",
- 0,
+ &_citrus_ctype_none,
{
{ NULL, NULL, NULL },
{ NULL, NULL, NULL },
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index bbe4cfb0f6e..8001b0087df 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setrunelocale.c,v 1.4 2008/06/26 05:42:05 ray Exp $ */
+/* $OpenBSD: setrunelocale.c,v 1.5 2010/07/27 16:59:04 stsp Exp $ */
/* $NetBSD: setrunelocale.c,v 1.14 2003/08/07 16:43:07 agc Exp $ */
/*-
@@ -151,10 +151,11 @@ found:
rl->rl_citrus_ctype = NULL;
- if (strcmp(rl->rl_encoding, _CITRUS_DEFAULT_CTYPE_NAME) != 0) {
+ if (_citrus_ctype_open(&rl->rl_citrus_ctype, rl->rl_encoding)) {
_NukeRune(rl);
return EINVAL;
}
+
/* register it */
lt = malloc(sizeof(struct localetable));
if (lt == NULL) {
diff --git a/lib/libc/locale/wcscoll.c b/lib/libc/locale/wcscoll.c
new file mode 100644
index 00000000000..6d476690c54
--- /dev/null
+++ b/lib/libc/locale/wcscoll.c
@@ -0,0 +1,43 @@
+/* $OpenBSD: wcscoll.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/* $NetBSD: wcscoll.c,v 1.1 2003/03/02 22:18:16 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * 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 <sys/cdefs.h>
+
+#include <assert.h>
+#include <wchar.h>
+
+/*
+ * Compare strings with using collating information.
+ */
+int
+wcscoll(const wchar_t *s1, const wchar_t *s2)
+{
+ /* XXX: LC_COLLATE should be implemented. */
+ return (wcscmp(s1, s2));
+}
diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c
new file mode 100644
index 00000000000..024e3afe874
--- /dev/null
+++ b/lib/libc/locale/wcstombs.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: wcstombs.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+size_t
+wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
+{
+ mbstate_t mbs;
+ const wchar_t *pwcsp;
+
+ memset(&mbs, 0, sizeof(mbs));
+ pwcsp = pwcs;
+ return (wcsrtombs(s, &pwcsp, n, &mbs));
+}
diff --git a/lib/libc/locale/mbrtowc_sb.c b/lib/libc/locale/wcsxfrm.c
index e47e06ae019..d2e9ff3fdfd 100644
--- a/lib/libc/locale/mbrtowc_sb.c
+++ b/lib/libc/locale/wcsxfrm.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: mbrtowc_sb.c,v 1.4 2005/11/27 20:03:06 cloder Exp $ */
+/* $OpenBSD: wcsxfrm.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/* $OpenBSD: wcsxfrm.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
/* $NetBSD: multibyte_sb.c,v 1.4 2003/08/07 16:43:04 agc Exp $ */
/*
@@ -30,35 +31,13 @@
* SUCH DAMAGE.
*/
-#include <errno.h>
-#include <stdlib.h>
+#include <sys/cdefs.h>
#include <wchar.h>
-/*ARGSUSED*/
-size_t
-mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+size_t
+wcsxfrm(wchar_t *dest, const wchar_t *src, size_t n)
{
-
- /* pwc may be NULL */
- /* s may be NULL */
- /* ps appears to be unused */
-
- if (s == NULL)
- return 0;
if (n == 0)
- return (size_t)-1;
- if (pwc)
- *pwc = (wchar_t)(unsigned char)*s;
- return (*s != '\0');
-}
-
-int
-mbtowc(wchar_t *pwc, const char *s, size_t n)
-{
-
- /* pwc may be NULL */
- /* s may be NULL */
-
- return mbrtowc(pwc, s, n, NULL);
+ return wcslen(src);
+ return wcslcpy(dest, src, n);
}
-
diff --git a/lib/libc/locale/wctob.c b/lib/libc/locale/wctob.c
new file mode 100644
index 00000000000..cc5a07c1484
--- /dev/null
+++ b/lib/libc/locale/wctob.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: wctob.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+wctob(wint_t c)
+{
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+
+ memset(&mbs, 0, sizeof(mbs));
+ if (c == WEOF || wcrtomb(buf, c, &mbs) != 1)
+ return (EOF);
+ return ((unsigned char)*buf);
+}
diff --git a/lib/libc/locale/wctomb.c b/lib/libc/locale/wctomb.c
new file mode 100644
index 00000000000..9cd1ee4d362
--- /dev/null
+++ b/lib/libc/locale/wctomb.c
@@ -0,0 +1,49 @@
+/* $OpenBSD: wctomb.c,v 1.1 2010/07/27 16:59:04 stsp Exp $ */
+
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+int
+wctomb(char *s, wchar_t wchar)
+{
+ static mbstate_t mbs;
+ size_t rval;
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ memset(&mbs, 0, sizeof(mbs));
+ return (0);
+ }
+ if ((rval = wcrtomb(s, wchar, &mbs)) == (size_t)-1)
+ return (-1);
+ return ((int)rval);
+}