Merge "Fix cpu_set_t"
diff --git a/libc/Android.mk b/libc/Android.mk
index 5cadba1..0b70e07 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -232,6 +232,7 @@
     upstream-freebsd/lib/libc/stdlib/labs.c \
     upstream-freebsd/lib/libc/stdlib/llabs.c \
     upstream-freebsd/lib/libc/stdlib/qsort.c \
+    upstream-freebsd/lib/libc/stdlib/quick_exit.c \
     upstream-freebsd/lib/libc/stdlib/realpath.c \
     upstream-freebsd/lib/libc/string/wcpcpy.c \
     upstream-freebsd/lib/libc/string/wcpncpy.c \
@@ -246,7 +247,6 @@
     upstream-freebsd/lib/libc/string/wcsnlen.c \
     upstream-freebsd/lib/libc/string/wcspbrk.c \
     upstream-freebsd/lib/libc/string/wcsspn.c \
-    upstream-freebsd/lib/libc/string/wcsstr.c \
     upstream-freebsd/lib/libc/string/wcstok.c \
     upstream-freebsd/lib/libc/string/wmemchr.c \
     upstream-freebsd/lib/libc/string/wmemcpy.c \
@@ -337,8 +337,23 @@
     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/wcstoimax.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/wcstoumax.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 \
@@ -349,11 +364,15 @@
     upstream-openbsd/lib/libc/stdio/fgetln.c \
     upstream-openbsd/lib/libc/stdio/fgetpos.c \
     upstream-openbsd/lib/libc/stdio/fgets.c \
+    upstream-openbsd/lib/libc/stdio/fgetwc.c \
+    upstream-openbsd/lib/libc/stdio/fgetws.c \
     upstream-openbsd/lib/libc/stdio/fileno.c \
     upstream-openbsd/lib/libc/stdio/fprintf.c \
     upstream-openbsd/lib/libc/stdio/fpurge.c \
     upstream-openbsd/lib/libc/stdio/fputc.c \
     upstream-openbsd/lib/libc/stdio/fputs.c \
+    upstream-openbsd/lib/libc/stdio/fputwc.c \
+    upstream-openbsd/lib/libc/stdio/fputws.c \
     upstream-openbsd/lib/libc/stdio/fread.c \
     upstream-openbsd/lib/libc/stdio/freopen.c \
     upstream-openbsd/lib/libc/stdio/fscanf.c \
@@ -363,17 +382,24 @@
     upstream-openbsd/lib/libc/stdio/funopen.c \
     upstream-openbsd/lib/libc/stdio/fvwrite.c \
     upstream-openbsd/lib/libc/stdio/fwalk.c \
+    upstream-openbsd/lib/libc/stdio/fwide.c \
+    upstream-openbsd/lib/libc/stdio/fwprintf.c \
+    upstream-openbsd/lib/libc/stdio/fwscanf.c \
     upstream-openbsd/lib/libc/stdio/getc.c \
     upstream-openbsd/lib/libc/stdio/getchar.c \
     upstream-openbsd/lib/libc/stdio/getdelim.c \
     upstream-openbsd/lib/libc/stdio/getline.c \
     upstream-openbsd/lib/libc/stdio/gets.c \
+    upstream-openbsd/lib/libc/stdio/getwc.c \
+    upstream-openbsd/lib/libc/stdio/getwchar.c \
     upstream-openbsd/lib/libc/stdio/perror.c \
     upstream-openbsd/lib/libc/stdio/printf.c \
     upstream-openbsd/lib/libc/stdio/putc.c \
     upstream-openbsd/lib/libc/stdio/putchar.c \
     upstream-openbsd/lib/libc/stdio/puts.c \
     upstream-openbsd/lib/libc/stdio/putw.c \
+    upstream-openbsd/lib/libc/stdio/putwc.c \
+    upstream-openbsd/lib/libc/stdio/putwchar.c \
     upstream-openbsd/lib/libc/stdio/refill.c \
     upstream-openbsd/lib/libc/stdio/remove.c \
     upstream-openbsd/lib/libc/stdio/rewind.c \
@@ -383,18 +409,29 @@
     upstream-openbsd/lib/libc/stdio/setbuffer.c \
     upstream-openbsd/lib/libc/stdio/sscanf.c \
     upstream-openbsd/lib/libc/stdio/stdio.c \
+    upstream-openbsd/lib/libc/stdio/swprintf.c \
+    upstream-openbsd/lib/libc/stdio/swscanf.c \
     upstream-openbsd/lib/libc/stdio/tempnam.c \
     upstream-openbsd/lib/libc/stdio/tmpnam.c \
     upstream-openbsd/lib/libc/stdio/ungetc.c \
+    upstream-openbsd/lib/libc/stdio/ungetwc.c \
     upstream-openbsd/lib/libc/stdio/vasprintf.c \
     upstream-openbsd/lib/libc/stdio/vfprintf.c \
     upstream-openbsd/lib/libc/stdio/vfscanf.c \
+    upstream-openbsd/lib/libc/stdio/vfwprintf.c \
+    upstream-openbsd/lib/libc/stdio/vfwscanf.c \
     upstream-openbsd/lib/libc/stdio/vprintf.c \
     upstream-openbsd/lib/libc/stdio/vscanf.c \
     upstream-openbsd/lib/libc/stdio/vsnprintf.c \
     upstream-openbsd/lib/libc/stdio/vsprintf.c \
     upstream-openbsd/lib/libc/stdio/vsscanf.c \
+    upstream-openbsd/lib/libc/stdio/vswprintf.c \
+    upstream-openbsd/lib/libc/stdio/vswscanf.c \
+    upstream-openbsd/lib/libc/stdio/vwprintf.c \
+    upstream-openbsd/lib/libc/stdio/vwscanf.c \
     upstream-openbsd/lib/libc/stdio/wbuf.c \
+    upstream-openbsd/lib/libc/stdio/wprintf.c \
+    upstream-openbsd/lib/libc/stdio/wscanf.c \
     upstream-openbsd/lib/libc/stdlib/atoi.c \
     upstream-openbsd/lib/libc/stdlib/atol.c \
     upstream-openbsd/lib/libc/stdlib/atoll.c \
@@ -419,6 +456,8 @@
     upstream-openbsd/lib/libc/string/strstr.c \
     upstream-openbsd/lib/libc/string/strtok.c \
     upstream-openbsd/lib/libc/string/wcslcpy.c \
+    upstream-openbsd/lib/libc/string/wcsstr.c \
+    upstream-openbsd/lib/libc/string/wcswcs.c \
     upstream-openbsd/lib/libc/string/wcswidth.c \
 
 libc_arch_static_src_files := \
diff --git a/libc/bionic/flockfile.cpp b/libc/bionic/flockfile.cpp
index c60497d..3381e8e 100644
--- a/libc/bionic/flockfile.cpp
+++ b/libc/bionic/flockfile.cpp
@@ -29,7 +29,7 @@
 #include <errno.h>
 #include <stdio.h>
 
-#include "fileext.h"
+#include "local.h"
 
 // We can't use the OpenBSD implementation which uses kernel-specific
 // APIs not available on Linux. Instead we use a pthread_mutex_t within
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 021d14b..badd256 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -29,72 +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);
-  int result = vfwprintf(stream, format, args);
-  va_end(args);
-  return result;
-}
-
-int wprintf(const wchar_t* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int result = vwprintf(format, args);
-  va_end(args);
-  return result;
-}
-
-int swprintf(wchar_t* s, size_t n, const wchar_t* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int result = vswprintf(s, n, format, args);
-  va_end(args);
-  return result;
-}
-
-int vwprintf(const wchar_t* format, va_list arg) {
-  return vfwprintf(stdout, format, arg);
-}
-
-int vfwprintf(FILE* /*stream*/, const wchar_t* /*format*/, va_list /*arg*/) {
-  errno = ENOTSUP;
-  return -1;
-}
-
-int vswprintf(wchar_t* /*s*/, size_t /*n*/, const wchar_t* /*format*/, va_list /*arg*/) {
-  errno = ENOTSUP;
-  return -1;
-}
-
-int fwscanf(FILE* /*stream*/, const wchar_t* /*format*/, ... ) {
-  errno = ENOTSUP;
-  return -1;
-}
-
-int wscanf(const wchar_t* format, ... ) {
-  va_list args;
-  va_start (args, format);
-  int result = fwscanf(stdout, format, args );
-  va_end (args);
-  return result;
-}
-
-int swscanf(const wchar_t* /*s*/, const wchar_t* /*format*/, ... ) {
-  errno = ENOTSUP;
-  return -1;
-}
-
 int iswalnum(wint_t wc) { return isalnum(wc); }
 int iswalpha(wint_t wc) { return isalpha(wc); }
 int iswblank(wint_t wc) { return isblank(wc); }
@@ -126,85 +67,61 @@
   }
 }
 
-wint_t fgetwc(FILE* stream) {
-  return static_cast<wint_t>(fgetc(stream));
-}
-
-wchar_t* fgetws(wchar_t* ws, int n, FILE* stream) {
-  return reinterpret_cast<wchar_t*>(fgets(reinterpret_cast<char*>(ws), n, stream));
-}
-
-wint_t fputwc(wchar_t wc, FILE* stream) {
-  return static_cast<wint_t>(fputc(static_cast<char>(wc), stream));
-}
-
-int fputws(const wchar_t* str, FILE* stream) {
-  return fputs(reinterpret_cast<const char*>(str), stream );
-}
-
-int fwide(FILE* /*stream*/, int mode) {
-  return mode;
-}
-
-wint_t getwc(FILE* stream) {
-  return getc(stream);
-}
-
-wint_t getwchar() {
-  return getchar();
-}
-
 int mbsinit(const mbstate_t* /*ps*/) {
   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) {
-    s   = "";
-    pwc = NULL;
+    return 0;
   }
   if (n == 0) {
-    if (pwc) {
-      *pwc = 0;
-      return 0;
-    }
+    return 0;
   }
-  if (pwc) {
+  if (pwc != NULL) {
     *pwc = *s;
   }
   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 (static_cast<uint8_t>((*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);
-}
-
-wint_t putwc(wchar_t wc, FILE* stream) {
-  return fputc(static_cast<char>(wc), stream);
-}
-
-wint_t putwchar(wchar_t wc) {
-  return putchar(static_cast<char>(wc));
+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 towlower(wint_t wc) {
@@ -215,10 +132,6 @@
   return toupper(wc);
 }
 
-wint_t ungetwc(wint_t wc, FILE* stream) {
-  return ungetc(static_cast<char>(wc), stream);
-}
-
 int wctomb(char* s, wchar_t wc) {
   if (s == NULL) {
     return 0;
@@ -243,10 +156,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;
@@ -256,7 +169,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]);
@@ -265,7 +178,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.
@@ -279,31 +192,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);
-}
-
-wchar_t* wcswcs(const wchar_t* ws1, const wchar_t* ws2) {
-  const char* s1 = reinterpret_cast<const char*>(ws1);
-  const char* s2 = reinterpret_cast<const char*>(ws2);
-  return reinterpret_cast<wchar_t*>(strstr(s1, s2));
-}
-
-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/inttypes.h b/libc/include/inttypes.h
index 5199e4d..8853c08 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -254,13 +254,14 @@
 } imaxdiv_t;
 
 __BEGIN_DECLS
-
 intmax_t	imaxabs(intmax_t) __pure2;
 imaxdiv_t	imaxdiv(intmax_t, intmax_t) __pure2;
-
 intmax_t	strtoimax(const char *, char **, int);
 uintmax_t	strtoumax(const char *, char **, int);
-
+intmax_t	wcstoimax(const wchar_t * __restrict,
+		    wchar_t ** __restrict, int);
+uintmax_t	wcstoumax(const wchar_t * __restrict,
+		    wchar_t ** __restrict, int);
 __END_DECLS
 
 #endif /* _INTTYPES_H_ */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 6c966f7..834dcda 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -46,6 +46,11 @@
 extern __noreturn void _Exit(int);
 extern int atexit(void (*)(void));
 
+#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
+int at_quick_exit(void (*)(void));
+void quick_exit(int) __noreturn;
+#endif
+
 extern char* getenv(const char*);
 extern int putenv(char*);
 extern int setenv(const char*, const char*, int);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 6251868..fe2fe07 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -94,7 +94,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);
@@ -103,9 +104,12 @@
 extern wint_t            towlower(wint_t);
 extern wint_t            towupper(wint_t);
 extern wint_t            ungetwc(wint_t, FILE *);
-extern int               vfwprintf(FILE *, const wchar_t *, va_list);
-extern int               vwprintf(const wchar_t *, va_list);
-extern int               vswprintf(wchar_t *, size_t, const wchar_t *, va_list);
+extern int vfwprintf(FILE*, const wchar_t*, va_list);
+extern int vfwscanf(FILE*, const wchar_t*, va_list);
+extern int vswprintf(wchar_t*, size_t, const wchar_t*, va_list);
+extern int vswscanf(const wchar_t*, const wchar_t*, va_list);
+extern int vwprintf(const wchar_t*, va_list);
+extern int vwscanf(const wchar_t*, va_list);
 extern size_t            wcrtomb(char *, wchar_t, mbstate_t *);
 extern int               wcscasecmp(const wchar_t *, const wchar_t *);
 extern wchar_t          *wcscat(wchar_t *, const wchar_t *);
@@ -120,16 +124,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/stdio/fileext.h b/libc/stdio/fileext.h
index 8641924..fa6fed6 100644
--- a/libc/stdio/fileext.h
+++ b/libc/stdio/fileext.h
@@ -30,7 +30,6 @@
  */
 
 #include <pthread.h>
-#include "wcio.h"
 
 /*
  * file extension
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 926e5a1..2dd32c9 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -61,11 +61,7 @@
 static struct glue *lastglue = &uglue;
 _THREAD_PRIVATE_MUTEX(__sfp_mutex);
 
-static struct __sfileext __sFext[3] = {
-	_FILEEXT_INITIALIZER,
-	_FILEEXT_INITIALIZER,
-	_FILEEXT_INITIALIZER,
-};
+static struct __sfileext __sFext[3];
 
 FILE __sF[3] = {
 	std(__SRD, STDIN_FILENO),		/* stdin */
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index eecfeef..5fb2292 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -32,15 +32,15 @@
  * SUCH DAMAGE.
  */
 
-#include "wcio.h"
-#include "fileext.h"
-
-
 /*
  * Information local to this implementation of stdio,
  * in particular, macros and private variables.
  */
 
+#include <wchar.h>
+#include "wcio.h"
+#include "fileext.h"
+
 int	__sflush(FILE *);
 int	__sflush_locked(FILE *);
 FILE	*__sfp(void);
@@ -56,7 +56,12 @@
 int	_fwalk(int (*)(FILE *));
 int	__swsetup(FILE *);
 int	__sflags(const char *, int *);
+wint_t __fgetwc_unlock(FILE *);
+wint_t	__ungetwc(wint_t, FILE *);
 int	__vfprintf(FILE *, const char *, __va_list);
+int	__svfscanf(FILE * __restrict, const char * __restrict, __va_list);
+int	__vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list);
+int	__vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
 
 /*
  * Function to clean up streams, called from abort() and exit().
diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h
index dd6db21..584a3f2 100644
--- a/libc/stdio/wcio.h
+++ b/libc/stdio/wcio.h
@@ -1,34 +1,34 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
+/*	$OpenBSD: wcio.h,v 1.2 2013/04/17 17:40:35 tedu Exp $	*/
+/* $NetBSD: wcio.h,v 1.3 2003/01/18 11:30:00 thorpej 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:
- *  * Redistributions of source code must retain the above copyright
+ * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
- *  * 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.
+ * 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 COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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
+ * 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$
  */
 
-/* this file is only used to quiet the BSD stdio implementation
- * since we don't implement wchar support at all
- */
 #ifndef _WCIO_H_
 #define _WCIO_H_
 
@@ -36,22 +36,46 @@
 #define WCIO_UNGETWC_BUFSIZE 1
 
 struct wchar_io_data {
-        int dummy;
+	mbstate_t wcio_mbstate_in;
+	mbstate_t wcio_mbstate_out;
+
+	wchar_t wcio_ungetwc_buf[WCIO_UNGETWC_BUFSIZE];
+	size_t wcio_ungetwc_inbuf;
+
+	int wcio_mode; /* orientation */
 };
 
-/* BIONIC: disable wchar support */
 #define WCIO_GET(fp) \
-	((struct wchar_io_data*) 0)
+	(_EXT(fp) ? &(_EXT(fp)->_wcio) : (struct wchar_io_data *)0)
 
-#define _SET_ORIENTATION(fp, mode) ((void)0)
+#define _SET_ORIENTATION(fp, mode) \
+do {\
+	struct wchar_io_data *_wcio = WCIO_GET(fp); \
+	if (_wcio && _wcio->wcio_mode == 0) \
+		_wcio->wcio_mode = (mode);\
+} while (0)
 
 /*
  * WCIO_FREE should be called by fclose
  */
-#define WCIO_FREE(fp) ((void)(0))
+#define WCIO_FREE(fp) \
+do {\
+	struct wchar_io_data *_wcio = WCIO_GET(fp); \
+	if (_wcio) { \
+		_wcio->wcio_mode = 0;\
+		_wcio->wcio_ungetwc_inbuf = 0;\
+	} \
+} while (0)
 
-#define WCIO_FREEUB(fp) ((void)0)
+#define WCIO_FREEUB(fp) \
+do {\
+	struct wchar_io_data *_wcio = WCIO_GET(fp); \
+	if (_wcio) { \
+		_wcio->wcio_ungetwc_inbuf = 0;\
+	} \
+} while (0)
 
-#define WCIO_INIT(fp)  ((void)0)
+#define WCIO_INIT(fp) \
+	memset(&(_EXT(fp)->_wcio), 0, sizeof(struct wchar_io_data))
 
 #endif /*_WCIO_H_*/
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
new file mode 100644
index 0000000..ef8cdb1
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2011 David Chisnall
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/**
+ * Linked list of quick exit handlers.  This is simpler than the atexit()
+ * version, because it is not required to support C++ destructors or
+ * DSO-specific cleanups.
+ */
+struct quick_exit_handler {
+	struct quick_exit_handler *next;
+	void (*cleanup)(void);
+};
+
+/**
+ * Lock protecting the handlers list.
+ */
+static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
+/**
+ * Stack of cleanup handlers.  These will be invoked in reverse order when 
+ */
+static struct quick_exit_handler *handlers;
+
+int
+at_quick_exit(void (*func)(void))
+{
+	struct quick_exit_handler *h;
+	
+	h = malloc(sizeof(*h));
+
+	if (NULL == h)
+		return (1);
+	h->cleanup = func;
+	pthread_mutex_lock(&atexit_mutex);
+	h->next = handlers;
+	handlers = h;
+	pthread_mutex_unlock(&atexit_mutex);
+	return (0);
+}
+
+void
+quick_exit(int status)
+{
+	struct quick_exit_handler *h;
+
+	/*
+	 * XXX: The C++ spec requires us to call std::terminate if there is an
+	 * exception here.
+	 */
+	for (h = handlers; NULL != h; h = h->next)
+		h->cleanup();
+	_Exit(status);
+}
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/mbtowc.c b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
new file mode 100644
index 0000000..920f4bf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
@@ -0,0 +1,50 @@
+/*	$OpenBSD: mbtowc.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 <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/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/wcstoimax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
new file mode 100644
index 0000000..d46a7c7
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoimax.c
@@ -0,0 +1,19 @@
+/*	$OpenBSD: wcstoimax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $	*/
+/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstoimax
+typedef intmax_t	int_type;
+#define	MIN_VALUE	INTMAX_MIN
+#define	MAX_VALUE	INTMAX_MAX
+
+#include "_wcstol.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/wcstoumax.c b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
new file mode 100644
index 0000000..ccd4713
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstoumax.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: wcstoumax.c,v 1.1 2009/01/13 18:13:51 kettenis Exp $	*/
+/*	$NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $	*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "wctoint.h"
+
+#define	FUNCNAME	wcstoumax
+typedef uintmax_t	uint_type;
+#define	MAX_VALUE	UINTMAX_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/libc/upstream-openbsd/lib/libc/stdio/fgetwc.c b/libc/upstream-openbsd/lib/libc/stdio/fgetwc.c
new file mode 100644
index 0000000..c16ffaf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetwc.c
@@ -0,0 +1,90 @@
+/*	$OpenBSD: fgetwc.c,v 1.4 2009/11/09 00:18:27 kurt Exp $	*/
+/* $NetBSD: fgetwc.c,v 1.3 2003/03/07 07:11:36 tshiozak 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$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wint_t
+__fgetwc_unlock(FILE *fp)
+{
+	struct wchar_io_data *wcio;
+	mbstate_t *st;
+	wchar_t wc;
+	size_t size;
+
+	_SET_ORIENTATION(fp, 1);
+	wcio = WCIO_GET(fp);
+	if (wcio == 0) {
+		errno = ENOMEM;
+		return WEOF;
+	}
+
+	/* if there're ungetwc'ed wchars, use them */
+	if (wcio->wcio_ungetwc_inbuf) {
+		wc = wcio->wcio_ungetwc_buf[--wcio->wcio_ungetwc_inbuf];
+
+		return wc;
+	}
+
+	st = &wcio->wcio_mbstate_in;
+
+	do {
+		char c;
+		int ch = __sgetc(fp);
+
+		if (ch == EOF) {
+			return WEOF;
+		}
+
+		c = ch;
+		size = mbrtowc(&wc, &c, 1, st);
+		if (size == (size_t)-1) {
+			errno = EILSEQ;
+			return WEOF;
+		}
+	} while (size == (size_t)-2);
+
+	return wc;
+}
+
+wint_t
+fgetwc(FILE *fp)
+{
+	wint_t r;
+
+	FLOCKFILE(fp);
+	r = __fgetwc_unlock(fp);
+	FUNLOCKFILE(fp);
+
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgetws.c b/libc/upstream-openbsd/lib/libc/stdio/fgetws.c
new file mode 100644
index 0000000..e8cd249
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetws.c
@@ -0,0 +1,79 @@
+/*	$OpenBSD: fgetws.c,v 1.6 2009/11/09 00:18:27 kurt Exp $	*/
+/* $NetBSD: fgetws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
+
+/*-
+ * Copyright (c) 2002 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.
+ *
+ * Original version ID:
+ * FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.4 2002/09/20 13:25:40 tjr Exp
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wchar_t *
+fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
+{
+	wchar_t *wsp;
+	wint_t wc;
+
+	FLOCKFILE(fp);
+	_SET_ORIENTATION(fp, 1);
+
+	if (n <= 0) {
+		errno = EINVAL;
+		goto error;
+	}
+
+	wsp = ws;
+	while (n-- > 1) {
+		if ((wc = __fgetwc_unlock(fp)) == WEOF && errno == EILSEQ) {
+			goto error;
+		}
+		if (wc == WEOF) {
+			if (wsp == ws) {
+				/* EOF/error, no characters read yet. */
+				goto error;
+			}
+			break;
+		}
+		*wsp++ = (wchar_t)wc;
+		if (wc == L'\n') {
+			break;
+		}
+	}
+
+	*wsp++ = L'\0';
+	FUNLOCKFILE(fp);
+
+	return (ws);
+
+error:
+	FUNLOCKFILE(fp);
+	return (NULL);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputwc.c b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
new file mode 100644
index 0000000..9db70d0
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
@@ -0,0 +1,88 @@
+/*	$OpenBSD: fputwc.c,v 1.4 2009/11/09 00:18:27 kurt Exp $	*/
+/* $NetBSD: fputwc.c,v 1.3 2003/03/07 07:11:37 tshiozak 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$
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+#include "fvwrite.h"
+
+wint_t
+__fputwc_unlock(wchar_t wc, FILE *fp)
+{
+	struct wchar_io_data *wcio;
+	mbstate_t *st;
+	size_t size;
+	char buf[MB_LEN_MAX];
+	struct __suio uio;
+	struct __siov iov;
+
+	/* LINTED we don't play with buf */
+	iov.iov_base = (void *)buf;
+	uio.uio_iov = &iov;
+	uio.uio_iovcnt = 1;
+
+	_SET_ORIENTATION(fp, 1);
+	wcio = WCIO_GET(fp);
+	if (wcio == 0) {
+		errno = ENOMEM;
+		return WEOF;
+	}
+
+	wcio->wcio_ungetwc_inbuf = 0;
+	st = &wcio->wcio_mbstate_out;
+
+	size = wcrtomb(buf, wc, st);
+	if (size == (size_t)-1) {
+		errno = EILSEQ;
+		return WEOF;
+	}
+
+	uio.uio_resid = iov.iov_len = size;
+	if (__sfvwrite(fp, &uio)) {
+		return WEOF;
+	}
+
+	return (wint_t)wc;
+}
+
+wint_t
+fputwc(wchar_t wc, FILE *fp)
+{
+	wint_t r;
+
+	FLOCKFILE(fp);
+	r = __fputwc_unlock(wc, fp);
+	FUNLOCKFILE(fp);
+
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputws.c b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
new file mode 100644
index 0000000..c4c2d8e
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -0,0 +1,58 @@
+/*	$OpenBSD: fputws.c,v 1.6 2013/04/17 17:40:35 tedu Exp $	*/
+/* $NetBSD: fputws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
+
+/*-
+ * Copyright (c) 2002 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.
+ *
+ * Original version ID:
+ * FreeBSD: src/lib/libc/stdio/fputws.c,v 1.4 2002/09/20 13:25:40 tjr Exp
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
+
+int
+fputws(ws, fp)
+	const wchar_t * __restrict ws;
+	FILE * __restrict fp;
+{
+	FLOCKFILE(fp);
+	_SET_ORIENTATION(fp, 1);
+
+	while (*ws != '\0') {
+		if (__fputwc_unlock(*ws++, fp) == WEOF) {
+			FUNLOCKFILE(fp);
+			return (-1);
+		}
+	}
+
+	FUNLOCKFILE(fp);
+
+	return (0);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwide.c b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
new file mode 100644
index 0000000..93cddc6
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
@@ -0,0 +1,64 @@
+/*	$OpenBSD: fwide.c,v 1.4 2009/11/09 00:18:27 kurt Exp $	*/
+/* $NetBSD: fwide.c,v 1.2 2003/01/18 11:29:54 thorpej 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$
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+int
+fwide(FILE *fp, int mode)
+{
+	struct wchar_io_data *wcio;
+
+	/*
+	 * this implementation use only -1, 0, 1
+	 * for mode value.
+	 * (we don't need to do this, but
+	 *  this can make things simpler.)
+	 */
+	if (mode > 0)
+		mode = 1;
+	else if (mode < 0)
+		mode = -1;
+
+	FLOCKFILE(fp);
+	wcio = WCIO_GET(fp);
+	if (!wcio)
+		return 0; /* XXX */
+
+	if (wcio->wcio_mode == 0 && mode != 0)
+		wcio->wcio_mode = mode;
+	else
+		mode = wcio->wcio_mode;
+	FUNLOCKFILE(fp);
+
+	return mode;
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/wcsstr.c b/libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
similarity index 74%
rename from libc/upstream-freebsd/lib/libc/string/wcsstr.c
rename to libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
index ce598a6..4474e8b 100644
--- a/libc/upstream-freebsd/lib/libc/string/wcsstr.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: fwprintf.c,v 1.3 2011/04/28 17:38:46 stsp Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,34 +31,18 @@
  * SUCH DAMAGE.
  */
 
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#include <stdio.h>
+#include <stdarg.h>
 #include <wchar.h>
 
-/*
- * Find the first occurrence of find in s.
- */
-wchar_t *
-wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
+int
+fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
 {
-	wchar_t c, sc;
-	size_t len;
+	int ret;
+	va_list ap;
 
-	if ((c = *find++) != L'\0') {
-		len = wcslen(find);
-		do {
-			do {
-				if ((sc = *s++) == L'\0')
-					return (NULL);
-			} while (sc != c);
-		} while (wcsncmp(s, find, len) != 0);
-		s--;
-	}
-	return ((wchar_t *)s);
+	va_start(ap, fmt);
+	ret = vfwprintf(fp, fmt, ap);
+	va_end(ap);
+	return (ret);
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c
new file mode 100644
index 0000000..b716cbf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: fwscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 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 <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+	r = vfwscanf(fp, fmt, ap);
+	va_end(ap);
+
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/getwc.c b/libc/upstream-openbsd/lib/libc/stdio/getwc.c
new file mode 100644
index 0000000..e9bbb7c
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/getwc.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: getwc.c,v 1.1 2005/06/17 20:40:32 espie Exp $	*/
+/* $NetBSD: getwc.c,v 1.2 2003/01/18 11:29:55 thorpej 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$
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+ * A subroutine version of the macro getwc.
+ */
+#undef getwc
+
+wint_t
+getwc(FILE *fp)
+{
+
+	return fgetwc(fp);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/getwchar.c b/libc/upstream-openbsd/lib/libc/stdio/getwchar.c
new file mode 100644
index 0000000..2a112ed
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/getwchar.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: getwchar.c,v 1.1 2005/06/17 20:40:32 espie Exp $	*/
+/* $NetBSD: getwchar.c,v 1.2 2003/01/18 11:29:55 thorpej 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$
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+ * A subroutine version of the macro getwchar.
+ */
+#undef getwchar
+
+wint_t
+getwchar()
+{
+
+	return fgetwc(stdin);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/putwc.c b/libc/upstream-openbsd/lib/libc/stdio/putwc.c
new file mode 100644
index 0000000..8e2ff2d
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/putwc.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: putwc.c,v 1.1 2005/06/17 20:40:32 espie Exp $	*/
+/* $NetBSD: putwc.c,v 1.3 2003/01/18 11:29:56 thorpej 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$
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+ * A subroutine version of the macro putwc.
+ */
+#undef putwc
+
+wint_t
+putwc(wchar_t wc, FILE *fp)
+{
+
+	return fputwc(wc, fp);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/putwchar.c b/libc/upstream-openbsd/lib/libc/stdio/putwchar.c
new file mode 100644
index 0000000..940ec05
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/putwchar.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: putwchar.c,v 1.1 2005/06/17 20:40:32 espie Exp $	*/
+/* $NetBSD: putwchar.c,v 1.3 2003/01/18 11:29:56 thorpej 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$
+ */
+
+#include <stdio.h>
+#include <wchar.h>
+
+/*
+ * A subroutine version of the macro putwchar.
+ */
+#undef putwchar
+
+wint_t
+putwchar(wchar_t wc)
+{
+
+	return fputwc(wc, stdout);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/swprintf.c b/libc/upstream-openbsd/lib/libc/stdio/swprintf.c
new file mode 100644
index 0000000..8928aea
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/swprintf.c
@@ -0,0 +1,45 @@
+/*	$OpenBSD: swprintf.c,v 1.5 2012/12/05 23:20:01 deraadt Exp $ */
+/*	$NetBSD: swprintf.c,v 1.1 2005/05/14 23:51:02 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2002 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 <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = vswprintf(s, n, fmt, ap);
+	va_end(ap);
+
+	return (ret);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/swscanf.c b/libc/upstream-openbsd/lib/libc/stdio/swscanf.c
new file mode 100644
index 0000000..a85e9ee
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/swscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: swscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 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 <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+	r = vswscanf(str, fmt, ap);
+	va_end(ap);
+
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
new file mode 100644
index 0000000..c0321e9
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/ungetwc.c
@@ -0,0 +1,77 @@
+/*	$OpenBSD: ungetwc.c,v 1.5 2011/10/16 13:20:51 stsp Exp $	*/
+/* $NetBSD: ungetwc.c,v 1.2 2003/01/18 11:29:59 thorpej 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$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "local.h"
+
+wint_t
+__ungetwc(wint_t wc, FILE *fp)
+{
+	struct wchar_io_data *wcio;
+
+	if (wc == WEOF)
+		return WEOF;
+
+	_SET_ORIENTATION(fp, 1);
+	/*
+	 * XXX since we have no way to transform a wchar string to
+	 * a char string in reverse order, we can't use ungetc.
+	 */
+	/* XXX should we flush ungetc buffer? */
+
+	wcio = WCIO_GET(fp);
+	if (wcio == 0) {
+		errno = ENOMEM; /* XXX */
+		return WEOF;
+	}
+
+	if (wcio->wcio_ungetwc_inbuf >= WCIO_UNGETWC_BUFSIZE) {
+		return WEOF;
+	}
+
+	wcio->wcio_ungetwc_buf[wcio->wcio_ungetwc_inbuf++] = wc;
+	__sclearerr(fp);
+
+	return wc;
+}
+
+wint_t
+ungetwc(wint_t wc, FILE *fp)
+{
+	wint_t r;
+
+	FLOCKFILE(fp);
+	r = __ungetwc(wc, fp);
+	FUNLOCKFILE(fp);
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
new file mode 100644
index 0000000..f76eed3
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
@@ -0,0 +1,1526 @@
+/*	$OpenBSD: vfwprintf.c,v 1.6 2013/04/17 17:40:35 tedu Exp $ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+/*
+ * Actual wprintf innards.
+ *
+ * This code is large and complicated...
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "local.h"
+#include "fvwrite.h"
+
+wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
+
+union arg {
+	int			intarg;
+	unsigned int		uintarg;
+	long			longarg;
+	unsigned long		ulongarg;
+	long long		longlongarg;
+	unsigned long long	ulonglongarg;
+	ptrdiff_t		ptrdiffarg;
+	size_t			sizearg;
+	ssize_t			ssizearg;
+	intmax_t		intmaxarg;
+	uintmax_t		uintmaxarg;
+	void			*pvoidarg;
+	char			*pchararg;
+	signed char		*pschararg;
+	short			*pshortarg;
+	int			*pintarg;
+	long			*plongarg;
+	long long		*plonglongarg;
+	ptrdiff_t		*pptrdiffarg;
+	ssize_t			*pssizearg;
+	intmax_t		*pintmaxarg;
+#ifdef FLOATING_POINT
+	double			doublearg;
+	long double		longdoublearg;
+#endif
+	wint_t			wintarg;
+	wchar_t			*pwchararg;
+};
+
+static int __find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable,
+    size_t *argtablesiz);
+static int __grow_type_table(unsigned char **typetable, int *tablesize);
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer.  We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap)
+{
+	int ret;
+	FILE fake;
+	struct __sfileext fakeext;
+	unsigned char buf[BUFSIZ];
+
+	_FILEEXT_SETUP(&fake, &fakeext);
+	/* copy the important variables */
+	fake._flags = fp->_flags & ~__SNBF;
+	fake._file = fp->_file;
+	fake._cookie = fp->_cookie;
+	fake._write = fp->_write;
+
+	/* set up the buffer */
+	fake._bf._base = fake._p = buf;
+	fake._bf._size = fake._w = sizeof(buf);
+	fake._lbfsize = 0;	/* not actually used, but Just In Case */
+
+	/* do the work, then copy any error status */
+	ret = __vfwprintf(&fake, fmt, ap);
+	if (ret >= 0 && __sflush(&fake))
+		ret = EOF;
+	if (fake._flags & __SERR)
+		fp->_flags |= __SERR;
+	return (ret);
+}
+
+/*
+ * Like __fputwc_unlock, but handles fake string (__SSTR) files properly.
+ * File must already be locked.
+ */
+static wint_t
+__xfputwc(wchar_t wc, FILE *fp)
+{
+	mbstate_t mbs;
+	char buf[MB_LEN_MAX];
+	struct __suio uio;
+	struct __siov iov;
+	size_t len;
+
+	if ((fp->_flags & __SSTR) == 0)
+		return (__fputwc_unlock(wc, fp));
+
+	bzero(&mbs, sizeof(mbs));
+	len = wcrtomb(buf, wc, &mbs);
+	if (len == (size_t)-1) {
+		fp->_flags |= __SERR;
+		errno = EILSEQ;
+		return (WEOF);
+	}
+	uio.uio_iov = &iov;
+	uio.uio_resid = len;
+	uio.uio_iovcnt = 1;
+	iov.iov_base = buf;
+	iov.iov_len = len;
+	return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
+}
+
+/*
+ * Convert a multibyte character string argument for the %s format to a wide
+ * string representation. ``prec'' specifies the maximum number of bytes
+ * to output. If ``prec'' is greater than or equal to zero, we can't assume
+ * that the multibyte character string ends in a null character.
+ * 
+ * Returns NULL on failure.
+ * To find out what happened check errno for ENOMEM, EILSEQ and EINVAL.
+ */
+static wchar_t *
+__mbsconv(char *mbsarg, int prec)
+{
+	mbstate_t mbs;
+	wchar_t *convbuf, *wcp;
+	const char *p;
+	size_t insize, nchars, nconv;
+
+	if (mbsarg == NULL)
+		return (NULL);
+
+	/*
+	 * Supplied argument is a multibyte string; convert it to wide
+	 * characters first.
+	 */
+	if (prec >= 0) {
+		/*
+		 * String is not guaranteed to be NUL-terminated. Find the
+		 * number of characters to print.
+		 */
+		p = mbsarg;
+		insize = nchars = nconv = 0;
+		bzero(&mbs, sizeof(mbs));
+		while (nchars != (size_t)prec) {
+			nconv = mbrlen(p, MB_CUR_MAX, &mbs);
+			if (nconv == (size_t)0 || nconv == (size_t)-1 ||
+			    nconv == (size_t)-2)
+				break;
+			p += nconv;
+			nchars++;
+			insize += nconv;
+		}
+		if (nconv == (size_t)-1 || nconv == (size_t)-2)
+			return (NULL);
+	} else
+		insize = strlen(mbsarg);
+
+	/*
+	 * Allocate buffer for the result and perform the conversion,
+	 * converting at most `size' bytes of the input multibyte string to
+	 * wide characters for printing.
+	 */
+	convbuf = calloc(insize + 1, sizeof(*convbuf));
+	if (convbuf == NULL)
+		return (NULL);
+	wcp = convbuf;
+	p = mbsarg;
+	bzero(&mbs, sizeof(mbs));
+	nconv = 0;
+	while (insize != 0) {
+		nconv = mbrtowc(wcp, p, insize, &mbs);
+		if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
+			break;
+		wcp++;
+		p += nconv;
+		insize -= nconv;
+	}
+	if (nconv == (size_t)-1 || nconv == (size_t)-2) {
+		free(convbuf);
+		return (NULL);
+	}
+	*wcp = '\0';
+
+	return (convbuf);
+}
+
+#ifdef FLOATING_POINT
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include "floatio.h"
+
+#define	DEFPREC		6
+
+extern char *__dtoa(double, int, int, int *, int *, char **);
+extern void  __freedtoa(char *);
+static int exponent(wchar_t *, int, int);
+#endif /* FLOATING_POINT */
+
+/*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things.  Technically, we would need the
+ * most space for base 10 conversions with thousands' grouping
+ * characters between each pair of digits.  100 bytes is a
+ * conservative overestimate even for a 128-bit uintmax_t.
+ */
+#define BUF	100
+
+#define STATIC_ARG_TBL_SIZE 8	/* Size of static argument table. */
+
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define	to_digit(c)	((c) - '0')
+#define is_digit(c)	((unsigned)to_digit(c) <= 9)
+#define	to_char(n)	((wchar_t)((n) + '0'))
+
+/*
+ * Flags used during conversion.
+ */
+#define	ALT		0x0001		/* alternate form */
+#define	LADJUST		0x0004		/* left adjustment */
+#define	LONGDBL		0x0008		/* long double */
+#define	LONGINT		0x0010		/* long integer */
+#define	LLONGINT	0x0020		/* long long integer */
+#define	SHORTINT	0x0040		/* short integer */
+#define	ZEROPAD		0x0080		/* zero (as opposed to blank) pad */
+#define FPT		0x0100		/* Floating point number */
+#define PTRINT		0x0200		/* (unsigned) ptrdiff_t */
+#define SIZEINT		0x0400		/* (signed) size_t */
+#define CHARINT		0x0800		/* 8 bit integer */
+#define MAXINT		0x1000		/* largest integer size (intmax_t) */
+
+int
+__vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, __va_list ap)
+{
+	wchar_t *fmt;		/* format string */
+	wchar_t ch;		/* character from fmt */
+	int n, n2, n3;		/* handy integers (short term usage) */
+	wchar_t *cp;		/* handy char pointer (short term usage) */
+	int flags;		/* flags as above */
+	int ret;		/* return value accumulator */
+	int width;		/* width from format (%8d), or 0 */
+	int prec;		/* precision from format; <0 for N/A */
+	wchar_t sign;		/* sign prefix (' ', '+', '-', or \0) */
+#ifdef FLOATING_POINT
+	/*
+	 * We can decompose the printed representation of floating
+	 * point numbers into several parts, some of which may be empty:
+	 *
+	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
+	 *    A       B     ---C---      D       E   F
+	 *
+	 * A:	'sign' holds this value if present; '\0' otherwise
+	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
+	 * C:	cp points to the string MMMNNN.  Leading and trailing
+	 *	zeros are not in the string and must be added.
+	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
+	 * F:	at least two digits for decimal, at least one digit for hex
+	 */
+	char *decimal_point = NULL;
+	int signflag;		/* true if float is negative */
+	union {			/* floating point arguments %[aAeEfFgG] */
+		double dbl;
+		long double ldbl;
+	} fparg;
+	int expt;		/* integer value of exponent */
+	char expchar;		/* exponent character: [eEpP\0] */
+	char *dtoaend;		/* pointer to end of converted digits */
+	int expsize;		/* character count for expstr */
+	int lead;		/* sig figs before decimal or group sep */
+	int ndig;		/* actual number of digits returned by dtoa */
+	wchar_t expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
+	char *dtoaresult = NULL;
+#endif
+
+	uintmax_t _umax;	/* integer arguments %[diouxX] */
+	enum { OCT, DEC, HEX } base;	/* base for %[diouxX] conversion */
+	int dprec;		/* a copy of prec if %[diouxX], 0 otherwise */
+	int realsz;		/* field size expanded by dprec */
+	int size;		/* size of converted field or string */
+	const char *xdigs;	/* digits for %[xX] conversion */
+#define NIOV 8
+	struct __suio uio;	/* output information: summary */
+	struct __siov iov[NIOV];/* ... and individual io vectors */
+	wchar_t buf[BUF];	/* buffer with space for digits of uintmax_t */
+	wchar_t ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
+	union arg *argtable;	/* args, built due to positional arg */
+	union arg statargtable[STATIC_ARG_TBL_SIZE];
+	size_t argtablesiz;
+	int nextarg;		/* 1-based argument index */
+	va_list orgap;		/* original argument pointer */
+	wchar_t *convbuf;	/* buffer for multibyte to wide conversion */
+
+	/*
+	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
+	 * fields occur frequently, increase PADSIZE and make the initialisers
+	 * below longer.
+	 */
+#define	PADSIZE	16		/* pad chunk size */
+	static wchar_t blanks[PADSIZE] =
+	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+	static wchar_t zeroes[PADSIZE] =
+	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+	static const char xdigs_lower[16] = "0123456789abcdef";
+	static const char xdigs_upper[16] = "0123456789ABCDEF";
+
+	/*
+	 * BEWARE, these `goto error' on error, PRINT uses 'n3',
+	 * PAD uses `n' and 'n3', and PRINTANDPAD uses 'n', 'n2', and 'n3'.
+	 */
+#define	PRINT(ptr, len)	do {	\
+	for (n3 = 0; n3 < (len); n3++) {	\
+		if ((__xfputwc((ptr)[n3], fp)) == WEOF)	\
+			goto error; \
+	} \
+} while (0)
+#define	PAD(howmany, with) do { \
+	if ((n = (howmany)) > 0) { \
+		while (n > PADSIZE) { \
+			PRINT(with, PADSIZE); \
+			n -= PADSIZE; \
+		} \
+		PRINT(with, n); \
+	} \
+} while (0)
+#define	PRINTANDPAD(p, ep, len, with) do {	\
+	n2 = (ep) - (p);       			\
+	if (n2 > (len))				\
+		n2 = (len);			\
+	if (n2 > 0)				\
+		PRINT((p), n2);			\
+	PAD((len) - (n2 > 0 ? n2 : 0), (with));	\
+} while(0)
+
+	/*
+	 * To extend shorts properly, we need both signed and unsigned
+	 * argument extraction methods.
+	 */
+#define	SARG() \
+	((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
+	    flags&LLONGINT ? GETARG(long long) : \
+	    flags&LONGINT ? GETARG(long) : \
+	    flags&PTRINT ? GETARG(ptrdiff_t) : \
+	    flags&SIZEINT ? GETARG(ssize_t) : \
+	    flags&SHORTINT ? (short)GETARG(int) : \
+	    flags&CHARINT ? (__signed char)GETARG(int) : \
+	    GETARG(int)))
+#define	UARG() \
+	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
+	    flags&LLONGINT ? GETARG(unsigned long long) : \
+	    flags&LONGINT ? GETARG(unsigned long) : \
+	    flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
+	    flags&SIZEINT ? GETARG(size_t) : \
+	    flags&SHORTINT ? (unsigned short)GETARG(int) : \
+	    flags&CHARINT ? (unsigned char)GETARG(int) : \
+	    GETARG(unsigned int)))
+
+	/*
+	 * Append a digit to a value and check for overflow.
+	 */
+#define APPEND_DIGIT(val, dig) do { \
+	if ((val) > INT_MAX / 10) \
+		goto overflow; \
+	(val) *= 10; \
+	if ((val) > INT_MAX - to_digit((dig))) \
+		goto overflow; \
+	(val) += to_digit((dig)); \
+} while (0)
+
+	 /*
+	  * Get * arguments, including the form *nn$.  Preserve the nextarg
+	  * that the argument can be gotten once the type is determined.
+	  */
+#define GETASTER(val) \
+	n2 = 0; \
+	cp = fmt; \
+	while (is_digit(*cp)) { \
+		APPEND_DIGIT(n2, *cp); \
+		cp++; \
+	} \
+	if (*cp == '$') { \
+		int hold = nextarg; \
+		if (argtable == NULL) { \
+			argtable = statargtable; \
+			__find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
+		} \
+		nextarg = n2; \
+		val = GETARG(int); \
+		nextarg = hold; \
+		fmt = ++cp; \
+	} else { \
+		val = GETARG(int); \
+	}
+
+/*
+* Get the argument indexed by nextarg.   If the argument table is
+* built, use it to get the argument.  If its not, get the next
+* argument (and arguments must be gotten sequentially).
+*/
+#define GETARG(type) \
+	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
+		(nextarg++, va_arg(ap, type)))
+
+	_SET_ORIENTATION(fp, 1);
+	/* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
+	if (cantwrite(fp)) {
+		errno = EBADF;
+		return (EOF);
+	}
+
+	/* optimise fwprintf(stderr) (and other unbuffered Unix files) */
+	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+	    fp->_file >= 0)
+		return (__sbprintf(fp, fmt0, ap));
+
+	fmt = (wchar_t *)fmt0;
+	argtable = NULL;
+	nextarg = 1;
+	va_copy(orgap, ap);
+	uio.uio_iov = iov;
+	uio.uio_resid = 0;
+	uio.uio_iovcnt = 0;
+	ret = 0;
+	convbuf = NULL;
+
+	/*
+	 * Scan the format for conversions (`%' character).
+	 */
+	for (;;) {
+		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+			continue;
+		if (fmt != cp) {
+			ptrdiff_t m = fmt - cp;
+			if (m < 0 || m > INT_MAX - ret)
+				goto overflow;
+			PRINT(cp, m);
+			ret += m;
+		}
+		if (ch == '\0')
+			goto done;
+		fmt++;		/* skip over '%' */
+
+		flags = 0;
+		dprec = 0;
+		width = 0;
+		prec = -1;
+		sign = '\0';
+		ox[1] = '\0';
+
+rflag:		ch = *fmt++;
+reswitch:	switch (ch) {
+		case ' ':
+			/*
+			 * ``If the space and + flags both appear, the space
+			 * flag will be ignored.''
+			 *	-- ANSI X3J11
+			 */
+			if (!sign)
+				sign = ' ';
+			goto rflag;
+		case '#':
+			flags |= ALT;
+			goto rflag;
+		case '\'':
+			/* grouping not implemented */
+			goto rflag;
+		case '*':
+			/*
+			 * ``A negative field width argument is taken as a
+			 * - flag followed by a positive field width.''
+			 *	-- ANSI X3J11
+			 * They don't exclude field widths read from args.
+			 */
+			GETASTER(width);
+			if (width >= 0)
+				goto rflag;
+			if (width == INT_MIN)
+				goto overflow;
+			width = -width;
+			/* FALLTHROUGH */
+		case '-':
+			flags |= LADJUST;
+			goto rflag;
+		case '+':
+			sign = '+';
+			goto rflag;
+		case '.':
+			if ((ch = *fmt++) == '*') {
+				GETASTER(n);
+				prec = n < 0 ? -1 : n;
+				goto rflag;
+			}
+			n = 0;
+			while (is_digit(ch)) {
+				APPEND_DIGIT(n, ch);
+				ch = *fmt++;
+			}
+			if (ch == '$') {
+				nextarg = n;
+				if (argtable == NULL) {
+					argtable = statargtable;
+					__find_arguments(fmt0, orgap,
+					    &argtable, &argtablesiz);
+				}
+				goto rflag;
+			}
+			prec = n;
+			goto reswitch;
+		case '0':
+			/*
+			 * ``Note that 0 is taken as a flag, not as the
+			 * beginning of a field width.''
+			 *	-- ANSI X3J11
+			 */
+			flags |= ZEROPAD;
+			goto rflag;
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			n = 0;
+			do {
+				APPEND_DIGIT(n, ch);
+				ch = *fmt++;
+			} while (is_digit(ch));
+			if (ch == '$') {
+				nextarg = n;
+				if (argtable == NULL) {
+					argtable = statargtable;
+					__find_arguments(fmt0, orgap,
+					    &argtable, &argtablesiz);
+				}
+				goto rflag;
+			}
+			width = n;
+			goto reswitch;
+#ifdef FLOATING_POINT
+		case 'L':
+			flags |= LONGDBL;
+			goto rflag;
+#endif
+		case 'h':
+			if (*fmt == 'h') {
+				fmt++;
+				flags |= CHARINT;
+			} else {
+				flags |= SHORTINT;
+			}
+			goto rflag;
+		case 'j':
+			flags |= MAXINT;
+			goto rflag;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONGINT;
+			} else {
+				flags |= LONGINT;
+			}
+			goto rflag;
+		case 'q':
+			flags |= LLONGINT;
+			goto rflag;
+		case 't':
+			flags |= PTRINT;
+			goto rflag;
+		case 'z':
+			flags |= SIZEINT;
+			goto rflag;
+		case 'C':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'c':
+			if (flags & LONGINT)
+				*(cp = buf) = (wchar_t)GETARG(wint_t);
+			else
+				*(cp = buf) = (wchar_t)btowc(GETARG(int));
+			size = 1;
+			sign = '\0';
+			break;
+		case 'D':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'd':
+		case 'i':
+			_umax = SARG();
+			if ((intmax_t)_umax < 0) {
+				_umax = -_umax;
+				sign = '-';
+			}
+			base = DEC;
+			goto number;
+#ifdef FLOATING_POINT
+		case 'a':
+		case 'A':
+			if (ch == 'a') {
+				ox[1] = 'x';
+				xdigs = xdigs_lower;
+				expchar = 'p';
+			} else {
+				ox[1] = 'X';
+				xdigs = xdigs_upper;
+				expchar = 'P';
+			}
+			if (prec >= 0)
+				prec++;
+			if (dtoaresult)
+				__freedtoa(dtoaresult);
+			if (flags & LONGDBL) {
+				fparg.ldbl = GETARG(long double);
+				dtoaresult =
+				    __hldtoa(fparg.ldbl, xdigs, prec,
+				    &expt, &signflag, &dtoaend);
+				if (dtoaresult == NULL) {
+					errno = ENOMEM;
+					goto error;
+				}
+			} else {
+				fparg.dbl = GETARG(double);
+				dtoaresult =
+				    __hdtoa(fparg.dbl, xdigs, prec,
+				    &expt, &signflag, &dtoaend);
+				if (dtoaresult == NULL) {
+					errno = ENOMEM;
+					goto error;
+				}
+			}
+			if (prec < 0)
+				prec = dtoaend - dtoaresult;
+			if (expt == INT_MAX)
+				ox[1] = '\0';
+			if (convbuf) {
+				free(convbuf);
+				convbuf = NULL;
+			}
+			cp = convbuf = __mbsconv(dtoaresult, -1);
+			if (cp == NULL)
+				goto error;
+			ndig = dtoaend - dtoaresult;
+			goto fp_common;
+		case 'e':
+		case 'E':
+			expchar = ch;
+			if (prec < 0)	/* account for digit before decpt */
+				prec = DEFPREC + 1;
+			else
+				prec++;
+			goto fp_begin;
+		case 'f':
+		case 'F':
+			expchar = '\0';
+			goto fp_begin;
+		case 'g':
+		case 'G':
+			expchar = ch - ('g' - 'e');
+ 			if (prec == 0)
+ 				prec = 1;
+fp_begin:
+			if (prec < 0)
+				prec = DEFPREC;
+			if (dtoaresult)
+				__freedtoa(dtoaresult);
+			if (flags & LONGDBL) {
+				fparg.ldbl = GETARG(long double);
+				dtoaresult =
+				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
+				    &expt, &signflag, &dtoaend);
+				if (dtoaresult == NULL) {
+					errno = ENOMEM;
+					goto error;
+				}
+			} else {
+				fparg.dbl = GETARG(double);
+				dtoaresult =
+				    __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
+				    &expt, &signflag, &dtoaend);
+				if (dtoaresult == NULL) {
+					errno = ENOMEM;
+					goto error;
+				}
+				if (expt == 9999)
+					expt = INT_MAX;
+ 			}
+			if (convbuf) {
+				free(convbuf);
+				convbuf = NULL;
+			}
+			cp = convbuf = __mbsconv(dtoaresult, -1);
+			if (cp == NULL)
+				goto error;
+			ndig = dtoaend - dtoaresult;
+fp_common:
+			if (signflag)
+				sign = '-';
+			if (expt == INT_MAX) {	/* inf or nan */
+				if (*cp == 'N') {
+					cp = (ch >= 'a') ? L"nan" : L"NAN";
+					sign = '\0';
+				} else
+					cp = (ch >= 'a') ? L"inf" : L"INF";
+ 				size = 3;
+				flags &= ~ZEROPAD;
+ 				break;
+ 			}
+			flags |= FPT;
+ 			if (ch == 'g' || ch == 'G') {
+				if (expt > -4 && expt <= prec) {
+					/* Make %[gG] smell like %[fF] */
+					expchar = '\0';
+					if (flags & ALT)
+						prec -= expt;
+					else
+						prec = ndig - expt;
+					if (prec < 0)
+						prec = 0;
+				} else {
+					/*
+					 * Make %[gG] smell like %[eE], but
+					 * trim trailing zeroes if no # flag.
+					 */
+					if (!(flags & ALT))
+						prec = ndig;
+				}
+ 			}
+			if (expchar) {
+				expsize = exponent(expstr, expt - 1, expchar);
+				size = expsize + prec;
+				if (prec > 1 || flags & ALT)
+ 					++size;
+			} else {
+				/* space for digits before decimal point */
+				if (expt > 0)
+					size = expt;
+				else	/* "0" */
+					size = 1;
+				/* space for decimal pt and following digits */
+				if (prec || flags & ALT)
+					size += prec + 1;
+				lead = expt;
+			}
+			break;
+#endif /* FLOATING_POINT */
+		case 'n':
+			if (flags & LLONGINT)
+				*GETARG(long long *) = ret;
+			else if (flags & LONGINT)
+				*GETARG(long *) = ret;
+			else if (flags & SHORTINT)
+				*GETARG(short *) = ret;
+			else if (flags & CHARINT)
+				*GETARG(__signed char *) = ret;
+			else if (flags & PTRINT)
+				*GETARG(ptrdiff_t *) = ret;
+			else if (flags & SIZEINT)
+				*GETARG(ssize_t *) = ret;
+			else if (flags & MAXINT)
+				*GETARG(intmax_t *) = ret;
+			else
+				*GETARG(int *) = ret;
+			continue;	/* no output */
+		case 'O':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'o':
+			_umax = UARG();
+			base = OCT;
+			goto nosign;
+		case 'p':
+			/*
+			 * ``The argument shall be a pointer to void.  The
+			 * value of the pointer is converted to a sequence
+			 * of printable characters, in an implementation-
+			 * defined manner.''
+			 *	-- ANSI X3J11
+			 */
+			/* NOSTRICT */
+			_umax = (u_long)GETARG(void *);
+			base = HEX;
+			xdigs = xdigs_lower;
+			ox[1] = 'x';
+			goto nosign;
+		case 'S':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 's':
+			if (flags & LONGINT) {
+				if ((cp = GETARG(wchar_t *)) == NULL)
+					cp = L"(null)";
+			} else {
+				char *mbsarg;
+				if ((mbsarg = GETARG(char *)) == NULL)
+					mbsarg = "(null)";
+				if (convbuf) {
+					free(convbuf);
+					convbuf = NULL;
+				}
+				convbuf = __mbsconv(mbsarg, prec);
+				if (convbuf == NULL) {
+					fp->_flags |= __SERR;
+					goto error;
+				} else
+					cp = convbuf;
+			}
+			if (prec >= 0) {
+				/*
+				 * can't use wcslen; can only look for the
+				 * NUL in the first `prec' characters, and
+				 * wcslen() will go further.
+				 */
+				wchar_t *p = wmemchr(cp, 0, prec);
+
+				size = p ? (p - cp) : prec;
+			} else {
+				size_t len;
+
+				if ((len = wcslen(cp)) > INT_MAX)
+					goto overflow;
+				size = (int)len;
+			}
+			sign = '\0';
+			break;
+		case 'U':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'u':
+			_umax = UARG();
+			base = DEC;
+			goto nosign;
+		case 'X':
+			xdigs = xdigs_upper;
+			goto hex;
+		case 'x':
+			xdigs = xdigs_lower;
+hex:			_umax = UARG();
+			base = HEX;
+			/* leading 0x/X only if non-zero */
+			if (flags & ALT && _umax != 0)
+				ox[1] = ch;
+
+			/* unsigned conversions */
+nosign:			sign = '\0';
+			/*
+			 * ``... diouXx conversions ... if a precision is
+			 * specified, the 0 flag will be ignored.''
+			 *	-- ANSI X3J11
+			 */
+number:			if ((dprec = prec) >= 0)
+				flags &= ~ZEROPAD;
+
+			/*
+			 * ``The result of converting a zero value with an
+			 * explicit precision of zero is no characters.''
+			 *	-- ANSI X3J11
+			 */
+			cp = buf + BUF;
+			if (_umax != 0 || prec != 0) {
+				/*
+				 * Unsigned mod is hard, and unsigned mod
+				 * by a constant is easier than that by
+				 * a variable; hence this switch.
+				 */
+				switch (base) {
+				case OCT:
+					do {
+						*--cp = to_char(_umax & 7);
+						_umax >>= 3;
+					} while (_umax);
+					/* handle octal leading 0 */
+					if (flags & ALT && *cp != '0')
+						*--cp = '0';
+					break;
+
+				case DEC:
+					/* many numbers are 1 digit */
+					while (_umax >= 10) {
+						*--cp = to_char(_umax % 10);
+						_umax /= 10;
+					}
+					*--cp = to_char(_umax);
+					break;
+
+				case HEX:
+					do {
+						*--cp = xdigs[_umax & 15];
+						_umax >>= 4;
+					} while (_umax);
+					break;
+
+				default:
+					cp = L"bug in vfwprintf: bad base";
+					size = wcslen(cp);
+					goto skipsize;
+				}
+			}
+			size = buf + BUF - cp;
+			if (size > BUF)	/* should never happen */
+				abort();
+		skipsize:
+			break;
+		default:	/* "%?" prints ?, unless ? is NUL */
+			if (ch == '\0')
+				goto done;
+			/* pretend it was %c with argument ch */
+			cp = buf;
+			*cp = ch;
+			size = 1;
+			sign = '\0';
+			break;
+		}
+
+		/*
+		 * All reasonable formats wind up here.  At this point, `cp'
+		 * points to a string which (if not flags&LADJUST) should be
+		 * padded out to `width' places.  If flags&ZEROPAD, it should
+		 * first be prefixed by any sign or other prefix; otherwise,
+		 * it should be blank padded before the prefix is emitted.
+		 * After any left-hand padding and prefixing, emit zeroes
+		 * required by a decimal %[diouxX] precision, then print the
+		 * string proper, then emit zeroes required by any leftover
+		 * floating precision; finally, if LADJUST, pad with blanks.
+		 *
+		 * Compute actual size, so we know how much to pad.
+		 * size excludes decimal prec; realsz includes it.
+		 */
+		realsz = dprec > size ? dprec : size;
+		if (sign)
+			realsz++;
+		if (ox[1])
+			realsz+= 2;
+
+		/* right-adjusting blank padding */
+		if ((flags & (LADJUST|ZEROPAD)) == 0)
+			PAD(width - realsz, blanks);
+
+		/* prefix */
+		if (sign)
+			PRINT(&sign, 1);
+		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
+			ox[0] = '0';
+			PRINT(ox, 2);
+		}
+
+		/* right-adjusting zero padding */
+		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+			PAD(width - realsz, zeroes);
+
+		/* leading zeroes from decimal precision */
+		PAD(dprec - size, zeroes);
+
+		/* the string or number proper */
+#ifdef FLOATING_POINT
+		if ((flags & FPT) == 0) {
+			PRINT(cp, size);
+		} else {	/* glue together f_p fragments */
+			if (decimal_point == NULL)
+				decimal_point = nl_langinfo(RADIXCHAR);
+			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
+				if (expt <= 0) {
+					PRINT(zeroes, 1);
+					if (prec || flags & ALT)
+						PRINT(decimal_point, 1);
+					PAD(-expt, zeroes);
+					/* already handled initial 0's */
+					prec += expt;
+ 				} else {
+					PRINTANDPAD(cp, convbuf + ndig,
+					    lead, zeroes);
+					cp += lead;
+					if (prec || flags & ALT)
+						PRINT(decimal_point, 1);
+				}
+				PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
+			} else {	/* %[eE] or sufficiently long %[gG] */
+				if (prec > 1 || flags & ALT) {
+					buf[0] = *cp++;
+					buf[1] = *decimal_point;
+					PRINT(buf, 2);
+					PRINT(cp, ndig-1);
+					PAD(prec - ndig, zeroes);
+				} else { /* XeYYY */
+					PRINT(cp, 1);
+				}
+				PRINT(expstr, expsize);
+			}
+		}
+#else
+		PRINT(cp, size);
+#endif
+		/* left-adjusting padding (always blank) */
+		if (flags & LADJUST)
+			PAD(width - realsz, blanks);
+
+		/* finally, adjust ret */
+		if (width < realsz)
+			width = realsz;
+		if (width > INT_MAX - ret)
+			goto overflow;
+		ret += width;
+	}
+done:
+error:
+	va_end(orgap);
+	if (__sferror(fp))
+		ret = -1;
+	goto finish;
+
+overflow:
+	errno = ENOMEM;
+	ret = -1;
+
+finish:
+	if (convbuf)
+		free(convbuf);
+#ifdef FLOATING_POINT
+	if (dtoaresult)
+		__freedtoa(dtoaresult);
+#endif
+	if (argtable != NULL && argtable != statargtable) {
+		munmap(argtable, argtablesiz);
+		argtable = NULL;
+	}
+	return (ret);
+}
+
+int
+vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, __va_list ap)
+{
+	int r;
+
+	FLOCKFILE(fp);
+	r = __vfwprintf(fp, fmt0, ap);
+	FUNLOCKFILE(fp);
+
+	return (r);
+}
+
+/*
+ * Type ids for argument type table.
+ */
+#define T_UNUSED	0
+#define T_SHORT		1
+#define T_U_SHORT	2
+#define TP_SHORT	3
+#define T_INT		4
+#define T_U_INT		5
+#define TP_INT		6
+#define T_LONG		7
+#define T_U_LONG	8
+#define TP_LONG		9
+#define T_LLONG		10
+#define T_U_LLONG	11
+#define TP_LLONG	12
+#define T_DOUBLE	13
+#define T_LONG_DOUBLE	14
+#define TP_CHAR		15
+#define TP_VOID		16
+#define T_PTRINT	17
+#define TP_PTRINT	18
+#define T_SIZEINT	19
+#define T_SSIZEINT	20
+#define TP_SSIZEINT	21
+#define T_MAXINT	22
+#define T_MAXUINT	23
+#define TP_MAXINT	24
+#define T_CHAR		25
+#define T_U_CHAR	26
+#define T_WINT		27
+#define TP_WCHAR	28
+
+/*
+ * Find all arguments when a positional parameter is encountered.  Returns a
+ * table, indexed by argument number, of pointers to each arguments.  The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
+ * used since we are attempting to make snprintf thread safe, and alloca is
+ * problematic since we have nested functions..)
+ */
+static int
+__find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable,
+    size_t *argtablesiz)
+{
+	wchar_t *fmt;		/* format string */
+	int ch;			/* character from fmt */
+	int n, n2;		/* handy integer (short term usage) */
+	wchar_t *cp;		/* handy char pointer (short term usage) */
+	int flags;		/* flags as above */
+	unsigned char *typetable; /* table of types */
+	unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
+	int tablesize;		/* current size of type table */
+	int tablemax;		/* largest used index in table */
+	int nextarg;		/* 1-based argument index */
+	int ret = 0;		/* return value */
+
+	/*
+	 * Add an argument type to the table, expanding if necessary.
+	 */
+#define ADDTYPE(type) \
+	((nextarg >= tablesize) ? \
+		__grow_type_table(&typetable, &tablesize) : 0, \
+	(nextarg > tablemax) ? tablemax = nextarg : 0, \
+	typetable[nextarg++] = type)
+
+#define	ADDSARG() \
+        ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
+	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+	    ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
+	    ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
+	    ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
+	    ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
+	    ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
+
+#define	ADDUARG() \
+        ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
+	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+	    ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
+	    ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
+	    ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
+	    ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
+	    ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
+
+	/*
+	 * Add * arguments to the type array.
+	 */
+#define ADDASTER() \
+	n2 = 0; \
+	cp = fmt; \
+	while (is_digit(*cp)) { \
+		APPEND_DIGIT(n2, *cp); \
+		cp++; \
+	} \
+	if (*cp == '$') { \
+		int hold = nextarg; \
+		nextarg = n2; \
+		ADDTYPE(T_INT); \
+		nextarg = hold; \
+		fmt = ++cp; \
+	} else { \
+		ADDTYPE(T_INT); \
+	}
+	fmt = (wchar_t *)fmt0;
+	typetable = stattypetable;
+	tablesize = STATIC_ARG_TBL_SIZE;
+	tablemax = 0;
+	nextarg = 1;
+	memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
+
+	/*
+	 * Scan the format for conversions (`%' character).
+	 */
+	for (;;) {
+		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+			continue;
+		if (ch == '\0')
+			goto done;
+		fmt++;		/* skip over '%' */
+
+		flags = 0;
+
+rflag:		ch = *fmt++;
+reswitch:	switch (ch) {
+		case ' ':
+		case '#':
+		case '\'':
+			goto rflag;
+		case '*':
+			ADDASTER();
+			goto rflag;
+		case '-':
+		case '+':
+			goto rflag;
+		case '.':
+			if ((ch = *fmt++) == '*') {
+				ADDASTER();
+				goto rflag;
+			}
+			while (is_digit(ch)) {
+				ch = *fmt++;
+			}
+			goto reswitch;
+		case '0':
+			goto rflag;
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			n = 0;
+			do {
+				APPEND_DIGIT(n ,ch);
+				ch = *fmt++;
+			} while (is_digit(ch));
+			if (ch == '$') {
+				nextarg = n;
+				goto rflag;
+			}
+			goto reswitch;
+#ifdef FLOATING_POINT
+		case 'L':
+			flags |= LONGDBL;
+			goto rflag;
+#endif
+		case 'h':
+			if (*fmt == 'h') {
+				fmt++;
+				flags |= CHARINT;
+			} else {
+				flags |= SHORTINT;
+			}
+			goto rflag;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONGINT;
+			} else {
+				flags |= LONGINT;
+			}
+			goto rflag;
+		case 'q':
+			flags |= LLONGINT;
+			goto rflag;
+		case 't':
+			flags |= PTRINT;
+			goto rflag;
+		case 'z':
+			flags |= SIZEINT;
+			goto rflag;
+		case 'C':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'c':
+			if (flags & LONGINT)
+				ADDTYPE(T_WINT);
+			else
+				ADDTYPE(T_INT);
+			break;
+		case 'D':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'd':
+		case 'i':
+			ADDSARG();
+			break;
+#ifdef FLOATING_POINT
+		case 'a':
+		case 'A':
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'F':
+		case 'g':
+		case 'G':
+			if (flags & LONGDBL)
+				ADDTYPE(T_LONG_DOUBLE);
+			else
+				ADDTYPE(T_DOUBLE);
+			break;
+#endif /* FLOATING_POINT */
+		case 'n':
+			if (flags & LLONGINT)
+				ADDTYPE(TP_LLONG);
+			else if (flags & LONGINT)
+				ADDTYPE(TP_LONG);
+			else if (flags & SHORTINT)
+				ADDTYPE(TP_SHORT);
+			else if (flags & PTRINT)
+				ADDTYPE(TP_PTRINT);
+			else if (flags & SIZEINT)
+				ADDTYPE(TP_SSIZEINT);
+			else if (flags & MAXINT)
+				ADDTYPE(TP_MAXINT);
+			else
+				ADDTYPE(TP_INT);
+			continue;	/* no output */
+		case 'O':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'o':
+			ADDUARG();
+			break;
+		case 'p':
+			ADDTYPE(TP_VOID);
+			break;
+		case 'S':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 's':
+			if (flags & LONGINT)
+				ADDTYPE(TP_CHAR);
+			else
+				ADDTYPE(TP_WCHAR);
+			break;
+		case 'U':
+			flags |= LONGINT;
+			/*FALLTHROUGH*/
+		case 'u':
+		case 'X':
+		case 'x':
+			ADDUARG();
+			break;
+		default:	/* "%?" prints ?, unless ? is NUL */
+			if (ch == '\0')
+				goto done;
+			break;
+		}
+	}
+done:
+	/*
+	 * Build the argument table.
+	 */
+	if (tablemax >= STATIC_ARG_TBL_SIZE) {
+		*argtablesiz = sizeof(union arg) * (tablemax + 1);
+		*argtable = mmap(NULL, *argtablesiz,
+		    PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if (*argtable == MAP_FAILED)
+			return (-1);
+	}
+
+#if 0
+	/* XXX is this required? */
+	(*argtable)[0].intarg = 0;
+#endif
+	for (n = 1; n <= tablemax; n++) {
+		switch (typetable[n]) {
+		case T_UNUSED:
+		case T_CHAR:
+		case T_U_CHAR:
+		case T_SHORT:
+		case T_U_SHORT:
+		case T_INT:
+			(*argtable)[n].intarg = va_arg(ap, int);
+			break;
+		case TP_SHORT:
+			(*argtable)[n].pshortarg = va_arg(ap, short *);
+			break;
+		case T_U_INT:
+			(*argtable)[n].uintarg = va_arg(ap, unsigned int);
+			break;
+		case TP_INT:
+			(*argtable)[n].pintarg = va_arg(ap, int *);
+			break;
+		case T_LONG:
+			(*argtable)[n].longarg = va_arg(ap, long);
+			break;
+		case T_U_LONG:
+			(*argtable)[n].ulongarg = va_arg(ap, unsigned long);
+			break;
+		case TP_LONG:
+			(*argtable)[n].plongarg = va_arg(ap, long *);
+			break;
+		case T_LLONG:
+			(*argtable)[n].longlongarg = va_arg(ap, long long);
+			break;
+		case T_U_LLONG:
+			(*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
+			break;
+		case TP_LLONG:
+			(*argtable)[n].plonglongarg = va_arg(ap, long long *);
+			break;
+#ifdef FLOATING_POINT
+		case T_DOUBLE:
+			(*argtable)[n].doublearg = va_arg(ap, double);
+			break;
+		case T_LONG_DOUBLE:
+			(*argtable)[n].longdoublearg = va_arg(ap, long double);
+			break;
+#endif
+		case TP_CHAR:
+			(*argtable)[n].pchararg = va_arg(ap, char *);
+			break;
+		case TP_VOID:
+			(*argtable)[n].pvoidarg = va_arg(ap, void *);
+			break;
+		case T_PTRINT:
+			(*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
+			break;
+		case TP_PTRINT:
+			(*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
+			break;
+		case T_SIZEINT:
+			(*argtable)[n].sizearg = va_arg(ap, size_t);
+			break;
+		case T_SSIZEINT:
+			(*argtable)[n].ssizearg = va_arg(ap, ssize_t);
+			break;
+		case TP_SSIZEINT:
+			(*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
+			break;
+		case TP_MAXINT:
+			(*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
+			break;
+		case T_WINT:
+			(*argtable)[n].wintarg = va_arg(ap, wint_t);
+			break;
+		case TP_WCHAR:
+			(*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
+			break;
+		}
+	}
+	goto finish;
+
+overflow:
+	errno = ENOMEM;
+	ret = -1;
+
+finish:
+	if (typetable != NULL && typetable != stattypetable) {
+		munmap(typetable, *argtablesiz);
+		typetable = NULL;
+	}
+	return (ret);
+}
+
+/*
+ * Increase the size of the type table.
+ */
+static int
+__grow_type_table(unsigned char **typetable, int *tablesize)
+{
+	unsigned char *oldtable = *typetable;
+	int newsize = *tablesize * 2;
+
+	if (newsize < getpagesize())
+		newsize = getpagesize();
+
+	if (*tablesize == STATIC_ARG_TBL_SIZE) {
+		*typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
+		    MAP_ANON|MAP_PRIVATE, -1, 0);
+		if (*typetable == MAP_FAILED)
+			return (-1);
+		bcopy(oldtable, *typetable, *tablesize);
+	} else {
+		unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
+		    MAP_ANON|MAP_PRIVATE, -1, 0);
+		if (new == MAP_FAILED)
+			return (-1);
+		memmove(new, *typetable, *tablesize);
+		munmap(*typetable, *tablesize);
+		*typetable = new;
+	}
+	memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
+
+	*tablesize = newsize;
+	return (0);
+}
+
+ 
+#ifdef FLOATING_POINT
+static int
+exponent(wchar_t *p0, int exp, int fmtch)
+{
+	wchar_t *p, *t;
+	wchar_t expbuf[MAXEXPDIG];
+
+	p = p0;
+	*p++ = fmtch;
+	if (exp < 0) {
+		exp = -exp;
+		*p++ = '-';
+	} else
+		*p++ = '+';
+	t = expbuf + MAXEXPDIG;
+	if (exp > 9) {
+		do {
+			*--t = to_char(exp % 10);
+		} while ((exp /= 10) > 9);
+		*--t = to_char(exp);
+		for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
+			/* nothing */;
+	} else {
+		/*
+		 * Exponents for decimal floating point conversions
+		 * (%[eEgG]) must be at least two characters long,
+		 * whereas exponents for hexadecimal conversions can
+		 * be only one character long.
+		 */
+		if (fmtch == 'e' || fmtch == 'E')
+			*p++ = '0';
+		*p++ = to_char(exp);
+	}
+	return (p - p0);
+}
+#endif /* FLOATING_POINT */
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
new file mode 100644
index 0000000..e5cf5e1
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
@@ -0,0 +1,799 @@
+/*	$OpenBSD: vfwscanf.c,v 1.2 2012/01/18 17:23:11 chl Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wctype.h>
+#include "local.h"
+
+#ifdef FLOATING_POINT
+#include "floatio.h"
+#endif
+
+#define	BUF		513	/* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define	LONG		0x00001	/* l: long or double */
+#define	LONGDBL		0x00002	/* L: long double */
+#define	SHORT		0x00004	/* h: short */
+#define	SHORTSHORT	0x00008	/* hh: 8 bit integer */
+#define LLONG		0x00010	/* ll: long long (+ deprecated q: quad) */
+#define	POINTER		0x00020	/* p: void * (as hex) */
+#define	SIZEINT		0x00040	/* z: (signed) size_t */
+#define	MAXINT		0x00080	/* j: intmax_t */
+#define	PTRINT		0x00100	/* t: ptrdiff_t */
+#define	NOSKIP		0x00200	/* [ or c: do not skip blanks */
+#define	SUPPRESS	0x00400	/* *: suppress assignment */
+#define	UNSIGNED	0x00800	/* %[oupxX] conversions */
+
+/*
+ * The following are used in numeric conversions only:
+ * SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
+ * SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
+ */
+#define	SIGNOK		0x01000	/* +/- is (still) legal */
+#define	HAVESIGN	0x02000	/* sign detected */
+#define	NDIGITS		0x04000	/* no digits detected */
+
+#define	DPTOK		0x08000	/* (float) decimal point is still legal */
+#define	EXPOK		0x10000	/* (float) exponent (e+3, etc) still legal */
+
+#define	PFXOK		0x08000	/* 0x prefix is (still) legal */
+#define	NZDIGITS	0x10000	/* no zero digits detected */
+
+/*
+ * Conversion types.
+ */
+#define	CT_CHAR		0	/* %c conversion */
+#define	CT_CCL		1	/* %[...] conversion */
+#define	CT_STRING	2	/* %s conversion */
+#define	CT_INT		3	/* integer, i.e., strtoimax or strtoumax */
+#define	CT_FLOAT	4	/* floating, i.e., strtod */
+
+#define u_char unsigned char
+#define u_long unsigned long
+
+#define	INCCL(_c)	\
+	(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
+	(wmemchr(ccls, (_c), ccle - ccls) != NULL))
+
+/*
+ * vfwscanf
+ */
+int
+__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
+{
+	wint_t c;	/* character from format, or conversion */
+	size_t width;	/* field width, or 0 */
+	wchar_t *p;	/* points into all kinds of strings */
+	int n;		/* handy integer */
+	int flags;	/* flags as defined above */
+	wchar_t *p0;	/* saves original value of p when necessary */
+	int nassigned;		/* number of fields assigned */
+	int nconversions;	/* number of conversions */
+	int nread;		/* number of characters consumed from fp */
+	int base;		/* base argument to strtoimax/strtouimax */
+	wchar_t buf[BUF];	/* buffer for numeric conversions */
+	const wchar_t *ccls;	/* character class start */
+	const wchar_t *ccle;	/* character class end */
+	int cclcompl;		/* ccl is complemented? */
+	wint_t wi;		/* handy wint_t */
+	char *mbp;		/* multibyte string pointer for %c %s %[ */
+	size_t nconv;		/* number of bytes in mb. conversion */
+	char mbbuf[MB_LEN_MAX];	/* temporary mb. character buffer */
+ 	mbstate_t mbs;
+#ifdef FLOATING_POINT
+	wchar_t decimal_point = 0;
+#endif
+
+	/* `basefix' is used to avoid `if' tests in the integer scanner */
+	static short basefix[17] =
+		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+	_SET_ORIENTATION(fp, 1);
+
+	nassigned = 0;
+	nconversions = 0;
+	nread = 0;
+	base = 0;		/* XXX just to keep gcc happy */
+	ccls = ccle = NULL;
+	for (;;) {
+		c = *fmt++;
+		if (c == 0) {
+			return (nassigned);
+		}
+		if (iswspace(c)) {
+			while ((c = __fgetwc_unlock(fp)) != WEOF &&
+			    iswspace(c))
+				;
+			if (c != WEOF)
+				__ungetwc(c, fp);
+			continue;
+		}
+		if (c != '%')
+			goto literal;
+		width = 0;
+		flags = 0;
+		/*
+		 * switch on the format.  continue if done;
+		 * break once format type is derived.
+		 */
+again:		c = *fmt++;
+		switch (c) {
+		case '%':
+literal:
+			if ((wi = __fgetwc_unlock(fp)) == WEOF)
+				goto input_failure;
+			if (wi != c) {
+				__ungetwc(wi, fp);
+				goto input_failure;
+			}
+			nread++;
+			continue;
+
+		case '*':
+			flags |= SUPPRESS;
+			goto again;
+		case 'j':
+			flags |= MAXINT;
+			goto again;
+		case 'L':
+			flags |= LONGDBL;
+			goto again;
+		case 'h':
+			if (*fmt == 'h') {
+				fmt++;
+				flags |= SHORTSHORT;
+			} else {
+				flags |= SHORT;
+			}
+			goto again;
+		case 'l':
+			if (*fmt == 'l') {
+				fmt++;
+				flags |= LLONG;
+			} else {
+				flags |= LONG;
+			}
+			goto again;
+		case 'q':
+			flags |= LLONG;		/* deprecated */
+			goto again;
+		case 't':
+			flags |= PTRINT;
+			goto again;
+		case 'z':
+			flags |= SIZEINT;
+			goto again;
+
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			width = width * 10 + c - '0';
+			goto again;
+
+		/*
+		 * Conversions.
+		 * Those marked `compat' are for 4.[123]BSD compatibility.
+		 *
+		 * (According to ANSI, E and X formats are supposed
+		 * to the same as e and x.  Sorry about that.)
+		 */
+		case 'D':	/* compat */
+			flags |= LONG;
+			/* FALLTHROUGH */
+		case 'd':
+			c = CT_INT;
+			base = 10;
+			break;
+
+		case 'i':
+			c = CT_INT;
+			base = 0;
+			break;
+
+		case 'O':	/* compat */
+			flags |= LONG;
+			/* FALLTHROUGH */
+		case 'o':
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 8;
+			break;
+
+		case 'u':
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 10;
+			break;
+
+		case 'X':
+		case 'x':
+			flags |= PFXOK;	/* enable 0x prefixing */
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 16;
+			break;
+
+#ifdef FLOATING_POINT
+		case 'e': case 'E':
+		case 'f': case 'F':
+		case 'g': case 'G':
+		case 'a': case 'A':
+			c = CT_FLOAT;
+			break;
+#endif
+
+		case 's':
+			c = CT_STRING;
+			break;
+
+		case '[':
+			ccls = fmt;
+			if (*fmt == '^') {
+				cclcompl = 1;
+				fmt++;
+			} else
+				cclcompl = 0;
+			if (*fmt == ']')
+				fmt++;
+			while (*fmt != '\0' && *fmt != ']')
+				fmt++;
+			ccle = fmt;
+			fmt++;
+			flags |= NOSKIP;
+			c = CT_CCL;
+			break;
+
+		case 'c':
+			flags |= NOSKIP;
+			c = CT_CHAR;
+			break;
+
+		case 'p':	/* pointer format is like hex */
+			flags |= POINTER | PFXOK;
+			c = CT_INT;
+			flags |= UNSIGNED;
+			base = 16;
+			break;
+
+		case 'n':
+			nconversions++;
+			if (flags & SUPPRESS)
+				continue;
+			if (flags & SHORTSHORT)
+				*va_arg(ap, __signed char *) = nread;
+			else if (flags & SHORT)
+				*va_arg(ap, short *) = nread;
+			else if (flags & LONG)
+				*va_arg(ap, long *) = nread;
+			else if (flags & SIZEINT)
+				*va_arg(ap, ssize_t *) = nread;
+			else if (flags & PTRINT)
+				*va_arg(ap, ptrdiff_t *) = nread;
+			else if (flags & LLONG)
+				*va_arg(ap, long long *) = nread;
+			else if (flags & MAXINT)
+				*va_arg(ap, intmax_t *) = nread;
+			else
+				*va_arg(ap, int *) = nread;
+			continue;
+
+		/*
+		 * Disgusting backwards compatibility hacks.	XXX
+		 */
+		case '\0':	/* compat */
+			return (EOF);
+
+		default:	/* compat */
+			if (isupper(c))
+				flags |= LONG;
+			c = CT_INT;
+			base = 10;
+			break;
+		}
+
+		/*
+		 * Consume leading white space, except for formats
+		 * that suppress this.
+		 */
+		if ((flags & NOSKIP) == 0) {
+			while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+			    iswspace(wi))
+				nread++;
+			if (wi == WEOF)
+				goto input_failure;
+			__ungetwc(wi, fp);
+		}
+
+		/*
+		 * Do the conversion.
+		 */
+		switch (c) {
+
+		case CT_CHAR:
+			/* scan arbitrary characters (sets NOSKIP) */
+			if (width == 0)
+				width = 1;
+ 			if (flags & LONG) {
+				if (!(flags & SUPPRESS))
+					p = va_arg(ap, wchar_t *);
+				n = 0;
+				while (width-- != 0 &&
+				    (wi = __fgetwc_unlock(fp)) != WEOF) {
+					if (!(flags & SUPPRESS))
+						*p++ = (wchar_t)wi;
+					n++;
+				}
+				if (n == 0)
+					goto input_failure;
+				nread += n;
+ 				if (!(flags & SUPPRESS))
+ 					nassigned++;
+			} else {
+				if (!(flags & SUPPRESS))
+					mbp = va_arg(ap, char *);
+				n = 0;
+				bzero(&mbs, sizeof(mbs));
+				while (width != 0 &&
+				    (wi = __fgetwc_unlock(fp)) != WEOF) {
+					if (width >= MB_CUR_MAX &&
+					    !(flags & SUPPRESS)) {
+						nconv = wcrtomb(mbp, wi, &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+					} else {
+						nconv = wcrtomb(mbbuf, wi,
+						    &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+						if (nconv > width) {
+							__ungetwc(wi, fp);
+ 							break;
+ 						}
+						if (!(flags & SUPPRESS))
+							memcpy(mbp, mbbuf,
+							    nconv);
+ 					}
+					if (!(flags & SUPPRESS))
+						mbp += nconv;
+					width -= nconv;
+					n++;
+ 				}
+				if (n == 0)
+ 					goto input_failure;
+				nread += n;
+				if (!(flags & SUPPRESS))
+					nassigned++;
+			}
+			nconversions++;
+			break;
+
+		case CT_CCL:
+			/* scan a (nonempty) character class (sets NOSKIP) */
+			if (width == 0)
+				width = (size_t)~0;	/* `infinity' */
+			/* take only those things in the class */
+			if ((flags & SUPPRESS) && (flags & LONG)) {
+				n = 0;
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width-- != 0 && INCCL(wi))
+					n++;
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+				if (n == 0)
+					goto match_failure;
+			} else if (flags & LONG) {
+				p0 = p = va_arg(ap, wchar_t *);
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width-- != 0 && INCCL(wi))
+					*p++ = (wchar_t)wi;
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+				n = p - p0;
+				if (n == 0)
+					goto match_failure;
+				*p = 0;
+				nassigned++;
+			} else {
+				if (!(flags & SUPPRESS))
+					mbp = va_arg(ap, char *);
+				n = 0;
+				bzero(&mbs, sizeof(mbs));
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width != 0 && INCCL(wi)) {
+					if (width >= MB_CUR_MAX &&
+					   !(flags & SUPPRESS)) {
+						nconv = wcrtomb(mbp, wi, &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+					} else {
+						nconv = wcrtomb(mbbuf, wi,
+						    &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+						if (nconv > width)
+							break;
+						if (!(flags & SUPPRESS))
+							memcpy(mbp, mbbuf,
+							    nconv);
+					}
+					if (!(flags & SUPPRESS))
+						mbp += nconv;
+					width -= nconv;
+					n++;
+				}
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+				if (!(flags & SUPPRESS)) {
+					*mbp = 0;
+					nassigned++;
+				}
+ 			}
+			nread += n;
+			nconversions++;
+			break;
+
+		case CT_STRING:
+			/* like CCL, but zero-length string OK, & no NOSKIP */
+			if (width == 0)
+				width = (size_t)~0;
+			if ((flags & SUPPRESS) && (flags & LONG)) {
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width-- != 0 &&
+				    !iswspace(wi))
+					nread++;
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+			} else if (flags & LONG) {
+				p0 = p = va_arg(ap, wchar_t *);
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width-- != 0 &&
+				    !iswspace(wi)) {
+					*p++ = (wchar_t)wi;
+					nread++;
+				}
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+				*p = 0;
+				nassigned++;
+			} else {
+				if (!(flags & SUPPRESS))
+					mbp = va_arg(ap, char *);
+				bzero(&mbs, sizeof(mbs));
+				while ((wi = __fgetwc_unlock(fp)) != WEOF &&
+				    width != 0 &&
+				    !iswspace(wi)) {
+					if (width >= MB_CUR_MAX &&
+					    !(flags & SUPPRESS)) {
+						nconv = wcrtomb(mbp, wi, &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+					} else {
+						nconv = wcrtomb(mbbuf, wi,
+						    &mbs);
+						if (nconv == (size_t)-1)
+							goto input_failure;
+						if (nconv > width)
+							break;
+						if (!(flags & SUPPRESS))
+							memcpy(mbp, mbbuf,
+							    nconv);
+					}
+					if (!(flags & SUPPRESS))
+						mbp += nconv;
+					width -= nconv;
+					nread++;
+				}
+				if (wi != WEOF)
+					__ungetwc(wi, fp);
+				if (!(flags & SUPPRESS)) {
+					*mbp = 0;
+ 					nassigned++;
+ 				}
+			}
+			nconversions++;
+			continue;
+
+		case CT_INT:
+			/* scan an integer as if by strtoimax/strtoumax */
+			if (width == 0 || width > sizeof(buf) /
+			    sizeof(*buf) - 1)
+				width = sizeof(buf) / sizeof(*buf) - 1;
+			flags |= SIGNOK | NDIGITS | NZDIGITS;
+			for (p = buf; width; width--) {
+				c = __fgetwc_unlock(fp);
+				/*
+				 * Switch on the character; `goto ok'
+				 * if we accept it as a part of number.
+				 */
+				switch (c) {
+
+				/*
+				 * The digit 0 is always legal, but is
+				 * special.  For %i conversions, if no
+				 * digits (zero or nonzero) have been
+				 * scanned (only signs), we will have
+				 * base==0.  In that case, we should set
+				 * it to 8 and enable 0x prefixing.
+				 * Also, if we have not scanned zero digits
+				 * before this, do not turn off prefixing
+				 * (someone else will turn it off if we
+				 * have scanned any nonzero digits).
+				 */
+				case '0':
+					if (base == 0) {
+						base = 8;
+						flags |= PFXOK;
+					}
+					if (flags & NZDIGITS)
+					    flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+					else
+					    flags &= ~(SIGNOK|PFXOK|NDIGITS);
+					goto ok;
+
+				/* 1 through 7 always legal */
+				case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+					base = basefix[base];
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* digits 8 and 9 ok iff decimal or hex */
+				case '8': case '9':
+					base = basefix[base];
+					if (base <= 8)
+						break;	/* not legal here */
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* letters ok iff hex */
+				case 'A': case 'B': case 'C':
+				case 'D': case 'E': case 'F':
+				case 'a': case 'b': case 'c':
+				case 'd': case 'e': case 'f':
+					/* no need to fix base here */
+					if (base <= 10)
+						break;	/* not legal here */
+					flags &= ~(SIGNOK | PFXOK | NDIGITS);
+					goto ok;
+
+				/* sign ok only as first character */
+				case '+': case '-':
+					if (flags & SIGNOK) {
+						flags &= ~SIGNOK;
+						flags |= HAVESIGN;
+						goto ok;
+					}
+					break;
+
+				/*
+				 * x ok iff flag still set and 2nd char (or
+				 * 3rd char if we have a sign).
+				 */
+				case 'x': case 'X':
+					if ((flags & PFXOK) && p ==
+					    buf + 1 + !!(flags & HAVESIGN)) {
+						base = 16;	/* if %i */
+						flags &= ~PFXOK;
+						goto ok;
+					}
+					break;
+				}
+
+				/*
+				 * If we got here, c is not a legal character
+				 * for a number.  Stop accumulating digits.
+				 */
+				if (c != WEOF)
+					__ungetwc(c, fp);
+				break;
+		ok:
+				/*
+				 * c is legal: store it and look at the next.
+				 */
+				*p++ = (wchar_t)c;
+			}
+			/*
+			 * If we had only a sign, it is no good; push
+			 * back the sign.  If the number ends in `x',
+			 * it was [sign] '0' 'x', so push back the x
+			 * and treat it as [sign] '0'.
+			 */
+			if (flags & NDIGITS) {
+				if (p > buf)
+					__ungetwc(*--p, fp);
+				goto match_failure;
+			}
+			c = p[-1];
+			if (c == 'x' || c == 'X') {
+				--p;
+				__ungetwc(c, fp);
+			}
+			if ((flags & SUPPRESS) == 0) {
+				uintmax_t res;
+
+				*p = '\0';
+				if (flags & UNSIGNED)
+					res = wcstoimax(buf, NULL, base);
+				else
+					res = wcstoumax(buf, NULL, base);
+				if (flags & POINTER)
+					*va_arg(ap, void **) =
+					    (void *)(uintptr_t)res;
+				else if (flags & MAXINT)
+					*va_arg(ap, intmax_t *) = res;
+				else if (flags & LLONG)
+					*va_arg(ap, long long *) = res;
+				else if (flags & SIZEINT)
+					*va_arg(ap, ssize_t *) = res;
+				else if (flags & PTRINT)
+					*va_arg(ap, ptrdiff_t *) = res;
+				else if (flags & LONG)
+					*va_arg(ap, long *) = res;
+				else if (flags & SHORT)
+					*va_arg(ap, short *) = res;
+				else if (flags & SHORTSHORT)
+					*va_arg(ap, __signed char *) = res;
+				else
+					*va_arg(ap, int *) = res;
+				nassigned++;
+			}
+			nread += p - buf;
+			nconversions++;
+			break;
+
+#ifdef FLOATING_POINT
+		case CT_FLOAT:
+			/* scan a floating point number as if by strtod */
+			if (width == 0 || width > sizeof(buf) /
+			    sizeof(*buf) - 1)
+				width = sizeof(buf) / sizeof(*buf) - 1;
+			flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
+			for (p = buf; width; width--) {
+				c = __fgetwc_unlock(fp);
+				/*
+				 * This code mimicks the integer conversion
+				 * code, but is much simpler.
+				 */
+				switch (c) {
+
+				case '0': case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+				case '8': case '9':
+					flags &= ~(SIGNOK | NDIGITS);
+					goto fok;
+
+				case '+': case '-':
+					if (flags & SIGNOK) {
+						flags &= ~SIGNOK;
+						goto fok;
+					}
+					break;
+				case 'e': case 'E':
+					/* no exponent without some digits */
+					if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
+						flags =
+						    (flags & ~(EXPOK|DPTOK)) |
+						    SIGNOK | NDIGITS;
+						goto fok;
+					}
+					break;
+				default:
+					if (decimal_point == 0) {
+						bzero(&mbs, sizeof(mbs));
+						nconv = mbrtowc(&decimal_point,
+						    localeconv()->decimal_point,
+					    	    MB_CUR_MAX, &mbs);
+						if (nconv == 0 ||
+						    nconv == (size_t)-1 ||
+						    nconv == (size_t)-2)
+							decimal_point = '.';
+					}
+					if (c == decimal_point &&
+					    (flags & DPTOK)) {
+						flags &= ~(SIGNOK | DPTOK);
+						goto fok;
+					}
+					break;
+				}
+				if (c != WEOF)
+					__ungetwc(c, fp);
+				break;
+		fok:
+				*p++ = c;
+			}
+			/*
+			 * If no digits, might be missing exponent digits
+			 * (just give back the exponent) or might be missing
+			 * regular digits, but had sign and/or decimal point.
+			 */
+			if (flags & NDIGITS) {
+				if (flags & EXPOK) {
+					/* no digits at all */
+					while (p > buf)
+						__ungetwc(*--p, fp);
+					goto match_failure;
+				}
+				/* just a bad exponent (e and maybe sign) */
+				c = *--p;
+				if (c != 'e' && c != 'E') {
+					__ungetwc(c, fp);/* sign */
+					c = *--p;
+				}
+				__ungetwc(c, fp);
+			}
+			if ((flags & SUPPRESS) == 0) {
+				*p = 0;
+				if (flags & LONGDBL) {
+					long double res = wcstold(buf, NULL);
+					*va_arg(ap, long double *) = res;
+				} else if (flags & LONG) {
+					double res = wcstod(buf, NULL);
+					*va_arg(ap, double *) = res;
+				} else {
+					float res = wcstof(buf, NULL);
+					*va_arg(ap, float *) = res;
+				}
+				nassigned++;
+			}
+			nread += p - buf;
+			nconversions++;
+			break;
+#endif /* FLOATING_POINT */
+		}
+	}
+input_failure:
+	return (nconversions != 0 ? nassigned : EOF);
+match_failure:
+	return (nassigned);
+}
+
+int
+vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
+{
+	int r;
+
+	FLOCKFILE(fp);
+	r = __vfwscanf(fp, fmt, ap);
+	FUNLOCKFILE(fp);
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vswprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vswprintf.c
new file mode 100644
index 0000000..da7c4de
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vswprintf.c
@@ -0,0 +1,96 @@
+/*	$OpenBSD: vswprintf.c,v 1.4 2012/12/05 23:20:01 deraadt Exp $	*/
+/*	$NetBSD: vswprintf.c,v 1.1 2005/05/14 23:51:02 christos Exp $	*/
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include "local.h"
+
+int
+vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
+    __va_list ap)
+{
+	mbstate_t mbs;
+	FILE f;
+	char *mbp;
+	int ret, sverrno;
+	size_t nwc;
+	struct __sfileext fext;
+
+	if (n == 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	_FILEEXT_SETUP(&f, &fext);
+	f._file = -1;
+	f._flags = __SWR | __SSTR | __SALC;
+	f._bf._base = f._p = (unsigned char *)malloc(128);
+	if (f._bf._base == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	f._bf._size = f._w = 127;		/* Leave room for the NUL */
+	ret = __vfwprintf(&f, fmt, ap);
+	if (ret < 0) {
+		sverrno = errno;
+		free(f._bf._base);
+		errno = sverrno;
+		return (-1);
+	}
+	if (ret == 0) {
+		s[0] = L'\0';
+		free(f._bf._base);
+		return (0);
+	}
+	*f._p = '\0';
+	mbp = (char *)f._bf._base;
+	/*
+	 * XXX Undo the conversion from wide characters to multibyte that
+	 * fputwc() did in __vfwprintf().
+	 */
+	bzero(&mbs, sizeof(mbs));
+	nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs);
+	free(f._bf._base);
+	if (nwc == (size_t)-1) {
+		errno = EILSEQ;
+		return (-1);
+	}
+	if (nwc == n) {
+		s[n - 1] = L'\0';
+		errno = EOVERFLOW;
+		return (-1);
+	}
+
+	return (ret);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
new file mode 100644
index 0000000..cbaa250
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vswscanf.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: vswscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * 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.
+ * 4. 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.
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "local.h"
+
+static int	eofread(void *, char *, int);
+
+static int
+eofread(void *cookie, char *buf, int len)
+{
+	return (0);
+}
+
+int
+vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
+    __va_list ap)
+{
+	mbstate_t mbs;
+	FILE f;
+	struct __sfileext fext;
+	char *mbstr;
+	size_t len, mlen;
+	int r;
+	const wchar_t *strp;
+
+	/*
+	 * XXX Convert the wide character string to multibyte, which
+	 * __vfwscanf() will convert back to wide characters.
+	 */
+	len = wcslen(str) * MB_CUR_MAX;
+	if ((mbstr = malloc(len + 1)) == NULL)
+		return (EOF);
+	bzero(&mbs, sizeof(mbs));
+	strp = str;
+	if ((mlen = wcsrtombs(mbstr, &strp, len, &mbs)) == (size_t)-1) {
+		free(mbstr);
+		return (EOF);
+	}
+	if (mlen == len)
+		mbstr[len] = '\0';
+	_FILEEXT_SETUP(&f, &fext);
+	f._flags = __SRD;
+	f._bf._base = f._p = (unsigned char *)mbstr;
+	f._bf._size = f._r = mlen;
+	f._read = eofread;
+	f._lb._base = NULL;
+	r = __vfwscanf(&f, fmt, ap);
+	free(mbstr);
+
+	return (r);
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/wcsstr.c b/libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
similarity index 74%
copy from libc/upstream-freebsd/lib/libc/string/wcsstr.c
copy to libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
index ce598a6..49569c1 100644
--- a/libc/upstream-freebsd/lib/libc/string/wcsstr.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: vwprintf.c,v 1.3 2011/04/28 17:38:46 stsp Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,34 +31,12 @@
  * SUCH DAMAGE.
  */
 
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#include <stdarg.h>
+#include <stdio.h>
 #include <wchar.h>
 
-/*
- * Find the first occurrence of find in s.
- */
-wchar_t *
-wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
+int
+vwprintf(const wchar_t * __restrict fmt, __va_list ap)
 {
-	wchar_t c, sc;
-	size_t len;
-
-	if ((c = *find++) != L'\0') {
-		len = wcslen(find);
-		do {
-			do {
-				if ((sc = *s++) == L'\0')
-					return (NULL);
-			} while (sc != c);
-		} while (wcsncmp(s, find, len) != 0);
-		s--;
-	}
-	return ((wchar_t *)s);
+	return (vfwprintf(stdout, fmt, ap));
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c
new file mode 100644
index 0000000..7039f02
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vwscanf.c
@@ -0,0 +1,38 @@
+/* $OpenBSD: vwscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 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 <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+vwscanf(const wchar_t * __restrict fmt, __va_list ap)
+{
+
+	return (vfwscanf(stdin, fmt, ap));
+}
diff --git a/libc/upstream-freebsd/lib/libc/string/wcsstr.c b/libc/upstream-openbsd/lib/libc/stdio/wprintf.c
similarity index 74%
copy from libc/upstream-freebsd/lib/libc/string/wcsstr.c
copy to libc/upstream-openbsd/lib/libc/stdio/wprintf.c
index ce598a6..9f7abb6 100644
--- a/libc/upstream-freebsd/lib/libc/string/wcsstr.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/wprintf.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: wprintf.c,v 1.3 2011/04/28 17:38:46 stsp Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,34 +31,18 @@
  * SUCH DAMAGE.
  */
 
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strstr.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#include <stdio.h>
+#include <stdarg.h>
 #include <wchar.h>
 
-/*
- * Find the first occurrence of find in s.
- */
-wchar_t *
-wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
+int
+wprintf(const wchar_t * __restrict fmt, ...)
 {
-	wchar_t c, sc;
-	size_t len;
+	int ret;
+	va_list ap;
 
-	if ((c = *find++) != L'\0') {
-		len = wcslen(find);
-		do {
-			do {
-				if ((sc = *s++) == L'\0')
-					return (NULL);
-			} while (sc != c);
-		} while (wcsncmp(s, find, len) != 0);
-		s--;
-	}
-	return ((wchar_t *)s);
+	va_start(ap, fmt);
+	ret = vfwprintf(stdout, fmt, ap);
+	va_end(ap);
+	return (ret);
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/wscanf.c b/libc/upstream-openbsd/lib/libc/stdio/wscanf.c
new file mode 100644
index 0000000..06c0829
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/wscanf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: wscanf.c,v 1.2 2012/12/05 23:20:01 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002 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 <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int
+wscanf(const wchar_t * __restrict fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+	r = vfwscanf(stdin, fmt, ap);
+	va_end(ap);
+
+	return (r);
+}
diff --git a/libc/upstream-openbsd/lib/libc/string/wcsstr.c b/libc/upstream-openbsd/lib/libc/string/wcsstr.c
new file mode 100644
index 0000000..669e340
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/string/wcsstr.c
@@ -0,0 +1,70 @@
+/*	$OpenBSD: wcsstr.c,v 1.3 2005/08/08 08:05:37 espie Exp $	*/
+/*	$NetBSD: wcsstr.c,v 1.3 2003/03/05 20:18:17 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)1999 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 Id: wcsstr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <wchar.h>
+
+wchar_t *
+#ifdef WCSWCS
+wcswcs(const wchar_t *big, const wchar_t *little)
+#else
+wcsstr(const wchar_t *big, const wchar_t *little)
+#endif
+{
+	const wchar_t *p;
+	const wchar_t *q;
+	const wchar_t *r;
+
+	if (!*little) {
+		/* LINTED interface specification */
+		return (wchar_t *)big;
+	}
+	if (wcslen(big) < wcslen(little))
+		return NULL;
+
+	p = big;
+	q = little;
+	while (*p) {
+		q = little;
+		r = p;
+		while (*q) {
+			if (*r != *q)
+				break;
+			q++;
+			r++;
+		}
+		if (!*q) {
+			/* LINTED interface specification */
+			return (wchar_t *)p;
+		}
+		p++;
+	}
+	return NULL;
+}
diff --git a/libc/upstream-openbsd/lib/libc/string/wcswcs.c b/libc/upstream-openbsd/lib/libc/string/wcswcs.c
new file mode 100644
index 0000000..bd35605
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/string/wcswcs.c
@@ -0,0 +1,5 @@
+/*	$OpenBSD: wcswcs.c,v 1.1 2005/04/13 16:35:58 espie Exp $	*/
+/* $NetBSD: wcswcs.c,v 1.1 2003/03/05 20:18:17 tshiozak Exp $ */
+
+#define WCSWCS
+#include "wcsstr.c"
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 5a53685..c1a0f16 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -18,8 +18,8 @@
 
 LOCAL_MODULE := $(module)
 LOCAL_MODULE_TAGS := $(module_tag)
-LOCAL_MULTILIB := $(multilib)
-ifeq ($(multilib),both)
+LOCAL_MULTILIB := $($(module)_multilib)
+ifeq ($(LOCAL_MULTILIB),both)
     LOCAL_MODULE_STEM_32 := $(module)32
     LOCAL_MODULE_STEM_64 := $(module)64
 endif
diff --git a/tests/Android.mk b/tests/Android.mk
index 0014af6..fccf3f1 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -38,6 +38,11 @@
     -Werror \
     -fno-builtin \
 
+test_cflags += -D__STDC_LIMIT_MACROS  # For glibc.
+
+test_cppflags = \
+    -std=gnu++11 \
+
 libBionicStandardTests_src_files := \
     buffer_tests.cpp \
     ctype_test.cpp \
@@ -89,6 +94,9 @@
 libBionicStandardTests_cflags := \
     $(test_cflags) \
 
+libBionicStandardTests_cppflags := \
+    $(test_cppflags) \
+
 libBionicStandardTests_ldlibs_host := \
     -lrt \
 
@@ -221,7 +229,7 @@
 
 module := bionic-unit-tests
 module_tag := optional
-multilib := both
+bionic-unit-tests_multilib := both
 build_type := target
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
@@ -243,7 +251,7 @@
 
 module := bionic-unit-tests-static
 module_tag := optional
-multilib := both
+bionic-unit-tests-static_multilib := both
 build_type := target
 build_target := NATIVE_TEST
 include $(LOCAL_PATH)/Android.build.mk
diff --git a/tests/inttypes_test.cpp b/tests/inttypes_test.cpp
index ac37e62..e588503 100644
--- a/tests/inttypes_test.cpp
+++ b/tests/inttypes_test.cpp
@@ -38,3 +38,11 @@
   sscanf(buf, "%08" SCNuPTR, &u);
   sscanf(buf, "%08" SCNxPTR, &u);
 }
+
+TEST(inttypes, wcstoimax) {
+  ASSERT_EQ(123, wcstoimax(L"123", NULL, 10));
+}
+
+TEST(inttypes, wcstoumax) {
+  ASSERT_EQ(123U, wcstoumax(L"123", NULL, 10));
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index bb395f0..fc0f0e1 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -203,6 +203,52 @@
   ASSERT_DOUBLE_EQ(1.23, strtold("1.23", NULL));
 }
 
+TEST(stdlib, quick_exit) {
+  pid_t pid = fork();
+  ASSERT_NE(-1, pid) << strerror(errno);
+
+  if (pid == 0) {
+    quick_exit(99);
+  }
+
+  int status;
+  ASSERT_EQ(pid, waitpid(pid, &status, 0));
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(99, WEXITSTATUS(status));
+}
+
+static int quick_exit_status = 0;
+
+static void quick_exit_1(void) {
+  ASSERT_EQ(quick_exit_status, 0);
+  quick_exit_status = 1;
+}
+
+static void quick_exit_2(void) {
+  ASSERT_EQ(quick_exit_status, 1);
+}
+
+static void not_run(void) {
+  FAIL();
+}
+
+TEST(stdlib, at_quick_exit) {
+  pid_t pid = fork();
+  ASSERT_NE(-1, pid) << strerror(errno);
+
+  if (pid == 0) {
+    ASSERT_EQ(at_quick_exit(quick_exit_2), 0);
+    ASSERT_EQ(at_quick_exit(quick_exit_1), 0);
+    atexit(not_run);
+    quick_exit(99);
+  }
+
+  int status;
+  ASSERT_EQ(pid, waitpid(pid, &status, 0));
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(99, WEXITSTATUS(status));
+}
+
 TEST(unistd, _Exit) {
   int pid = fork();
   ASSERT_NE(-1, pid) << strerror(errno);
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 be451c1..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) {
@@ -159,3 +160,109 @@
 TEST(wchar, limits) {
   ASSERT_LT(WCHAR_MIN, WCHAR_MAX);
 }
+
+TEST(wchar, wcsstr_wcswcs) {
+  const wchar_t* haystack = L"matches hello world, not the second hello world";
+  const wchar_t* empty_needle = L"";
+  const wchar_t* good_needle = L"ll";
+  const wchar_t* bad_needle = L"wort";
+
+  ASSERT_EQ(haystack, wcsstr(haystack, empty_needle));
+  ASSERT_EQ(&haystack[10], wcsstr(haystack, good_needle));
+  ASSERT_EQ(NULL, wcsstr(haystack, bad_needle));
+
+  ASSERT_EQ(haystack, wcswcs(haystack, empty_needle));
+  ASSERT_EQ(&haystack[10], wcswcs(haystack, good_needle));
+  ASSERT_EQ(NULL, wcswcs(haystack, bad_needle));
+}
+
+TEST(wchar, mbtowc) {
+  wchar_t out[8];
+
+  out[0] = 'x';
+  ASSERT_EQ(0, mbtowc(out, "hello", 0));
+  ASSERT_EQ('x', out[0]);
+
+  ASSERT_EQ(0, mbtowc(out, "hello", 0));
+  ASSERT_EQ(0, mbtowc(out, "", 0));
+  ASSERT_EQ(1, mbtowc(out, "hello", 1));
+  ASSERT_EQ(L'h', out[0]);
+
+  ASSERT_EQ(0, mbtowc(NULL, "hello", 0));
+  ASSERT_EQ(0, mbtowc(NULL, "", 0));
+  ASSERT_EQ(1, mbtowc(NULL, "hello", 1));
+
+  ASSERT_EQ(0, mbtowc(NULL, NULL, 0));
+}
+
+TEST(wchar, mbrtowc) {
+  wchar_t out[8];
+
+  out[0] = 'x';
+  ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
+  ASSERT_EQ('x', out[0]);
+
+  ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
+  ASSERT_EQ(0U, mbrtowc(out, "", 0, NULL));
+  ASSERT_EQ(1U, mbrtowc(out, "hello", 1, NULL));
+  ASSERT_EQ(L'h', out[0]);
+
+  ASSERT_EQ(0U, mbrtowc(NULL, "hello", 0, NULL));
+  ASSERT_EQ(0U, mbrtowc(NULL, "", 0, NULL));
+  ASSERT_EQ(1U, mbrtowc(NULL, "hello", 1, NULL));
+
+  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);
+}