Merge "Handle empty relro segment or incorrectly sized file."
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index 25e2ed9..cf3d692 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -54,4 +54,27 @@
 LOCAL_SRC_FILES := $(benchmark_src_files)
 include $(BUILD_EXECUTABLE)
 
+ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+ifeq ($(TARGET_ARCH),x86)
+LINKER = linker
+NATIVE_SUFFIX=32
+else
+LINKER = linker64
+NATIVE_SUFFIX=64
+endif
+
+bionic-benchmarks-run-on-host: bionic-benchmarks $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
+	if [ ! -d /system -o ! -d /system/bin ]; then \
+	  echo "Attempting to create /system/bin"; \
+	  sudo mkdir -p -m 0777 /system/bin; \
+	fi
+	mkdir -p $(TARGET_OUT_DATA)/local/tmp
+	cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin
+	cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
+	ANDROID_DATA=$(TARGET_OUT_DATA) \
+	ANDROID_ROOT=$(TARGET_OUT) \
+	LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
+		$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks$(NATIVE_SUFFIX) $(BIONIC_BENCHMARKS_FLAGS)
+endif # linux-x86
+
 endif # !BUILD_TINY_ANDROID
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 4311a1d..6d17ec7 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -15,6 +15,9 @@
  */
 
 #include "benchmark.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
@@ -32,10 +35,17 @@
     LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
         static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_";
 
-        char dir_template[] = "/data/local/tmp/prop-XXXXXX";
+        const char* android_data = getenv("ANDROID_DATA");
+        if (android_data == NULL) {
+          printf("ANDROID_DATA environment variable not set\n");
+          return;
+        }
+        char dir_template[PATH_MAX];
+        snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
         char *dirname = mkdtemp(dir_template);
         if (!dirname) {
-            perror("making temp file for test state failed (is /data/local/tmp writable?)");
+            printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
+                   android_data, strerror(errno));
             return;
         }
 
diff --git a/libc/Android.mk b/libc/Android.mk
index 864287a..4b81f7e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -129,6 +129,8 @@
     bionic/inotify_init.cpp \
     bionic/lchown.cpp \
     bionic/lfs64_support.cpp \
+    bionic/__libc_current_sigrtmax.cpp \
+    bionic/__libc_current_sigrtmin.cpp \
     bionic/libc_init_common.cpp \
     bionic/libc_logging.cpp \
     bionic/libgen.cpp \
@@ -212,6 +214,7 @@
     bionic/utimes.cpp \
     bionic/wait.cpp \
     bionic/wchar.cpp \
+    bionic/wctype.cpp \
 
 libc_upstream_freebsd_src_files := \
     upstream-freebsd/lib/libc/gen/ldexp.c \
@@ -220,11 +223,9 @@
     upstream-freebsd/lib/libc/stdio/fclose.c \
     upstream-freebsd/lib/libc/stdio/flags.c \
     upstream-freebsd/lib/libc/stdio/fopen.c \
-    upstream-freebsd/lib/libc/stdio/fwrite.c \
     upstream-freebsd/lib/libc/stdio/makebuf.c \
     upstream-freebsd/lib/libc/stdio/mktemp.c \
     upstream-freebsd/lib/libc/stdio/setvbuf.c \
-    upstream-freebsd/lib/libc/stdio/wsetup.c \
     upstream-freebsd/lib/libc/stdlib/abs.c \
     upstream-freebsd/lib/libc/stdlib/getopt_long.c \
     upstream-freebsd/lib/libc/stdlib/imaxabs.c \
@@ -232,6 +233,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 \
@@ -336,9 +338,24 @@
     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/locale/wctomb.c \
     upstream-openbsd/lib/libc/stdio/asprintf.c \
     upstream-openbsd/lib/libc/stdio/clrerr.c \
     upstream-openbsd/lib/libc/stdio/fdopen.c \
@@ -349,11 +366,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 +384,25 @@
     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/fwrite.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 +412,30 @@
     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/stdio/wsetup.c \
     upstream-openbsd/lib/libc/stdlib/atoi.c \
     upstream-openbsd/lib/libc/stdlib/atol.c \
     upstream-openbsd/lib/libc/stdlib/atoll.c \
@@ -513,6 +554,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-c-files-under,tzcode)
+# tzcode doesn't include wcsftime, so we use the OpenBSD one.
+LOCAL_SRC_FILES += upstream-openbsd/lib/libc/time/wcsftime.c
 
 LOCAL_CFLAGS := $(libc_common_cflags)
 # Don't use ridiculous amounts of stack.
@@ -528,7 +571,7 @@
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
-LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_C_INCLUDES := $(libc_common_c_includes) $(LOCAL_PATH)/tzcode/
 LOCAL_MODULE := libc_tzcode
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -630,6 +673,7 @@
     $(libc_common_cflags) \
     -I$(LOCAL_PATH)/upstream-openbsd/android/include \
     -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
+    -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
     -include openbsd-compat.h
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
diff --git a/libc/NOTICE b/libc/NOTICE
index 82733a2..4334275 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -8,6 +8,38 @@
 
 -------------------------------------------------------------------
 
+Based on the UCB version with the ID appearing below.
+This is ANSIish only when "multibyte character == plain character".
+
+Copyright (c) 1989, 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.
+
+-------------------------------------------------------------------
+
 Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 All rights reserved.
 
@@ -1201,35 +1233,6 @@
 -------------------------------------------------------------------
 
 Copyright (c) 1988, 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
    The Regents of the University of California.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -1804,6 +1807,38 @@
 
 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.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1990, 1993
+   The Regents of the University of California.  All rights reserved.
 (c) UNIX System Laboratories, Inc.
 All or some portions of this file are derived from material licensed
 to the University of California by American Telephone and Telegraph
@@ -2704,6 +2739,33 @@
 
 -------------------------------------------------------------------
 
+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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
 All rights reserved.
 
@@ -3378,6 +3440,32 @@
 
 -------------------------------------------------------------------
 
+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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
 
 Permission to use, copy, modify, and distribute this software for any
@@ -3398,6 +3486,84 @@
 
 -------------------------------------------------------------------
 
+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.
+
+-------------------------------------------------------------------
+
+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.
+
+-------------------------------------------------------------------
+
+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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
 
 Redistribution and use in source and binary forms, with or without
@@ -4057,6 +4223,32 @@
 
 -------------------------------------------------------------------
 
+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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 2011 Intel Corporation
 All rights reserved.
 
@@ -4421,6 +4613,32 @@
 
 -------------------------------------------------------------------
 
+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.
+
+-------------------------------------------------------------------
+
 Copyright (c)2001 Citrus Project,
 All rights reserved.
 
diff --git a/libc/arch-common/bionic/atexit.h b/libc/arch-common/bionic/atexit.h
index 16ae7aa..90aa030 100644
--- a/libc/arch-common/bionic/atexit.h
+++ b/libc/arch-common/bionic/atexit.h
@@ -26,11 +26,20 @@
  * SUCH DAMAGE.
  */
 
+#include <stddef.h>
+
 extern void* __dso_handle;
 
 extern int __cxa_atexit(void (*)(void*), void*, void*);
 
 __attribute__ ((visibility ("hidden")))
+void __atexit_handler_wrapper(void* func) {
+  if (func != NULL) {
+    (*(void (*)(void))func)();
+  }
+}
+
+__attribute__ ((visibility ("hidden")))
 int atexit(void (*func)(void)) {
-  return (__cxa_atexit((void (*)(void*)) func, (void*) 0, &__dso_handle));
+  return (__cxa_atexit(&__atexit_handler_wrapper, func, &__dso_handle));
 }
diff --git a/libc/bionic/__libc_current_sigrtmax.cpp b/libc/bionic/__libc_current_sigrtmax.cpp
new file mode 100644
index 0000000..27fcb35
--- /dev/null
+++ b/libc/bionic/__libc_current_sigrtmax.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 The Android Open Source 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
+ *    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.
+ *
+ * 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
+ * SUCH DAMAGE.
+ */
+
+#include <signal.h>
+
+int __libc_current_sigrtmax(void) {
+  return __SIGRTMAX;
+}
diff --git a/libc/bionic/__libc_current_sigrtmin.cpp b/libc/bionic/__libc_current_sigrtmin.cpp
new file mode 100644
index 0000000..16b037d
--- /dev/null
+++ b/libc/bionic/__libc_current_sigrtmin.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source 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
+ *    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.
+ *
+ * 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
+ * SUCH DAMAGE.
+ */
+
+#include <signal.h>
+
+// POSIX timers use __SIGRTMIN + 0.
+// libbacktrace uses __SIGRTMIN + 1.
+// libcore uses __SIGRTMIN + 2.
+
+int __libc_current_sigrtmin(void) {
+  return __SIGRTMIN + 3;
+}
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/locale.cpp b/libc/bionic/locale.cpp
index 5ab834d..3752fa4 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -75,8 +75,12 @@
   gLocale.int_n_sign_posn = CHAR_MAX;
 }
 
+static bool __bionic_current_locale_is_utf8 = false;
+
 static bool __is_supported_locale(const char* locale) {
-  return (strcmp(locale, "") == 0 || strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0);
+  return (strcmp(locale, "") == 0 ||
+          strcmp(locale, "C") == 0 || strcmp(locale, "C.UTF-8") == 0 ||
+          strcmp(locale, "POSIX") == 0);
 }
 
 static locale_t __new_locale() {
@@ -115,26 +119,24 @@
   return __new_locale();
 }
 
-char* setlocale(int category, char const* locale_name) {
+char* setlocale(int category, const char* locale_name) {
   // Is 'category' valid?
   if (category < LC_CTYPE || category > LC_IDENTIFICATION) {
     errno = EINVAL;
     return NULL;
   }
 
-  // Caller just wants to query the current locale?
-  if (locale_name == NULL) {
-    return const_cast<char*>("C");
+  // Caller wants to set the locale rather than just query?
+  if (locale_name != NULL) {
+    if (!__is_supported_locale(locale_name)) {
+      // We don't support this locale.
+      errno = ENOENT;
+      return NULL;
+    }
+    __bionic_current_locale_is_utf8 = (strstr(locale_name, "UTF-8") != NULL);
   }
 
-  // Caller wants one of the mandatory POSIX locales?
-  if (__is_supported_locale(locale_name)) {
-    return const_cast<char*>("C");
-  }
-
-  // We don't support any other locales.
-  errno = ENOENT;
-  return NULL;
+  return const_cast<char*>(__bionic_current_locale_is_utf8 ? "C.UTF-8" : "C");
 }
 
 locale_t uselocale(locale_t new_locale) {
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index 59933ec..312bf9e 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -52,7 +52,7 @@
 // end up with one of our POSIX timer threads handling it (meaning that the intended recipient
 // doesn't). glibc uses SIGRTMIN for its POSIX timer implementation, so in the absence of any
 // reason to use anything else, we use that too.
-static const int TIMER_SIGNAL = SIGRTMIN;
+static const int TIMER_SIGNAL = (__SIGRTMIN + 0);
 
 struct PosixTimer {
   __kernel_timer_t kernel_timer_id;
diff --git a/libc/bionic/sched_cpucount.c b/libc/bionic/sched_cpucount.c
index 9458dc8..2ea1d3f 100644
--- a/libc/bionic/sched_cpucount.c
+++ b/libc/bionic/sched_cpucount.c
@@ -28,13 +28,14 @@
 #define _GNU_SOURCE 1
 #include <sched.h>
 
-int __sched_cpucount(size_t setsize, cpu_set_t* set)
-{
-    int nn = 0, nn_max = setsize / sizeof(__CPU_BITTYPE);
-    int count = 0;
+int __sched_cpucount(size_t setsize, cpu_set_t* set) {
+  int nn = 0;
+  int nn_max = setsize / sizeof(__CPU_BITTYPE);
+  int count = 0;
 
-    for ( ; nn < nn_max; nn++ )
-        count += __builtin_popcount(set->__bits[nn]);
+  for ( ; nn < nn_max; nn++ ) {
+    count += __builtin_popcountl(set->__bits[nn]);
+  }
 
-    return count;
+  return count;
 }
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 674dc3a..b46ad49 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -1,315 +1,306 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
+/*	$OpenBSD: citrus_utf8.c,v 1.6 2012/12/05 23:19:59 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:
- *  * 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.
  */
 
-#include <ctype.h>
 #include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <wchar.h>
 
-/* stubs for wide-char functions */
+//
+// This file is basically OpenBSD's citrus_utf8.c but rewritten to not require a 12-byte mbstate_t
+// so we're backwards-compatible with our LP32 ABI where mbstate_t was only 4 bytes. An additional
+// advantage of this is that callers who don't supply their own mbstate_t won't be accessing shared
+// state.
+//
+// We also implement the POSIX interface directly rather than being accessed via function pointers.
+//
 
-wint_t btowc(int c) {
-  return (c == EOF) ? WEOF : c;
-}
+#define ERR_ILLEGAL_SEQUENCE static_cast<size_t>(-1)
+#define ERR_INCOMPLETE_SEQUENCE static_cast<size_t>(-2)
 
-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); }
-int iswcntrl(wint_t wc) { return iscntrl(wc); }
-int iswdigit(wint_t wc) { return isdigit(wc); }
-int iswgraph(wint_t wc) { return isgraph(wc); }
-int iswlower(wint_t wc) { return islower(wc); }
-int iswprint(wint_t wc) { return isprint(wc); }
-int iswpunct(wint_t wc) { return ispunct(wc); }
-int iswspace(wint_t wc) { return isspace(wc); }
-int iswupper(wint_t wc) { return isupper(wc); }
-int iswxdigit(wint_t wc) { return isxdigit(wc); }
-
-int iswctype(wint_t wc, wctype_t char_class) {
-  switch (char_class) {
-    case WC_TYPE_ALNUM: return isalnum(wc);
-    case WC_TYPE_ALPHA: return isalpha(wc);
-    case WC_TYPE_BLANK: return isblank(wc);
-    case WC_TYPE_CNTRL: return iscntrl(wc);
-    case WC_TYPE_DIGIT: return isdigit(wc);
-    case WC_TYPE_GRAPH: return isgraph(wc);
-    case WC_TYPE_LOWER: return islower(wc);
-    case WC_TYPE_PRINT: return isprint(wc);
-    case WC_TYPE_PUNCT: return ispunct(wc);
-    case WC_TYPE_SPACE: return isspace(wc);
-    case WC_TYPE_UPPER: return isupper(wc);
-    case WC_TYPE_XDIGIT: return isxdigit(wc);
-    default: return 0;
-  }
-}
-
-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*/) {
+int mbsinit(const mbstate_t*) {
+  // We have no state, so we're always in the initial state.
   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*/) {
+size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t*) {
   if (s == NULL) {
-    return 0;
+    s = "";
+    n = 1;
+    pwc = NULL;
   }
+
   if (n == 0) {
     return 0;
   }
-  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;
+  int ch;
+  if (((ch = static_cast<uint8_t>(*s)) & ~0x7f) == 0) {
+    // Fast path for plain ASCII characters.
+    if (pwc != NULL) {
+      *pwc = ch;
+    }
+    return (ch != '\0' ? 1 : 0);
   }
 
-  if (dst) {
-    memcpy(reinterpret_cast<char*>(dst), s, len );
-  }
+  // Determine the number of octets that make up this character
+  // from the first octet, and a mask that extracts the
+  // interesting bits of the first octet. We already know
+  // the character is at least two bytes long.
+  size_t length;
+  int mask;
 
-  *src = s + len;
-  return len;
-}
+  // We also specify a lower bound for the character code to
+  // detect redundant, non-"shortest form" encodings. For
+  // example, the sequence C0 80 is _not_ a legal representation
+  // of the null character. This enforces a 1-to-1 mapping
+  // between character codes and their multibyte representations.
+  wchar_t lower_bound;
 
-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));
-}
-
-wint_t towlower(wint_t wc) {
-  return tolower(wc);
-}
-
-wint_t towupper(wint_t wc) {
-  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;
-  }
-  if (wc <= 0xff) {
-    *s = static_cast<char>(wc);
+  ch = static_cast<uint8_t>(*s);
+  if ((ch & 0x80) == 0) {
+    mask = 0x7f;
+    length = 1;
+    lower_bound = 0;
+  } else if ((ch & 0xe0) == 0xc0) {
+    mask = 0x1f;
+    length = 2;
+    lower_bound = 0x80;
+  } else if ((ch & 0xf0) == 0xe0) {
+    mask = 0x0f;
+    length = 3;
+    lower_bound = 0x800;
+  } else if ((ch & 0xf8) == 0xf0) {
+    mask = 0x07;
+    length = 4;
+    lower_bound = 0x10000;
   } else {
-    *s = '?';
+    // Malformed input; input is not UTF-8. See RFC 3629.
+    errno = EILSEQ;
+    return ERR_ILLEGAL_SEQUENCE;
   }
-  return 1;
-}
 
-size_t wcrtomb(char* s, wchar_t wc, mbstate_t* /*ps*/) {
-  if (s == NULL) {
-    char buf[MB_LEN_MAX];
-    return wctomb(buf, L'\0');
-  }
-  return wctomb(s, wc);
-}
-
-size_t wcsftime(wchar_t* wcs, size_t maxsize, const wchar_t* format,  const struct tm* timptr) {
-  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 i = 0; // Number of input characters read.
-  size_t o = 0; // Number of output bytes written.
-  for (; (*src)[i] != 0; ++i) {
-    // TODO: UTF-8 support.
-    if ((*src)[i] > 0x7f) {
+  // Decode the octet sequence representing the character in chunks
+  // of 6 bits, most significant first.
+  wchar_t wch = static_cast<uint8_t>(*s++) & mask;
+  size_t i;
+  for (i = 1; i < MIN(length, n); i++) {
+    if ((*s & 0xc0) != 0x80) {
+      // Malformed input; bad characters in the middle of a character.
       errno = EILSEQ;
-      if (dst != NULL) {
-        *src = &(*src)[i];
+      return ERR_ILLEGAL_SEQUENCE;
+    }
+    wch <<= 6;
+    wch |= *s++ & 0x3f;
+  }
+  if (i < length) {
+    return ERR_INCOMPLETE_SEQUENCE;
+  }
+  if (wch < lower_bound) {
+    // Malformed input; redundant encoding.
+    errno = EILSEQ;
+    return ERR_ILLEGAL_SEQUENCE;
+  }
+  if ((wch >= 0xd800 && wch <= 0xdfff) || wch == 0xfffe || wch == 0xffff) {
+    // Malformed input; invalid code points.
+    errno = EILSEQ;
+    return ERR_ILLEGAL_SEQUENCE;
+  }
+  if (pwc != NULL) {
+    *pwc = wch;
+  }
+  return (wch == L'\0' ? 0 : length);
+}
+
+size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstate_t* ps) {
+  size_t i, o, r;
+
+  if (dst == NULL) {
+    for (i = o = 0; i < nmc; i += r, o++) {
+      if (static_cast<uint8_t>((*src)[i]) < 0x80) {
+        // Fast path for plain ASCII characters.
+        if ((*src)[i] == '\0') {
+          return o;
+        }
+        r = 1;
+      } else {
+        r = mbrtowc(NULL, *src + i, nmc - i, ps);
+        if (r == ERR_ILLEGAL_SEQUENCE) {
+          return r;
+        }
+        if (r == ERR_INCOMPLETE_SEQUENCE) {
+          return o;
+        }
+        if (r == 0) {
+          return o;
+        }
       }
-      return static_cast<size_t>(-1);
     }
-    if (dst != NULL) {
-      if (o + 1 > n) {
-        break;
+    return o;
+  }
+
+  for (i = o = 0; i < nmc && o < len; i += r, o++) {
+    if (static_cast<uint8_t>((*src)[i]) < 0x80) {
+      // Fast path for plain ASCII characters.
+      dst[o] = (*src)[i];
+      if ((*src)[i] == '\0') {
+        *src = NULL;
+        return o;
       }
-      dst[o++] = static_cast<char>((*src)[i]);
+      r = 1;
     } else {
-      ++o;
+      r = mbrtowc(dst + o, *src + i, nmc - i, ps);
+      if (r == ERR_ILLEGAL_SEQUENCE) {
+        *src += i;
+        return r;
+      }
+      if (r == ERR_INCOMPLETE_SEQUENCE) {
+        *src += nmc;
+        return o;
+      }
+      if (r == 0) {
+        *src = NULL;
+        return o;
+      }
     }
   }
-  // If we consumed all the input, terminate the output.
-  if (dst != NULL && o < n) {
-    dst[o] = 0;
-  }
-  // 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.
-    }
-  }
+  *src += i;
   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);
+size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps) {
+  return mbsnrtowcs(dst, src, SIZE_MAX, len, ps);
 }
 
-double wcstod(const wchar_t* nptr, wchar_t** endptr) {
-  return strtod(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr));
+size_t wcrtomb(char* s, wchar_t wc, mbstate_t*) {
+  if (s == NULL) {
+    // Reset to initial shift state (no-op).
+    return 1;
+  }
+
+  if ((wc & ~0x7f) == 0) {
+    // Fast path for plain ASCII characters.
+    *s = wc;
+    return 1;
+  }
+
+  // Determine the number of octets needed to represent this character.
+  // We always output the shortest sequence possible. Also specify the
+  // first few bits of the first octet, which contains the information
+  // about the sequence length.
+  uint8_t lead;
+  size_t length;
+  if ((wc & ~0x7f) == 0) {
+    lead = 0;
+    length = 1;
+  } else if ((wc & ~0x7ff) == 0) {
+    lead = 0xc0;
+    length = 2;
+  } else if ((wc & ~0xffff) == 0) {
+    lead = 0xe0;
+    length = 3;
+  } else if ((wc & ~0x1fffff) == 0) {
+    lead = 0xf0;
+    length = 4;
+  } else {
+    errno = EILSEQ;
+    return ERR_ILLEGAL_SEQUENCE;
+  }
+
+  // Output the octets representing the character in chunks
+  // of 6 bits, least significant last. The first octet is
+  // a special case because it contains the sequence length
+  // information.
+  for (size_t i = length - 1; i > 0; i--) {
+    s[i] = (wc & 0x3f) | 0x80;
+    wc >>= 6;
+  }
+  *s = (wc & 0xff) | lead;
+
+  return length;
 }
 
-long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base) {
-  return strtol(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr), base);
-}
+size_t wcsnrtombs(char* dst, const wchar_t** src, size_t nwc, size_t len, mbstate_t* ps) {
+  char buf[MB_LEN_MAX];
+  size_t i, o, r;
+  if (dst == NULL) {
+    for (i = o = 0; i < nwc; i++, o += r) {
+      wchar_t wc = (*src)[i];
+      if (static_cast<uint32_t>(wc) < 0x80) {
+        // Fast path for plain ASCII characters.
+        if (wc == 0) {
+          return o;
+        }
+        r = 1;
+      } else {
+        r = wcrtomb(buf, wc, ps);
+        if (r == ERR_ILLEGAL_SEQUENCE) {
+          return r;
+        }
+      }
+    }
+    return o;
+  }
 
-unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base) {
-  return strtoul(reinterpret_cast<const char*>(nptr), reinterpret_cast<char**>(endptr), base);
-}
-
-int wctob(wint_t c) {
-  return c;
-}
-
-wctype_t wctype(const char* property) {
-  static const char* const  properties[WC_TYPE_MAX] = {
-    "<invalid>",
-    "alnum", "alpha", "blank", "cntrl", "digit", "graph",
-    "lower", "print", "punct", "space", "upper", "xdigit"
-  };
-  for (size_t i = 0; i < WC_TYPE_MAX; ++i) {
-    if (!strcmp(properties[i], property)) {
-      return static_cast<wctype_t>(i);
+  for (i = o = 0; i < nwc && o < len; i++, o += r) {
+    wchar_t wc = (*src)[i];
+    if (static_cast<uint32_t>(wc) < 0x80) {
+      // Fast path for plain ASCII characters.
+      dst[o] = wc;
+      if (wc == 0) {
+        *src = NULL;
+        return o;
+      }
+      r = 1;
+    } else if (len - o >= sizeof(buf)) {
+      // Enough space to translate in-place.
+      r = wcrtomb(dst + o, wc, ps);
+      if (r == ERR_ILLEGAL_SEQUENCE) {
+        *src += i;
+        return r;
+      }
+    } else {
+      // May not be enough space; use temp buffer.
+      r = wcrtomb(buf, wc, ps);
+      if (r == ERR_ILLEGAL_SEQUENCE) {
+        *src += i;
+        return r;
+      }
+      if (r > len - o) {
+        break;
+      }
+      memcpy(dst + o, buf, r);
     }
   }
-  return static_cast<wctype_t>(0);
+  *src += i;
+  return o;
 }
 
-int wcwidth(wchar_t wc) {
-  return (wc > 0);
+size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
+  return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
 }
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
new file mode 100644
index 0000000..673402d
--- /dev/null
+++ b/libc/bionic/wctype.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 The Android Open Source 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
+ *    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.
+ *
+ * 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
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
+
+int iswalnum(wint_t wc) { return isalnum(wc); }
+int iswalpha(wint_t wc) { return isalpha(wc); }
+int iswblank(wint_t wc) { return isblank(wc); }
+int iswcntrl(wint_t wc) { return iscntrl(wc); }
+int iswdigit(wint_t wc) { return isdigit(wc); }
+int iswgraph(wint_t wc) { return isgraph(wc); }
+int iswlower(wint_t wc) { return islower(wc); }
+int iswprint(wint_t wc) { return isprint(wc); }
+int iswpunct(wint_t wc) { return ispunct(wc); }
+int iswspace(wint_t wc) { return isspace(wc); }
+int iswupper(wint_t wc) { return isupper(wc); }
+int iswxdigit(wint_t wc) { return isxdigit(wc); }
+
+int iswctype(wint_t wc, wctype_t char_class) {
+  switch (char_class) {
+    case WC_TYPE_ALNUM: return iswalnum(wc);
+    case WC_TYPE_ALPHA: return iswalpha(wc);
+    case WC_TYPE_BLANK: return iswblank(wc);
+    case WC_TYPE_CNTRL: return iswcntrl(wc);
+    case WC_TYPE_DIGIT: return iswdigit(wc);
+    case WC_TYPE_GRAPH: return iswgraph(wc);
+    case WC_TYPE_LOWER: return iswlower(wc);
+    case WC_TYPE_PRINT: return iswprint(wc);
+    case WC_TYPE_PUNCT: return iswpunct(wc);
+    case WC_TYPE_SPACE: return iswspace(wc);
+    case WC_TYPE_UPPER: return iswupper(wc);
+    case WC_TYPE_XDIGIT: return iswxdigit(wc);
+    default: return 0;
+  }
+}
+
+wint_t towlower(wint_t wc) { return tolower(wc); }
+wint_t towupper(wint_t wc) { return toupper(wc); }
+
+wctype_t wctype(const char* property) {
+  static const char* const  properties[WC_TYPE_MAX] = {
+    "<invalid>",
+    "alnum", "alpha", "blank", "cntrl", "digit", "graph",
+    "lower", "print", "punct", "space", "upper", "xdigit"
+  };
+  for (size_t i = 0; i < WC_TYPE_MAX; ++i) {
+    if (!strcmp(properties[i], property)) {
+      return static_cast<wctype_t>(i);
+    }
+  }
+  return static_cast<wctype_t>(0);
+}
+
+int wcwidth(wchar_t wc) {
+  return (wc > 0);
+}
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/limits.h b/libc/include/limits.h
index a70021a..dc45902 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -112,7 +112,7 @@
 
 #define SSIZE_MAX LONG_MAX
 
-#define MB_LEN_MAX 1 /* No multibyte characters. */
+#define MB_LEN_MAX 6
 
 /* New code should use sysconf(_SC_PAGE_SIZE) instead. */
 #ifndef PAGE_SIZE
diff --git a/libc/include/sched.h b/libc/include/sched.h
index 7649e83..68115bb 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -59,151 +59,90 @@
 extern int sched_getcpu(void);
 extern int setns(int, int);
 
-/* Our implementation supports up to 32 independent CPUs, which is also
- * the maximum supported by the kernel at the moment. GLibc uses 1024 by
- * default.
- *
- * If you want to use more than that, you should use CPU_ALLOC() / CPU_FREE()
- * and the CPU_XXX_S() macro variants.
- */
-#define CPU_SETSIZE   32
+#ifdef __LP32__
+#define CPU_SETSIZE 32
+#else
+#define CPU_SETSIZE 1024
+#endif
 
-#define __CPU_BITTYPE    unsigned long int  /* mandated by the kernel  */
-#define __CPU_BITSHIFT   5                  /* should be log2(BITTYPE) */
-#define __CPU_BITS       (1 << __CPU_BITSHIFT)
-#define __CPU_ELT(x)     ((x) >> __CPU_BITSHIFT)
-#define __CPU_MASK(x)    ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS-1)))
+#define __CPU_BITTYPE  unsigned long int  /* mandated by the kernel  */
+#define __CPU_BITS     (8 * sizeof(__CPU_BITTYPE))
+#define __CPU_ELT(x)   ((x) / __CPU_BITS)
+#define __CPU_MASK(x)  ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
 
 typedef struct {
-    __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
+  __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
 } cpu_set_t;
 
 extern int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set);
 
 extern int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set);
 
-/* Provide optimized implementation for 32-bit cpu_set_t */
-#if CPU_SETSIZE == __CPU_BITS
+#define CPU_ZERO(set)          CPU_ZERO_S(sizeof(cpu_set_t), set)
+#define CPU_SET(cpu, set)      CPU_SET_S(cpu, sizeof(cpu_set_t), set)
+#define CPU_CLR(cpu, set)      CPU_CLR_S(cpu, sizeof(cpu_set_t), set)
+#define CPU_ISSET(cpu, set)    CPU_ISSET_S(cpu, sizeof(cpu_set_t), set)
+#define CPU_COUNT(set)         CPU_COUNT_S(sizeof(cpu_set_t), set)
+#define CPU_EQUAL(set1, set2)  CPU_EQUAL_S(sizeof(cpu_set_t), set1, set2)
 
-#  define CPU_ZERO(set_)   \
-    do{ \
-        (set_)->__bits[0] = 0; \
-    }while(0)
+#define CPU_AND(dst, set1, set2)  __CPU_OP(dst, set1, set2, &)
+#define CPU_OR(dst, set1, set2)   __CPU_OP(dst, set1, set2, |)
+#define CPU_XOR(dst, set1, set2)  __CPU_OP(dst, set1, set2, ^)
 
-#  define CPU_SET(cpu_,set_) \
-    do {\
-        size_t __cpu = (cpu_); \
-        if (__cpu < CPU_SETSIZE) \
-            (set_)->__bits[0] |= __CPU_MASK(__cpu); \
-    }while (0)
-
-#  define CPU_CLR(cpu_,set_) \
-    do {\
-        size_t __cpu = (cpu_); \
-        if (__cpu < CPU_SETSIZE) \
-            (set_)->__bits[0] &= ~__CPU_MASK(__cpu); \
-    }while (0)
-
-#  define CPU_ISSET(cpu_, set_) \
-    (__extension__({\
-        size_t  __cpu = (cpu_); \
-        (cpu_ < CPU_SETSIZE) \
-            ? ((set_)->__bits[0] & __CPU_MASK(__cpu)) != 0 \
-            : 0; \
-    }))
-
-#  define CPU_EQUAL(set1_, set2_) \
-    ((set1_)->__bits[0] == (set2_)->__bits[0])
-
-#  define __CPU_OP(dst_, set1_, set2_, op_) \
-    do { \
-        (dst_)->__bits[0] = (set1_)->__bits[0] op_ (set2_)->__bits[0]; \
-    } while (0)
-
-#  define CPU_COUNT(set_)  __builtin_popcountl((set_)->__bits[0])
-
-#else /* CPU_SETSIZE != __CPU_BITS */
-
-#  define CPU_ZERO(set_)          CPU_ZERO_S(sizeof(cpu_set_t), set_)
-#  define CPU_SET(cpu_,set_)      CPU_SET_S(cpu_,sizeof(cpu_set_t),set_)
-#  define CPU_CLR(cpu_,set_)      CPU_CLR_S(cpu_,sizeof(cpu_set_t),set_)
-#  define CPU_ISSET(cpu_,set_)    CPU_ISSET_S(cpu_,sizeof(cpu_set_t),set_)
-#  define CPU_COUNT(set_)         CPU_COUNT_S(sizeof(cpu_set_t),set_)
-#  define CPU_EQUAL(set1_,set2_)  CPU_EQUAL_S(sizeof(cpu_set_t),set1_,set2_)
-
-#  define __CPU_OP(dst_,set1_,set2_,op_)  __CPU_OP_S(sizeof(cpu_set_t),dst_,set1_,set2_,op_)
-
-#endif /* CPU_SETSIZE != __CPU_BITS */
-
-#define CPU_AND(set1_,set2_)   __CPU_OP(set1_,set2_,&)
-#define CPU_OR(set1_,set2_)    __CPU_OP(set1_,set2_,|)
-#define CPU_XOR(set1_,set2_)   __CPU_OP(set1_,set2_,^)
+#define __CPU_OP(dst, set1, set2, op)  __CPU_OP_S(sizeof(cpu_set_t), dst, set1, set2, op)
 
 /* Support for dynamically-allocated cpu_set_t */
 
 #define CPU_ALLOC_SIZE(count) \
-    __CPU_ELT((count) + (__CPU_BITS-1))*sizeof(__CPU_BITTYPE)
+  __CPU_ELT((count) + (__CPU_BITS - 1)) * sizeof(__CPU_BITTYPE)
 
-#define CPU_ALLOC(count)   __sched_cpualloc((count));
-#define CPU_FREE(set)      __sched_cpufree((set))
+#define CPU_ALLOC(count)  __sched_cpualloc((count))
+#define CPU_FREE(set)     __sched_cpufree((set))
 
 extern cpu_set_t* __sched_cpualloc(size_t count);
 extern void       __sched_cpufree(cpu_set_t* set);
 
-#define CPU_ZERO_S(setsize_,set_)  \
-    do { \
-        size_t __nn = 0; \
-        size_t __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
-        for (; __nn < __nn_max; __nn++) \
-            (set_)->__bits[__nn] = 0; \
-    } while (0)
+#define CPU_ZERO_S(setsize, set)  __builtin_memset(set, 0, setsize)
 
-#define CPU_SET_S(cpu_,setsize_,set_) \
-    do { \
-        size_t __cpu = (cpu_); \
-        if (__cpu < 8*(setsize_)) \
-            (set_)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
-    } while (0)
+#define CPU_SET_S(cpu, setsize, set) \
+  do { \
+    size_t __cpu = (cpu); \
+    if (__cpu < 8 * (setsize)) \
+      (set)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
+  } while (0)
 
-#define CPU_CLR_S(cpu_,setsize_,set_) \
-    do { \
-        size_t __cpu = (cpu_); \
-        if (__cpu < 8*(setsize_)) \
-            (set_)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
-    } while (0)
+#define CPU_CLR_S(cpu, setsize, set) \
+  do { \
+    size_t __cpu = (cpu); \
+    if (__cpu < 8 * (setsize)) \
+      (set)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
+  } while (0)
 
-#define CPU_ISSET_S(cpu_, setsize_, set_) \
-    (__extension__ ({ \
-        size_t __cpu = (cpu_); \
-        (__cpu < 8*(setsize_)) \
-          ? ((set_)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
-          : 0; \
-    }))
+#define CPU_ISSET_S(cpu, setsize, set) \
+  (__extension__ ({ \
+    size_t __cpu = (cpu); \
+    (__cpu < 8 * (setsize)) \
+      ? ((set)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
+      : 0; \
+  }))
 
-#define CPU_EQUAL_S(setsize_, set1_, set2_) \
-    (__extension__ ({ \
-        __const __CPU_BITTYPE* __src1 = (set1_)->__bits; \
-        __const __CPU_BITTYPE* __src2 = (set2_)->__bits; \
-        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
-        for (; __nn < __nn_max; __nn++) { \
-            if (__src1[__nn] != __src2[__nn]) \
-                break; \
-        } \
-        __nn == __nn_max; \
-    }))
+#define CPU_EQUAL_S(setsize, set1, set2)  (__builtin_memcmp(set1, set2, setsize) == 0)
 
-#define __CPU_OP_S(setsize_, dstset_, srcset1_, srcset2_, op) \
-    do { \
-        cpu_set_t* __dst = (dstset); \
-        const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
-        const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
-        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
-        for (; __nn < __nn_max; __nn++) \
-            (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
-    } while (0)
+#define CPU_AND_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, &)
+#define CPU_OR_S(setsize, dst, set1, set2)   __CPU_OP_S(setsize, dst, set1, set2, |)
+#define CPU_XOR_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, ^)
 
-#define CPU_COUNT_S(setsize_, set_) \
-    __sched_cpucount((setsize_), (set_))
+#define __CPU_OP_S(setsize, dstset, srcset1, srcset2, op) \
+  do { \
+    cpu_set_t* __dst = (dstset); \
+    const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
+    const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
+    size_t __nn = 0, __nn_max = (setsize)/sizeof(__CPU_BITTYPE); \
+    for (; __nn < __nn_max; __nn++) \
+      (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
+  } while (0)
+
+#define CPU_COUNT_S(setsize, set)  __sched_cpucount((setsize), (set))
 
 extern int __sched_cpucount(size_t setsize, cpu_set_t* set);
 
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 267f3e6..45c1cda 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -60,6 +60,12 @@
 #define _NSIG (_KERNEL__NSIG + 1)
 #define NSIG _NSIG
 
+/* We take a few real-time signals for ourselves. May as well use the same names as glibc. */
+#define SIGRTMIN (__libc_current_sigrtmin())
+#define SIGRTMAX (__libc_current_sigrtmax())
+extern int __libc_current_sigrtmin(void);
+extern int __libc_current_sigrtmax(void);
+
 extern const char* const sys_siglist[];
 extern const char* const sys_signame[]; /* BSD compatibility. */
 
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/sys/epoll.h b/libc/include/sys/epoll.h
index c06a081..4a5a37c 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -67,7 +67,11 @@
 struct epoll_event {
   uint32_t events;
   epoll_data_t data;
-};
+}
+#ifdef __x86_64__
+__packed
+#endif
+;
 
 int epoll_create(int);
 int epoll_create1(int);
diff --git a/libc/include/time64.h b/libc/include/time64.h
index b4f1280..905669d 100644
--- a/libc/include/time64.h
+++ b/libc/include/time64.h
@@ -33,12 +33,7 @@
 
 #if defined(__LP64__)
 
-/* TODO: remove this when external/chromium_org is fixed. */
-#define time64_t time_t
-#define gmtime64_r gmtime_r
-#define localtime64_r localtime_r
-#define mktime64 mktime
-#define timegm64 timegm
+#error Your time_t is already 64-bit.
 
 #else
 
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 0029a65..fe2fe07 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -39,8 +39,15 @@
 
 __BEGIN_DECLS
 
-typedef __WINT_TYPE__           wint_t;
-typedef struct { int  dummy; }  mbstate_t;
+typedef __WINT_TYPE__  wint_t;
+typedef struct {
+#ifdef __LP32__
+  int dummy;
+#else
+  // 8 bytes should be enough to support at least UTF-8
+  char __reserved[8];
+#endif
+} mbstate_t;
 
 typedef enum {
     WC_TYPE_INVALID = 0,
@@ -87,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);
@@ -96,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 *);
@@ -113,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/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index e825ae0..238087b 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -7,7 +7,7 @@
 
 noUpdate = 1
 
-def  cleanupFile( path, original_path):
+def cleanupFile(path, original_path):
     """reads an original header and perform the cleanup operation on it
        this functions returns the destination path and the clean header
        as a single string"""
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 2c40d7c..2be9532 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -685,9 +685,9 @@
         # we have the defined keyword, check the rest
         self.i += 1
         self.skip_spaces()
-        use_parens = 0
+        used_parens = 0
         if self.i < self.n and self.tok[self.i].id == tokLPAREN:
-            use_parens = 1
+            used_parens = 1
             self.i += 1
             self.skip_spaces()
 
@@ -699,7 +699,7 @@
             self.throw(CppConstantExpected,i,"### 'defined' must be followed by macro name")
 
         self.i += 1
-        if use_parens:
+        if used_parens:
             self.expectId(tokRPAREN)
 
         return ("defined", t.value)
@@ -1162,7 +1162,7 @@
         return self.directive in ["if","ifdef","ifndef","elif"]
 
     def isInclude(self):
-        """checks wether this is a #include directive. if true, then returns the
+        """checks whether this is a #include directive. if true, then returns the
            corresponding file name (with brackets or double-qoutes). None otherwise"""
         if self.directive != "include":
             return None
@@ -1517,15 +1517,20 @@
         tokens = tokens[:-1]  # remove trailing tokLN
         self.blocks = [ Block(tokens) ] + self.blocks
 
-    def replaceTokens(self,replacements=dict()):
-        """replace tokens according to the given dict
-           """
+    def replaceTokens(self,replacements):
+        """replace tokens according to the given dict"""
         for b in self.blocks:
-            if (not b.isDirective()) or b.isDefine():
+            made_change = False
+            if b.isInclude() == None:
                 for tok in b.tokens:
                     if tok.id == tokIDENT:
                         if tok.value in replacements:
                             tok.value = replacements[tok.value]
+                            made_change = True
+
+            if made_change and b.isIf():
+                # Keep 'expr' in sync with 'tokens'.
+                b.expr = CppExpr(b.tokens)
 
 class BlockParser:
     """a class used to convert an input source file into a BlockList object"""
@@ -1798,6 +1803,10 @@
 #define X
 #endif
 
+#ifndef SIGRTMAX
+#define SIGRTMAX 123
+#endif /* SIGRTMAX */
+
 #if 0
 #if 1
 #define  BAD_6
@@ -1817,12 +1826,17 @@
 #define X
 #endif
 
+#ifndef __SIGRTMAX
+#define __SIGRTMAX 123
+#endif
+
 """
 
     out = StringOutput()
     lines = string.split(text, '\n')
     list = BlockParser().parse( CppLinesTokenizer(lines) )
     #D_setlevel(2)
+    list.replaceTokens( kernel_token_replacements )
     list.optimizeAll( {"__KERNEL__":kCppUndefinedMacro} )
     list.write(out)
     if out.get() != expected:
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index b4d823e..8c41cc6 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -63,6 +63,9 @@
     # The kernel's _NSIG/NSIG are one less than the userspace value, so we need to move them aside.
     "_NSIG": "_KERNEL__NSIG",
     "NSIG": "_KERNEL_NSIG",
+    # The kernel's SIGRTMIN/SIGRTMAX are absolute limits; userspace steals a few.
+    "SIGRTMIN": "__SIGRTMIN",
+    "SIGRTMAX": "__SIGRTMAX",
     }
 
 # this is the set of known static inline functions that we want to keep
diff --git a/libc/kernel/uapi/asm-arm/asm/signal.h b/libc/kernel/uapi/asm-arm/asm/signal.h
index 512e22a..fd39aaa 100644
--- a/libc/kernel/uapi/asm-arm/asm/signal.h
+++ b/libc/kernel/uapi/asm-arm/asm/signal.h
@@ -66,8 +66,8 @@
 #define SIGSYS 31
 #define SIGUNUSED 31
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SIGRTMIN 32
-#define SIGRTMAX _KERNEL__NSIG
+#define __SIGRTMIN 32
+#define __SIGRTMAX _KERNEL__NSIG
 #define SIGSWI 32
 #define SA_NOCLDSTOP 0x00000001
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-generic/signal.h b/libc/kernel/uapi/asm-generic/signal.h
index fe7d9a0..e103240 100644
--- a/libc/kernel/uapi/asm-generic/signal.h
+++ b/libc/kernel/uapi/asm-generic/signal.h
@@ -66,9 +66,9 @@
 #define SIGSYS 31
 #define SIGUNUSED 31
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SIGRTMIN 32
-#ifndef SIGRTMAX
-#define SIGRTMAX _KERNEL__NSIG
+#define __SIGRTMIN 32
+#ifndef __SIGRTMAX
+#define __SIGRTMAX _KERNEL__NSIG
 #endif
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define SA_NOCLDSTOP 0x00000001
diff --git a/libc/kernel/uapi/asm-mips/asm/signal.h b/libc/kernel/uapi/asm-mips/asm/signal.h
index 53f5015..b774a66 100644
--- a/libc/kernel/uapi/asm-mips/asm/signal.h
+++ b/libc/kernel/uapi/asm-mips/asm/signal.h
@@ -71,8 +71,8 @@
 #define SIGXCPU 30
 #define SIGXFSZ 31
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SIGRTMIN 32
-#define SIGRTMAX _KERNEL__NSIG
+#define __SIGRTMIN 32
+#define __SIGRTMAX _KERNEL__NSIG
 #define SA_ONSTACK 0x08000000
 #define SA_RESETHAND 0x80000000
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-x86/asm/signal.h b/libc/kernel/uapi/asm-x86/asm/signal.h
index 6f5b435..308c7a9 100644
--- a/libc/kernel/uapi/asm-x86/asm/signal.h
+++ b/libc/kernel/uapi/asm-x86/asm/signal.h
@@ -71,8 +71,8 @@
 #define SIGSYS 31
 #define SIGUNUSED 31
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define SIGRTMIN 32
-#define SIGRTMAX _KERNEL__NSIG
+#define __SIGRTMIN 32
+#define __SIGRTMAX _KERNEL__NSIG
 #define SA_NOCLDSTOP 0x00000001u
 #define SA_NOCLDWAIT 0x00000002u
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
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..907fd21 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().
@@ -97,6 +102,7 @@
 #define FLOATING_POINT
 #define PRINTF_WIDE_CHAR
 #define SCANF_WIDE_CHAR
+#define NO_PRINTF_PERCENT_N
 
 /* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
 __BEGIN_DECLS
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/stdlib/atexit.c b/libc/stdlib/atexit.c
index 4e14434..b051e22 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -41,11 +41,52 @@
 struct atexit *__atexit;
 
 /*
+ * TODO: Read this before upstreaming:
+ *
+ * As of Apr 2014 there is a bug regaring function type detection logic in
+ * Free/Open/NetBSD implementations of __cxa_finalize().
+ *
+ * What it is about:
+ * First of all there are two kind of atexit handlers:
+ *  1) void handler(void) - this is the regular type
+ *     available for to user via atexit(.) function call.
+ *
+ *  2) void internal_handler(void*) - this is the type
+ *     __cxa_atexit() function expects. This handler is used
+ *     by C++ compiler to register static destructor calls.
+ *     Note that calling this function as the handler of type (1)
+ *     results in incorrect this pointer in static d-tors.
+ *
+ * What is wrong with BSD implementations:
+ *
+ *  They use dso argument to identify the handler type. The problem
+ *  with it is dso is also used to identify the handlers associated
+ *  with particular dynamic library and allow __cxa_finalize to call correct
+ *  set of functions on dlclose(). And it cannot identify both.
+ *
+ * What is correct way to identify function type?
+ *
+ *  Consider this:
+ *  1. __cxa_finalize and __cxa_atexit are part of libc and do not have access to hidden
+ *     &__dso_handle.
+ *  2. __cxa_atexit has only 3 arguments: function pointer, function argument, dso.
+ *     none of them can be reliably used to pass information about handler type.
+ *  3. following http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (3.3.5.3 - B)
+ *     translation of user atexit -> __cxa_atexit(f, NULL, NULL) results in crashes
+ *     on exit() after dlclose() of a library with an atexit() call.
+ *
+ *  One way to resolve this is to always call second form of handler, which will
+ *  result in storing unused argument in register/stack depending on architecture
+ *  and should not present any problems.
+ *
+ *  Another way is to make them dso-local in one way or the other.
+ */
+
+/*
  * Function pointers are stored in a linked list of pages. The list
  * is initially empty, and pages are allocated on demand. The first
  * function pointer in the first allocated page (the last one in
  * the linked list) was reserved for the cleanup function.
- * TODO: switch to the regular FreeBSD/NetBSD atexit implementation.
  *
  * Outside the following functions, all pages are mprotect()'ed
  * to prevent unintentional/malicious corruption.
@@ -94,7 +135,7 @@
 			__atexit_invalid = 0;
 	}
 	fnp = &p->fns[p->ind++];
-	fnp->fn_ptr.cxa_func = func;
+	fnp->cxa_func = func;
 	fnp->fn_arg = arg;
 	fnp->fn_dso = dso;
 	if (mprotect(p, pgsize, PROT_READ))
@@ -113,57 +154,59 @@
 void
 __cxa_finalize(void *dso)
 {
-	struct atexit *p, *q;
+	struct atexit *p, *q, *original_atexit;
 	struct atexit_fn fn;
-	int n, pgsize = getpagesize();
+	int n, pgsize = getpagesize(), original_ind;
 	static int call_depth;
 
 	if (__atexit_invalid)
 		return;
-
 	_ATEXIT_LOCK();
 	call_depth++;
 
-	for (p = __atexit; p != NULL; p = p->next) {
-		for (n = p->ind; --n >= 0;) {
-			if (p->fns[n].fn_ptr.cxa_func == NULL)
-				continue;	/* already called */
-			if (dso != NULL && dso != p->fns[n].fn_dso)
-				continue;	/* wrong DSO */
-
+	p = original_atexit = __atexit;
+	n = original_ind = p != NULL ? p->ind : 0;
+	while (p != NULL) {
+		if (p->fns[n].cxa_func != NULL /* not called */
+				&& (dso == NULL || dso == p->fns[n].fn_dso)) { /* correct DSO */
 			/*
 			 * Mark handler as having been already called to avoid
 			 * dupes and loops, then call the appropriate function.
 			 */
 			fn = p->fns[n];
 			if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
-				p->fns[n].fn_ptr.cxa_func = NULL;
+				p->fns[n].cxa_func = NULL;
 				mprotect(p, pgsize, PROT_READ);
 			}
+
 			_ATEXIT_UNLOCK();
-#if ANDROID
-                        /* it looks like we should always call the function
-                         * with an argument, even if dso is not NULL. Otherwise
-                         * static destructors will not be called properly on
-                         * the ARM.
-                         */
-                        (*fn.fn_ptr.cxa_func)(fn.fn_arg);
-#else /* !ANDROID */
-			if (dso != NULL)
-				(*fn.fn_ptr.cxa_func)(fn.fn_arg);
-			else
-				(*fn.fn_ptr.std_func)();
-#endif /* !ANDROID */
+			(*fn.cxa_func)(fn.fn_arg);
 			_ATEXIT_LOCK();
+			// check for new atexit handlers
+			if ((__atexit->ind != original_ind) || (__atexit != original_atexit)) {
+				// need to restart now to preserve correct
+				// call order - LIFO
+				p = original_atexit = __atexit;
+				n = original_ind = p->ind;
+				continue;
+			}
+		}
+		if (n == 0) {
+			p = p->next;
+			n = p != NULL ? p->ind : 0;
+		} else {
+			--n;
 		}
 	}
 
+	--call_depth;
+
 	/*
 	 * If called via exit(), unmap the pages since we have now run
 	 * all the handlers.  We defer this until calldepth == 0 so that
 	 * we don't unmap things prematurely if called recursively.
 	 */
-	if (dso == NULL && --call_depth == 0) {
+	if (dso == NULL && call_depth == 0) {
 		for (p = __atexit; p != NULL; ) {
 			q = p;
 			p = p->next;
diff --git a/libc/stdlib/atexit.h b/libc/stdlib/atexit.h
index 4b3e5ab..2e88ad6 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/stdlib/atexit.h
@@ -37,10 +37,7 @@
 	int ind;			/* next index in this table */
 	int max;			/* max entries >= ATEXIT_SIZE */
 	struct atexit_fn {
-		union {
-			void (*std_func)(void);
-			void (*cxa_func)(void *);
-		} fn_ptr;
+		void (*cxa_func)(void *);
 		void *fn_arg;		/* argument for CXA callback */
 		void *fn_dso;		/* shared module handle */
 	} fns[1];			/* the table itself */
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate-NOTICE.py
index 3fad656..6d4c761 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate-NOTICE.py
@@ -55,10 +55,13 @@
             break
         if "\tcitrus Id: " in lines[i]:
             break
-        if "\t$OpenBSD: " in lines[i] or " $FreeBSD: " in lines[i] or "\t$NetBSD: " in lines[i]:
+        if "\t$Citrus: " in lines[i] or "\t$OpenBSD: " in lines[i] or " $FreeBSD: " in lines[i] or "\t$NetBSD: " in lines[i]:
             break
         if "$FreeBSD$" in lines[i] or "$Citrus$" in lines[i]:
             break
+        # OpenBSD likes to say where stuff originally came from:
+        if "Original version ID:" in lines[i]:
+            break
         i += 1
 
     end = i
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 1164a13..2a1db64 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -37,7 +37,12 @@
 #include "fcntl.h"
 #include "locale.h"
 #include <ctype.h>
+#if defined(__LP64__)
+#define time64_t time_t
+#define mktime64 mktime
+#else
 #include <time64.h>
+#endif
 #include "private/bionic_time.h"  /* for strftime_tz */
 
 /* struct lc_time_T is now defined as strftime_locale
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/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index c3d1a3c..2c860f7 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fnmatch.c,v 1.16 2011/12/06 11:47:46 stsp Exp $	*/
+/*	$OpenBSD: fnmatch.c,v 1.17 2013/11/24 23:51:29 deraadt Exp $	*/
 
 /* Copyright (c) 2011, VMware, Inc.
  * All rights reserved.
@@ -214,10 +214,13 @@
                 /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
                 if ((**string >= *startch) && (**string <= **pattern))
                     result = 0;
-                else if (nocase && (isupper(**string) || isupper(*startch)
-                                                      || isupper(**pattern))
-                            && (tolower(**string) >= tolower(*startch)) 
-                            && (tolower(**string) <= tolower(**pattern)))
+                else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)*startch) ||
+                            isupper((unsigned char)**pattern))
+                            && (tolower((unsigned char)**string) >=
+			        tolower((unsigned char)*startch)) 
+                            && (tolower((unsigned char)**string) <=
+				tolower((unsigned char)**pattern)))
                     result = 0;
 
                 ++*pattern;
@@ -227,8 +230,10 @@
             /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
             if ((**string == **pattern))
                 result = 0;
-            else if (nocase && (isupper(**string) || isupper(**pattern))
-                            && (tolower(**string) == tolower(**pattern)))
+            else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)**pattern))
+                            && (tolower((unsigned char)**string) ==
+				tolower((unsigned char)**pattern)))
                 result = 0;
 
             ++*pattern;
@@ -254,8 +259,10 @@
     /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
     if (**string == **pattern)
         result = 0;
-    else if (nocase && (isupper(**string) || isupper(**pattern))
-                    && (tolower(**string) == tolower(**pattern)))
+    else if (nocase && (isupper((unsigned char)**string) ||
+		    isupper((unsigned char)**pattern))
+                    && (tolower((unsigned char)**string) ==
+			tolower((unsigned char)**pattern)))
         result = 0;
 
     /* Refuse to advance over trailing slash or nulls
diff --git a/libc/upstream-openbsd/lib/libc/gen/getprogname.c b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
index 1cf498c..17046ab 100644
--- a/libc/upstream-openbsd/lib/libc/gen/getprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getprogname.c,v 1.2 2013/05/31 21:19:01 tedu Exp $ */
+/* $OpenBSD: getprogname.c,v 1.3 2013/11/12 06:09:48 deraadt Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -15,6 +15,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <stdlib.h>
+
 extern const char *__progname;
 
 const char *
diff --git a/libc/upstream-openbsd/lib/libc/gen/setprogname.c b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
index 18b2ce0..089a15a 100644
--- a/libc/upstream-openbsd/lib/libc/gen/setprogname.c
+++ b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setprogname.c,v 1.3 2013/06/01 01:43:43 tedu Exp $ */
+/* $OpenBSD: setprogname.c,v 1.4 2013/11/12 06:09:48 deraadt Exp $ */
 /*
  * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
  *
@@ -16,6 +16,7 @@
  */
 
 #include <string.h>
+#include <stdlib.h>
 
 extern const char *__progname;
 
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstod.h b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h
new file mode 100644
index 0000000..ae993ad
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h
@@ -0,0 +1,153 @@
+/*	$OpenBSD: _wcstod.h,v 1.2 2013/06/02 15:22:20 matthew Exp $	*/
+/* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */
+
+/*-
+ * Copyright (c)1999, 2000, 2001 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $
+ */
+
+/*
+ * function template for wcstof, wcstod and wcstold.
+ *
+ * parameters:
+ *	FUNCNAME : function name
+ *      float_type : return type
+ *      STRTOD_FUNC : conversion function
+ */
+
+float_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr)
+{
+	const wchar_t *src;
+	size_t size;
+	const wchar_t *start;
+	const wchar_t *aftersign;
+
+	/*
+	 * check length of string and call strtod
+	 */
+	src = nptr;
+
+	/* skip space first */
+	while (iswspace(*src)) {
+		src++;
+	}
+
+	/* get length of string */
+	start = src;
+	if (*src && wcschr(L"+-", *src))
+		src++;
+	aftersign = src;
+	if (wcsncasecmp(src, L"inf", 3) == 0) {
+		src += 3;
+		if (wcsncasecmp(src, L"inity", 5) == 0)
+			src += 5;
+		goto match;
+	}
+	if (wcsncasecmp(src, L"nan", 3) == 0) {
+		src += 3;
+		if (*src == L'(') {
+			size = 1;
+			while (src[size] != L'\0' && src[size] != L')')
+				size++;
+			if (src[size] == L')')
+				src += size + 1;
+		}
+		goto match;
+	}
+	size = wcsspn(src, L"0123456789");
+	src += size;
+	if (*src == L'.') {/* XXX use localeconv */
+		src++;
+		size = wcsspn(src, L"0123456789");
+		src += size;
+	}
+	if (*src && wcschr(L"Ee", *src)) {
+		src++;
+		if (*src && wcschr(L"+-", *src))
+			src++;
+		size = wcsspn(src, L"0123456789");
+		src += size;
+	}
+match:
+	size = src - start;
+
+	/*
+	 * convert to a char-string and pass it to strtod.
+	 */
+	if (src > aftersign) {
+		mbstate_t st;
+		char *buf;
+		char *end;
+		const wchar_t *s;
+		size_t size_converted;
+		float_type result;
+		size_t bufsize;
+
+		s = start;
+		memset(&st, 0, sizeof(st));
+		bufsize = wcsnrtombs(NULL, &s, size, 0, &st);
+
+		buf = malloc(bufsize + 1);
+		if (!buf) {
+			errno = ENOMEM; /* XXX */
+			goto fail;
+		}
+
+		s = start;
+		memset(&st, 0, sizeof(st));
+		size_converted = wcsnrtombs(buf, &s, size, bufsize, &st);
+		if (size_converted != bufsize) {
+			/* XXX should not happen */
+			free(buf);
+			errno = EILSEQ;
+			goto fail;
+		}
+
+		buf[bufsize] = 0;
+		result = STRTOD_FUNC(buf, &end);
+
+		if (endptr) {
+			const char *s = buf;
+			memset(&st, 0, sizeof(st));
+			size = mbsnrtowcs(NULL, &s, end - buf, 0, &st);
+
+			/* LINTED bad interface */
+			*endptr = (wchar_t*)start + size;
+		}
+
+		free(buf);
+
+		return result;
+	}
+
+fail:
+	if (endptr)
+		/* LINTED bad interface */
+		*endptr = (wchar_t*)nptr;
+
+	return 0;
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
new file mode 100644
index 0000000..7b49bbf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h
@@ -0,0 +1,136 @@
+/*	$OpenBSD: _wcstol.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Original version ID:
+ * @(#)strtol.c	8.1 (Berkeley) 6/4/93
+ * NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp
+ * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp
+ */
+
+/*
+ * function template for wcstol, wcstoll and wcstoimax.
+ *
+ * parameters:
+ *	FUNCNAME : function name
+ *      int_type : return type
+ *      MIN_VALUE : lower limit of the return type
+ *      MAX_VALUE : upper limit of the return type
+ */
+
+int_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
+{
+	const wchar_t *s;
+	int_type acc, cutoff;
+	wint_t wc;
+	int i;
+	int neg, any, cutlim;
+
+	/* check base value */
+	if (base && (base < 2 || base > 36)) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		wc = (wchar_t) *s++;
+	} while (iswspace(wc));
+	if (wc == L'-') {
+		neg = 1;
+		wc = *s++;
+	} else {
+		neg = 0;
+		if (wc == L'+')
+			wc = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    wc == L'0' && (*s == L'x' || *s == L'X')) {
+		wc = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = wc == L'0' ? 8 : 10;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	cutoff = neg ? MIN_VALUE : MAX_VALUE;
+	cutlim = (int)(cutoff % base);
+	cutoff /= base;
+	if (neg) {
+		if (cutlim > 0) {
+			cutlim -= base;
+			cutoff += 1;
+		}
+		cutlim = -cutlim;
+	}
+	for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
+		i = wctoint(wc);
+		if (i == -1)
+			break;
+		if (i >= base)
+			break;
+		if (any < 0)
+			continue;
+		if (neg) {
+			if (acc < cutoff || (acc == cutoff && i > cutlim)) {
+				any = -1;
+				acc = MIN_VALUE;
+				errno = ERANGE;
+			} else {
+				any = 1;
+				acc *= base;
+				acc -= i;
+			}
+		} else {
+			if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+				any = -1;
+				acc = MAX_VALUE;
+				errno = ERANGE;
+			} else {
+				any = 1;
+				acc *= base;
+				acc += i;
+			}
+		}
+	}
+	if (endptr != 0)
+		/* LINTED interface specification */
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
new file mode 100644
index 0000000..736b38f
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h
@@ -0,0 +1,116 @@
+/*	$OpenBSD: _wcstoul.h,v 1.1 2005/07/01 08:59:27 espie Exp $	*/
+/* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Original version ID:
+ * @(#)strtoul.c	8.1 (Berkeley) 6/4/93
+ * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp
+ * NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp
+ */
+
+/*
+ * function template for wcstoul, wcstoull and wcstoumax.
+ *
+ * parameters:
+ *	FUNCNAME  : function name
+ *      uint_type : return type
+ *      MAX_VALUE : upper limit of the return type
+ */
+
+uint_type
+FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base)
+{
+	const wchar_t *s;
+	uint_type acc, cutoff;
+	wint_t wc;
+	int i;
+	int neg, any, cutlim;
+
+	if (base && (base < 2 || base > 36)) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		wc = (wchar_t) *s++;
+	} while (iswspace(wc));
+	if (wc == L'-') {
+		neg = 1;
+		wc = *s++;
+	} else {
+		neg = 0;
+		if (wc == L'+')
+			wc = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    wc == L'0' && (*s == L'x' || *s == L'X')) {
+		wc = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = wc == L'0' ? 8 : 10;
+
+	/*
+	 * See strtoul for comments as to the logic used.
+	 */
+	cutoff = MAX_VALUE / (uint_type)base;
+	cutlim = (int)(MAX_VALUE % (uint_type)base);
+	for (acc = 0, any = 0;; wc = (wchar_t) *s++) {
+		i = wctoint(wc);
+		if (i == (wint_t)-1)
+			break;
+		if (i >= base)
+			break;
+		if (any < 0)
+			continue;
+		if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+			any = -1;
+			acc = MAX_VALUE;
+			errno = ERANGE;
+		} else {
+			any = 1;
+			acc *= (uint_type)base;
+			acc += i;
+		}
+	}
+	if (neg && any > 0)
+		acc = -acc;
+	if (endptr != 0)
+		/* LINTED interface specification */
+		*endptr = (wchar_t *)(any ? s - 1 : nptr);
+	return (acc);
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/btowc.c b/libc/upstream-openbsd/lib/libc/locale/btowc.c
new file mode 100644
index 0000000..9627340
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/btowc.c
@@ -0,0 +1,52 @@
+/*	$OpenBSD: btowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+wint_t
+btowc(int c)
+{
+	mbstate_t mbs;
+	char cc;
+	wchar_t wc;
+
+	if (c == EOF)
+		return (WEOF);
+	/*
+	 * We expect mbrtowc() to return 0 or 1, hence the check for n > 1
+	 * which detects error return values as well as "impossible" byte
+	 * counts.
+	 */
+	memset(&mbs, 0, sizeof(mbs));
+	cc = (char)c;
+	if (mbrtowc(&wc, &cc, 1, &mbs) > 1)
+		return (WEOF);
+	return (wc);
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/mbrlen.c b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
new file mode 100644
index 0000000..0f05bd0
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c
@@ -0,0 +1,39 @@
+/*	$OpenBSD: mbrlen.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <wchar.h>
+
+size_t
+mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps)
+{
+	static mbstate_t mbs;
+
+	if (ps == NULL)
+		ps = &mbs;
+	return (mbrtowc(NULL, s, n, ps));
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c
new file mode 100644
index 0000000..c17a858
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c
@@ -0,0 +1,44 @@
+/*	$OpenBSD: mbstowcs.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+size_t
+mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
+{
+	mbstate_t mbs;
+	const char *sp;
+
+	memset(&mbs, 0, sizeof(mbs));
+	sp = s;
+	return (mbsrtowcs(pwcs, &sp, n, &mbs));
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstod.c b/libc/upstream-openbsd/lib/libc/locale/wcstod.c
new file mode 100644
index 0000000..957d0a1
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstod.c
@@ -0,0 +1,13 @@
+/*	$OpenBSD: wcstod.c,v 1.3 2009/01/13 18:18:31 kettenis Exp $	*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define FUNCNAME	wcstod
+typedef double		float_type;
+#define STRTOD_FUNC	strtod
+
+#include "_wcstod.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstof.c b/libc/upstream-openbsd/lib/libc/locale/wcstof.c
new file mode 100644
index 0000000..40d76c7
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wcstof.c
@@ -0,0 +1,13 @@
+/*	$OpenBSD: wcstof.c,v 1.1 2009/01/13 18:18:31 kettenis Exp $	*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define FUNCNAME	wcstof
+typedef float		float_type;
+#define STRTOD_FUNC	strtof
+
+#include "_wcstod.h"
diff --git a/libc/upstream-openbsd/lib/libc/locale/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/locale/wctomb.c b/libc/upstream-openbsd/lib/libc/locale/wctomb.c
new file mode 100644
index 0000000..39f7a7c
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/wctomb.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: wctomb.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>
+
+int
+wctomb(char *s, wchar_t wchar)
+{
+	static mbstate_t mbs;
+	size_t rval;
+
+	if (s == NULL) {
+		/* No support for state dependent encodings. */
+		memset(&mbs, 0, sizeof(mbs));
+		return (0);
+	}
+	if ((rval = wcrtomb(s, wchar, &mbs)) == (size_t)-1)
+		return (-1);
+	return ((int)rval);
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
index 539b3c0..d0c0809 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fgetln.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*	$OpenBSD: fgetln.c,v 1.12 2013/11/12 07:04:06 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -43,7 +43,7 @@
  * so we add 1 here.
 #endif
  */
-int
+static int
 __slbexpand(FILE *fp, size_t newsize)
 {
 	void *p;
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..108846e
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -0,0 +1,57 @@
+/*	$OpenBSD: fputws.c,v 1.7 2013/11/12 07:04:35 deraadt 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"
+#include "fvwrite.h"
+
+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/fread.c b/libc/upstream-openbsd/lib/libc/stdio/fread.c
index 430865d..8a592f6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fread.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fread.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fread.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*	$OpenBSD: fread.c,v 1.12 2014/05/01 16:40:36 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -33,8 +33,12 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdint.h>
+#include <errno.h>
 #include "local.h"
 
+#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
+
 size_t
 fread(void *buf, size_t size, size_t count, FILE *fp)
 {
@@ -44,6 +48,16 @@
 	size_t total;
 
 	/*
+	 * Extension:  Catch integer overflow
+	 */
+	if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
+	    size > 0 && SIZE_MAX / size < count) {
+		errno = EOVERFLOW;
+		fp->_flags |= __SERR;
+		return (0);
+	}
+
+	/*
 	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
 	 */
 	if ((resid = count * size) == 0)
diff --git a/libc/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
similarity index 93%
rename from libc/stdio/fvwrite.h
rename to libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
index 96f65de..d3a309b 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
+/*	$OpenBSD: fvwrite.h,v 1.6 2013/11/12 07:04:35 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -36,7 +36,7 @@
  * I/O descriptors for __sfvwrite().
  */
 struct __siov {
-	const void	*iov_base;
+	void	*iov_base;
 	size_t	iov_len;
 };
 struct __suio {
@@ -46,3 +46,4 @@
 };
 
 extern int __sfvwrite(FILE *, struct __suio *);
+wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
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/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
similarity index 84%
copy from libc/stdio/fvwrite.h
copy to libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
index 96f65de..4474e8b 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwprintf.c
@@ -1,5 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
-
+/*	$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.
@@ -32,17 +31,18 @@
  * SUCH DAMAGE.
  */
 
-/*
- * I/O descriptors for __sfvwrite().
- */
-struct __siov {
-	const void	*iov_base;
-	size_t	iov_len;
-};
-struct __suio {
-	struct	__siov *uio_iov;
-	int	uio_iovcnt;
-	int	uio_resid;
-};
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
 
-extern int __sfvwrite(FILE *, struct __suio *);
+int
+fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = vfwprintf(fp, fmt, ap);
+	va_end(ap);
+	return (ret);
+}
diff --git a/libc/upstream-freebsd/lib/libc/stdio/fwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
similarity index 74%
rename from libc/upstream-freebsd/lib/libc/stdio/fwrite.c
rename to libc/upstream-openbsd/lib/libc/stdio/fwrite.c
index 707d362..f0a17bf 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/fwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: fwrite.c,v 1.11 2014/05/01 16:40:36 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,67 +31,58 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fwrite.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "namespace.h"
-#include <errno.h>
-#include <stdint.h>
 #include <stdio.h>
-#include "un-namespace.h"
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
 #include "local.h"
 #include "fvwrite.h"
-#include "libc_private.h"
+
+#define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
 
 /*
  * Write `count' objects (each size `size') from memory to the given file.
  * Return the number of whole objects written.
  */
 size_t
-fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+fwrite(const void *buf, size_t size, size_t count, FILE *fp)
 {
 	size_t n;
 	struct __suio uio;
 	struct __siov iov;
+	int ret;
 
 	/*
-	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+	 * Extension:  Catch integer overflow
 	 */
-	if ((count == 0) || (size == 0))
-		return (0);
-
-	/*
-	 * Check for integer overflow.  As an optimization, first check that
-	 * at least one of {count, size} is at least 2^16, since if both
-	 * values are less than that, their product can't possible overflow
-	 * (size_t is always at least 32 bits on FreeBSD).
-	 */
-	if (((count | size) > 0xFFFF) &&
-	    (count > SIZE_MAX / size)) {
-		errno = EINVAL;
+	if ((size >= MUL_NO_OVERFLOW || count >= MUL_NO_OVERFLOW) &&
+	    size > 0 && SIZE_MAX / size < count) {
+		errno = EOVERFLOW;
 		fp->_flags |= __SERR;
 		return (0);
 	}
 
-	n = count * size;
+	/*
+	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+	 */
+	if ((n = count * size) == 0)
+		return (0);
 
 	iov.iov_base = (void *)buf;
 	uio.uio_resid = iov.iov_len = n;
 	uio.uio_iov = &iov;
 	uio.uio_iovcnt = 1;
 
-	FLOCKFILE(fp);
-	ORIENT(fp, -1);
 	/*
 	 * The usual case is success (__sfvwrite returns 0);
 	 * skip the divide if this happens, since divides are
 	 * generally slow and since this occurs whenever size==0.
 	 */
-	if (__sfvwrite(fp, &uio) != 0)
-	    count = (n - uio.uio_resid) / size;
+	FLOCKFILE(fp);
+	_SET_ORIENTATION(fp, -1);
+	ret = __sfvwrite(fp, &uio);
 	FUNLOCKFILE(fp);
-	return (count);
+	if (ret == 0)
+		return (count);
+	return ((n - uio.uio_resid) / size);
 }
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/vfprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
index b4f8f29..7f8ff31 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfprintf.c,v 1.63 2013/03/02 19:40:08 guenther Exp $	*/
+/*	$OpenBSD: vfprintf.c,v 1.66 2014/05/03 12:36:45 deraadt Exp $	*/
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -216,11 +216,10 @@
 #include <locale.h>
 #include <math.h>
 #include "floatio.h"
+#include "gdtoa.h"
 
 #define	DEFPREC		6
 
-extern char *__dtoa(double, int, int, int *, int *, char **);
-extern void  __freedtoa(char *);
 static int exponent(char *, int, int);
 #endif /* FLOATING_POINT */
 
@@ -399,7 +398,7 @@
 	    flags&PTRINT ? GETARG(ptrdiff_t) : \
 	    flags&SIZEINT ? GETARG(ssize_t) : \
 	    flags&SHORTINT ? (short)GETARG(int) : \
-	    flags&CHARINT ? (__signed char)GETARG(int) : \
+	    flags&CHARINT ? (signed char)GETARG(int) : \
 	    GETARG(int)))
 #define	UARG() \
 	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
@@ -802,6 +801,7 @@
 			}
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				*GETARG(long long *) = ret;
@@ -810,7 +810,7 @@
 			else if (flags & SHORTINT)
 				*GETARG(short *) = ret;
 			else if (flags & CHARINT)
-				*GETARG(__signed char *) = ret;
+				*GETARG(signed char *) = ret;
 			else if (flags & PTRINT)
 				*GETARG(ptrdiff_t *) = ret;
 			else if (flags & SIZEINT)
@@ -820,6 +820,7 @@
 			else
 				*GETARG(int *) = ret;
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
@@ -1318,6 +1319,7 @@
 				ADDTYPE(T_DOUBLE);
 			break;
 #endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
 		case 'n':
 			if (flags & LLONGINT)
 				ADDTYPE(TP_LLONG);
@@ -1334,6 +1336,7 @@
 			else
 				ADDTYPE(TP_INT);
 			continue;	/* no output */
+#endif /* NO_PRINTF_PERCENT_N */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c b/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
index c2996a9..abefe32 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfscanf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vfscanf.c,v 1.30 2013/04/17 17:40:35 tedu Exp $ */
+/*	$OpenBSD: vfscanf.c,v 1.31 2014/03/19 05:17:01 guenther Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -273,7 +273,7 @@
 			if (flags & SUPPRESS)
 				continue;
 			if (flags & SHORTSHORT)
-				*va_arg(ap, __signed char *) = nread;
+				*va_arg(ap, signed char *) = nread;
 			else if (flags & SHORT)
 				*va_arg(ap, short *) = nread;
 			else if (flags & LONG)
@@ -749,7 +749,7 @@
 				else if (flags & SHORT)
 					*va_arg(ap, short *) = res;
 				else if (flags & SHORTSHORT)
-					*va_arg(ap, __signed char *) = res;
+					*va_arg(ap, signed char *) = res;
 				else
 					*va_arg(ap, int *) = res;
 				nassigned++;
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..745b4d9
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
@@ -0,0 +1,1527 @@
+/*	$OpenBSD: vfwprintf.c,v 1.10 2014/05/03 12:36:45 deraadt 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"
+
+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"
+#include "gdtoa.h"
+
+#define	DEFPREC		6
+
+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 */
+#ifndef NO_PRINTF_PERCENT_N
+		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 */
+#endif /* NO_PRINTF_PERCENT_N */
+		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 */
+#ifndef NO_PRINTF_PERCENT_N
+		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 */
+#endif /* NO_PRINTF_PERCENT_N */
+		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..cbb36be
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfwscanf.c
@@ -0,0 +1,798 @@
+/*	$OpenBSD: vfwscanf.c,v 1.4 2014/03/19 05:17:01 guenther 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 <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 (iswupper(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/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
similarity index 84%
copy from libc/stdio/fvwrite.h
copy to libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
index 96f65de..49569c1 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/vwprintf.c
@@ -1,5 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
-
+/*	$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.
@@ -32,17 +31,12 @@
  * SUCH DAMAGE.
  */
 
-/*
- * I/O descriptors for __sfvwrite().
- */
-struct __siov {
-	const void	*iov_base;
-	size_t	iov_len;
-};
-struct __suio {
-	struct	__siov *uio_iov;
-	int	uio_iovcnt;
-	int	uio_resid;
-};
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
 
-extern int __sfvwrite(FILE *, struct __suio *);
+int
+vwprintf(const wchar_t * __restrict fmt, __va_list ap)
+{
+	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/stdio/fvwrite.h b/libc/upstream-openbsd/lib/libc/stdio/wprintf.c
similarity index 84%
copy from libc/stdio/fvwrite.h
copy to libc/upstream-openbsd/lib/libc/stdio/wprintf.c
index 96f65de..9f7abb6 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/wprintf.c
@@ -1,5 +1,4 @@
-/*	$OpenBSD: fvwrite.h,v 1.5 2003/06/02 20:18:37 millert Exp $	*/
-
+/*	$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.
@@ -32,17 +31,18 @@
  * SUCH DAMAGE.
  */
 
-/*
- * I/O descriptors for __sfvwrite().
- */
-struct __siov {
-	const void	*iov_base;
-	size_t	iov_len;
-};
-struct __suio {
-	struct	__siov *uio_iov;
-	int	uio_iovcnt;
-	int	uio_resid;
-};
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
 
-extern int __sfvwrite(FILE *, struct __suio *);
+int
+wprintf(const wchar_t * __restrict fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	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-freebsd/lib/libc/stdio/wsetup.c b/libc/upstream-openbsd/lib/libc/stdio/wsetup.c
similarity index 87%
rename from libc/upstream-freebsd/lib/libc/stdio/wsetup.c
rename to libc/upstream-openbsd/lib/libc/stdio/wsetup.c
index 70f8247..0834223 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/wsetup.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/wsetup.c
@@ -1,3 +1,4 @@
+/*	$OpenBSD: wsetup.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -30,13 +31,6 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)wsetup.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "local.h"
@@ -44,7 +38,7 @@
 /*
  * Various output routines call wsetup to be sure it is safe to write,
  * because either _flags does not include __SWR, or _buf is NULL.
- * _wsetup returns 0 if OK to write; otherwise, it returns EOF and sets errno.
+ * _wsetup returns 0 if OK to write, nonzero otherwise.
  */
 int
 __swsetup(FILE *fp)
@@ -57,11 +51,8 @@
 	 * If we are not writing, we had better be reading and writing.
 	 */
 	if ((fp->_flags & __SWR) == 0) {
-		if ((fp->_flags & __SRW) == 0) {
-			errno = EBADF;
-			fp->_flags |= __SERR;
+		if ((fp->_flags & __SRW) == 0)
 			return (EOF);
-		}
 		if (fp->_flags & __SRD) {
 			/* clobber any ungetc data */
 			if (HASUB(fp))
@@ -76,8 +67,11 @@
 	/*
 	 * Make a buffer if necessary, then set _w.
 	 */
-	if (fp->_bf._base == NULL)
+	if (fp->_bf._base == NULL) {
+		if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
+			return (EOF);
 		__smakebuf(fp);
+	}
 	if (fp->_flags & __SLBF) {
 		/*
 		 * It is line buffered, so make _lbfsize be -_bufsize
diff --git a/libc/upstream-openbsd/lib/libc/string/strsep.c b/libc/upstream-openbsd/lib/libc/string/strsep.c
index bcca681..2ffc4b4 100644
--- a/libc/upstream-openbsd/lib/libc/string/strsep.c
+++ b/libc/upstream-openbsd/lib/libc/string/strsep.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $	*/
+/*	$OpenBSD: strsep.c,v 1.7 2014/02/05 20:42:32 stsp Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -30,7 +30,6 @@
  */
 
 #include <string.h>
-#include <stdio.h>
 
 /*
  * Get next token from string *stringp, where tokens are possibly-empty
diff --git a/libc/upstream-openbsd/lib/libc/time/wcsftime.c b/libc/upstream-openbsd/lib/libc/time/wcsftime.c
new file mode 100644
index 0000000..5760493
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/time/wcsftime.c
@@ -0,0 +1,575 @@
+/*	$OpenBSD: wcsftime.c,v 1.2 2013/01/20 20:29:02 millert Exp $ */
+#include "private.h"
+
+/*
+** Based on the UCB version with the ID appearing below.
+** This is ANSIish only when "multibyte character == plain character".
+**
+** Copyright (c) 1989, 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.
+*/
+
+#include "tzfile.h"
+#include "fcntl.h"
+#include <locale.h>
+#include <wchar.h>
+
+struct lc_time_T {
+	const wchar_t *	mon[MONSPERYEAR];
+	const wchar_t *	month[MONSPERYEAR];
+	const wchar_t *	wday[DAYSPERWEEK];
+	const wchar_t *	weekday[DAYSPERWEEK];
+	const wchar_t *	X_fmt;
+	const wchar_t *	x_fmt;
+	const wchar_t *	c_fmt;
+	const wchar_t *	am;
+	const wchar_t *	pm;
+	const wchar_t *	date_fmt;
+};
+
+#define Locale	(&C_time_locale)
+
+static const struct lc_time_T	C_time_locale = {
+	{
+		L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+		L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+	}, {
+		L"January", L"February", L"March", L"April", L"May", L"June",
+		L"July", L"August", L"September", L"October", L"November", 
+		L"December"
+	}, {
+		L"Sun", L"Mon", L"Tue", L"Wed",
+		L"Thu", L"Fri", L"Sat"
+	}, {
+		L"Sunday", L"Monday", L"Tuesday", L"Wednesday",
+		L"Thursday", L"Friday", L"Saturday"
+	},
+
+	/* X_fmt */
+	L"%H:%M:%S",
+
+	/*
+	** x_fmt
+	** C99 requires this format.
+	** Using just numbers (as here) makes Quakers happier;
+	** it's also compatible with SVR4.
+	*/
+	L"%m/%d/%y",
+
+	/*
+	** c_fmt
+	** C99 requires this format.
+	** Previously this code used "%D %X", but we now conform to C99.
+	** Note that
+	**	"%a %b %d %H:%M:%S %Y"
+	** is used by Solaris 2.3.
+	*/
+	L"%a %b %e %T %Y",
+
+	/* am */
+	L"AM",
+
+	/* pm */
+	L"PM",
+
+	/* date_fmt */
+	L"%a %b %e %H:%M:%S %Z %Y"
+};
+
+#define UNKNOWN L"?"
+static wchar_t *	_add(const wchar_t *, wchar_t *, const wchar_t *);
+static wchar_t *	_sadd(const char *, wchar_t *, const wchar_t *);
+static wchar_t *	_conv(int, const wchar_t *, wchar_t *, const wchar_t *);
+static wchar_t *	_fmt(const wchar_t *, const struct tm *, wchar_t *, const wchar_t *,
+			int *);
+static wchar_t *	_yconv(int, int, int, int, wchar_t *, const wchar_t *);
+
+extern char *	tzname[];
+
+#ifndef YEAR_2000_NAME
+#define YEAR_2000_NAME	"CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
+#endif /* !defined YEAR_2000_NAME */
+
+#define IN_NONE	0
+#define IN_SOME	1
+#define IN_THIS	2
+#define IN_ALL	3
+
+size_t
+wcsftime(wchar_t *__restrict s, size_t maxsize, 
+    const wchar_t *__restrict format, const struct tm *__restrict t)
+{
+	wchar_t *p;
+	int	warn;
+
+	tzset();
+	warn = IN_NONE;
+	p = _fmt(((format == NULL) ? L"%c" : format), t, s, s + maxsize, &warn);
+#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+	if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
+		(void) fprintf(stderr, "\n");
+		if (format == NULL)
+			(void) fprintf(stderr, "NULL strftime format ");
+		else	(void) fwprintf(stderr, "strftime format \"%ls\" ",
+				format);
+		(void) fprintf(stderr, "yields only two digits of years in ");
+		if (warn == IN_SOME)
+			(void) fprintf(stderr, "some locales");
+		else if (warn == IN_THIS)
+			(void) fprintf(stderr, "the current locale");
+		else	(void) fprintf(stderr, "all locales");
+		(void) fprintf(stderr, "\n");
+	}
+#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
+	if (p == s + maxsize) {
+		if (maxsize > 0)
+			s[maxsize - 1] = '\0';
+		return 0;
+	}
+	*p = L'\0';
+	return p - s;
+}
+
+static wchar_t *
+_fmt(const wchar_t *format, const struct tm *t, wchar_t *pt, 
+    const wchar_t *ptlim, int *warnp)
+{
+	for ( ; *format; ++format) {
+		if (*format != L'%') {
+			if (pt == ptlim)
+				break;
+			*pt++ = *format;
+			continue;
+		}
+label:
+		switch (*++format) {
+		case '\0':
+			--format;
+			break;
+		case 'A':
+			pt = _add((t->tm_wday < 0 ||
+				t->tm_wday >= DAYSPERWEEK) ?
+				UNKNOWN : Locale->weekday[t->tm_wday],
+				pt, ptlim);
+			continue;
+		case 'a':
+			pt = _add((t->tm_wday < 0 ||
+				t->tm_wday >= DAYSPERWEEK) ?
+				UNKNOWN : Locale->wday[t->tm_wday],
+				pt, ptlim);
+			continue;
+		case 'B':
+			pt = _add((t->tm_mon < 0 ||
+				t->tm_mon >= MONSPERYEAR) ?
+				UNKNOWN : Locale->month[t->tm_mon],
+				pt, ptlim);
+			continue;
+		case 'b':
+		case 'h':
+			pt = _add((t->tm_mon < 0 ||
+				t->tm_mon >= MONSPERYEAR) ?
+				UNKNOWN : Locale->mon[t->tm_mon],
+				pt, ptlim);
+			continue;
+		case 'C':
+			/*
+			** %C used to do a...
+			**	_fmt("%a %b %e %X %Y", t);
+			** ...whereas now POSIX 1003.2 calls for
+			** something completely different.
+			** (ado, 1993-05-24)
+			*/
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+				pt, ptlim);
+			continue;
+		case 'c':
+			{
+			int warn2 = IN_SOME;
+
+			pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
+			if (warn2 == IN_ALL)
+				warn2 = IN_THIS;
+			if (warn2 > *warnp)
+				*warnp = warn2;
+			}
+			continue;
+		case 'D':
+			pt = _fmt(L"%m/%d/%y", t, pt, ptlim, warnp);
+			continue;
+		case 'd':
+			pt = _conv(t->tm_mday, L"%02d", pt, ptlim);
+			continue;
+		case 'E':
+		case 'O':
+			/*
+			** C99 locale modifiers.
+			** The sequences
+			**	%Ec %EC %Ex %EX %Ey %EY
+			**	%Od %oe %OH %OI %Om %OM
+			**	%OS %Ou %OU %OV %Ow %OW %Oy
+			** are supposed to provide alternate
+			** representations.
+			*/
+			goto label;
+		case 'e':
+			pt = _conv(t->tm_mday, L"%2d", pt, ptlim);
+			continue;
+		case 'F':
+			pt = _fmt(L"%Y-%m-%d", t, pt, ptlim, warnp);
+			continue;
+		case 'H':
+			pt = _conv(t->tm_hour, L"%02d", pt, ptlim);
+			continue;
+		case 'I':
+			pt = _conv((t->tm_hour % 12) ?
+				(t->tm_hour % 12) : 12,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'j':
+			pt = _conv(t->tm_yday + 1, L"%03d", pt, ptlim);
+			continue;
+		case 'k':
+			/*
+			** This used to be...
+			**	_conv(t->tm_hour % 12 ?
+			**		t->tm_hour % 12 : 12, 2, ' ');
+			** ...and has been changed to the below to
+			** match SunOS 4.1.1 and Arnold Robbins'
+			** strftime version 3.0. That is, "%k" and
+			** "%l" have been swapped.
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv(t->tm_hour, L"%2d", pt, ptlim);
+			continue;
+		case 'l':
+			/*
+			** This used to be...
+			**	_conv(t->tm_hour, 2, ' ');
+			** ...and has been changed to the below to
+			** match SunOS 4.1.1 and Arnold Robbin's
+			** strftime version 3.0. That is, "%k" and
+			** "%l" have been swapped.
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv((t->tm_hour % 12) ?
+				(t->tm_hour % 12) : 12,
+				L"%2d", pt, ptlim);
+			continue;
+		case 'M':
+			pt = _conv(t->tm_min, L"%02d", pt, ptlim);
+			continue;
+		case 'm':
+			pt = _conv(t->tm_mon + 1, L"%02d", pt, ptlim);
+			continue;
+		case 'n':
+			pt = _add(L"\n", pt, ptlim);
+			continue;
+		case 'p':
+			pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
+				Locale->pm :
+				Locale->am,
+				pt, ptlim);
+			continue;
+		case 'R':
+			pt = _fmt(L"%H:%M", t, pt, ptlim, warnp);
+			continue;
+		case 'r':
+			pt = _fmt(L"%I:%M:%S %p", t, pt, ptlim, warnp);
+			continue;
+		case 'S':
+			pt = _conv(t->tm_sec, L"%02d", pt, ptlim);
+			continue;
+		case 's':
+			{
+				struct tm	tm;
+				wchar_t		buf[INT_STRLEN_MAXIMUM(
+							time_t) + 1];
+				time_t		mkt;
+
+				tm = *t;
+				mkt = mktime(&tm);
+				if (TYPE_SIGNED(time_t))
+					(void) swprintf(buf, 
+					    sizeof buf/sizeof buf[0],
+					    L"%ld", (long) mkt);
+				else	
+					(void) swprintf(buf, 
+					    sizeof buf/sizeof buf[0],
+					    L"%lu", (unsigned long) mkt);
+				pt = _add(buf, pt, ptlim);
+			}
+			continue;
+		case 'T':
+			pt = _fmt(L"%H:%M:%S", t, pt, ptlim, warnp);
+			continue;
+		case 't':
+			pt = _add(L"\t", pt, ptlim);
+			continue;
+		case 'U':
+			pt = _conv((t->tm_yday + DAYSPERWEEK -
+				t->tm_wday) / DAYSPERWEEK,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'u':
+			/*
+			** From Arnold Robbins' strftime version 3.0:
+			** "ISO 8601: Weekday as a decimal number
+			** [1 (Monday) - 7]"
+			** (ado, 1993-05-24)
+			*/
+			pt = _conv((t->tm_wday == 0) ?
+				DAYSPERWEEK : t->tm_wday,
+				L"%d", pt, ptlim);
+			continue;
+		case 'V':	/* ISO 8601 week number */
+		case 'G':	/* ISO 8601 year (four digits) */
+		case 'g':	/* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0: "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7). For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+			{
+			int	year;
+			int	base;
+			int	yday;
+			int	wday;
+			int	w;
+
+			year = t->tm_year;
+			base = TM_YEAR_BASE;
+			yday = t->tm_yday;
+			wday = t->tm_wday;
+			for ( ; ; ) {
+				int	len;
+				int	bot;
+				int	top;
+
+				len = isleap_sum(year, base) ?
+					DAYSPERLYEAR :
+					DAYSPERNYEAR;
+				/*
+				** What yday (-3 ... 3) does the ISO year 
+				** begin on?
+				*/
+				bot = ((yday + 11 - wday) % DAYSPERWEEK) - 3;
+				/*
+				** What yday does the NEXT ISO year begin on?
+				*/
+				top = bot - (len % DAYSPERWEEK);
+				if (top < -3)
+					top += DAYSPERWEEK;
+				top += len;
+				if (yday >= top) {
+					++base;
+					w = 1;
+					break;
+				}
+				if (yday >= bot) {
+					w = 1 + ((yday - bot) / DAYSPERWEEK);
+					break;
+				}
+				--base;
+				yday += isleap_sum(year, base) ?
+					DAYSPERLYEAR :
+					DAYSPERNYEAR;
+			}
+			if ((w == 52 && t->tm_mon == TM_JANUARY) ||
+				(w == 1 && t->tm_mon == TM_DECEMBER))
+					w = 53;
+			if (*format == 'V')
+				pt = _conv(w, L"%02d", pt, ptlim);
+			else if (*format == 'g') {
+				*warnp = IN_ALL;
+				pt = _yconv(year, base, 0, 1, pt, ptlim);
+			} else	
+				pt = _yconv(year, base, 1, 1, pt, ptlim);
+			}
+			continue;
+		case 'v':
+			/*
+			** From Arnold Robbins' strftime version 3.0:
+			** "date as dd-bbb-YYYY"
+			** (ado, 1993-05-24)
+			*/
+			pt = _fmt(L"%e-%b-%Y", t, pt, ptlim, warnp);
+			continue;
+		case 'W':
+			pt = _conv((t->tm_yday + DAYSPERWEEK -
+				(t->tm_wday ?
+				(t->tm_wday - 1) :
+				(DAYSPERWEEK - 1))) / DAYSPERWEEK,
+				L"%02d", pt, ptlim);
+			continue;
+		case 'w':
+			pt = _conv(t->tm_wday, L"%d", pt, ptlim);
+			continue;
+		case 'X':
+			pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
+			continue;
+		case 'x':
+			{
+			int	warn2 = IN_SOME;
+
+			pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
+			if (warn2 == IN_ALL)
+				warn2 = IN_THIS;
+			if (warn2 > *warnp)
+				*warnp = warn2;
+			}
+			continue;
+		case 'y':
+			*warnp = IN_ALL;
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, pt, ptlim);
+			continue;
+		case 'Y':
+			pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, pt, ptlim);
+			continue;
+		case 'Z':
+			if (t->tm_zone != NULL)
+				pt = _sadd(t->TM_ZONE, pt, ptlim);
+			else
+				if (t->tm_isdst >= 0)
+					pt = _sadd(tzname[t->tm_isdst != 0], 
+					    pt, ptlim);
+			/*
+			** C99 says that %Z must be replaced by the
+			** empty string if the time zone is not
+			** determinable.
+			*/
+			continue;
+		case 'z':
+			{
+			int		diff;
+			wchar_t const *	sign;
+
+			if (t->tm_isdst < 0)
+				continue;
+			diff = t->tm_gmtoff;
+			if (diff < 0) {
+				sign = L"-";
+				diff = -diff;
+			} else	
+				sign = L"+";
+			pt = _add(sign, pt, ptlim);
+			diff /= SECSPERMIN;
+			diff = (diff / MINSPERHOUR) * 100 +
+				(diff % MINSPERHOUR);
+			pt = _conv(diff, L"%04d", pt, ptlim);
+			}
+			continue;
+		case '+':
+			pt = _fmt(Locale->date_fmt, t, pt, ptlim, warnp);
+			continue;
+		case '%':
+		/*
+		** X311J/88-090 (4.12.3.5): if conversion wchar_t is
+		** undefined, behavior is undefined. Print out the
+		** character itself as printf(3) also does.
+		*/
+		default:
+			if (pt != ptlim)
+				*pt++ = *format;
+			break;
+		}
+	}
+	return pt;
+}
+
+static wchar_t *
+_conv(int n, const wchar_t *format, wchar_t *pt, const wchar_t *ptlim)
+{
+	wchar_t	buf[INT_STRLEN_MAXIMUM(int) + 1];
+
+	(void) swprintf(buf, sizeof buf/sizeof buf[0], format, n);
+	return _add(buf, pt, ptlim);
+}
+
+static wchar_t *
+_add(const wchar_t *str, wchar_t *pt, const wchar_t *ptlim)
+{
+	while (pt < ptlim && (*pt = *str++) != L'\0')
+		++pt;
+	return pt;
+}
+
+static wchar_t *
+_sadd(const char *str, wchar_t *pt, const wchar_t *ptlim)
+{
+	while (pt < ptlim && (*pt = btowc(*str++)) != L'\0')
+		++pt;
+	return pt;
+}
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static wchar_t *
+_yconv(int a, int b, int convert_top, int convert_yy, wchar_t *pt, 
+    const wchar_t *ptlim)
+{
+	register int	lead;
+	register int	trail;
+
+#define DIVISOR	100
+	trail = a % DIVISOR + b % DIVISOR;
+	lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+	trail %= DIVISOR;
+	if (trail < 0 && lead > 0) {
+		trail += DIVISOR;
+		--lead;
+	} else if (lead < 0 && trail > 0) {
+		trail -= DIVISOR;
+		++lead;
+	}
+	if (convert_top) {
+		if (lead == 0 && trail < 0)
+			pt = _add(L"-0", pt, ptlim);
+		else	pt = _conv(lead, L"%02d", pt, ptlim);
+	}
+	if (convert_yy)
+		pt = _conv(((trail < 0) ? -trail : trail), L"%02d", pt, ptlim);
+	return pt;
+}
+
diff --git a/libm/NOTICE b/libm/NOTICE
index 5a8e139..5be60db 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -155,6 +155,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (C) 2014 The Android Open Source 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.
+
+-------------------------------------------------------------------
+
 Copyright (c) 1985, 1993
    The Regents of the University of California.  All rights reserved.
 
@@ -312,32 +338,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
-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.
-
--------------------------------------------------------------------
-
 Copyright (c) 2003 Dag-Erling Smørgrav
 All rights reserved.
 
@@ -976,6 +976,32 @@
 
 -------------------------------------------------------------------
 
+Copyright (c) 2013 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.
+
+-------------------------------------------------------------------
+
 From: @(#)s_ilogb.c 5.1 93/09/24
 ====================================================
 Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4d8563e..08231ea 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -680,6 +680,9 @@
       return fd;
     }
     // ...but nvidia binary blobs (at least) rely on this behavior, so fall through for now.
+#if defined(__LP64__)
+    return -1;
+#endif
   }
 
   // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
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 c6fa54e..9db372a 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 \
 
@@ -217,6 +225,18 @@
 include $(LOCAL_PATH)/Android.build.mk
 
 # -----------------------------------------------------------------------------
+# This library used by atexit tests
+# -----------------------------------------------------------------------------
+
+libtest_atexit_src_files := \
+    atexit_testlib.cpp
+
+module := libtest_atexit
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
 # Tests for the device using bionic's .so. Run with:
 #   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
 # -----------------------------------------------------------------------------
@@ -224,6 +244,7 @@
     libBionicTests \
 
 bionic-unit-tests_src_files := \
+    atexit_test.cpp \
     dlext_test.cpp \
     dlfcn_test.cpp \
 
@@ -236,7 +257,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
@@ -258,7 +279,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
@@ -270,11 +291,14 @@
 
 ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
 
+bionic-unit-tests-glibc_src_files := \
+    atexit_test.cpp \
+
 bionic-unit-tests-glibc_whole_static_libraries := \
     libBionicStandardTests \
 
 bionic-unit-tests-glibc_ldlibs := \
-    -lrt \
+    -lrt -ldl \
 
 module := bionic-unit-tests-glibc
 module_tag := optional
diff --git a/tests/atexit_test.cpp b/tests/atexit_test.cpp
new file mode 100644
index 0000000..e52235d
--- /dev/null
+++ b/tests/atexit_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <dlfcn.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <string>
+
+TEST(atexit, combined_test) {
+  std::string atexit_call_sequence;
+  bool valid_this_in_static_dtor = false;
+  void* handle = dlopen("libtest_atexit.so", RTLD_NOW);
+  ASSERT_TRUE(handle != NULL);
+
+  void* sym = dlsym(handle, "register_atexit");
+  ASSERT_TRUE(sym != NULL);
+  reinterpret_cast<void (*)(std::string*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor);
+
+  ASSERT_EQ(0, dlclose(handle));
+  // this test verifies atexit call from atexit handler. as well as the order of calls
+  ASSERT_EQ("Humpty Dumpty sat on a wall", atexit_call_sequence);
+  ASSERT_TRUE(valid_this_in_static_dtor);
+}
+
+// TODO: test for static dtor calls from from exit(.) -> __cxa_finalize(NULL)
+
diff --git a/tests/atexit_testlib.cpp b/tests/atexit_testlib.cpp
new file mode 100644
index 0000000..36393e7
--- /dev/null
+++ b/tests/atexit_testlib.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+// use external control number from main test
+static std::string* atexit_sequence = NULL;
+static bool* atexit_valid_this_in_static_dtor = NULL;
+
+class AtExitStaticClass;
+
+static const AtExitStaticClass* valid_this = NULL;
+
+static class AtExitStaticClass {
+public:
+  AtExitStaticClass() { valid_this = this; }
+  ~AtExitStaticClass() {
+    if (atexit_valid_this_in_static_dtor) {
+      *atexit_valid_this_in_static_dtor = (valid_this == this);
+    }
+  }
+} staticObj;
+
+// 4
+static void atexit_handler_from_atexit_from_atexit2() {
+  *atexit_sequence += " on";
+}
+
+// 3
+static void atexit_handler_from_atexit_from_atexit1() {
+  *atexit_sequence += " sat";
+}
+
+// 2
+static void atexit_handler_from_atexit() {
+  *atexit_sequence += " Dumpty";
+  // register 2 others
+  atexit(atexit_handler_from_atexit_from_atexit2);
+  atexit(atexit_handler_from_atexit_from_atexit1);
+}
+
+// 1
+static void atexit_handler_with_atexit() {
+  *atexit_sequence += "Humpty";
+  atexit(atexit_handler_from_atexit);
+}
+
+// last
+static void atexit_handler_regular() {
+  *atexit_sequence += " a wall";
+}
+
+extern "C" void register_atexit(std::string* sequence, bool* valid_this_in_static_dtor) {
+  atexit_sequence = sequence;
+  atexit_valid_this_in_static_dtor = valid_this_in_static_dtor;
+  atexit(atexit_handler_regular);
+  atexit(atexit_handler_with_atexit);
+  atexit(NULL);
+}
+
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/sched_test.cpp b/tests/sched_test.cpp
index 49f1642..8dba948 100644
--- a/tests/sched_test.cpp
+++ b/tests/sched_test.cpp
@@ -50,3 +50,207 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 }
 #endif
+
+TEST(sched, cpu_set) {
+  cpu_set_t set;
+
+  CPU_ZERO(&set);
+  CPU_SET(0, &set);
+  CPU_SET(17, &set);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 0 || i == 17, CPU_ISSET(i, &set));
+  }
+
+  // We should fail silently if we try to set/test outside the range.
+  CPU_SET(CPU_SETSIZE, &set);
+  ASSERT_FALSE(CPU_ISSET(CPU_SETSIZE, &set));
+}
+
+TEST(sched, cpu_count) {
+  cpu_set_t set;
+
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, CPU_COUNT(&set));
+  CPU_SET(2, &set);
+  CPU_SET(10, &set);
+  ASSERT_EQ(2, CPU_COUNT(&set));
+  CPU_CLR(10, &set);
+  ASSERT_EQ(1, CPU_COUNT(&set));
+}
+
+TEST(sched, cpu_zero) {
+  cpu_set_t set;
+
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, CPU_COUNT(&set));
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_FALSE(CPU_ISSET(i, &set));
+  }
+}
+
+TEST(sched, cpu_clr) {
+  cpu_set_t set;
+
+  CPU_ZERO(&set);
+  CPU_SET(0, &set);
+  CPU_SET(1, &set);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 0 || i == 1, CPU_ISSET(i, &set));
+  }
+  CPU_CLR(1, &set);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 0, CPU_ISSET(i, &set));
+  }
+
+  // We should fail silently if we try to clear/test outside the range.
+  CPU_CLR(CPU_SETSIZE, &set);
+  ASSERT_FALSE(CPU_ISSET(CPU_SETSIZE, &set));
+}
+
+TEST(sched, cpu_equal) {
+  cpu_set_t set1;
+  cpu_set_t set2;
+
+  CPU_ZERO(&set1);
+  CPU_ZERO(&set2);
+  CPU_SET(1, &set1);
+  ASSERT_FALSE(CPU_EQUAL(&set1, &set2));
+  CPU_SET(1, &set2);
+  ASSERT_TRUE(CPU_EQUAL(&set1, &set2));
+}
+
+TEST(sched, cpu_op) {
+  cpu_set_t set1;
+  cpu_set_t set2;
+  cpu_set_t set3;
+
+  CPU_ZERO(&set1);
+  CPU_ZERO(&set2);
+  CPU_ZERO(&set3);
+  CPU_SET(0, &set1);
+  CPU_SET(0, &set2);
+  CPU_SET(1, &set2);
+
+  CPU_AND(&set3, &set1, &set2);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 0, CPU_ISSET(i, &set3));
+  }
+
+  CPU_XOR(&set3, &set1, &set2);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 1, CPU_ISSET(i, &set3));
+  }
+
+  CPU_OR(&set3, &set1, &set2);
+  for (int i = 0; i < CPU_SETSIZE; i++) {
+    ASSERT_EQ(i == 0 || i == 1, CPU_ISSET(i, &set3));
+  }
+}
+
+
+TEST(sched, cpu_alloc_small) {
+  cpu_set_t* set = CPU_ALLOC(17);
+  size_t size = CPU_ALLOC_SIZE(17);
+
+  CPU_ZERO_S(size, set);
+  ASSERT_EQ(0, CPU_COUNT_S(size, set));
+  CPU_SET_S(16, size, set);
+  ASSERT_TRUE(CPU_ISSET_S(16, size, set));
+
+  CPU_FREE(set);
+}
+
+TEST(sched, cpu_alloc_big) {
+  cpu_set_t* set = CPU_ALLOC(10 * CPU_SETSIZE);
+  size_t size = CPU_ALLOC_SIZE(10 * CPU_SETSIZE);
+
+  CPU_ZERO_S(size, set);
+  ASSERT_EQ(0, CPU_COUNT_S(size, set));
+  CPU_SET_S(CPU_SETSIZE, size, set);
+  ASSERT_TRUE(CPU_ISSET_S(CPU_SETSIZE, size, set));
+
+  CPU_FREE(set);
+}
+
+TEST(sched, cpu_s_macros) {
+  int set_size = 64;
+  size_t size = CPU_ALLOC_SIZE(set_size);
+  cpu_set_t* set = CPU_ALLOC(set_size);
+
+  CPU_ZERO_S(size, set);
+  for (int i = 0; i < set_size; i++) {
+    ASSERT_FALSE(CPU_ISSET_S(i, size, set));
+    CPU_SET_S(i, size, set);
+    ASSERT_TRUE(CPU_ISSET_S(i, size, set));
+    ASSERT_EQ(i + 1, CPU_COUNT_S(size, set));
+  }
+
+  for (int i = 0; i < set_size; i++) {
+    CPU_CLR_S(i, size, set);
+    ASSERT_FALSE(CPU_ISSET_S(i, size, set));
+    ASSERT_EQ(set_size - i - 1, CPU_COUNT_S(size, set));
+  }
+
+  CPU_FREE(set);
+}
+
+TEST(sched, cpu_op_s_macros) {
+  int set_size1 = 64;
+  int set_size2 = set_size1 * 2;
+  int set_size3 = set_size1 * 3;
+  size_t size1 = CPU_ALLOC_SIZE(set_size1);
+  size_t size2 = CPU_ALLOC_SIZE(set_size2);
+  size_t size3 = CPU_ALLOC_SIZE(set_size3);
+
+  cpu_set_t* set1 = CPU_ALLOC(set_size1);
+  cpu_set_t* set2 = CPU_ALLOC(set_size2);
+  cpu_set_t* set3 = CPU_ALLOC(set_size3);
+  CPU_ZERO_S(size1, set1);
+  CPU_ZERO_S(size2, set2);
+  CPU_ZERO_S(size3, set3);
+
+  CPU_SET_S(0, size1, set1);
+  CPU_SET_S(0, size2, set2);
+  CPU_SET_S(1, size3, set2);
+
+  CPU_AND_S(size1, set3, set1, set2);
+  for (int i = 0; i < set_size3; i++) {
+    ASSERT_EQ(i == 0, CPU_ISSET_S(i, size3, set3));
+  }
+
+  CPU_OR_S(size1, set3, set1, set2);
+  for (int i = 0; i < set_size3; i++) {
+    ASSERT_EQ(i == 0 || i == 1, CPU_ISSET_S(i, size3, set3));
+  }
+
+  CPU_XOR_S(size1, set3, set1, set2);
+  for (int i = 0; i < set_size3; i++) {
+    ASSERT_EQ(i == 1, CPU_ISSET_S(i, size3, set3));
+  }
+
+  CPU_FREE(set1);
+  CPU_FREE(set2);
+  CPU_FREE(set3);
+}
+
+TEST(sched, cpu_equal_s) {
+  int set_size1 = 64;
+  int set_size2 = set_size1 * 2;
+  size_t size1 = CPU_ALLOC_SIZE(set_size1);
+  size_t size2 = CPU_ALLOC_SIZE(set_size2);
+
+  cpu_set_t* set1 = CPU_ALLOC(set_size1);
+  cpu_set_t* set2 = CPU_ALLOC(set_size2);
+
+  CPU_ZERO_S(size1, set1);
+  CPU_ZERO_S(size2, set2);
+
+  CPU_SET_S(0, size1, set1);
+  ASSERT_TRUE(CPU_EQUAL_S(size1, set1, set1));
+  ASSERT_FALSE(CPU_EQUAL_S(size1, set1, set2));
+  CPU_SET_S(0, size2, set2);
+  ASSERT_TRUE(CPU_EQUAL_S(size1, set1, set2));
+
+  CPU_FREE(set1);
+  CPU_FREE(set2);
+}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 6d55bef..af98964 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -252,3 +252,21 @@
   ASSERT_TRUE(sys_siglist[0] == NULL);
   ASSERT_STREQ("Hangup", sys_siglist[SIGHUP]);
 }
+
+TEST(signal, limits) {
+  // This comes from the kernel.
+  ASSERT_EQ(32, __SIGRTMIN);
+
+  // We reserve a non-zero number at the bottom for ourselves.
+  ASSERT_GT(SIGRTMIN, __SIGRTMIN);
+
+  // MIPS has more signals than everyone else.
+#if defined(__mips__)
+  ASSERT_EQ(128, __SIGRTMAX);
+#else
+  ASSERT_EQ(64, __SIGRTMAX);
+#endif
+
+  // We don't currently reserve any at the top.
+  ASSERT_EQ(SIGRTMAX, __SIGRTMAX);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index d825c14..73e9dcd 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -220,11 +220,16 @@
 }
 
 TEST(stdio, snprintf_n) {
+#if !defined(__GLIBC__)
+  // http://b/14492135
   char buf[32];
-  int i = 0;
-  EXPECT_EQ(4, snprintf(buf, sizeof(buf), "a %n b", &i));
-  EXPECT_EQ(2, i);
-  EXPECT_STREQ("a  b", buf);
+  int i = 1234;
+  EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
+  EXPECT_EQ(1234, i);
+  EXPECT_STREQ("a n b", buf);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(stdio, snprintf_smoke) {
@@ -436,3 +441,45 @@
   ASSERT_EQ(123, i1);
   ASSERT_DOUBLE_EQ(1.23, d1);
 }
+
+TEST(stdio, cantwrite_EBADF) {
+  // If we open a file read-only...
+  FILE* fp = fopen("/proc/version", "r");
+
+  // ...all attempts to write to that file should return failure.
+
+  // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
+  // glibc gets the wide-character functions wrong.
+
+  errno = 0;
+  EXPECT_EQ(EOF, putc('x', fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fprintf(fp, "hello"));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
+#if !defined(__GLIBC__)
+  EXPECT_EQ(EBADF, errno);
+#endif
+
+  errno = 0;
+  EXPECT_EQ(EOF, putw(1234, fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(EOF, fputs("hello", fp));
+  EXPECT_EQ(EBADF, errno);
+
+  errno = 0;
+  EXPECT_EQ(WEOF, fputwc(L'x', fp));
+#if !defined(__GLIBC__)
+  EXPECT_EQ(EBADF, errno);
+#endif
+}
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/string_test.cpp b/tests/string_test.cpp
index 14b284e..5ccc63d 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -100,11 +100,9 @@
   ASSERT_STREQ("Hangup", strsignal(1));
 
   // A real-time signal.
-#ifdef __GLIBC__ // glibc reserves real-time signals for internal use, and doesn't count those.
-  ASSERT_STREQ("Real-time signal 14", strsignal(48));
-#else
-  ASSERT_STREQ("Real-time signal 16", strsignal(48));
-#endif
+  ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14));
+  // One of the signals the C library keeps to itself.
+  ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN));
 
   // Errors.
   ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index daa064a..6e7a807 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -17,8 +17,10 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <sys/epoll.h>
+#include <unistd.h>
 
 TEST(sys_epoll, smoke) {
   int epoll_fd = epoll_create(1);
@@ -37,3 +39,30 @@
   sigaddset(&ss, SIGPIPE);
   ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, &ss));
 }
+
+TEST(sys_epoll, epoll_event_data) {
+  int epoll_fd = epoll_create(1);
+  ASSERT_NE(-1, epoll_fd) << strerror(errno);
+
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+
+  const uint64_t expected = 0x123456789abcdef0;
+
+  // Get ready to poll on read end of pipe.
+  epoll_event ev;
+  ev.events = EPOLLIN;
+  ev.data.u64 = expected;
+  ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
+
+  // Ensure there's something in the pipe.
+  ASSERT_EQ(1, write(fds[1], "\n", 1));
+
+  // Poll.
+  epoll_event events[1];
+  ASSERT_EQ(1, epoll_wait(epoll_fd, events, 1, 1));
+  ASSERT_EQ(expected, events[0].data.u64);
+
+  close(fds[0]);
+  close(fds[1]);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f56b767..ce0beba 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -18,8 +18,6 @@
 #include "ScopedSignalHandler.h"
 #include "TemporaryFile.h"
 
-#define __STDC_LIMIT_MACROS // For glibc.
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 3c38f1f..a92ac9d 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -18,6 +18,8 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <locale.h>
+#include <stdint.h>
 #include <wchar.h>
 
 TEST(wchar, sizeof_wchar_t) {
@@ -48,18 +50,46 @@
   EXPECT_EQ(1U, wcrtomb(bytes, L'\0', NULL));
 
   // ...and for regular characters.
-  bytes[0] = 'x';
+  memset(bytes, 0, sizeof(bytes));
   EXPECT_EQ(1, wctomb(bytes, L'h'));
   EXPECT_EQ('h', bytes[0]);
-
-  bytes[0] = 'x';
+  memset(bytes, 0, sizeof(bytes));
   EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
   EXPECT_EQ('h', bytes[0]);
+
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  // 1-byte UTF-8.
+  memset(bytes, 0, sizeof(bytes));
+  EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
+  EXPECT_EQ('h', bytes[0]);
+  // 2-byte UTF-8.
+  memset(bytes, 0, sizeof(bytes));
+  EXPECT_EQ(2U, wcrtomb(bytes, 0x00a2, NULL));
+  EXPECT_EQ('\xc2', bytes[0]);
+  EXPECT_EQ('\xa2', bytes[1]);
+  // 3-byte UTF-8.
+  memset(bytes, 0, sizeof(bytes));
+  EXPECT_EQ(3U, wcrtomb(bytes, 0x20ac, NULL));
+  EXPECT_EQ('\xe2', bytes[0]);
+  EXPECT_EQ('\x82', bytes[1]);
+  EXPECT_EQ('\xac', bytes[2]);
+  // 4-byte UTF-8.
+  memset(bytes, 0, sizeof(bytes));
+  EXPECT_EQ(4U, wcrtomb(bytes, 0x24b62, NULL));
+  EXPECT_EQ('\xf0', bytes[0]);
+  EXPECT_EQ('\xa4', bytes[1]);
+  EXPECT_EQ('\xad', bytes[2]);
+  EXPECT_EQ('\xa2', bytes[3]);
+  // Invalid code point.
+  EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(bytes, 0xffffffff, NULL));
+  EXPECT_EQ(EILSEQ, errno);
 }
 
 TEST(wchar, wcstombs_wcrtombs) {
   const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
-  const wchar_t bad_chars[] = { L'h', L'i', 666, 0 };
+  const wchar_t bad_chars[] = { L'h', L'i', static_cast<wchar_t>(0xffffffff), 0 };
   const wchar_t* src;
   char bytes[BUFSIZ];
 
@@ -211,4 +241,96 @@
   ASSERT_EQ(1U, mbrtowc(NULL, "hello", 1, NULL));
 
   ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL));
+
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  // 1-byte UTF-8.
+  ASSERT_EQ(1U, mbrtowc(out, "abcdef", 6, NULL));
+  ASSERT_EQ(L'a', out[0]);
+  // 2-byte UTF-8.
+  ASSERT_EQ(2U, mbrtowc(out, "\xc2\xa2" "cdef", 6, NULL));
+  ASSERT_EQ(0x00a2, out[0]);
+  // 3-byte UTF-8.
+  ASSERT_EQ(3U, mbrtowc(out, "\xe2\x82\xac" "def", 6, NULL));
+  ASSERT_EQ(0x20ac, out[0]);
+  // 4-byte UTF-8.
+  ASSERT_EQ(4U, mbrtowc(out, "\xf0\xa4\xad\xa2" "ef", 6, NULL));
+  ASSERT_EQ(0x24b62, out[0]);
+#if __BIONIC__ // glibc allows this.
+  // Illegal 5-byte UTF-8.
+  ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf8\xa1\xa2\xa3\xa4" "f", 6, NULL));
+  ASSERT_EQ(EILSEQ, errno);
+#endif
+  // Illegal over-long sequence.
+  ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf0\x82\x82\xac" "ef", 6, NULL));
+  ASSERT_EQ(EILSEQ, errno);
+}
+
+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);
+}
+
+TEST(wchar, wcsftime) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+  t.tm_year = 200;
+  t.tm_mon = 2;
+  t.tm_mday = 10;
+
+  wchar_t buf[64];
+
+  EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t));
+  EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
 }