Switch to the OpenBSD wcsto* functions.

This replaces a partial set of non-functional functions with a complete
set of functions, all of which actually work.

This requires us to implement mbsnrtowcs and wcsnrtombs which completes
the set of what we need for libc++.

The mbsnrtowcs is basically a copy & paste of wcsnrtombs, but I'm going
to go straight to looking at using the OpenBSD UTF-8 implementation rather
than keep polishing our home-grown turd.

(This patch also opportunistically switches us over to upstream btowc,
mbrlen, and wctob, since they're all trivially expressed in terms of
other functions.)

Change-Id: I0f81443840de0f1aa73b96f0b51988976793a323
diff --git a/libc/Android.mk b/libc/Android.mk
index 864287a..0fee71a 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -336,9 +336,21 @@
     upstream-openbsd/lib/libc/gen/time.c \
     upstream-openbsd/lib/libc/gen/tolower_.c \
     upstream-openbsd/lib/libc/gen/toupper_.c \
+    upstream-openbsd/lib/libc/locale/btowc.c \
+    upstream-openbsd/lib/libc/locale/mbrlen.c \
+    upstream-openbsd/lib/libc/locale/mbstowcs.c \
     upstream-openbsd/lib/libc/locale/mbtowc.c \
     upstream-openbsd/lib/libc/locale/wcscoll.c \
+    upstream-openbsd/lib/libc/locale/wcstod.c \
+    upstream-openbsd/lib/libc/locale/wcstof.c \
+    upstream-openbsd/lib/libc/locale/wcstol.c \
+    upstream-openbsd/lib/libc/locale/wcstold.c \
+    upstream-openbsd/lib/libc/locale/wcstoll.c \
+    upstream-openbsd/lib/libc/locale/wcstombs.c \
+    upstream-openbsd/lib/libc/locale/wcstoul.c \
+    upstream-openbsd/lib/libc/locale/wcstoull.c \
     upstream-openbsd/lib/libc/locale/wcsxfrm.c \
+    upstream-openbsd/lib/libc/locale/wctob.c \
     upstream-openbsd/lib/libc/stdio/asprintf.c \
     upstream-openbsd/lib/libc/stdio/clrerr.c \
     upstream-openbsd/lib/libc/stdio/fdopen.c \
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 674dc3a..4e62f61 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -29,16 +29,13 @@
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 
 /* stubs for wide-char functions */
 
-wint_t btowc(int c) {
-  return (c == EOF) ? WEOF : c;
-}
-
 int fwprintf(FILE* stream, const wchar_t* format, ...) {
   va_list args;
   va_start(args, format);
@@ -158,10 +155,6 @@
   return 1;
 }
 
-size_t mbrlen(const char* s, size_t n, mbstate_t* /*ps*/) {
-  return (n == 0 || s[0] == 0) ? 0 : 1;
-}
-
 size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* /*ps*/) {
   if (s == NULL) {
     return 0;
@@ -175,24 +168,44 @@
   return (*s != 0);
 }
 
-size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* /*ps*/) {
-  const char* s  = *src;
-  const char* s2 = reinterpret_cast<const char*>(memchr(s, 0, len));
-
-  if (s2 != NULL) {
-    len = (size_t)(s2 - s) + 1U;
+size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t n, size_t dst_size, mbstate_t* /*ps*/) {
+  size_t i = 0; // Number of input bytes read.
+  size_t o = 0; // Number of output characters written.
+  for (; i < n && (*src)[i] != 0; ++i) {
+    // TODO: UTF-8 support.
+    if ((*src)[i] > 0x7f) {
+      errno = EILSEQ;
+      if (dst != NULL) {
+        *src = &(*src)[i];
+      }
+      return static_cast<size_t>(-1);
+    }
+    if (dst != NULL) {
+      if (o + 1 > dst_size) {
+        break;
+      }
+      dst[o++] = static_cast<wchar_t>((*src)[i]);
+    } else {
+      ++o;
+    }
   }
-
-  if (dst) {
-    memcpy(reinterpret_cast<char*>(dst), s, len );
+  // If we consumed all the input, terminate the output.
+  if (dst != NULL && o < dst_size) {
+    dst[o] = 0;
   }
-
-  *src = s + len;
-  return len;
+  // If we were actually consuming input, record how far we got.
+  if (dst != NULL) {
+    if ((*src)[i] != 0) {
+      *src = &(*src)[i]; // This is where the next call should pick up.
+    } else {
+      *src = NULL; // We consumed everything.
+    }
+  }
+  return o;
 }
 
-size_t mbstowcs(wchar_t* dst, const char* src, size_t len) {
-  return mbsrtowcs(dst, &src, len, NULL);
+size_t mbsrtowcs(wchar_t* dst, const char** src, size_t dst_size, mbstate_t* ps) {
+  return mbsnrtowcs(dst, src, SIZE_MAX, dst_size, ps);
 }
 
 wint_t putwc(wchar_t wc, FILE* stream) {
@@ -239,10 +252,10 @@
   return strftime(reinterpret_cast<char*>(wcs), maxsize, reinterpret_cast<const char*>(format), timptr);
 }
 
-size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) {
+size_t wcsnrtombs(char* dst, const wchar_t** src, size_t n, size_t dst_size, mbstate_t* /*ps*/) {
   size_t i = 0; // Number of input characters read.
   size_t o = 0; // Number of output bytes written.
-  for (; (*src)[i] != 0; ++i) {
+  for (; i < n && (*src)[i] != 0; ++i) {
     // TODO: UTF-8 support.
     if ((*src)[i] > 0x7f) {
       errno = EILSEQ;
@@ -252,7 +265,7 @@
       return static_cast<size_t>(-1);
     }
     if (dst != NULL) {
-      if (o + 1 > n) {
+      if (o + 1 > dst_size) {
         break;
       }
       dst[o++] = static_cast<char>((*src)[i]);
@@ -261,7 +274,7 @@
     }
   }
   // If we consumed all the input, terminate the output.
-  if (dst != NULL && o < n) {
+  if (dst != NULL && o < dst_size) {
     dst[o] = 0;
   }
   // If we were actually consuming input, record how far we got.
@@ -275,25 +288,8 @@
   return o;
 }
 
-size_t wcstombs(char* dst, const wchar_t* src, size_t len) {
-  const wchar_t* p = src;
-  return wcsrtombs(dst, &p, len, NULL);
-}
-
-double wcstod(const wchar_t* nptr, wchar_t** endptr) {
-  return strtod(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr));
-}
-
-long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base) {
-  return strtol(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr), base);
-}
-
-unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base) {
-  return strtoul(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr), base);
-}
-
-int wctob(wint_t c) {
-  return c;
+size_t wcsrtombs(char* dst, const wchar_t** src, size_t dst_size, mbstate_t* ps) {
+  return wcsnrtombs(dst, src, SIZE_MAX, dst_size, ps);
 }
 
 wctype_t wctype(const char* property) {
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 0029a65..12715c2 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -87,7 +87,8 @@
 extern int               mbsinit(const mbstate_t *);
 extern size_t            mbrlen(const char *, size_t, mbstate_t *);
 extern size_t            mbrtowc(wchar_t *, const char *, size_t, mbstate_t *);
-extern size_t            mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *);
+extern size_t mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*);
+extern size_t mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*);
 extern size_t            mbstowcs(wchar_t *, const char *, size_t);
 extern wint_t            putwc(wchar_t, FILE *);
 extern wint_t            putwchar(wchar_t);
@@ -113,16 +114,20 @@
 extern wchar_t          *wcsncat(wchar_t *, const wchar_t *, size_t);
 extern int               wcsncmp(const wchar_t *, const wchar_t *, size_t);
 extern wchar_t          *wcsncpy(wchar_t *, const wchar_t *, size_t);
+extern size_t wcsnrtombs(char*, const wchar_t**, size_t, size_t, mbstate_t*);
 extern wchar_t          *wcspbrk(const wchar_t *, const wchar_t *);
 extern wchar_t          *wcsrchr(const wchar_t *, wchar_t);
-extern size_t            wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *);
+extern size_t wcsrtombs(char*, const wchar_t**, size_t, mbstate_t*);
 extern size_t            wcsspn(const wchar_t *, const wchar_t *);
 extern wchar_t          *wcsstr(const wchar_t *, const wchar_t *);
-extern double            wcstod(const wchar_t *, wchar_t **);
-extern wchar_t          *wcstok(wchar_t *, const wchar_t *, wchar_t **);
-extern long int          wcstol(const wchar_t *, wchar_t **, int);
-extern size_t            wcstombs(char *, const wchar_t *, size_t);
-extern unsigned long int wcstoul(const wchar_t *, wchar_t **, int);
+extern double wcstod(const wchar_t*, wchar_t**);
+extern float wcstof(const wchar_t*, wchar_t**);
+extern wchar_t* wcstok(wchar_t*, const wchar_t*, wchar_t**);
+extern long wcstol(const wchar_t*, wchar_t**, int);
+extern long long wcstoll(const wchar_t*, wchar_t**, int);
+extern long double wcstold(const wchar_t*, wchar_t**);
+extern unsigned long wcstoul(const wchar_t*, wchar_t**, int);
+extern unsigned long long wcstoull(const wchar_t*, wchar_t**, int);
 extern wchar_t          *wcswcs(const wchar_t *, const wchar_t *);
 extern int               wcswidth(const wchar_t *, size_t);
 extern size_t            wcsxfrm(wchar_t *, const wchar_t *, size_t);
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstod.h b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h
new file mode 100644
index 0000000..ae993ad
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h
@@ -0,0 +1,153 @@
+/*	$OpenBSD: _wcstod.h,v 1.2 2013/06/02 15:22:20 matthew Exp $	*/
+/* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */
+
+/*-
+ * Copyright (c)1999, 2000, 2001 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.
+ *
+ *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $
+ */
+
+/*
+ * function template for wcstof, wcstod and wcstold.
+ *
+ * parameters:
+ *	FUNCNAME : function name
+ *      float_type : return type
+ *      STRTOD_FUNC : conversion function
+ */
+
+float_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr)
+{
+	const wchar_t *src;
+	size_t size;
+	const wchar_t *start;
+	const wchar_t *aftersign;
+
+	/*
+	 * check length of string and call strtod
+	 */
+	src = nptr;
+
+	/* skip space first */
+	while (iswspace(*src)) {
+		src++;
+	}
+
+	/* get length of string */
+	start = src;
+	if (*src && wcschr(L"+-", *src))
+		src++;
+	aftersign = src;
+	if (wcsncasecmp(src, L"inf", 3) == 0) {
+		src += 3;
+		if (wcsncasecmp(src, L"inity", 5) == 0)
+			src += 5;
+		goto match;
+	}
+	if (wcsncasecmp(src, L"nan", 3) == 0) {
+		src += 3;
+		if (*src == L'(') {
+			size = 1;
+			while (src[size] != L'\0' && src[size] != L')')
+				size++;
+			if (src[size] == L')')
+				src += size + 1;
+		}
+		goto match;
+	}
+	size = wcsspn(src, L"0123456789");
+	src += size;
+	if (*src == L'.') {/* XXX use localeconv */
+		src++;
+		size = wcsspn(src, L"0123456789");
+		src += size;
+	}
+	if (*src && wcschr(L"Ee", *src)) {
+		src++;
+		if (*src && wcschr(L"+-", *src))
+			src++;
+		size = wcsspn(src, L"0123456789");
+		src += size;
+	}
+match:
+	size = src - start;
+
+	/*
+	 * convert to a char-string and pass it to strtod.
+	 */
+	if (src > aftersign) {
+		mbstate_t st;
+		char *buf;
+		char *end;
+		const wchar_t *s;
+		size_t size_converted;
+		float_type result;
+		size_t bufsize;
+
+		s = start;
+		memset(&st, 0, sizeof(st));
+		bufsize = wcsnrtombs(NULL, &s, size, 0, &st);
+
+		buf = malloc(bufsize + 1);
+		if (!buf) {
+			errno = ENOMEM; /* XXX */
+			goto fail;
+		}
+
+		s = start;
+		memset(&st, 0, sizeof(st));
+		size_converted = wcsnrtombs(buf, &s, size, bufsize, &st);
+		if (size_converted != bufsize) {
+			/* XXX should not happen */
+			free(buf);
+			errno = EILSEQ;
+			goto fail;
+		}
+
+		buf[bufsize] = 0;
+		result = STRTOD_FUNC(buf, &end);
+
+		if (endptr) {
+			const char *s = buf;
+			memset(&st, 0, sizeof(st));
+			size = mbsnrtowcs(NULL, &s, end - buf, 0, &st);
+
+			/* LINTED bad interface */
+			*endptr = (wchar_t*)start + size;
+		}
+
+		free(buf);
+
+		return result;
+	}
+
+fail:
+	if (endptr)
+		/* LINTED bad interface */
+		*endptr = (wchar_t*)nptr;
+
+	return 0;
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
new file mode 100644
index 0000000..7b49bbf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
@@ -0,0 +1,136 @@
+/*	$OpenBSD: _wcstol.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  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.
+ * 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
+ * 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
+ * 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.
+ *
+ * Original version ID:
+ * @(#)strtol.c	8.1 (Berkeley) 6/4/93
+ * NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp
+ * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp
+ */
+
+/*
+ * function template for wcstol, wcstoll and wcstoimax.
+ *
+ * parameters:
+ *	FUNCNAME : function name
+ *      int_type : return type
+ *      MIN_VALUE : lower limit of the return type
+ *      MAX_VALUE : upper limit of the return type
+ */
+
+int_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
+{
+	const wchar_t *s;
+	int_type acc, cutoff;
+	wint_t wc;
+	int i;
+	int neg, any, cutlim;
+
+	/* check base value */
+	if (base && (base < 2 || base > 36)) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		wc = (wchar_t) *s++;
+	} while (iswspace(wc));
+	if (wc == L'-') {
+		neg = 1;
+		wc = *s++;
+	} else {
+		neg = 0;
+		if (wc == L'+')
+			wc = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    wc == L'0' && (*s == L'x' || *s == L'X')) {
+		wc = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = wc == L'0' ? 8 : 10;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	cutoff = neg ? MIN_VALUE : MAX_VALUE;
+	cutlim = (int)(cutoff % base);
+	cutoff /= base;
+	if (neg) {
+		if (cutlim > 0) {
+			cutlim -= base;
+			cutoff += 1;
+		}
+		cutlim = -cutlim;
+	}
+	for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
+		i = wctoint(wc);
+		if (i == -1)
+			break;
+		if (i >= base)
+			break;
+		if (any < 0)
+			continue;
+		if (neg) {
+			if (acc < cutoff || (acc == cutoff && i > cutlim)) {
+				any = -1;
+				acc = MIN_VALUE;
+				errno = ERANGE;
+			} else {
+				any = 1;
+				acc *= base;
+				acc -= i;
+			}
+		} else {
+			if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+				any = -1;
+				acc = MAX_VALUE;
+				errno = ERANGE;
+			} else {
+				any = 1;
+				acc *= base;
+				acc += i;
+			}
+		}
+	}
+	if (endptr != 0)
+		/* LINTED interface specification */
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
new file mode 100644
index 0000000..736b38f
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
@@ -0,0 +1,116 @@
+/*	$OpenBSD: _wcstoul.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  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.
+ * 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
+ * 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
+ * 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.
+ *
+ * Original version ID:
+ * @(#)strtoul.c	8.1 (Berkeley) 6/4/93
+ * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp
+ * NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp
+ */
+
+/*
+ * function template for wcstoul, wcstoull and wcstoumax.
+ *
+ * parameters:
+ *	FUNCNAME  : function name
+ *      uint_type : return type
+ *      MAX_VALUE : upper limit of the return type
+ */
+
+uint_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
+{
+	const wchar_t *s;
+	uint_type acc, cutoff;
+	wint_t wc;
+	int i;
+	int neg, any, cutlim;
+
+	if (base && (base < 2 || base > 36)) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		wc = (wchar_t) *s++;
+	} while (iswspace(wc));
+	if (wc == L'-') {
+		neg = 1;
+		wc = *s++;
+	} else {
+		neg = 0;
+		if (wc == L'+')
+			wc = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    wc == L'0' && (*s == L'x' || *s == L'X')) {
+		wc = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = wc == L'0' ? 8 : 10;
+
+	/*
+	 * See strtoul for comments as to the logic used.
+	 */
+	cutoff = MAX_VALUE / (uint_type)base;
+	cutlim = (int)(MAX_VALUE % (uint_type)base);
+	for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
+		i = wctoint(wc);
+		if (i == (wint_t)-1)
+			break;
+		if (i >= base)
+			break;
+		if (any < 0)
+			continue;
+		if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+			any = -1;
+			acc = MAX_VALUE;
+			errno = ERANGE;
+		} else {
+			any = 1;
+			acc *= (uint_type)base;
+			acc += i;
+		}
+	}
+	if (neg && any > 0)
+		acc = -acc;
+	if (endptr != 0)
+		/* LINTED interface specification */
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/btowc.c b/libc/upstream-openbsd/lib/libc/locale/btowc.c
new file mode 100644
index 0000000..9627340
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/btowc.c
@@ -0,0 +1,52 @@
+/*	$OpenBSD: btowc.c,v 1.2 2012/12/05 23:20:00 deraadt 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 <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/libc/upstream-openbsd/lib/libc/locale/mbrlen.c b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
new file mode 100644
index 0000000..0f05bd0
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
@@ -0,0 +1,39 @@
+/*	$OpenBSD: mbrlen.c,v 1.2 2012/12/05 23:20:00 deraadt 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 <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/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c
new file mode 100644
index 0000000..c17a858
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c
@@ -0,0 +1,44 @@
+/*	$OpenBSD: mbstowcs.c,v 1.2 2012/12/05 23:20:00 deraadt 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 <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/libc/upstream-openbsd/lib/libc/locale/wcstod.c b/libc/upstream-openbsd/lib/libc/locale/wcstod.c
new file mode 100644
index 0000000..957d0a1
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstod.c
@@ -0,0 +1,13 @@
+/*	$OpenBSD: wcstod.c,v 1.3 2009/01/13 18:18:31 kettenis Exp $	*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define FUNCNAME	wcstod
+typedef double		float_type;
+#define STRTOD_FUNC	strtod
+
+#include "_wcstod.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstof.c b/libc/upstream-openbsd/lib/libc/locale/wcstof.c
new file mode 100644
index 0000000..40d76c7
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstof.c
@@ -0,0 +1,13 @@
+/*	$OpenBSD: wcstof.c,v 1.1 2009/01/13 18:18:31 kettenis Exp $	*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define FUNCNAME	wcstof
+typedef float		float_type;
+#define STRTOD_FUNC	strtof
+
+#include "_wcstod.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstol.c b/libc/upstream-openbsd/lib/libc/locale/wcstol.c
new file mode 100644
index 0000000..03395a0
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstol.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: wcstol.c,v 1.2 2005/08/08 08:05:35 espie Exp $	*/
+/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstol
+typedef long int_type;
+#define	MIN_VALUE	LONG_MIN
+#define	MAX_VALUE	LONG_MAX
+
+#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstold.c b/libc/upstream-openbsd/lib/libc/locale/wcstold.c
new file mode 100644
index 0000000..a642542
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstold.c
@@ -0,0 +1,13 @@
+/*	$OpenBSD: wcstold.c,v 1.1 2009/01/13 18:18:31 kettenis Exp $	*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define FUNCNAME	wcstold
+typedef long double	float_type;
+#define STRTOD_FUNC	strtold
+
+#include "_wcstod.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
new file mode 100644
index 0000000..926db70
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: wcstoll.c,v 1.2 2005/08/08 08:05:35 espie Exp $	*/
+/* $NetBSD: wcstoll.c,v 1.1 2003/03/11 09:21:23 tshiozak Exp $ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstoll
+typedef long long int int_type;
+#define	MIN_VALUE	LLONG_MIN
+#define	MAX_VALUE	LLONG_MAX
+
+#include "_wcstol.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstombs.c b/libc/upstream-openbsd/lib/libc/locale/wcstombs.c
new file mode 100644
index 0000000..e8054c4
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstombs.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: wcstombs.c,v 1.2 2012/12/05 23:20:00 deraadt 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 <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/libc/upstream-openbsd/lib/libc/locale/wcstoul.c b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
new file mode 100644
index 0000000..e863862
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c
@@ -0,0 +1,17 @@
+/*	$OpenBSD: wcstoul.c,v 1.2 2005/08/08 08:05:35 espie Exp $	*/
+/*	$NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $	*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstoul
+typedef unsigned long uint_type;
+#define	MAX_VALUE	ULONG_MAX
+
+#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
new file mode 100644
index 0000000..6671c37
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c
@@ -0,0 +1,17 @@
+/*	$OpenBSD: wcstoull.c,v 1.2 2005/08/08 08:05:35 espie Exp $	*/
+/*	$NetBSD: wcstoull.c,v 1.1 2003/03/11 09:21:24 tshiozak Exp $	*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstoull
+typedef unsigned long long int uint_type;
+#define	MAX_VALUE	ULLONG_MAX
+
+#include "_wcstoul.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wctob.c b/libc/upstream-openbsd/lib/libc/locale/wctob.c
new file mode 100644
index 0000000..ea1f40c
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wctob.c
@@ -0,0 +1,43 @@
+/*	$OpenBSD: wctob.c,v 1.2 2012/12/05 23:20:00 deraadt 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 <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/libc/upstream-openbsd/lib/libc/locale/wctoint.h b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
new file mode 100644
index 0000000..c9bf084
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wctoint.h
@@ -0,0 +1,79 @@
+/*	$OpenBSD: wctoint.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/* $NetBSD: __wctoint.h,v 1.1 2001/09/28 11:25:37 yamt Exp $ */
+
+/*-
+ * Copyright (c)2001 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.
+ *
+ *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/__wctoint.h,v 1.1 2001/09/21 13:52:32 yamt Exp $
+ */
+
+
+__inline static int
+wctoint(wchar_t wc)
+{
+	int n;
+
+	switch (wc) {
+	case L'0': n = 0; break;
+	case L'1': n = 1; break;
+	case L'2': n = 2; break;
+	case L'3': n = 3; break;
+	case L'4': n = 4; break;
+	case L'5': n = 5; break;
+	case L'6': n = 6; break;
+	case L'7': n = 7; break;
+	case L'8': n = 8; break;
+	case L'9': n = 9; break;
+	case L'A': case L'a': n = 10; break;
+	case L'B': case L'b': n = 11; break;
+	case L'C': case L'c': n = 12; break;
+	case L'D': case L'd': n = 13; break;
+	case L'E': case L'e': n = 14; break;
+	case L'F': case L'f': n = 15; break;
+	case L'G': case L'g': n = 16; break;
+	case L'H': case L'h': n = 17; break;
+	case L'I': case L'i': n = 18; break;
+	case L'J': case L'j': n = 19; break;
+	case L'K': case L'k': n = 20; break;
+	case L'L': case L'l': n = 21; break;
+	case L'M': case L'm': n = 22; break;
+	case L'N': case L'n': n = 23; break;
+	case L'O': case L'o': n = 24; break;
+	case L'P': case L'p': n = 25; break;
+	case L'Q': case L'q': n = 26; break;
+	case L'R': case L'r': n = 27; break;
+	case L'S': case L's': n = 28; break;
+	case L'T': case L't': n = 29; break;
+	case L'U': case L'u': n = 30; break;
+	case L'V': case L'v': n = 31; break;
+	case L'W': case L'w': n = 32; break;
+	case L'X': case L'x': n = 33; break;
+	case L'Y': case L'y': n = 34; break;
+	case L'Z': case L'z': n = 35; break;
+	default: n = -1; break; /* error */
+	}
+
+	return n;
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index 0014af6..e7acc8b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -38,6 +38,8 @@
     -Werror \
     -fno-builtin \
 
+test_cflags += -D__STDC_LIMIT_MACROS  # For glibc.
+
 libBionicStandardTests_src_files := \
     buffer_tests.cpp \
     ctype_test.cpp \
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f56b767..ce0beba 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -18,8 +18,6 @@
 #include "ScopedSignalHandler.h"
 #include "TemporaryFile.h"
 
-#define __STDC_LIMIT_MACROS // For glibc.
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 3c38f1f..f6c2683 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -18,6 +18,7 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <stdint.h>
 #include <wchar.h>
 
 TEST(wchar, sizeof_wchar_t) {
@@ -212,3 +213,56 @@
 
   ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL));
 }
+
+TEST(wchar, wcstod) {
+  ASSERT_DOUBLE_EQ(1.23, wcstod(L"1.23", NULL));
+}
+
+TEST(wchar, wcstof) {
+  ASSERT_FLOAT_EQ(1.23f, wcstof(L"1.23", NULL));
+}
+
+TEST(wchar, wcstol) {
+  ASSERT_EQ(123L, wcstol(L"123", NULL, 0));
+}
+
+TEST(wchar, wcstoll) {
+  ASSERT_EQ(123LL, wcstol(L"123", NULL, 0));
+}
+
+TEST(wchar, wcstold) {
+  ASSERT_DOUBLE_EQ(1.23L, wcstold(L"1.23", NULL));
+}
+
+TEST(wchar, wcstoul) {
+  ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0));
+}
+
+TEST(wchar, wcstoull) {
+  ASSERT_EQ(123ULL, wcstoul(L"123", NULL, 0));
+}
+
+TEST(wchar, mbsnrtowcs) {
+  wchar_t dst[128];
+  const char* s = "hello, world!";
+  const char* src;
+
+  memset(dst, 0, sizeof(dst));
+  src = s;
+  ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, NULL));
+
+  memset(dst, 0, sizeof(dst));
+  src = s;
+  ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, NULL)); // glibc chokes on SIZE_MAX here.
+  ASSERT_EQ(L'h', dst[0]);
+  ASSERT_EQ(L'e', dst[1]);
+  ASSERT_EQ(&s[2], src);
+
+  memset(dst, 0, sizeof(dst));
+  src = s;
+  ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, NULL));
+  ASSERT_EQ(L'h', dst[0]);
+  ASSERT_EQ(L'e', dst[1]);
+  ASSERT_EQ(L'l', dst[2]);
+  ASSERT_EQ(&s[3], src);
+}