Merge "Revert "Reserve space in pthread structures for future extensibility.""
diff --git a/HACKING.txt b/HACKING.txt
index 9f45903..fb93b5a 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -97,8 +97,14 @@
upstream-openbsd/
# These directories contain unmolested upstream source. Any time we can
# just use a BSD implementation of something unmodified, we should.
- # See files like netbsd-compat.h for various ways in which we manage to
- # build BSD source in bionic.
+ # The structure under these directories mimics the upstream tree,
+ # but there's also...
+ android/
+ include/
+ # This is where we keep the hacks necessary to build BSD source
+ # in our world. The *-compat.h files are automatically included
+ # using -include, but we also provide equivalents for missing
+ # header/source files needed by the BSD implementation.
bionic/
# This is the biggest mess. The C++ files are files we own, typically
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index 797ce62..25e2ed9 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -44,6 +44,9 @@
# adb shell bionic-benchmarks
include $(CLEAR_VARS)
LOCAL_MODULE := bionic-benchmarks
+LOCAL_MODULE_STEM_32 := bionic-benchmarks32
+LOCAL_MODULE_STEM_64 := bionic-benchmarks64
+LOCAL_MULTILIB := both
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CFLAGS += $(benchmark_c_flags)
LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
diff --git a/libc/Android.mk b/libc/Android.mk
index b94e573..4f6afe8 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -39,7 +39,6 @@
libc_common_src_files := \
bionic/arc4random.c \
bionic/bindresvport.c \
- bionic/clearenv.c \
bionic/daemon.c \
bionic/err.c \
bionic/ether_aton.c \
@@ -69,23 +68,12 @@
bionic/sigblock.c \
bionic/siginterrupt.c \
bionic/sigsetmask.c \
- bionic/strntoimax.c \
- bionic/strntoumax.c \
bionic/system_properties_compat.c \
- bionic/time64.c \
bionic/unlockpt.c \
stdio/findfp.c \
- stdio/fread.c \
- stdio/fvwrite.c \
stdio/snprintf.c\
stdio/sprintf.c \
- stdio/vfprintf.c \
stdlib/atexit.c \
- stdlib/ctype_.c \
- stdlib/getenv.c \
- stdlib/putenv.c \
- stdlib/setenv.c \
- stdlib/strtod.c \
unistd/syslog.c \
# Fortify implementations of libc functions.
@@ -118,6 +106,7 @@
bionic/brk.cpp \
bionic/chmod.cpp \
bionic/chown.cpp \
+ bionic/clearenv.cpp \
bionic/clock.cpp \
bionic/clone.cpp \
bionic/cmsg_nxthdr.cpp \
@@ -208,7 +197,6 @@
bionic/strerror.cpp \
bionic/strerror_r.cpp \
bionic/strsignal.cpp \
- bionic/strtof.cpp \
bionic/strtold.cpp \
bionic/stubs.cpp \
bionic/symlink.cpp \
@@ -311,12 +299,41 @@
upstream-netbsd/lib/libc/thread-stub/__isthreaded.c \
upstream-netbsd/lib/libc/unistd/killpg.c \
+libc_upstream_openbsd_gdtoa_src_files := \
+ upstream-openbsd/android/gdtoa_support.cpp \
+ upstream-openbsd/lib/libc/gdtoa/dmisc.c \
+ upstream-openbsd/lib/libc/gdtoa/dtoa.c \
+ upstream-openbsd/lib/libc/gdtoa/gdtoa.c \
+ upstream-openbsd/lib/libc/gdtoa/gethex.c \
+ upstream-openbsd/lib/libc/gdtoa/gmisc.c \
+ upstream-openbsd/lib/libc/gdtoa/hd_init.c \
+ upstream-openbsd/lib/libc/gdtoa/hdtoa.c \
+ upstream-openbsd/lib/libc/gdtoa/hexnan.c \
+ upstream-openbsd/lib/libc/gdtoa/ldtoa.c \
+ upstream-openbsd/lib/libc/gdtoa/misc.c \
+ upstream-openbsd/lib/libc/gdtoa/smisc.c \
+ upstream-openbsd/lib/libc/gdtoa/strtod.c \
+ upstream-openbsd/lib/libc/gdtoa/strtodg.c \
+ upstream-openbsd/lib/libc/gdtoa/strtof.c \
+ upstream-openbsd/lib/libc/gdtoa/strtord.c \
+ upstream-openbsd/lib/libc/gdtoa/sum.c \
+ upstream-openbsd/lib/libc/gdtoa/ulp.c \
+
+libc_upstream_openbsd_gdtoa_src_files_32 := \
+ $(libc_upstream_openbsd_gdtoa_src_files) \
+
+libc_upstream_openbsd_gdtoa_src_files_64 := \
+ $(libc_upstream_openbsd_gdtoa_src_files) \
+ upstream-openbsd/lib/libc/gdtoa/strtorQ.c \
+
libc_upstream_openbsd_src_files := \
upstream-openbsd/lib/libc/gen/alarm.c \
+ upstream-openbsd/lib/libc/gen/ctype_.c \
upstream-openbsd/lib/libc/gen/exec.c \
upstream-openbsd/lib/libc/gen/fnmatch.c \
upstream-openbsd/lib/libc/gen/ftok.c \
upstream-openbsd/lib/libc/gen/getprogname.c \
+ upstream-openbsd/lib/libc/gen/isctype.c \
upstream-openbsd/lib/libc/gen/setprogname.c \
upstream-openbsd/lib/libc/gen/time.c \
upstream-openbsd/lib/libc/gen/tolower_.c \
@@ -338,12 +355,14 @@
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/fread.c \
upstream-openbsd/lib/libc/stdio/freopen.c \
upstream-openbsd/lib/libc/stdio/fscanf.c \
upstream-openbsd/lib/libc/stdio/fseek.c \
upstream-openbsd/lib/libc/stdio/fsetpos.c \
upstream-openbsd/lib/libc/stdio/ftell.c \
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/getc.c \
upstream-openbsd/lib/libc/stdio/getchar.c \
@@ -369,6 +388,7 @@
upstream-openbsd/lib/libc/stdio/tmpnam.c \
upstream-openbsd/lib/libc/stdio/ungetc.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/vprintf.c \
upstream-openbsd/lib/libc/stdio/vscanf.c \
@@ -379,6 +399,8 @@
upstream-openbsd/lib/libc/stdlib/atoi.c \
upstream-openbsd/lib/libc/stdlib/atol.c \
upstream-openbsd/lib/libc/stdlib/atoll.c \
+ upstream-openbsd/lib/libc/stdlib/getenv.c \
+ upstream-openbsd/lib/libc/stdlib/setenv.c \
upstream-openbsd/lib/libc/stdlib/strtoimax.c \
upstream-openbsd/lib/libc/stdlib/strtol.c \
upstream-openbsd/lib/libc/stdlib/strtoll.c \
@@ -445,9 +467,7 @@
# ========================================================
libc_common_c_includes := \
$(LOCAL_PATH)/stdlib \
- $(LOCAL_PATH)/string \
$(LOCAL_PATH)/stdio \
- external/safe-iop/include
# ========================================================
# Add in the arch-specific flags.
@@ -523,7 +543,7 @@
-I$(LOCAL_PATH)/dns/include \
-I$(LOCAL_PATH)/private \
-I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
- -include upstream-netbsd/netbsd-compat.h
+ -include upstream-netbsd/android/include/netbsd-compat.h
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -547,9 +567,9 @@
LOCAL_SRC_FILES := $(libc_upstream_freebsd_src_files)
LOCAL_CFLAGS := \
$(libc_common_cflags) \
- -I$(LOCAL_PATH)/upstream-freebsd \
+ -I$(LOCAL_PATH)/upstream-freebsd/android/include \
-I$(LOCAL_PATH)/upstream-freebsd/lib/libc/include \
- -include upstream-freebsd/freebsd-compat.h
+ -include freebsd-compat.h
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -574,9 +594,9 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-DPOSIX_MISTAKE \
- -I$(LOCAL_PATH)/upstream-netbsd \
+ -I$(LOCAL_PATH)/upstream-netbsd/android/include \
-I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
- -include upstream-netbsd/netbsd-compat.h
+ -include netbsd-compat.h
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -600,9 +620,9 @@
LOCAL_SRC_FILES := $(libc_upstream_openbsd_src_files)
LOCAL_CFLAGS := \
$(libc_common_cflags) \
- -I$(LOCAL_PATH)/upstream-openbsd \
+ -I$(LOCAL_PATH)/upstream-openbsd/android/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
- -include upstream-openbsd/openbsd-compat.h
+ -include openbsd-compat.h
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -615,6 +635,35 @@
# ========================================================
+# libc_gdtoa.a - upstream OpenBSD C library gdtoa code
+# ========================================================
+#
+# These files are built with the openbsd-compat.h header file
+# automatically included.
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES_32 := $(libc_upstream_openbsd_gdtoa_src_files_32)
+LOCAL_SRC_FILES_64 := $(libc_upstream_openbsd_gdtoa_src_files_64)
+LOCAL_CFLAGS := \
+ $(libc_common_cflags) \
+ -fvisibility=hidden \
+ -I$(LOCAL_PATH)/upstream-openbsd/android/include \
+ -I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
+ -include openbsd-compat.h \
+
+LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
+LOCAL_CPPFLAGS := $(libc_common_cppflags)
+LOCAL_C_INCLUDES := $(libc_common_c_includes)
+LOCAL_MODULE := libc_gdtoa
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+
+$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
+include $(BUILD_STATIC_LIBRARY)
+
+
+# ========================================================
# libc_bionic.a - home-grown C library code
# ========================================================
@@ -676,6 +725,7 @@
libc_bionic \
libc_dns \
libc_freebsd \
+ libc_gdtoa \
libc_netbsd \
libc_openbsd \
libc_stack_protector \
@@ -773,7 +823,7 @@
bionic/pthread_debug.cpp \
bionic/libc_init_dynamic.cpp \
-LOCAL_MODULE:= libc
+LOCAL_MODULE := libc
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_REQUIRED_MODULES := tzdata
@@ -786,7 +836,7 @@
# ensures that symbols that are pulled into those new libraries from libgcc.a are not declared
# external; if that were the case, then libc would not pull those symbols from libgcc.a as it
# should, instead relying on the external symbols from the dependent libraries. That would
-# create an "cloaked" dependency on libgcc.a in libc though the libraries, which is not what
+# create a "cloaked" dependency on libgcc.a in libc though the libraries, which is not what
# you wanted!
LOCAL_SHARED_LIBRARIES := libdl
@@ -834,7 +884,7 @@
bionic/malloc_debug_leak.cpp \
bionic/malloc_debug_check.cpp \
-LOCAL_MODULE:= libc_malloc_debug_leak
+LOCAL_MODULE := libc_malloc_debug_leak
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SHARED_LIBRARIES := libc libdl
@@ -865,7 +915,7 @@
LOCAL_SRC_FILES := \
bionic/malloc_debug_qemu.cpp
-LOCAL_MODULE:= libc_malloc_debug_qemu
+LOCAL_MODULE := libc_malloc_debug_qemu
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SHARED_LIBRARIES := libc libdl
diff --git a/libc/NOTICE b/libc/NOTICE
index 2091e63..82733a2 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -127,6 +127,35 @@
-------------------------------------------------------------------
+Copyright (C) 2008 The Android Open Source Project
+All rights reserved.
+Copyright (c) 2013-2014, NVIDIA Corporation. 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.
+
+-------------------------------------------------------------------
+
Copyright (C) 2008-2010 The Android Open Source Project
All rights reserved.
@@ -390,6 +419,35 @@
-------------------------------------------------------------------
+Copyright (C) 2013 The Android Open Source Project
+Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+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.
+
+-------------------------------------------------------------------
+
Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -1405,6 +1463,38 @@
Copyright (c) 1989, 1993
The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Roger L. Snyder.
+
+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) 1989, 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
@@ -2166,44 +2256,6 @@
Copyright (c) 1992, 1993
The Regents of the University of California. All rights reserved.
-
-This software was developed by the Computer Systems Engineering group
-at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
-contributed to Berkeley.
-
-All advertising materials mentioning features or use of this software
-must display the following acknowledgement:
- This product includes software developed by the University of
- California, Lawrence Berkeley Laboratory.
-
-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) 1992, 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
@@ -2759,42 +2811,6 @@
-------------------------------------------------------------------
-Copyright (c) 1997, 1998, 2003 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by J.T. Conklin, by Nathan J. Williams, and by Jason R. Thorpe.
-
-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. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the NetBSD
- Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 1997, 2005 Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
@@ -3321,13 +3337,6 @@
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. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by the NetBSD
- Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -3417,6 +3426,32 @@
-------------------------------------------------------------------
+Copyright (c) 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 Networks Associates Technology, Inc.
All rights reserved.
@@ -3658,6 +3693,32 @@
-------------------------------------------------------------------
+Copyright (c) 2004, 2005 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) 2005 Tim J. Robbins.
All rights reserved.
@@ -4386,6 +4447,32 @@
-------------------------------------------------------------------
+Copyright (c)2003 Citrus Project,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright 2000 David E. O'Brien, John D. Polstra.
All rights reserved.
@@ -4411,32 +4498,6 @@
-------------------------------------------------------------------
-Copyright 2006, The Android Open Source Project
-
-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.
- Neither the name of Google Inc. 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 Google Inc. ``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 Google Inc. 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 2008 Android Open Source Project (source port randomization)
Copyright (c) 1985, 1989, 1993
The Regents of the University of California. All rights reserved.
@@ -4560,18 +4621,157 @@
The author of this software is David M. Gay.
-Copyright (c) 1991 by AT&T.
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
-Permission to use, copy, modify, and distribute this software for any
-purpose without fee is hereby granted, provided that this entire notice
-is included in all copies of any software which is or includes a copy
-or modification of this software and in all copies of the supporting
-documentation for such software.
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
-THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
-WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
-REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
-OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
-------------------------------------------------------------------
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index cbc5fa7..2dbcb56 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -4,6 +4,7 @@
libc_common_src_files_arm := \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
+ bionic/time64.c \
# These are shared by all the 32-bit targets, but not the 64-bit ones.
libc_bionic_src_files_arm := \
diff --git a/libc/arch-arm/bionic/libgcc_compat.c b/libc/arch-arm/bionic/libgcc_compat.c
index c45e6e2..10faf2d 100644
--- a/libc/arch-arm/bionic/libgcc_compat.c
+++ b/libc/arch-arm/bionic/libgcc_compat.c
@@ -1,91 +1,159 @@
/* Generated by genlibgcc_compat.py */
-#define COMPAT_FUNCTIONS_LIST \
- XX(__adddf3) \
- XX(__addsf3) \
- XX(__aeabi_cdcmpeq) \
- XX(__aeabi_cdcmple) \
- XX(__aeabi_cdrcmple) \
- XX(__aeabi_d2f) \
- XX(__aeabi_d2iz) \
- XX(__aeabi_dadd) \
- XX(__aeabi_dcmpeq) \
- XX(__aeabi_dcmpge) \
- XX(__aeabi_dcmpgt) \
- XX(__aeabi_dcmple) \
- XX(__aeabi_dcmplt) \
- XX(__aeabi_dcmpun) \
- XX(__aeabi_ddiv) \
- XX(__aeabi_dmul) \
- XX(__aeabi_drsub) \
- XX(__aeabi_dsub) \
- XX(__aeabi_f2d) \
- XX(__aeabi_f2iz) \
- XX(__aeabi_f2uiz) \
- XX(__aeabi_fadd) \
- XX(__aeabi_fcmpun) \
- XX(__aeabi_fdiv) \
- XX(__aeabi_fmul) \
- XX(__aeabi_frsub) \
- XX(__aeabi_fsub) \
- XX(__aeabi_i2d) \
- XX(__aeabi_i2f) \
- XX(__aeabi_idiv) \
- XX(__aeabi_idivmod) \
- XX(__aeabi_l2d) \
- XX(__aeabi_l2f) \
- XX(__aeabi_lasr) \
- XX(__aeabi_ldivmod) \
- XX(__aeabi_llsl) \
- XX(__aeabi_llsr) \
- XX(__aeabi_lmul) \
- XX(__aeabi_ui2d) \
- XX(__aeabi_ui2f) \
- XX(__aeabi_uidiv) \
- XX(__aeabi_uidivmod) \
- XX(__aeabi_ul2d) \
- XX(__aeabi_ul2f) \
- XX(__aeabi_uldivmod) \
- XX(__aeabi_unwind_cpp_pr0) \
- XX(__aeabi_unwind_cpp_pr1) \
- XX(__cmpdf2) \
- XX(__divdf3) \
- XX(__divsf3) \
- XX(__eqdf2) \
- XX(__extendsfdf2) \
- XX(__fixdfsi) \
- XX(__fixsfsi) \
- XX(__floatdidf) \
- XX(__floatdisf) \
- XX(__floatsidf) \
- XX(__floatsisf) \
- XX(__floatundidf) \
- XX(__floatundisf) \
- XX(__floatunsidf) \
- XX(__floatunsisf) \
- XX(__gedf2) \
- XX(__gtdf2) \
- XX(__ledf2) \
- XX(__ltdf2) \
- XX(__muldf3) \
- XX(__muldi3) \
- XX(__mulsf3) \
- XX(__nedf2) \
- XX(__popcount_tab) \
- XX(__popcountsi2) \
- XX(__subdf3) \
- XX(__subsf3) \
- XX(__truncdfsf2) \
- XX(__unorddf2) \
- XX(__unordsf2) \
+extern char __adddf3;
+extern char __addsf3;
+extern char __aeabi_cdcmpeq;
+extern char __aeabi_cdcmple;
+extern char __aeabi_cdrcmple;
+extern char __aeabi_d2f;
+extern char __aeabi_d2iz;
+extern char __aeabi_dadd;
+extern char __aeabi_dcmpeq;
+extern char __aeabi_dcmpge;
+extern char __aeabi_dcmpgt;
+extern char __aeabi_dcmple;
+extern char __aeabi_dcmplt;
+extern char __aeabi_dcmpun;
+extern char __aeabi_ddiv;
+extern char __aeabi_dmul;
+extern char __aeabi_drsub;
+extern char __aeabi_dsub;
+extern char __aeabi_f2d;
+extern char __aeabi_f2iz;
+extern char __aeabi_f2uiz;
+extern char __aeabi_fadd;
+extern char __aeabi_fcmpun;
+extern char __aeabi_fdiv;
+extern char __aeabi_fmul;
+extern char __aeabi_frsub;
+extern char __aeabi_fsub;
+extern char __aeabi_i2d;
+extern char __aeabi_i2f;
+extern char __aeabi_idiv;
+extern char __aeabi_idivmod;
+extern char __aeabi_l2d;
+extern char __aeabi_l2f;
+extern char __aeabi_lasr;
+extern char __aeabi_ldivmod;
+extern char __aeabi_llsl;
+extern char __aeabi_llsr;
+extern char __aeabi_lmul;
+extern char __aeabi_ui2d;
+extern char __aeabi_ui2f;
+extern char __aeabi_uidiv;
+extern char __aeabi_uidivmod;
+extern char __aeabi_ul2d;
+extern char __aeabi_ul2f;
+extern char __aeabi_uldivmod;
+extern char __aeabi_unwind_cpp_pr0;
+extern char __aeabi_unwind_cpp_pr1;
+extern char __cmpdf2;
+extern char __divdf3;
+extern char __divsf3;
+extern char __eqdf2;
+extern char __extendsfdf2;
+extern char __fixdfsi;
+extern char __fixsfsi;
+extern char __floatdidf;
+extern char __floatdisf;
+extern char __floatsidf;
+extern char __floatsisf;
+extern char __floatundidf;
+extern char __floatundisf;
+extern char __floatunsidf;
+extern char __floatunsisf;
+extern char __gedf2;
+extern char __gtdf2;
+extern char __ledf2;
+extern char __ltdf2;
+extern char __muldf3;
+extern char __muldi3;
+extern char __mulsf3;
+extern char __nedf2;
+extern char __popcount_tab;
+extern char __popcountsi2;
+extern char __subdf3;
+extern char __subsf3;
+extern char __truncdfsf2;
+extern char __unorddf2;
+extern char __unordsf2;
-
-#define XX(f) extern void f(void);
-COMPAT_FUNCTIONS_LIST
-#undef XX
-
-void __bionic_libgcc_compat_hooks(void) {
-#define XX(f) f();
-COMPAT_FUNCTIONS_LIST
-#undef XX
-}
+void* __bionic_libgcc_compat_symbols[] = {
+ &__adddf3,
+ &__addsf3,
+ &__aeabi_cdcmpeq,
+ &__aeabi_cdcmple,
+ &__aeabi_cdrcmple,
+ &__aeabi_d2f,
+ &__aeabi_d2iz,
+ &__aeabi_dadd,
+ &__aeabi_dcmpeq,
+ &__aeabi_dcmpge,
+ &__aeabi_dcmpgt,
+ &__aeabi_dcmple,
+ &__aeabi_dcmplt,
+ &__aeabi_dcmpun,
+ &__aeabi_ddiv,
+ &__aeabi_dmul,
+ &__aeabi_drsub,
+ &__aeabi_dsub,
+ &__aeabi_f2d,
+ &__aeabi_f2iz,
+ &__aeabi_f2uiz,
+ &__aeabi_fadd,
+ &__aeabi_fcmpun,
+ &__aeabi_fdiv,
+ &__aeabi_fmul,
+ &__aeabi_frsub,
+ &__aeabi_fsub,
+ &__aeabi_i2d,
+ &__aeabi_i2f,
+ &__aeabi_idiv,
+ &__aeabi_idivmod,
+ &__aeabi_l2d,
+ &__aeabi_l2f,
+ &__aeabi_lasr,
+ &__aeabi_ldivmod,
+ &__aeabi_llsl,
+ &__aeabi_llsr,
+ &__aeabi_lmul,
+ &__aeabi_ui2d,
+ &__aeabi_ui2f,
+ &__aeabi_uidiv,
+ &__aeabi_uidivmod,
+ &__aeabi_ul2d,
+ &__aeabi_ul2f,
+ &__aeabi_uldivmod,
+ &__aeabi_unwind_cpp_pr0,
+ &__aeabi_unwind_cpp_pr1,
+ &__cmpdf2,
+ &__divdf3,
+ &__divsf3,
+ &__eqdf2,
+ &__extendsfdf2,
+ &__fixdfsi,
+ &__fixsfsi,
+ &__floatdidf,
+ &__floatdisf,
+ &__floatsidf,
+ &__floatsisf,
+ &__floatundidf,
+ &__floatundisf,
+ &__floatunsidf,
+ &__floatunsisf,
+ &__gedf2,
+ &__gtdf2,
+ &__ledf2,
+ &__ltdf2,
+ &__muldf3,
+ &__muldi3,
+ &__mulsf3,
+ &__nedf2,
+ &__popcount_tab,
+ &__popcountsi2,
+ &__subdf3,
+ &__subsf3,
+ &__truncdfsf2,
+ &__unorddf2,
+ &__unordsf2,
+};
diff --git a/libc/arch-arm/include/machine/ieee.h b/libc/arch-arm/include/machine/ieee.h
deleted file mode 100644
index cf06580..0000000
--- a/libc/arch-arm/include/machine/ieee.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/* $OpenBSD: ieee.h,v 1.4 2011/11/08 17:06:51 deraadt Exp $ */
-/* $NetBSD: ieee.h,v 1.2 2001/02/21 17:43:50 bjh21 Exp $ */
-
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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.
- *
- * @(#)ieee.h 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point.
- */
-
-/*
- * Define the number of bits in each fraction and exponent.
- *
- * k k+1
- * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
- *
- * (-exp_bias+1)
- * as fractions that look like 0.fffff x 2 . This means that
- *
- * -126
- * the number 0.10000 x 2 , for instance, is the same as the normalized
- *
- * -127 -128
- * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
- *
- * -129
- * in the fraction; to represent 2 , we need two, and so on. This
- *
- * (-exp_bias-fracbits+1)
- * implies that the smallest denormalized number is 2
- *
- * for whichever format we are talking about: for single precision, for
- *
- * -126 -149
- * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
- *
- * -149 == -127 - 23 + 1.
- */
-
-/*
- * The ARM has two sets of FP data formats. The FPA supports 32-bit, 64-bit
- * and 96-bit IEEE formats, with the words in big-endian order. VFP supports
- * 32-bin and 64-bit IEEE formats with the words in the CPU's native byte
- * order.
- *
- * The FPA also has two packed decimal formats, but we ignore them here.
- */
-
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
-
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
-
-#ifndef __VFP_FP__
-#define E80_EXPBITS 15
-#define E80_FRACHBITS 31
-#define E80_FRACLBITS 32
-#define E80_FRACBITS 64
-
-#define EXT_EXPBITS 15
-#define EXT_FRACHBITS 16
-#define EXT_FRACHMBITS 32
-#define EXT_FRACLMBITS 32
-#define EXT_FRACLBITS 32
-#define EXT_FRACBITS 112
-#endif
-
-struct ieee_single {
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
-};
-
-#ifdef __VFP_FP__
-struct ieee_double {
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
-};
-#else /* !__VFP_FP__ */
-struct ieee_double {
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
- u_int dbl_fracl;
-};
-
-union ieee_double_u {
- double dblu_d;
- struct ieee_double dblu_dbl;
-};
-
-
-struct ieee_e80 {
- u_int e80_exp:15;
- u_int e80_zero:16;
- u_int e80_sign:1;
- u_int e80_frach:31;
- u_int e80_j:1;
- u_int e80_fracl;
-};
-
-struct ieee_ext {
- u_int ext_frach:16;
- u_int ext_exp:15;
- u_int ext_sign:1;
- u_int ext_frachm;
- u_int ext_fraclm;
- u_int ext_fracl;
-};
-#endif /* !__VFP_FP__ */
-
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#ifndef __VFP_FP__
-#define E80_EXP_INFNAN 32767
-#define EXT_EXP_INFNAN 32767
-#endif /* !__VFP_FP__ */
-
-#if 0
-#define SNG_QUIETNAN (1 << 22)
-#define DBL_QUIETNAN (1 << 19)
-#ifndef __VFP_FP__
-#define E80_QUIETNAN (1 << 15)
-#define EXT_QUIETNAN (1 << 15)
-#endif /* !__VFP_FP__ */
-#endif
-
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#ifndef __VFP_FP__
-#define E80_EXP_BIAS 16383
-#define EXT_EXP_BIAS 16383
-#endif /* !__VFP_FP__ */
diff --git a/libc/arch-mips/include/machine/ieee.h b/libc/arch-mips/include/machine/ieee.h
deleted file mode 100644
index 520a77b..0000000
--- a/libc/arch-mips/include/machine/ieee.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* $OpenBSD: ieee.h,v 1.4 2010/01/23 19:11:21 miod Exp $ */
-
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * 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.
- *
- * @(#)ieee.h 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point. It does *not* define (yet?) any of the rounding
- * mode bits, exceptions, and so forth.
- */
-
-/*
- * Define the number of bits in each fraction and exponent.
- *
- * k k+1
- * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
- *
- * (-exp_bias+1)
- * as fractions that look like 0.fffff x 2 . This means that
- *
- * -126
- * the number 0.10000 x 2 , for instance, is the same as the normalized
- *
- * -127 -128
- * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
- *
- * -129
- * in the fraction; to represent 2 , we need two, and so on. This
- *
- * (-exp_bias-fracbits+1)
- * implies that the smallest denormalized number is 2
- *
- * for whichever format we are talking about: for single precision, for
- *
- * -126 -149
- * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
- *
- * -149 == -127 - 23 + 1.
- */
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
-
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
-
-#define EXT_EXPBITS 15
-#define EXT_FRACHBITS 16
-#define EXT_FRACHMBITS 32
-#define EXT_FRACLMBITS 32
-#define EXT_FRACLBITS 32
-#define EXT_FRACBITS 112
-
-#define EXT_IMPLICIT_NBIT
-
-#define EXT_TO_ARRAY32(p, a) do { \
- (a)[0] = (uint32_t)(p)->ext_fracl; \
- (a)[1] = (uint32_t)(p)->ext_fraclm; \
- (a)[2] = (uint32_t)(p)->ext_frachm; \
- (a)[3] = (uint32_t)(p)->ext_frach; \
-} while(0)
-
-struct ieee_single {
-#ifdef __MIPSEB__
- u_int sng_sign:1;
- u_int sng_exp:8;
- u_int sng_frac:23;
-#else
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
-#endif
-};
-
-struct ieee_double {
-#ifdef __MIPSEB__
- u_int dbl_sign:1;
- u_int dbl_exp:11;
- u_int dbl_frach:20;
- u_int dbl_fracl;
-#else
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
-#endif
-};
-
-struct ieee_ext {
-#ifdef __MIPSEB__
- u_int ext_sign:1;
- u_int ext_exp:15;
- u_int ext_frach:16;
- u_int ext_frachm;
- u_int ext_fraclm;
- u_int ext_fracl;
-#else
- u_int ext_fracl;
- u_int ext_fraclm;
- u_int ext_frachm;
- u_int ext_frach:16;
- u_int ext_exp:15;
- u_int ext_sign:1;
-#endif
-};
-
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#define EXT_EXP_INFNAN 32767
-
-#if 0
-#define SNG_QUIETNAN (1 << 22)
-#define DBL_QUIETNAN (1 << 19)
-#define EXT_QUIETNAN (1 << 15)
-#endif
-
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#define EXT_EXP_BIAS 16383
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 1af4a65..53fa223 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -4,6 +4,7 @@
libc_common_src_files_mips := \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
+ bionic/time64.c \
# These are shared by all the 32-bit targets, but not the 64-bit ones.
libc_bionic_src_files_mips += \
diff --git a/libc/arch-mips64/include/machine/ieee.h b/libc/arch-mips64/include/machine/ieee.h
deleted file mode 100644
index 520a77b..0000000
--- a/libc/arch-mips64/include/machine/ieee.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* $OpenBSD: ieee.h,v 1.4 2010/01/23 19:11:21 miod Exp $ */
-
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * 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.
- *
- * @(#)ieee.h 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point. It does *not* define (yet?) any of the rounding
- * mode bits, exceptions, and so forth.
- */
-
-/*
- * Define the number of bits in each fraction and exponent.
- *
- * k k+1
- * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
- *
- * (-exp_bias+1)
- * as fractions that look like 0.fffff x 2 . This means that
- *
- * -126
- * the number 0.10000 x 2 , for instance, is the same as the normalized
- *
- * -127 -128
- * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
- *
- * -129
- * in the fraction; to represent 2 , we need two, and so on. This
- *
- * (-exp_bias-fracbits+1)
- * implies that the smallest denormalized number is 2
- *
- * for whichever format we are talking about: for single precision, for
- *
- * -126 -149
- * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
- *
- * -149 == -127 - 23 + 1.
- */
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
-
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
-
-#define EXT_EXPBITS 15
-#define EXT_FRACHBITS 16
-#define EXT_FRACHMBITS 32
-#define EXT_FRACLMBITS 32
-#define EXT_FRACLBITS 32
-#define EXT_FRACBITS 112
-
-#define EXT_IMPLICIT_NBIT
-
-#define EXT_TO_ARRAY32(p, a) do { \
- (a)[0] = (uint32_t)(p)->ext_fracl; \
- (a)[1] = (uint32_t)(p)->ext_fraclm; \
- (a)[2] = (uint32_t)(p)->ext_frachm; \
- (a)[3] = (uint32_t)(p)->ext_frach; \
-} while(0)
-
-struct ieee_single {
-#ifdef __MIPSEB__
- u_int sng_sign:1;
- u_int sng_exp:8;
- u_int sng_frac:23;
-#else
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
-#endif
-};
-
-struct ieee_double {
-#ifdef __MIPSEB__
- u_int dbl_sign:1;
- u_int dbl_exp:11;
- u_int dbl_frach:20;
- u_int dbl_fracl;
-#else
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
-#endif
-};
-
-struct ieee_ext {
-#ifdef __MIPSEB__
- u_int ext_sign:1;
- u_int ext_exp:15;
- u_int ext_frach:16;
- u_int ext_frachm;
- u_int ext_fraclm;
- u_int ext_fracl;
-#else
- u_int ext_fracl;
- u_int ext_fraclm;
- u_int ext_frachm;
- u_int ext_frach:16;
- u_int ext_exp:15;
- u_int ext_sign:1;
-#endif
-};
-
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#define EXT_EXP_INFNAN 32767
-
-#if 0
-#define SNG_QUIETNAN (1 << 22)
-#define DBL_QUIETNAN (1 << 19)
-#define EXT_QUIETNAN (1 << 15)
-#endif
-
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#define EXT_EXP_BIAS 16383
diff --git a/libc/arch-x86/include/machine/ieee.h b/libc/arch-x86/include/machine/ieee.h
deleted file mode 100644
index 865fcb9..0000000
--- a/libc/arch-x86/include/machine/ieee.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* $OpenBSD: ieee.h,v 1.3 2008/09/07 20:36:06 martynas Exp $ */
-/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */
-
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * 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.
- *
- * @(#)ieee.h 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point. It does *not* define (yet?) any of the rounding
- * mode bits, exceptions, and so forth.
- */
-
-/*
- * Define the number of bits in each fraction and exponent.
- *
- * k k+1
- * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
- *
- * (-exp_bias+1)
- * as fractions that look like 0.fffff x 2 . This means that
- *
- * -126
- * the number 0.10000 x 2 , for instance, is the same as the normalized
- *
- * -127 -128
- * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
- *
- * -129
- * in the fraction; to represent 2 , we need two, and so on. This
- *
- * (-exp_bias-fracbits+1)
- * implies that the smallest denormalized number is 2
- *
- * for whichever format we are talking about: for single precision, for
- *
- * -126 -149
- * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
- *
- * -149 == -127 - 23 + 1.
- */
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
-
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
-
-#define EXT_EXPBITS 15
-#define EXT_FRACHBITS 32
-#define EXT_FRACLBITS 32
-#define EXT_FRACBITS 64
-
-#define EXT_TO_ARRAY32(p, a) do { \
- (a)[0] = (uint32_t)(p)->ext_fracl; \
- (a)[1] = (uint32_t)(p)->ext_frach; \
-} while(0)
-
-struct ieee_single {
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
-};
-
-struct ieee_double {
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
-};
-
-struct ieee_ext {
- u_int ext_fracl;
- u_int ext_frach;
- u_int ext_exp:15;
- u_int ext_sign:1;
- u_int ext_pad:16;
-};
-
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#define EXT_EXP_INFNAN 32767
-
-#if 0
-#define SNG_QUIETNAN (1 << 22)
-#define DBL_QUIETNAN (1 << 19)
-#define EXT_QUIETNAN (1 << 15)
-#endif
-
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#define EXT_EXP_BIAS 16383
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 846bb42..a1d55f0 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -4,6 +4,7 @@
libc_common_src_files_x86 := \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
+ bionic/time64.c \
# Fortify implementations of libc functions.
libc_common_src_files_x86 += \
diff --git a/libc/arch-x86_64/include/machine/ieee.h b/libc/arch-x86_64/include/machine/ieee.h
deleted file mode 100644
index 74856b2..0000000
--- a/libc/arch-x86_64/include/machine/ieee.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* $OpenBSD: ieee.h,v 1.2 2008/09/07 20:36:06 martynas Exp $ */
-/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */
-
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory.
- *
- * 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.
- *
- * @(#)ieee.h 8.1 (Berkeley) 6/11/93
- */
-
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point. It does *not* define (yet?) any of the rounding
- * mode bits, exceptions, and so forth.
- */
-
-/*
- * Define the number of bits in each fraction and exponent.
- *
- * k k+1
- * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
- *
- * (-exp_bias+1)
- * as fractions that look like 0.fffff x 2 . This means that
- *
- * -126
- * the number 0.10000 x 2 , for instance, is the same as the normalized
- *
- * -127 -128
- * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
- *
- * -129
- * in the fraction; to represent 2 , we need two, and so on. This
- *
- * (-exp_bias-fracbits+1)
- * implies that the smallest denormalized number is 2
- *
- * for whichever format we are talking about: for single precision, for
- *
- * -126 -149
- * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
- *
- * -149 == -127 - 23 + 1.
- */
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
-
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
-
-#define EXT_EXPBITS 15
-#define EXT_FRACHBITS 32
-#define EXT_FRACLBITS 32
-#define EXT_FRACBITS 64
-
-#define EXT_TO_ARRAY32(p, a) do { \
- (a)[0] = (uint32_t)(p)->ext_fracl; \
- (a)[1] = (uint32_t)(p)->ext_frach; \
-} while(0)
-
-struct ieee_single {
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
-};
-
-struct ieee_double {
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
-};
-
-struct ieee_ext {
- u_int ext_fracl;
- u_int ext_frach;
- u_int ext_exp:15;
- u_int ext_sign:1;
- u_int ext_padl:16;
- u_int ext_padh;
-};
-
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#define EXT_EXP_INFNAN 32767
-
-#if 0
-#define SNG_QUIETNAN (1 << 22)
-#define DBL_QUIETNAN (1 << 19)
-#define EXT_QUIETNAN (1 << 15)
-#endif
-
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#define EXT_EXP_BIAS 16383
diff --git a/libc/bionic/clearenv.c b/libc/bionic/clearenv.cpp
similarity index 88%
rename from libc/bionic/clearenv.c
rename to libc/bionic/clearenv.cpp
index 0f6f066..c70cc3e 100644
--- a/libc/bionic/clearenv.c
+++ b/libc/bionic/clearenv.cpp
@@ -26,17 +26,15 @@
* SUCH DAMAGE.
*/
-#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
-extern char** environ;
-
-int clearenv(void)
-{
- char **P = environ;
-
- if (P != NULL) {
- for (; *P; ++P)
- *P = NULL;
+int clearenv() {
+ char** e = environ;
+ if (e != NULL) {
+ for (; *e; ++e) {
+ *e = NULL;
}
- return 0;
+ }
+ return 0;
}
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 83171ad..4207a3f 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -87,18 +87,6 @@
}
};
-#if defined(__arm__) && !defined(_Unwind_GetIP)
-// Older versions of Clang don't provide a definition of _Unwind_GetIP(), so
-// we include an appropriate version of our own. Once we have updated to
-// Clang 3.4, this code can be removed.
-static __inline__
-uintptr_t _Unwind_GetIP(struct _Unwind_Context *__context) {
- uintptr_t __ip = 0;
- _Unwind_VRS_Get(__context, _UVRSC_CORE, 15, _UVRSD_UINT32, &__ip);
- return __ip & ~0x1;
-}
-#endif
-
static _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) {
stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg);
diff --git a/libc/bionic/fpclassify.cpp b/libc/bionic/fpclassify.cpp
index 8231093..21ff946 100644
--- a/libc/bionic/fpclassify.cpp
+++ b/libc/bionic/fpclassify.cpp
@@ -90,28 +90,47 @@
}
__strong_alias(isnanf, __isnanf);
+int __isfinite(double d) {
+ int type = __fpclassifyd(d);
+ return ((type != FP_NAN) && (type != FP_INFINITE));
+}
+__strong_alias(isfinite, __isfinite);
+
+int __isfinitef(float f) {
+ int type = __fpclassifyf(f);
+ return ((type != FP_NAN) && (type != FP_INFINITE));
+}
+__strong_alias(isfinitef, __isfinitef);
+
+int __isnormal(double d) {
+ return (__fpclassifyd(d) == FP_NORMAL);
+}
+__strong_alias(isnormal, __isnormal);
+
+int __isnormalf(float f) {
+ return (__fpclassifyf(f) == FP_NORMAL);
+}
+__strong_alias(isnormalf, __isnormalf);
+
#if __LP64__
// LP64 uses 128-bit long doubles.
union long_double_u {
long double ld;
- struct {
- unsigned long fracl:64;
- unsigned long frach:48;
- unsigned int exp:15;
- unsigned int sign:1;
- } bits;
+ ieee_ext bits;
};
+#define zero_frac(b) ((b.ext_fracl | b.ext_fraclm | b.ext_frachm | b.ext_frach) == 0)
+
int __fpclassifyl(long double ld) {
long_double_u u;
u.ld = ld;
- if (u.bits.exp == 0) {
- return ((u.bits.fracl | u.bits.frach) == 0) ? FP_ZERO : FP_SUBNORMAL;
+ if (u.bits.ext_exp == 0) {
+ return zero_frac(u.bits) ? FP_ZERO : FP_SUBNORMAL;
}
- if (u.bits.exp == EXT_EXP_INFNAN) {
- return ((u.bits.fracl | u.bits.frach) == 0) ? FP_INFINITE : FP_NAN;
+ if (u.bits.ext_exp == EXT_EXP_INFNAN) {
+ return zero_frac(u.bits) ? FP_INFINITE : FP_NAN;
}
return FP_NORMAL;
}
@@ -124,6 +143,15 @@
return (__fpclassifyl(ld) == FP_NAN);
}
+int __isfinitel(long double ld) {
+ int type = __fpclassifyl(ld);
+ return ((type != FP_NAN) && (type != FP_INFINITE));
+}
+
+int __isnormall(long double ld) {
+ return (__fpclassifyl(ld) == FP_NORMAL);
+}
+
#else
// LP32 uses double as long double.
@@ -131,8 +159,12 @@
__strong_alias(__fpclassifyl, __fpclassify);
__strong_alias(__isinfl, __isinf);
__strong_alias(__isnanl, __isnan);
+__strong_alias(__isfinitel, __isfinite);
+__strong_alias(__isnormall, __isnormal);
#endif
__strong_alias(isinfl, __isinfl);
__strong_alias(isnanl, __isnanl);
+__strong_alias(isfinitel, __isfinitel);
+__strong_alias(isnormall, __isnormall);
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 4fade84..5ab834d 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -39,8 +39,11 @@
static pthread_once_t gLocaleOnce = PTHREAD_ONCE_INIT;
static lconv gLocale;
-static pthread_once_t gUselocaleKeyOnce = PTHREAD_ONCE_INIT;
+// We don't use pthread_once for this so that we know when the resource (a TLS slot) will be taken.
static pthread_key_t gUselocaleKey;
+__attribute__((constructor)) static void __bionic_tls_uselocale_key_init() {
+ pthread_key_create(&gUselocaleKey, NULL);
+}
static void __locale_init() {
gLocale.decimal_point = const_cast<char*>(".");
@@ -72,10 +75,6 @@
gLocale.int_n_sign_posn = CHAR_MAX;
}
-static void __uselocale_key_init() {
- pthread_key_create(&gUselocaleKey, NULL);
-}
-
static bool __is_supported_locale(const char* locale) {
return (strcmp(locale, "") == 0 || strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0);
}
@@ -139,8 +138,6 @@
}
locale_t uselocale(locale_t new_locale) {
- pthread_once(&gUselocaleKeyOnce, __uselocale_key_init);
-
locale_t old_locale = static_cast<locale_t>(pthread_getspecific(gUselocaleKey));
// If this is the first call to uselocale(3) on this thread, we return LC_GLOBAL_LOCALE.
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index 7826651..2fed492 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -116,4 +116,72 @@
return s;
}
+static inline int digitval(int ch) {
+ unsigned d;
+
+ d = (unsigned)(ch - '0');
+ if (d < 10) return (int)d;
+
+ d = (unsigned)(ch - 'a');
+ if (d < 6) return (int)(d+10);
+
+ d = (unsigned)(ch - 'A');
+ if (d < 6) return (int)(d+10);
+
+ return -1;
+}
+
+// This non-standard function was in our <inttypes.h> for some reason.
+extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
+ const unsigned char* p = (const unsigned char *)nptr;
+ const unsigned char* end = p + n;
+ int minus = 0;
+ uintmax_t v = 0;
+ int d;
+
+ while (p < end && isspace(*p)) {
+ p++;
+ }
+
+ if (p < end) {
+ char c = p[0];
+ if (c == '-' || c == '+') {
+ minus = (c == '-');
+ p++;
+ }
+ }
+
+ if (base == 0) {
+ if (p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ p += 2;
+ base = 16;
+ } else if (p+1 < end && p[0] == '0') {
+ p += 1;
+ base = 8;
+ } else {
+ base = 10;
+ }
+ } else if (base == 16) {
+ if (p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ p += 2;
+ }
+ }
+
+ while (p < end && (d = digitval(*p)) >= 0 && d < base) {
+ v = v*base + d;
+ p += 1;
+ }
+
+ if (endptr) {
+ *endptr = (char*) p;
+ }
+
+ return minus ? -v : v;
+}
+
+// This non-standard function was in our <inttypes.h> for some reason.
+extern "C" intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
+ return (intmax_t) strntoumax(nptr, endptr, base, n);
+}
+
#endif
diff --git a/libc/bionic/strntoimax.c b/libc/bionic/strntoimax.c
deleted file mode 100644
index 2f3cd9a..0000000
--- a/libc/bionic/strntoimax.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 <stddef.h>
-#include <inttypes.h>
-
-intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n)
-{
- return (intmax_t) strntoumax(nptr, endptr, base, n);
-}
diff --git a/libc/bionic/strntoumax.c b/libc/bionic/strntoumax.c
deleted file mode 100644
index 050d718..0000000
--- a/libc/bionic/strntoumax.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 <stddef.h>
-#include <stdint.h>
-#include <ctype.h>
-
-static inline int digitval(int ch)
-{
- unsigned d;
-
- d = (unsigned)(ch - '0');
- if (d < 10) return (int)d;
-
- d = (unsigned)(ch - 'a');
- if (d < 6) return (int)(d+10);
-
- d = (unsigned)(ch - 'A');
- if (d < 6) return (int)(d+10);
-
- return -1;
-}
-
-uintmax_t
-strntoumax(const char *nptr, char **endptr, int base, size_t n)
-{
- const unsigned char* p = (const unsigned char *)nptr;
- const unsigned char* end = p + n;
- int minus = 0;
- uintmax_t v = 0;
- int d;
-
- /* skip leading space */
- while (p < end && isspace(*p))
- p++;
-
- /* Single optional + or - */
- if (p < end) {
- char c = p[0];
- if ( c == '-' || c == '+' ) {
- minus = (c == '-');
- p++;
- }
- }
-
- if ( base == 0 ) {
- if ( p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X') ) {
- p += 2;
- base = 16;
- } else if ( p+1 < end && p[0] == '0' ) {
- p += 1;
- base = 8;
- } else {
- base = 10;
- }
- } else if ( base == 16 ) {
- if ( p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X') ) {
- p += 2;
- }
- }
-
- while ( p < end && (d = digitval(*p)) >= 0 && d < base ) {
- v = v*base + d;
- p += 1;
- }
-
- if ( endptr )
- *endptr = (char *)p;
-
- return minus ? -v : v;
-}
diff --git a/libc/bionic/strtold.cpp b/libc/bionic/strtold.cpp
index 079f393..5616cf7 100644
--- a/libc/bionic/strtold.cpp
+++ b/libc/bionic/strtold.cpp
@@ -26,9 +26,18 @@
* SUCH DAMAGE.
*/
+#include <float.h>
#include <stdlib.h>
+extern "C" int __strtorQ(const char*, char**, int, void*);
+
long double strtold(const char* s, char** end_ptr) {
- // TODO: this is fine for LP32 where double == long double, but is broken on LP64.
+#if __LP64__
+ long double result;
+ __strtorQ(s, end_ptr, FLT_ROUNDS, &result);
+ return result;
+#else
+ // This is fine for LP32 where long double is just double.
return strtod(s, end_ptr);
+#endif
}
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index 9aa5d4f..7163b34 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -28,6 +28,10 @@
/* See http://code.google.com/p/y2038 for this code's origin */
+#if defined(__LP64__)
+#error This cruft should be LP32 only!
+#endif
+
/*
Programmers who have available to them 64-bit time values as a 'long
@@ -268,7 +272,7 @@
assert(tm->tm_wday >= 0);
assert(tm->tm_wday <= 6);
-
+
assert(tm->tm_yday >= 0);
assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]);
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index 8367817..021d14b 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -243,21 +243,45 @@
return strftime(reinterpret_cast<char*>(wcs), maxsize, reinterpret_cast<const char*>(format), timptr);
}
-size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* /*ps*/) {
- const char* s = reinterpret_cast<const char*>(*src);
- const char* s2 = reinterpret_cast<const char*>(memchr(s, 0, len));
- if (s2 != NULL) {
- len = (s2 - s)+1;
+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) {
+ errno = EILSEQ;
+ if (dst != NULL) {
+ *src = &(*src)[i];
+ }
+ return static_cast<size_t>(-1);
+ }
+ if (dst != NULL) {
+ if (o + 1 > n) {
+ break;
+ }
+ dst[o++] = static_cast<char>((*src)[i]);
+ } else {
+ ++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) {
- memcpy( dst, s, len );
+ if ((*src)[i] != 0) {
+ *src = &(*src)[i]; // This is where the next call should pick up.
+ } else {
+ *src = NULL; // We consumed everything.
+ }
}
- *src = (wchar_t*)(s + len);
- return len;
+ return o;
}
size_t wcstombs(char* dst, const wchar_t* src, size_t len) {
- return wcsrtombs(dst, &src, len, NULL);
+ const wchar_t* p = src;
+ return wcsrtombs(dst, &p, len, NULL);
}
double wcstod(const wchar_t* nptr, wchar_t** endptr) {
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
new file mode 100644
index 0000000..90962fa
--- /dev/null
+++ b/libc/include/android/dlext.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#ifndef __ANDROID_DLEXT_H__
+#define __ANDROID_DLEXT_H__
+
+#include <stddef.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* bitfield definitions for android_dlextinfo.flags */
+enum {
+ /* When set, the reserved_addr and reserved_size fields must point to an
+ * already-reserved region of address space which will be used to load the
+ * library if it fits. If the reserved region is not large enough, the load
+ * will fail.
+ */
+ ANDROID_DLEXT_RESERVED_ADDRESS = 0x1,
+
+ /* As DLEXT_RESERVED_ADDRESS, but if the reserved region is not large enough,
+ * the linker will choose an available address instead.
+ */
+ ANDROID_DLEXT_RESERVED_ADDRESS_HINT = 0x2,
+
+ /* When set, write the GNU RELRO section of the mapped library to relro_fd
+ * after relocation has been performed, to allow it to be reused by another
+ * process loading the same library at the same address. This implies
+ * ANDROID_DLEXT_USE_RELRO.
+ */
+ ANDROID_DLEXT_WRITE_RELRO = 0x4,
+
+ /* When set, compare the GNU RELRO section of the mapped library to relro_fd
+ * after relocation has been performed, and replace any relocated pages that
+ * are identical with a version mapped from the file.
+ */
+ ANDROID_DLEXT_USE_RELRO = 0x8,
+
+ /* Mask of valid bits */
+ ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
+ ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
+ ANDROID_DLEXT_WRITE_RELRO |
+ ANDROID_DLEXT_USE_RELRO,
+};
+
+typedef struct {
+ int flags;
+ void* reserved_addr;
+ size_t reserved_size;
+ int relro_fd;
+} android_dlextinfo;
+
+extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
+
+__END_DECLS
+
+#endif /* __ANDROID_DLEXT_H__ */
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 5557e31..a66df12 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -44,12 +44,14 @@
#define _CTYPE_U 0x01
#define _CTYPE_L 0x02
-#define _CTYPE_N 0x04
+#define _CTYPE_D 0x04
#define _CTYPE_S 0x08
#define _CTYPE_P 0x10
#define _CTYPE_C 0x20
#define _CTYPE_X 0x40
#define _CTYPE_B 0x80
+#define _CTYPE_R (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_D|_CTYPE_B)
+#define _CTYPE_A (_CTYPE_L|_CTYPE_U)
__BEGIN_DECLS
@@ -57,17 +59,6 @@
extern const short *_tolower_tab_;
extern const short *_toupper_tab_;
-/* extern __inline is a GNU C extension */
-#ifdef __GNUC__
-# if defined(__GNUC_STDC_INLINE__)
-#define __CTYPE_INLINE extern __inline __attribute__((__gnu_inline__))
-# else
-#define __CTYPE_INLINE extern __inline
-# endif
-#else
-#define __CTYPE_INLINE static __inline
-#endif
-
#if defined(__GNUC__) || defined(_ANSI_LIBRARY) || defined(lint)
int isalnum(int);
int isalpha(int);
@@ -97,111 +88,6 @@
#endif /* __GNUC__ || _ANSI_LIBRARY || lint */
-#if defined(NDEBUG)
-
-__CTYPE_INLINE int isalnum(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_U|_CTYPE_L|_CTYPE_N)));
-}
-
-__CTYPE_INLINE int isalpha(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_U|_CTYPE_L)));
-}
-
-__CTYPE_INLINE int iscntrl(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_C));
-}
-
-__CTYPE_INLINE int isdigit(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_N));
-}
-
-__CTYPE_INLINE int isgraph(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N)));
-}
-
-__CTYPE_INLINE int islower(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_L));
-}
-
-__CTYPE_INLINE int isprint(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N|_CTYPE_B)));
-}
-
-__CTYPE_INLINE int ispunct(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_P));
-}
-
-__CTYPE_INLINE int isspace(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_S));
-}
-
-__CTYPE_INLINE int isupper(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_U));
-}
-
-__CTYPE_INLINE int isxdigit(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_N|_CTYPE_X)));
-}
-
-__CTYPE_INLINE int tolower(int c)
-{
- if ((unsigned int)c > 255)
- return (c);
- return ((_tolower_tab_ + 1)[c]);
-}
-
-__CTYPE_INLINE int toupper(int c)
-{
- if ((unsigned int)c > 255)
- return (c);
- return ((_toupper_tab_ + 1)[c]);
-}
-
-#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \
- || __XPG_VISIBLE > 600
-__CTYPE_INLINE int isblank(int c)
-{
- return (c == ' ' || c == '\t');
-}
-#endif
-
-#if __BSD_VISIBLE || __XPG_VISIBLE
-__CTYPE_INLINE int isascii(int c)
-{
- return ((unsigned int)c <= 0177);
-}
-
-__CTYPE_INLINE int toascii(int c)
-{
- return (c & 0177);
-}
-
-__CTYPE_INLINE int _tolower(int c)
-{
- return (c - 'A' + 'a');
-}
-
-__CTYPE_INLINE int _toupper(int c)
-{
- return (c - 'a' + 'A');
-}
-#endif /* __BSD_VISIBLE || __XPG_VISIBLE */
-
-#endif /* NDEBUG */
-
__END_DECLS
-#undef __CTYPE_INLINE
-
#endif /* !_CTYPE_H_ */
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 2fd2415..5199e4d 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -261,9 +261,6 @@
intmax_t strtoimax(const char *, char **, int);
uintmax_t strtoumax(const char *, char **, int);
-intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n);
-uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);
-
__END_DECLS
#endif /* _INTTYPES_H_ */
diff --git a/libc/include/locale.h b/libc/include/locale.h
index 6989851..7fd8c2c 100644
--- a/libc/include/locale.h
+++ b/libc/include/locale.h
@@ -33,21 +33,19 @@
__BEGIN_DECLS
-enum {
- LC_CTYPE = 0,
- LC_NUMERIC = 1,
- LC_TIME = 2,
- LC_COLLATE = 3,
- LC_MONETARY = 4,
- LC_MESSAGES = 5,
- LC_ALL = 6,
- LC_PAPER = 7,
- LC_NAME = 8,
- LC_ADDRESS = 9,
- LC_TELEPHONE = 10,
- LC_MEASUREMENT = 11,
- LC_IDENTIFICATION = 12
-};
+#define LC_CTYPE 0
+#define LC_NUMERIC 1
+#define LC_TIME 2
+#define LC_COLLATE 3
+#define LC_MONETARY 4
+#define LC_MESSAGES 5
+#define LC_ALL 6
+#define LC_PAPER 7
+#define LC_NAME 8
+#define LC_ADDRESS 9
+#define LC_TELEPHONE 10
+#define LC_MEASUREMENT 11
+#define LC_IDENTIFICATION 12
#define LC_CTYPE_MASK (1 << LC_CTYPE)
#define LC_NUMERIC_MASK (1 << LC_NUMERIC)
diff --git a/libc/arch-arm64/include/machine/ieee.h b/libc/include/machine/ieee.h
similarity index 66%
rename from libc/arch-arm64/include/machine/ieee.h
rename to libc/include/machine/ieee.h
index a6c024e..c579969 100644
--- a/libc/arch-arm64/include/machine/ieee.h
+++ b/libc/include/machine/ieee.h
@@ -45,48 +45,74 @@
* @(#)ieee.h 8.1 (Berkeley) 6/11/93
*/
-/*
- * ieee.h defines the machine-dependent layout of the machine's IEEE
- * floating point.
- */
+#ifndef _MACHINE_IEEE_H_
+#define _MACHINE_IEEE_H_
-#define SNG_EXPBITS 8
-#define SNG_FRACBITS 23
+#include <sys/types.h>
-#define DBL_EXPBITS 11
-#define DBL_FRACHBITS 20
-#define DBL_FRACLBITS 32
-#define DBL_FRACBITS 52
+__BEGIN_DECLS
+
+#define SNG_EXPBITS 8
+#define SNG_FRACBITS 23
+
+#define SNG_EXP_INFNAN 255
+#define SNG_EXP_BIAS 127
struct ieee_single {
- u_int sng_frac:23;
- u_int sng_exp:8;
- u_int sng_sign:1;
+ unsigned sng_frac:23;
+ unsigned sng_exp:8;
+ unsigned sng_sign:1;
};
+#define DBL_EXPBITS 11
+#define DBL_FRACHBITS 20
+#define DBL_FRACLBITS 32
+#define DBL_FRACBITS 52
+
+#define DBL_EXP_INFNAN 2047
+#define DBL_EXP_BIAS 1023
+
struct ieee_double {
- u_int dbl_fracl;
- u_int dbl_frach:20;
- u_int dbl_exp:11;
- u_int dbl_sign:1;
+ unsigned dbl_fracl;
+ unsigned dbl_frach:20;
+ unsigned dbl_exp:11;
+ unsigned dbl_sign:1;
};
-/*
- * Floats whose exponent is in [1..INFNAN) (of whatever type) are
- * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
- * Floats whose exponent is zero are either zero (iff all fraction
- * bits are zero) or subnormal values.
- *
- * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
- * high fraction; if the bit is set, it is a `quiet NaN'.
- */
-#define SNG_EXP_INFNAN 255
-#define DBL_EXP_INFNAN 2047
-#define EXT_EXP_INFNAN 32767
+#if __LP64__
-/*
- * Exponent biases.
- */
-#define SNG_EXP_BIAS 127
-#define DBL_EXP_BIAS 1023
-#define EXT_EXP_BIAS 16383
+/* 64-bit Android uses ld128 long doubles. */
+
+#define EXT_EXPBITS 15
+#define EXT_FRACHBITS 16
+#define EXT_FRACHMBITS 32
+#define EXT_FRACLMBITS 32
+#define EXT_FRACLBITS 32
+#define EXT_FRACBITS 112
+
+#define EXT_EXP_INFNAN 32767
+#define EXT_EXP_BIAS 16383
+
+#define EXT_IMPLICIT_NBIT
+
+#define EXT_TO_ARRAY32(p, a) do { \
+ (a)[0] = (uint32_t)(p)->ext_fracl; \
+ (a)[1] = (uint32_t)(p)->ext_fraclm; \
+ (a)[2] = (uint32_t)(p)->ext_frachm; \
+ (a)[3] = (uint32_t)(p)->ext_frach; \
+} while(0)
+
+struct ieee_ext {
+ unsigned ext_fracl;
+ unsigned ext_fraclm;
+ unsigned ext_frachm;
+ unsigned ext_frach:16;
+ unsigned ext_exp:15;
+ unsigned ext_sign:1;
+};
+
+#endif
+
+__END_DECLS
+
+#endif /* _MACHINE_IEEE_H_ */
diff --git a/libc/bionic/strtof.cpp b/libc/include/machine/wchar_limits.h
similarity index 79%
rename from libc/bionic/strtof.cpp
rename to libc/include/machine/wchar_limits.h
index a41e4d4..94cbd7e 100644
--- a/libc/bionic/strtof.cpp
+++ b/libc/include/machine/wchar_limits.h
@@ -26,9 +26,17 @@
* SUCH DAMAGE.
*/
-#include <stdlib.h>
+#ifndef _MACHINE_WCHAR_LIMITS_H_
+#define _MACHINE_WCHAR_LIMITS_H_
-float strtof(const char* s, char** end_ptr) {
- // TODO: upgrade to a non-hack implementation.
- return strtod(s, end_ptr);
-}
+/* Both GCC and clang define __WCHAR_MAX__. */
+#define WCHAR_MAX __WCHAR_MAX__
+
+/* As of 3.4, clang still doesn't define __WCHAR_MIN__. */
+#if defined(__WCHAR_UNSIGNED__)
+# define WCHAR_MIN L'\0'
+#else
+# define WCHAR_MIN (-(WCHAR_MAX) - 1)
+#endif
+
+#endif /* _MACHINE_WCHAR_LIMITS_H_ */
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index 1f3d003..f34843c 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -30,6 +30,7 @@
#define _STDINT_H
#include <stddef.h>
+#include <machine/wchar_limits.h>
typedef __signed char __int8_t;
typedef unsigned char __uint8_t;
@@ -86,7 +87,7 @@
typedef int64_t int_fast64_t;
typedef uint64_t uint_fast64_t;
-#ifdef __LP64__
+#if defined(__LP64__)
typedef int64_t int_fast16_t;
typedef uint64_t uint_fast16_t;
typedef int64_t int_fast32_t;
@@ -135,7 +136,7 @@
#define INTMAX_C(c) INT64_C(c)
#define UINTMAX_C(c) UINT64_C(c)
-#ifdef __LP64__
+#if defined(__LP64__)
# define INT64_C(c) c ## L
# define UINT64_C(c) c ## UL
# define INTPTR_C(c) INT64_C(c)
@@ -200,15 +201,15 @@
#define SIG_ATOMIC_MAX INT32_MAX
#define SIG_ATOMIC_MIN INT32_MIN
-#ifndef WCHAR_MAX /* These might also have been defined by <wchar.h>. */
-# define WCHAR_MAX INT32_MAX
-# define WCHAR_MIN INT32_MIN
+#if defined(__WINT_UNSIGNED__)
+# define WINT_MAX UINT32_MAX
+# define WINT_MIN UINT32_MIN
+#else
+# define WINT_MAX INT32_MAX
+# define WINT_MIN INT32_MIN
#endif
-#define WINT_MAX INT32_MAX
-#define WINT_MIN INT32_MIN
-
-#ifdef __LP64__
+#if defined(__LP64__)
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 2c797c5..6c966f7 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -46,10 +46,10 @@
extern __noreturn void _Exit(int);
extern int atexit(void (*)(void));
-extern char *getenv(const char *);
-extern int putenv(const char *);
-extern int setenv(const char *, const char *, int);
-extern int unsetenv(const char *);
+extern char* getenv(const char*);
+extern int putenv(char*);
+extern int setenv(const char*, const char*, int);
+extern int unsetenv(const char*);
extern int clearenv(void);
extern char* mkdtemp(char*);
@@ -65,9 +65,10 @@
extern int posix_memalign(void **memptr, size_t alignment, size_t size);
extern double atof(const char*);
-extern double strtod(const char*, char**);
-extern float strtof(const char*, char**);
-extern long double strtold(const char*, char**);
+
+extern double strtod(const char*, char**) __LIBC_ABI_PUBLIC__;
+extern float strtof(const char*, char**) __LIBC_ABI_PUBLIC__;
+extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
extern int atoi(const char*) __purefunc;
extern long atol(const char*) __purefunc;
diff --git a/libc/include/sys/cdefs_elf.h b/libc/include/sys/cdefs_elf.h
index bb846b7..c21214c 100644
--- a/libc/include/sys/cdefs_elf.h
+++ b/libc/include/sys/cdefs_elf.h
@@ -61,24 +61,11 @@
#define __SECTIONSTRING(_sec, _str) \
__asm__(".section " #_sec "\n\t.asciz \"" _str "\"\n\t.previous")
-/* GCC visibility helper macro */
-/* This must be used to tag non-static functions that are private, i.e.
- * never exposed by the shared library. */
-#define __LIBC_HIDDEN__ \
- __attribute__ ((visibility ("hidden")))
+/* Used to tag non-static symbols that are private and never exposed by the shared library. */
+#define __LIBC_HIDDEN__ __attribute__((visibility ("hidden")))
-/* This must be used to tag non-static functions that are public, i.e.
- * exposed by the shared library, and part of the stable NDK ABI */
-#define __LIBC_ABI_PUBLIC__ \
- __attribute__ ((visibility ("default")))
-
-/* This must be used to tag non-static functions that must be exported
- * by the shared library, but whose implementation is private to the
- * platform. For now this is equivalent to __LIBC_ABI_PUBLIC__, but we
- * may want to change this later.
- */
-#define __LIBC_ABI_PRIVATE__ \
- __attribute__ ((visibility ("default")))
+/* Used to tag non-static symbols that are public and exposed by the shared library. */
+#define __LIBC_ABI_PUBLIC__ __attribute__((visibility ("default")))
#define __IDSTRING(_n,_s) __SECTIONSTRING(.ident,_s)
diff --git a/libc/include/time64.h b/libc/include/time64.h
index 7ec05af..b4f1280 100644
--- a/libc/include/time64.h
+++ b/libc/include/time64.h
@@ -31,29 +31,41 @@
#ifndef TIME64_H
#define TIME64_H
+#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
+
+#else
+
+/* Legacy cruft for LP32 where time_t was 32-bit. */
+
#include <sys/cdefs.h>
#include <time.h>
#include <stdint.h>
__BEGIN_DECLS
-typedef int64_t time64_t;
+typedef int64_t time64_t;
-struct tm *gmtime64_r (const time64_t *, struct tm *);
-struct tm *localtime64_r (const time64_t *, struct tm *);
-struct tm *gmtime64 (const time64_t *);
-struct tm *localtime64 (const time64_t *);
-
-char *asctime64 (const struct tm *);
-char *asctime64_r (const struct tm *, char *);
-
-char *ctime64 (const time64_t*);
-char *ctime64_r (const time64_t*, char*);
-
-time64_t timegm64 (const struct tm *);
-time64_t mktime64 (const struct tm *);
-time64_t timelocal64 (const struct tm *);
+char* asctime64(const struct tm*);
+char* asctime64_r(const struct tm*, char*);
+char* ctime64(const time64_t*);
+char* ctime64_r(const time64_t*, char*);
+struct tm* gmtime64(const time64_t*);
+struct tm* gmtime64_r(const time64_t*, struct tm*);
+struct tm* localtime64(const time64_t*);
+struct tm* localtime64_r(const time64_t*, struct tm*);
+time64_t mktime64(const struct tm*);
+time64_t timegm64(const struct tm*);
+time64_t timelocal64(const struct tm*);
__END_DECLS
+#endif
+
#endif /* TIME64_H */
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index d21f23d..6cb36d8 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -47,7 +47,8 @@
#define SEEK_CUR 1
#define SEEK_END 2
-extern char **environ;
+extern char** environ;
+
extern __noreturn void _exit(int);
extern pid_t fork(void);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 04818b9..0029a65 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -34,7 +34,8 @@
#include <stdarg.h>
#include <stddef.h>
#include <time.h>
-#include <malloc.h>
+
+#include <machine/wchar_limits.h>
__BEGIN_DECLS
@@ -58,11 +59,6 @@
WC_TYPE_MAX
} wctype_t;
-#ifndef WCHAR_MAX
-#define WCHAR_MAX INT_MAX
-#define WCHAR_MIN INT_MIN
-#endif
-
#define WEOF ((wint_t)(-1))
extern wint_t btowc(int);
diff --git a/libc/kernel/uapi/linux/prctl.h b/libc/kernel/uapi/linux/prctl.h
index 87c7e2f..baa597e 100644
--- a/libc/kernel/uapi/linux/prctl.h
+++ b/libc/kernel/uapi/linux/prctl.h
@@ -117,7 +117,8 @@
#define PR_GET_NO_NEW_PRIVS 39
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define PR_GET_TID_ADDRESS 40
+#define PR_SET_TIMERSLACK_PID 41
#define PR_SET_VMA 0x53564d41
#define PR_SET_VMA_ANON_NAME 0
-#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index a42a8ab..d0a0201 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -80,7 +80,7 @@
* pthread_key_create; grep for GLOBAL_INIT_THREAD_LOCAL_BUFFER to find those. We need to manually
* maintain that second number, but pthread_test will fail if we forget.
*/
-#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 4
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 5
#define BIONIC_ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c
deleted file mode 100644
index 649db17..0000000
--- a/libc/stdio/fread.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* $OpenBSD: fread.c,v 1.6 2005/08/08 08:05:36 espie 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 <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "local.h"
-
-static int
-lflush(FILE *fp)
-{
- if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
- return (__sflush_locked(fp));
- return (0);
-}
-
-size_t
-fread(void *buf, size_t size, size_t count, FILE *fp)
-{
- size_t resid;
- char *p;
- int r;
- size_t total;
-
- /*
- * The ANSI standard requires a return value of 0 for a count
- * or a size of 0. Peculiarily, it imposes no such requirements
- * on fwrite; it only requires fread to be broken.
- */
- if ((resid = count * size) == 0)
- return (0);
- FLOCKFILE(fp);
- if (fp->_r < 0)
- fp->_r = 0;
- total = resid;
- p = buf;
-
-#if 1 /* BIONIC: optimize unbuffered reads */
- if (fp->_flags & __SNBF && fp->_ur == 0)
- {
- /* the following comes mainly from __srefill(), with slight
- * modifications
- */
-
- /* make sure stdio is set up */
- if (!__sdidinit)
- __sinit();
-
- fp->_r = 0; /* largely a convenience for callers */
-
- /* SysV does not make this test; take it out for compatibility */
- if (fp->_flags & __SEOF) {
- FUNLOCKFILE(fp);
- return (EOF);
- }
-
- /* if not already reading, have to be reading and writing */
- if ((fp->_flags & __SRD) == 0) {
- if ((fp->_flags & __SRW) == 0) {
- fp->_flags |= __SERR;
- FUNLOCKFILE(fp);
- errno = EBADF;
- return (EOF);
- }
- /* switch to reading */
- if (fp->_flags & __SWR) {
- if (__sflush(fp)) {
- FUNLOCKFILE(fp);
- return (EOF);
- }
- fp->_flags &= ~__SWR;
- fp->_w = 0;
- fp->_lbfsize = 0;
- }
- fp->_flags |= __SRD;
- } else {
- /*
- * We were reading. If there is an ungetc buffer,
- * we must have been reading from that. Drop it,
- * restoring the previous buffer (if any). If there
- * is anything in that buffer, return.
- */
- if (HASUB(fp)) {
- FREEUB(fp);
- }
- }
-
- /*
- * Before reading from a line buffered or unbuffered file,
- * flush all line buffered output files, per the ANSI C
- * standard.
- */
-
- if (fp->_flags & (__SLBF|__SNBF)) {
- /* Ignore this file in _fwalk to deadlock. */
- fp->_flags |= __SIGN;
- (void) _fwalk(lflush);
- fp->_flags &= ~__SIGN;
-
- /* Now flush this file without locking it. */
- if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
- __sflush(fp);
- }
-
- while (resid > 0) {
- int len = (*fp->_read)(fp->_cookie, p, resid );
- fp->_flags &= ~__SMOD;
- if (len <= 0) {
- if (len == 0)
- fp->_flags |= __SEOF;
- else {
- fp->_flags |= __SERR;
- }
- FUNLOCKFILE(fp);
- return ((total - resid) / size);
- }
- p += len;
- resid -= len;
- }
- FUNLOCKFILE(fp);
- return (count);
- }
- else
-#endif
- {
- while (resid > (size_t)(r = fp->_r)) {
- (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
- fp->_p += r;
- /* fp->_r = 0 ... done in __srefill */
- p += r;
- resid -= r;
- if (__srefill(fp)) {
- /* no more input: return partial result */
- FUNLOCKFILE(fp);
- return ((total - resid) / size);
- }
- }
- }
-
- (void)memcpy((void *)p, (void *)fp->_p, resid);
- fp->_r -= resid;
- fp->_p += resid;
- FUNLOCKFILE(fp);
- return (count);
-}
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index facaa66..eecfeef 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -95,6 +95,8 @@
#define FUNLOCKFILE(fp) funlockfile(fp)
#define FLOATING_POINT
+#define PRINTF_WIDE_CHAR
+#define SCANF_WIDE_CHAR
/* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
__BEGIN_DECLS
diff --git a/libc/stdlib/ctype_.c b/libc/stdlib/ctype_.c
deleted file mode 100644
index 3703f64..0000000
--- a/libc/stdlib/ctype_.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* $OpenBSD: ctype_.c,v 1.9 2005/08/08 08:05:33 espie Exp $ */
-/*
- * Copyright (c) 1989 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
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, 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.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ctype.h>
-#include "ctype_private.h"
-
-#define _U _CTYPE_U
-#define _L _CTYPE_L
-#define _N _CTYPE_N
-#define _S _CTYPE_S
-#define _P _CTYPE_P
-#define _C _CTYPE_C
-#define _X _CTYPE_X
-#define _B _CTYPE_B
-
-const char _C_ctype_[1 + CTYPE_NUM_CHARS] = {
- 0,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _C, _C, _C, _C, _C, _C, _C, _C,
- _S|(char)_B, _P, _P, _P, _P, _P, _P, _P,
- _P, _P, _P, _P, _P, _P, _P, _P,
- _N, _N, _N, _N, _N, _N, _N, _N,
- _N, _N, _P, _P, _P, _P, _P, _P,
- _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _U, _U, _U, _U, _U,
- _U, _U, _U, _P, _P, _P, _P, _P,
- _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- _L, _L, _L, _L, _L, _L, _L, _L,
- /* determine printability based on the IS0 8859 8-bit standard */
- _L, _L, _L, _P, _P, _P, _P, _C,
-
- _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */
- _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */
- _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */
- _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */
- _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */
- _P, _P, _P, _P, _P, _P, _P, _P /* F8 */
-};
-
-const char *_ctype_ = _C_ctype_;
-
-
-// TODO: fix the header file so we don't have to duplicate all this inlined stuff.
-
-#if 1 /* ndef NDEBUG */
-int isalnum(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L|_N)));
-}
-
-int isalpha(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L)));
-}
-
-int iscntrl(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _C));
-}
-
-int isdigit(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _N));
-}
-
-int isgraph(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N)));
-}
-
-int islower(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _L));
-}
-
-int isprint(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N|_B)));
-}
-
-int ispunct(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _P));
-}
-
-int isspace(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _S));
-}
-
-int isupper(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _U));
-}
-
-int isxdigit(int c)
-{
- return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_N|_X)));
-}
-
-#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \
- || __XPG_VISIBLE > 600
-int isblank(int c)
-{
- return (c == ' ' || c == '\t');
-}
-#endif
-
-#if __BSD_VISIBLE || __XPG_VISIBLE
-int isascii(int c)
-{
- return ((unsigned int)c <= 0177);
-}
-
-int toascii(int c)
-{
- return (c & 0177);
-}
-
-#endif /* __BSD_VISIBLE || __XPG_VISIBLE */
-
-#endif /* !NDBEUG */
diff --git a/libc/stdlib/putenv.c b/libc/stdlib/putenv.c
deleted file mode 100644
index 54482f6..0000000
--- a/libc/stdlib/putenv.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $OpenBSD: putenv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
-/*-
- * 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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-int
-putenv(const char *str)
-{
- char *p, *equal;
- int rval;
-
- if ((p = strdup(str)) == NULL)
- return (-1);
- if ((equal = strchr(p, '=')) == NULL) {
- (void)free(p);
- return (-1);
- }
- *equal = '\0';
- rval = setenv(p, equal + 1, 1);
- (void)free(p);
- return (rval);
-}
diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c
deleted file mode 100644
index 856db5e..0000000
--- a/libc/stdlib/setenv.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */
-/*
- * Copyright (c) 1987 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 <stdlib.h>
-#include <string.h>
-
-char *__findenv(const char *name, int *offset);
-
-extern char **environ;
-
-/*
- * setenv --
- * Set the value of the environmental variable "name" to be
- * "value". If rewrite is set, replace any current value.
- */
-int
-setenv(const char *name, const char *value, int rewrite)
-{
- static char **lastenv; /* last value of environ */
- char *C;
- int l_value, offset;
-
- if (*value == '=') /* no `=' in value */
- ++value;
- l_value = strlen(value);
- if ((C = __findenv(name, &offset))) { /* find if already exists */
- if (!rewrite)
- return (0);
- if ((int)strlen(C) >= l_value) { /* old larger; copy over */
- while ((*C++ = *value++))
- ;
- return (0);
- }
- } else { /* create new slot */
- size_t cnt;
- char **P;
-
- for (P = environ; *P != NULL; P++)
- ;
- cnt = P - environ;
- P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
- if (!P)
- return (-1);
- if (lastenv != environ)
- memcpy(P, environ, cnt * sizeof(char *));
- lastenv = environ = P;
- offset = cnt;
- environ[cnt + 1] = NULL;
- }
- for (C = (char *)name; *C && *C != '='; ++C)
- ; /* no `=' in name */
- if (!(environ[offset] = /* name + `=' + value */
- malloc((size_t)((int)(C - name) + l_value + 2))))
- return (-1);
- for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
- ;
- for (*C++ = '='; (*C++ = *value++); )
- ;
- return (0);
-}
-
-/*
- * unsetenv(name) --
- * Delete environmental variable "name".
- */
-int
-unsetenv(const char *name)
-{
- char **P;
- int offset;
-
- while (__findenv(name, &offset)) /* if set multiple times */
- for (P = &environ[offset];; ++P)
- if (!(*P = *(P + 1)))
- break;
-
- return 0;
-}
diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c
deleted file mode 100644
index 95d0e19..0000000
--- a/libc/stdlib/strtod.c
+++ /dev/null
@@ -1,2689 +0,0 @@
-/* $NetBSD: strtod.c,v 1.45.2.1 2005/04/19 13:35:54 tron Exp $ */
-
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991 by AT&T.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to
- David M. Gay
- AT&T Bell Laboratories, Room 2C-463
- 600 Mountain Avenue
- Murray Hill, NJ 07974-2070
- U.S.A.
- dmg@research.att.com or research!dmg
- */
-
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule. Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- * 1. We only require IEEE, IBM, or VAX double-precision
- * arithmetic (not IEEE double-extended).
- * 2. We get by with floating-point arithmetic in a case that
- * Clinger missed -- when we're computing d * 10^n
- * for a small integer d and the integer n is not too
- * much larger than 22 (the maximum integer k for which
- * we can represent 10^k exactly), we may be able to
- * compute (d*10^k) * 10^(e-k) with just one roundoff.
- * 3. Rather than a bit-at-a-time adjustment of the binary
- * result in the hard case, we use floating-point
- * arithmetic to determine the adjustment to within
- * one bit; only in really hard cases do we need to
- * compute a second residual.
- * 4. Because of 3., we don't need a large table of powers of 10
- * for ten-to-e (just some small tables, e.g. of 10^k
- * for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
- * significant byte has the lowest address.
- * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
- * significant byte has the lowest address.
- * #define Long int on machines with 32-bit ints and 64-bit longs.
- * #define Sudden_Underflow for IEEE-format machines without gradual
- * underflow (i.e., that flush to zero on underflow).
- * #define IBM for IBM mainframe-style floating-point arithmetic.
- * #define VAX for VAX-style floating-point arithmetic.
- * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
- * #define No_leftright to omit left-right logic in fast floating-point
- * computation of dtoa.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
- * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
- * that use extended-precision instructions to compute rounded
- * products and quotients) with IBM.
- * #define ROUND_BIASED for IEEE-format with biased rounding.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- * products but inaccurate quotients, e.g., for Intel i860.
- * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
- * integer arithmetic. Whether this speeds things up or slows things
- * down depends on the machine and the number being converted.
- * #define KR_headers for old-style C function headers.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
- * if memory is available and otherwise does something you deem
- * appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strtod.c,v 1.45.2.1 2005/04/19 13:35:54 tron Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#define Unsigned_Shifts
-#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
- defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
- defined(__powerpc__) || defined(__sh__) || defined(__x86_64__) || \
- defined(__hppa__) || \
- (defined(__arm__) && defined(__VFP_FP__)) || defined(__aarch64__)
-#include <endian.h>
-#if BYTE_ORDER == BIG_ENDIAN
-#define IEEE_BIG_ENDIAN
-#else
-#define IEEE_LITTLE_ENDIAN
-#endif
-#endif
-
-#if defined(__arm__) && !defined(__VFP_FP__)
-/*
- * Although the CPU is little endian the FP has different
- * byte and word endianness. The byte order is still little endian
- * but the word order is big endian.
- */
-#define IEEE_BIG_ENDIAN
-#endif
-
-#ifdef __vax__
-#define VAX
-#endif
-
-#if defined(__hppa__) || defined(__mips__) || defined(__sh__)
-#define NAN_WORD0 0x7ff40000
-#else
-#define NAN_WORD0 0x7ff80000
-#endif
-#define NAN_WORD1 0
-
-#define Long int32_t
-#define ULong u_int32_t
-
-#ifdef DEBUG
-#include "stdio.h"
-#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
-#endif
-
-#ifdef __cplusplus
-#include "malloc.h"
-#include "memory.h"
-#else
-#ifndef KR_headers
-#include "stdlib.h"
-#include "string.h"
-#include "locale.h"
-#else
-#include "malloc.h"
-#include "memory.h"
-#endif
-#endif
-#include "../upstream-netbsd/extern.h" /* Android-changed. */
-#include "../upstream-netbsd/reentrant.h" /* Android-changed. */
-
-#ifdef MALLOC
-#ifdef KR_headers
-extern char *MALLOC();
-#else
-extern void *MALLOC(size_t);
-#endif
-#else
-#define MALLOC malloc
-#endif
-
-#include "ctype.h"
-#include "errno.h"
-#include "float.h"
-
-#ifndef __MATH_H__
-#include "math.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef CONST
-#ifdef KR_headers
-#define CONST /* blank */
-#else
-#define CONST const
-#endif
-#endif
-
-#ifdef Unsigned_Shifts
-#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
-#else
-#define Sign_Extend(a,b) /*no-op*/
-#endif
-
-#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
- defined(IBM) != 1
-Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
-IBM should be defined.
-#endif
-
-typedef union {
- double d;
- ULong ul[2];
-} _double;
-#define value(x) ((x).d)
-#ifdef IEEE_LITTLE_ENDIAN
-#define word0(x) ((x).ul[1])
-#define word1(x) ((x).ul[0])
-#else
-#define word0(x) ((x).ul[0])
-#define word1(x) ((x).ul[1])
-#endif
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
-#define Storeinc(a,b,c) \
- (((u_short *)(void *)a)[1] = \
- (u_short)b, ((u_short *)(void *)a)[0] = (u_short)c, a++)
-#else
-#define Storeinc(a,b,c) \
- (((u_short *)(void *)a)[0] = \
- (u_short)b, ((u_short *)(void *)a)[1] = (u_short)c, a++)
-#endif
-
-/* #define P DBL_MANT_DIG */
-/* Ten_pmax = floor(P*log(2)/log(5)) */
-/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
-/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
-/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
-
-#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
-#define Exp_shift 20
-#define Exp_shift1 20
-#define Exp_msk1 0x100000
-#define Exp_msk11 0x100000
-#define Exp_mask 0x7ff00000
-#define P 53
-#define Bias 1023
-#define IEEE_Arith
-#define Emin (-1022)
-#define Exp_1 0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask 0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask 0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
-#else
-#undef Sudden_Underflow
-#define Sudden_Underflow
-#ifdef IBM
-#define Exp_shift 24
-#define Exp_shift1 24
-#define Exp_msk1 0x1000000
-#define Exp_msk11 0x1000000
-#define Exp_mask 0x7f000000
-#define P 14
-#define Bias 65
-#define Exp_1 0x41000000
-#define Exp_11 0x41000000
-#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
-#define Frac_mask 0xffffff
-#define Frac_mask1 0xffffff
-#define Bletch 4
-#define Ten_pmax 22
-#define Bndry_mask 0xefffff
-#define Bndry_mask1 0xffffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 4
-#define Tiny0 0x100000
-#define Tiny1 0
-#define Quick_max 14
-#define Int_max 15
-#else /* VAX */
-#define Exp_shift 23
-#define Exp_shift1 7
-#define Exp_msk1 0x80
-#define Exp_msk11 0x800000
-#define Exp_mask 0x7f80
-#define P 56
-#define Bias 129
-#define Exp_1 0x40800000
-#define Exp_11 0x4080
-#define Ebits 8
-#define Frac_mask 0x7fffff
-#define Frac_mask1 0xffff007f
-#define Ten_pmax 24
-#define Bletch 2
-#define Bndry_mask 0xffff007f
-#define Bndry_mask1 0xffff007f
-#define LSB 0x10000
-#define Sign_bit 0x8000
-#define Log2P 1
-#define Tiny0 0x80
-#define Tiny1 0
-#define Quick_max 15
-#define Int_max 15
-#endif
-#endif
-
-#ifndef IEEE_Arith
-#define ROUND_BIASED
-#endif
-
-#ifdef RND_PRODQUOT
-#define rounded_product(a,b) a = rnd_prod(a, b)
-#define rounded_quotient(a,b) a = rnd_quot(a, b)
-#ifdef KR_headers
-extern double rnd_prod(), rnd_quot();
-#else
-extern double rnd_prod(double, double), rnd_quot(double, double);
-#endif
-#else
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
-#endif
-
-#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
-#define Big1 0xffffffff
-
-#ifndef Just_16
-/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower. Hence the default is now to store 32 bits per Long.
- */
-#ifndef Pack_32
-#define Pack_32
-#endif
-#endif
-
-#define Kmax 15
-
-#ifdef __cplusplus
-extern "C" double strtod(const char *s00, char **se);
-extern "C" char *__dtoa(double d, int mode, int ndigits,
- int *decpt, int *sign, char **rve);
-#endif
-
- struct
-Bigint {
- struct Bigint *next;
- int k, maxwds, sign, wds;
- ULong x[1];
-};
-
- typedef struct Bigint Bigint;
-
- static Bigint *freelist[Kmax+1];
-
-#ifdef _REENTRANT
- static mutex_t freelist_mutex = MUTEX_INITIALIZER;
-#endif
-
-/* Special value used to indicate an invalid Bigint value,
- * e.g. when a memory allocation fails. The idea is that we
- * want to avoid introducing NULL checks everytime a bigint
- * computation is performed. Also the NULL value can also be
- * already used to indicate "value not initialized yet" and
- * returning NULL might alter the execution code path in
- * case of OOM.
- */
-#define BIGINT_INVALID ((Bigint *)&bigint_invalid_value)
-
-static const Bigint bigint_invalid_value;
-
-
-/* Return BIGINT_INVALID on allocation failure.
- *
- * Most of the code here depends on the fact that this function
- * never returns NULL.
- */
- static Bigint *
-Balloc
-#ifdef KR_headers
- (k) int k;
-#else
- (int k)
-#endif
-{
- int x;
- Bigint *rv;
-
- mutex_lock(&freelist_mutex);
-
- if ((rv = freelist[k]) != NULL) {
- freelist[k] = rv->next;
- }
- else {
- x = 1 << k;
- rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
- if (rv == NULL) {
- rv = BIGINT_INVALID;
- goto EXIT;
- }
- rv->k = k;
- rv->maxwds = x;
- }
- rv->sign = rv->wds = 0;
-EXIT:
- mutex_unlock(&freelist_mutex);
-
- return rv;
-}
-
- static void
-Bfree
-#ifdef KR_headers
- (v) Bigint *v;
-#else
- (Bigint *v)
-#endif
-{
- if (v && v != BIGINT_INVALID) {
- mutex_lock(&freelist_mutex);
-
- v->next = freelist[v->k];
- freelist[v->k] = v;
-
- mutex_unlock(&freelist_mutex);
- }
-}
-
-#define Bcopy_valid(x,y) memcpy(&(x)->sign, &(y)->sign, \
- (y)->wds*sizeof(Long) + 2*sizeof(int))
-
-#define Bcopy(x,y) Bcopy_ptr(&(x),(y))
-
- static void
-Bcopy_ptr(Bigint **px, Bigint *y)
-{
- if (*px == BIGINT_INVALID)
- return; /* no space to store copy */
- if (y == BIGINT_INVALID) {
- Bfree(*px); /* invalid input */
- *px = BIGINT_INVALID;
- } else {
- Bcopy_valid(*px,y);
- }
-}
-
- static Bigint *
-multadd
-#ifdef KR_headers
- (b, m, a) Bigint *b; int m, a;
-#else
- (Bigint *b, int m, int a) /* multiply by m and add a */
-#endif
-{
- int i, wds;
- ULong *x, y;
-#ifdef Pack_32
- ULong xi, z;
-#endif
- Bigint *b1;
-
- if (b == BIGINT_INVALID)
- return b;
-
- wds = b->wds;
- x = b->x;
- i = 0;
- do {
-#ifdef Pack_32
- xi = *x;
- y = (xi & 0xffff) * m + a;
- z = (xi >> 16) * m + (y >> 16);
- a = (int)(z >> 16);
- *x++ = (z << 16) + (y & 0xffff);
-#else
- y = *x * m + a;
- a = (int)(y >> 16);
- *x++ = y & 0xffff;
-#endif
- }
- while(++i < wds);
- if (a) {
- if (wds >= b->maxwds) {
- b1 = Balloc(b->k+1);
- if (b1 == BIGINT_INVALID) {
- Bfree(b);
- return b1;
- }
- Bcopy_valid(b1, b);
- Bfree(b);
- b = b1;
- }
- b->x[wds++] = a;
- b->wds = wds;
- }
- return b;
-}
-
- static Bigint *
-s2b
-#ifdef KR_headers
- (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
-#else
- (CONST char *s, int nd0, int nd, ULong y9)
-#endif
-{
- Bigint *b;
- int i, k;
- Long x, y;
-
- x = (nd + 8) / 9;
- for(k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
- b = Balloc(k);
- if (b == BIGINT_INVALID)
- return b;
- b->x[0] = y9;
- b->wds = 1;
-#else
- b = Balloc(k+1);
- if (b == BIGINT_INVALID)
- return b;
-
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
- i = 9;
- if (9 < nd0) {
- s += 9;
- do b = multadd(b, 10, *s++ - '0');
- while(++i < nd0);
- s++;
- }
- else
- s += 10;
- for(; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
-}
-
- static int
-hi0bits
-#ifdef KR_headers
- (x) ULong x;
-#else
- (ULong x)
-#endif
-{
- int k = 0;
-
- if (!(x & 0xffff0000)) {
- k = 16;
- x <<= 16;
- }
- if (!(x & 0xff000000)) {
- k += 8;
- x <<= 8;
- }
- if (!(x & 0xf0000000)) {
- k += 4;
- x <<= 4;
- }
- if (!(x & 0xc0000000)) {
- k += 2;
- x <<= 2;
- }
- if (!(x & 0x80000000)) {
- k++;
- if (!(x & 0x40000000))
- return 32;
- }
- return k;
-}
-
- static int
-lo0bits
-#ifdef KR_headers
- (y) ULong *y;
-#else
- (ULong *y)
-#endif
-{
- int k;
- ULong x = *y;
-
- if (x & 7) {
- if (x & 1)
- return 0;
- if (x & 2) {
- *y = x >> 1;
- return 1;
- }
- *y = x >> 2;
- return 2;
- }
- k = 0;
- if (!(x & 0xffff)) {
- k = 16;
- x >>= 16;
- }
- if (!(x & 0xff)) {
- k += 8;
- x >>= 8;
- }
- if (!(x & 0xf)) {
- k += 4;
- x >>= 4;
- }
- if (!(x & 0x3)) {
- k += 2;
- x >>= 2;
- }
- if (!(x & 1)) {
- k++;
- x >>= 1;
- if (!x & 1)
- return 32;
- }
- *y = x;
- return k;
-}
-
- static Bigint *
-i2b
-#ifdef KR_headers
- (i) int i;
-#else
- (int i)
-#endif
-{
- Bigint *b;
-
- b = Balloc(1);
- if (b != BIGINT_INVALID) {
- b->x[0] = i;
- b->wds = 1;
- }
- return b;
-}
-
- static Bigint *
-mult
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- Bigint *c;
- int k, wa, wb, wc;
- ULong carry, y, z;
- ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
-#ifdef Pack_32
- ULong z2;
-#endif
-
- if (a == BIGINT_INVALID || b == BIGINT_INVALID)
- return BIGINT_INVALID;
-
- if (a->wds < b->wds) {
- c = a;
- a = b;
- b = c;
- }
- k = a->k;
- wa = a->wds;
- wb = b->wds;
- wc = wa + wb;
- if (wc > a->maxwds)
- k++;
- c = Balloc(k);
- if (c == BIGINT_INVALID)
- return c;
- for(x = c->x, xa = x + wc; x < xa; x++)
- *x = 0;
- xa = a->x;
- xae = xa + wa;
- xb = b->x;
- xbe = xb + wb;
- xc0 = c->x;
-#ifdef Pack_32
- for(; xb < xbe; xb++, xc0++) {
- if ((y = *xb & 0xffff) != 0) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
- carry = z >> 16;
- z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
- carry = z2 >> 16;
- Storeinc(xc, z2, z);
- }
- while(x < xae);
- *xc = carry;
- }
- if ((y = *xb >> 16) != 0) {
- x = xa;
- xc = xc0;
- carry = 0;
- z2 = *xc;
- do {
- z = (*x & 0xffff) * y + (*xc >> 16) + carry;
- carry = z >> 16;
- Storeinc(xc, z, z2);
- z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
- carry = z2 >> 16;
- }
- while(x < xae);
- *xc = z2;
- }
- }
-#else
- for(; xb < xbe; xc0++) {
- if (y = *xb++) {
- x = xa;
- xc = xc0;
- carry = 0;
- do {
- z = *x++ * y + *xc + carry;
- carry = z >> 16;
- *xc++ = z & 0xffff;
- }
- while(x < xae);
- *xc = carry;
- }
- }
-#endif
- for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
- c->wds = wc;
- return c;
-}
-
- static Bigint *p5s;
- static pthread_mutex_t p5s_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- static Bigint *
-pow5mult
-#ifdef KR_headers
- (b, k) Bigint *b; int k;
-#else
- (Bigint *b, int k)
-#endif
-{
- Bigint *b1, *p5, *p51;
- int i;
- static const int p05[3] = { 5, 25, 125 };
-
- if (b == BIGINT_INVALID)
- return b;
-
- if ((i = k & 3) != 0)
- b = multadd(b, p05[i-1], 0);
-
- if (!(k = (unsigned int) k >> 2))
- return b;
- mutex_lock(&p5s_mutex);
- if (!(p5 = p5s)) {
- /* first time */
- p5 = i2b(625);
- if (p5 == BIGINT_INVALID) {
- Bfree(b);
- mutex_unlock(&p5s_mutex);
- return p5;
- }
- p5s = p5;
- p5->next = 0;
- }
- for(;;) {
- if (k & 1) {
- b1 = mult(b, p5);
- Bfree(b);
- b = b1;
- }
- if (!(k = (unsigned int) k >> 1))
- break;
- if (!(p51 = p5->next)) {
- p51 = mult(p5,p5);
- if (p51 == BIGINT_INVALID) {
- Bfree(b);
- mutex_unlock(&p5s_mutex);
- return p51;
- }
- p5->next = p51;
- p51->next = 0;
- }
- p5 = p51;
- }
- mutex_unlock(&p5s_mutex);
- return b;
-}
-
- static Bigint *
-lshift
-#ifdef KR_headers
- (b, k) Bigint *b; int k;
-#else
- (Bigint *b, int k)
-#endif
-{
- int i, k1, n, n1;
- Bigint *b1;
- ULong *x, *x1, *xe, z;
-
- if (b == BIGINT_INVALID)
- return b;
-
-#ifdef Pack_32
- n = (unsigned int)k >> 5;
-#else
- n = (unsigned int)k >> 4;
-#endif
- k1 = b->k;
- n1 = n + b->wds + 1;
- for(i = b->maxwds; n1 > i; i <<= 1)
- k1++;
- b1 = Balloc(k1);
- if (b1 == BIGINT_INVALID) {
- Bfree(b);
- return b1;
- }
- x1 = b1->x;
- for(i = 0; i < n; i++)
- *x1++ = 0;
- x = b->x;
- xe = x + b->wds;
-#ifdef Pack_32
- if (k &= 0x1f) {
- k1 = 32 - k;
- z = 0;
- do {
- *x1++ = *x << k | z;
- z = *x++ >> k1;
- }
- while(x < xe);
- if ((*x1 = z) != 0)
- ++n1;
- }
-#else
- if (k &= 0xf) {
- k1 = 16 - k;
- z = 0;
- do {
- *x1++ = *x << k & 0xffff | z;
- z = *x++ >> k1;
- }
- while(x < xe);
- if (*x1 = z)
- ++n1;
- }
-#endif
- else do
- *x1++ = *x++;
- while(x < xe);
- b1->wds = n1 - 1;
- Bfree(b);
- return b1;
-}
-
- static int
-cmp
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- ULong *xa, *xa0, *xb, *xb0;
- int i, j;
-
- if (a == BIGINT_INVALID || b == BIGINT_INVALID)
-#ifdef DEBUG
- Bug("cmp called with a or b invalid");
-#else
- return 0; /* equal - the best we can do right now */
-#endif
-
- i = a->wds;
- j = b->wds;
-#ifdef DEBUG
- if (i > 1 && !a->x[i-1])
- Bug("cmp called with a->x[a->wds-1] == 0");
- if (j > 1 && !b->x[j-1])
- Bug("cmp called with b->x[b->wds-1] == 0");
-#endif
- if (i -= j)
- return i;
- xa0 = a->x;
- xa = xa0 + j;
- xb0 = b->x;
- xb = xb0 + j;
- for(;;) {
- if (*--xa != *--xb)
- return *xa < *xb ? -1 : 1;
- if (xa <= xa0)
- break;
- }
- return 0;
-}
-
- static Bigint *
-diff
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- Bigint *c;
- int i, wa, wb;
- Long borrow, y; /* We need signed shifts here. */
- ULong *xa, *xae, *xb, *xbe, *xc;
-#ifdef Pack_32
- Long z;
-#endif
-
- if (a == BIGINT_INVALID || b == BIGINT_INVALID)
- return BIGINT_INVALID;
-
- i = cmp(a,b);
- if (!i) {
- c = Balloc(0);
- if (c != BIGINT_INVALID) {
- c->wds = 1;
- c->x[0] = 0;
- }
- return c;
- }
- if (i < 0) {
- c = a;
- a = b;
- b = c;
- i = 1;
- }
- else
- i = 0;
- c = Balloc(a->k);
- if (c == BIGINT_INVALID)
- return c;
- c->sign = i;
- wa = a->wds;
- xa = a->x;
- xae = xa + wa;
- wb = b->wds;
- xb = b->x;
- xbe = xb + wb;
- xc = c->x;
- borrow = 0;
-#ifdef Pack_32
- do {
- y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
- borrow = (ULong)y >> 16;
- Sign_Extend(borrow, y);
- z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
- borrow = (ULong)z >> 16;
- Sign_Extend(borrow, z);
- Storeinc(xc, z, y);
- }
- while(xb < xbe);
- while(xa < xae) {
- y = (*xa & 0xffff) + borrow;
- borrow = (ULong)y >> 16;
- Sign_Extend(borrow, y);
- z = (*xa++ >> 16) + borrow;
- borrow = (ULong)z >> 16;
- Sign_Extend(borrow, z);
- Storeinc(xc, z, y);
- }
-#else
- do {
- y = *xa++ - *xb++ + borrow;
- borrow = y >> 16;
- Sign_Extend(borrow, y);
- *xc++ = y & 0xffff;
- }
- while(xb < xbe);
- while(xa < xae) {
- y = *xa++ + borrow;
- borrow = y >> 16;
- Sign_Extend(borrow, y);
- *xc++ = y & 0xffff;
- }
-#endif
- while(!*--xc)
- wa--;
- c->wds = wa;
- return c;
-}
-
- static double
-ulp
-#ifdef KR_headers
- (_x) double _x;
-#else
- (double _x)
-#endif
-{
- _double x;
- Long L;
- _double a;
-
- value(x) = _x;
- L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
-#ifndef Sudden_Underflow
- if (L > 0) {
-#endif
-#ifdef IBM
- L |= Exp_msk1 >> 4;
-#endif
- word0(a) = L;
- word1(a) = 0;
-#ifndef Sudden_Underflow
- }
- else {
- L = (ULong)-L >> Exp_shift;
- if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
- }
- else {
- word0(a) = 0;
- L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << (31 - L);
- }
- }
-#endif
- return value(a);
-}
-
- static double
-b2d
-#ifdef KR_headers
- (a, e) Bigint *a; int *e;
-#else
- (Bigint *a, int *e)
-#endif
-{
- ULong *xa, *xa0, w, y, z;
- int k;
- _double d;
-#ifdef VAX
- ULong d0, d1;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
- if (a == BIGINT_INVALID)
- return NAN;
-
- xa0 = a->x;
- xa = xa0 + a->wds;
- y = *--xa;
-#ifdef DEBUG
- if (!y) Bug("zero y in b2d");
-#endif
- k = hi0bits(y);
- *e = 32 - k;
-#ifdef Pack_32
- if (k < Ebits) {
- d0 = Exp_1 | y >> (Ebits - k);
- w = xa > xa0 ? *--xa : 0;
- d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> (32 - k);
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> (32 - k);
- }
- else {
- d0 = Exp_1 | y;
- d1 = z;
- }
-#else
- if (k < Ebits + 16) {
- z = xa > xa0 ? *--xa : 0;
- d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
- w = xa > xa0 ? *--xa : 0;
- y = xa > xa0 ? *--xa : 0;
- d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
- goto ret_d;
- }
- z = xa > xa0 ? *--xa : 0;
- w = xa > xa0 ? *--xa : 0;
- k -= Ebits + 16;
- d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
- y = xa > xa0 ? *--xa : 0;
- d1 = w << k + 16 | y << k;
-#endif
- ret_d:
-#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
-#else
-#undef d0
-#undef d1
-#endif
- return value(d);
-}
-
- static Bigint *
-d2b
-#ifdef KR_headers
- (_d, e, bits) double d; int *e, *bits;
-#else
- (double _d, int *e, int *bits)
-#endif
-{
- Bigint *b;
- int de, i, k;
- ULong *x, y, z;
- _double d;
-#ifdef VAX
- ULong d0, d1;
-#endif
-
- value(d) = _d;
-#ifdef VAX
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-#ifdef Pack_32
- b = Balloc(1);
-#else
- b = Balloc(2);
-#endif
- if (b == BIGINT_INVALID)
- return b;
- x = b->x;
-
- z = d0 & Frac_mask;
- d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
- de = (int)(d0 >> Exp_shift);
-#ifndef IBM
- z |= Exp_msk11;
-#endif
-#else
- if ((de = (int)(d0 >> Exp_shift)) != 0)
- z |= Exp_msk1;
-#endif
-#ifdef Pack_32
- if ((y = d1) != 0) {
- if ((k = lo0bits(&y)) != 0) {
- x[0] = y | z << (32 - k);
- z >>= k;
- }
- else
- x[0] = y;
- i = b->wds = (x[1] = z) ? 2 : 1;
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- x[0] = z;
- i = b->wds = 1;
- k += 32;
- }
-#else
- if (y = d1) {
- if (k = lo0bits(&y))
- if (k >= 16) {
- x[0] = y | z << 32 - k & 0xffff;
- x[1] = z >> k - 16 & 0xffff;
- x[2] = z >> k;
- i = 2;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16 | z << 16 - k & 0xffff;
- x[2] = z >> k & 0xffff;
- x[3] = z >> k+16;
- i = 3;
- }
- else {
- x[0] = y & 0xffff;
- x[1] = y >> 16;
- x[2] = z & 0xffff;
- x[3] = z >> 16;
- i = 3;
- }
- }
- else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
- k = lo0bits(&z);
- if (k >= 16) {
- x[0] = z;
- i = 0;
- }
- else {
- x[0] = z & 0xffff;
- x[1] = z >> 16;
- i = 1;
- }
- k += 32;
- }
- while(!x[i])
- --i;
- b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
- if (de) {
-#endif
-#ifdef IBM
- *e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
-#else
- *e = de - Bias - (P-1) + k;
- *bits = P - k;
-#endif
-#ifndef Sudden_Underflow
- }
- else {
- *e = de - Bias - (P-1) + 1 + k;
-#ifdef Pack_32
- *bits = 32*i - hi0bits(x[i-1]);
-#else
- *bits = (i+2)*16 - hi0bits(x[i]);
-#endif
- }
-#endif
- return b;
-}
-#undef d0
-#undef d1
-
- static double
-ratio
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- _double da, db;
- int k, ka, kb;
-
- if (a == BIGINT_INVALID || b == BIGINT_INVALID)
- return NAN; /* for lack of better value ? */
-
- value(da) = b2d(a, &ka);
- value(db) = b2d(b, &kb);
-#ifdef Pack_32
- k = ka - kb + 32*(a->wds - b->wds);
-#else
- k = ka - kb + 16*(a->wds - b->wds);
-#endif
-#ifdef IBM
- if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- da *= 1 << k;
- }
- else {
- k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- db *= 1 << k;
- }
-#else
- if (k > 0)
- word0(da) += k*Exp_msk1;
- else {
- k = -k;
- word0(db) += k*Exp_msk1;
- }
-#endif
- return value(da) / value(db);
-}
-
-static CONST double
-tens[] = {
- 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
- 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
- 1e20, 1e21, 1e22
-#ifdef VAX
- , 1e23, 1e24
-#endif
-};
-
-#ifdef IEEE_Arith
-static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-#define n_bigtens 5
-#else
-#ifdef IBM
-static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
-static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
-#define n_bigtens 3
-#else
-static CONST double bigtens[] = { 1e16, 1e32 };
-static CONST double tinytens[] = { 1e-16, 1e-32 };
-#define n_bigtens 2
-#endif
-#endif
-
- double
-strtod
-#ifdef KR_headers
- (s00, se) CONST char *s00; char **se;
-#else
- (CONST char *s00, char **se)
-#endif
-{
- int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
- e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
- CONST char *s, *s0, *s1;
- double aadj, aadj1, adj;
- _double rv, rv0;
- Long L;
- ULong y, z;
- Bigint *bb1, *bd0;
- Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */
-
-#ifndef KR_headers
- CONST char decimal_point = localeconv()->decimal_point[0];
-#else
- CONST char decimal_point = '.';
-#endif
-
- sign = nz0 = nz = 0;
- value(rv) = 0.;
-
-
- for(s = s00; isspace((unsigned char) *s); s++)
- ;
-
- if (*s == '-') {
- sign = 1;
- s++;
- } else if (*s == '+') {
- s++;
- }
-
- if (*s == '\0') {
- s = s00;
- goto ret;
- }
-
- /* "INF" or "INFINITY" */
- if (tolower((unsigned char)*s) == 'i' && strncasecmp(s, "inf", 3) == 0) {
- if (strncasecmp(s + 3, "inity", 5) == 0)
- s += 8;
- else
- s += 3;
-
- value(rv) = HUGE_VAL;
- goto ret;
- }
-
-#ifdef IEEE_Arith
- /* "NAN" or "NAN(n-char-sequence-opt)" */
- if (tolower((unsigned char)*s) == 'n' && strncasecmp(s, "nan", 3) == 0) {
- /* Build a quiet NaN. */
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
- s+= 3;
-
- /* Don't interpret (n-char-sequence-opt), for now. */
- if (*s == '(') {
- s0 = s;
- for (s++; *s != ')' && *s != '\0'; s++)
- ;
- if (*s == ')')
- s++; /* Skip over closing paren ... */
- else
- s = s0; /* ... otherwise go back. */
- }
-
- goto ret;
- }
-#endif
-
- if (*s == '0') {
- nz0 = 1;
- while(*++s == '0') ;
- if (!*s)
- goto ret;
- }
- s0 = s;
- y = z = 0;
- for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
- if (nd < 9)
- y = 10*y + c - '0';
- else if (nd < 16)
- z = 10*z + c - '0';
- nd0 = nd;
- if (c == decimal_point) {
- c = *++s;
- if (!nd) {
- for(; c == '0'; c = *++s)
- nz++;
- if (c > '0' && c <= '9') {
- s0 = s;
- nf += nz;
- nz = 0;
- goto have_dig;
- }
- goto dig_done;
- }
- for(; c >= '0' && c <= '9'; c = *++s) {
- have_dig:
- nz++;
- if (c -= '0') {
- nf += nz;
- for(i = 1; i < nz; i++)
- if (nd++ < 9)
- y *= 10;
- else if (nd <= DBL_DIG + 1)
- z *= 10;
- if (nd++ < 9)
- y = 10*y + c;
- else if (nd <= DBL_DIG + 1)
- z = 10*z + c;
- nz = 0;
- }
- }
- }
- dig_done:
- e = 0;
- if (c == 'e' || c == 'E') {
- if (!nd && !nz && !nz0) {
- s = s00;
- goto ret;
- }
- s00 = s;
- esign = 0;
- switch(c = *++s) {
- case '-':
- esign = 1;
- /* FALLTHROUGH */
- case '+':
- c = *++s;
- }
- if (c >= '0' && c <= '9') {
- while(c == '0')
- c = *++s;
- if (c > '0' && c <= '9') {
- L = c - '0';
- s1 = s;
- while((c = *++s) >= '0' && c <= '9')
- L = 10*L + c - '0';
- if (s - s1 > 8 || L > 19999)
- /* Avoid confusion from exponents
- * so large that e might overflow.
- */
- e = 19999; /* safe for 16 bit ints */
- else
- e = (int)L;
- if (esign)
- e = -e;
- }
- else
- e = 0;
- }
- else
- s = s00;
- }
- if (!nd) {
- if (!nz && !nz0)
- s = s00;
- goto ret;
- }
- e1 = e -= nf;
-
- /* Now we have nd0 digits, starting at s0, followed by a
- * decimal point, followed by nd-nd0 digits. The number we're
- * after is the integer represented by those digits times
- * 10**e */
-
- if (!nd0)
- nd0 = nd;
- k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- value(rv) = y;
- if (k > 9)
- value(rv) = tens[k - 9] * value(rv) + z;
- bd0 = 0;
- if (nd <= DBL_DIG
-#ifndef RND_PRODQUOT
- && FLT_ROUNDS == 1
-#endif
- ) {
- if (!e)
- goto ret;
- if (e > 0) {
- if (e <= Ten_pmax) {
-#ifdef VAX
- goto vax_ovfl_check;
-#else
- /* value(rv) = */ rounded_product(value(rv),
- tens[e]);
- goto ret;
-#endif
- }
- i = DBL_DIG - nd;
- if (e <= Ten_pmax + i) {
- /* A fancier test would sometimes let us do
- * this for larger i values.
- */
- e -= i;
- value(rv) *= tens[i];
-#ifdef VAX
- /* VAX exponent range is so narrow we must
- * worry about overflow here...
- */
- vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* value(rv) = */ rounded_product(value(rv),
- tens[e]);
- if ((word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
- goto ovfl;
- word0(rv) += P*Exp_msk1;
-#else
- /* value(rv) = */ rounded_product(value(rv),
- tens[e]);
-#endif
- goto ret;
- }
- }
-#ifndef Inaccurate_Divide
- else if (e >= -Ten_pmax) {
- /* value(rv) = */ rounded_quotient(value(rv),
- tens[-e]);
- goto ret;
- }
-#endif
- }
- e1 += nd - k;
-
- /* Get starting approximation = rv * 10**e1 */
-
- if (e1 > 0) {
- if ((i = e1 & 15) != 0)
- value(rv) *= tens[i];
- if (e1 &= ~15) {
- if (e1 > DBL_MAX_10_EXP) {
- ovfl:
- errno = ERANGE;
- value(rv) = HUGE_VAL;
- if (bd0)
- goto retfree;
- goto ret;
- }
- if ((e1 = (unsigned int)e1 >> 4) != 0) {
- for(j = 0; e1 > 1; j++,
- e1 = (unsigned int)e1 >> 1)
- if (e1 & 1)
- value(rv) *= bigtens[j];
- /* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- value(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
- > Exp_msk1*(DBL_MAX_EXP+Bias-P))
- goto ovfl;
- if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
- /* set to largest number */
- /* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- }
- }
- else if (e1 < 0) {
- e1 = -e1;
- if ((i = e1 & 15) != 0)
- value(rv) /= tens[i];
- if (e1 &= ~15) {
- e1 = (unsigned int)e1 >> 4;
- if (e1 >= 1 << n_bigtens)
- goto undfl;
- for(j = 0; e1 > 1; j++,
- e1 = (unsigned int)e1 >> 1)
- if (e1 & 1)
- value(rv) *= tinytens[j];
- /* The last multiplication could underflow. */
- value(rv0) = value(rv);
- value(rv) *= tinytens[j];
- if (!value(rv)) {
- value(rv) = 2.*value(rv0);
- value(rv) *= tinytens[j];
- if (!value(rv)) {
- undfl:
- value(rv) = 0.;
- errno = ERANGE;
- if (bd0)
- goto retfree;
- goto ret;
- }
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- /* The refinement below will clean
- * this approximation up.
- */
- }
- }
- }
-
- /* Now the hard part -- adjusting rv to the correct value.*/
-
- /* Put digits into bd: true value = bd * 10^e */
-
- bd0 = s2b(s0, nd0, nd, y);
-
- for(;;) {
- bd = Balloc(bd0->k);
- Bcopy(bd, bd0);
- bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
- bs = i2b(1);
-
- if (e >= 0) {
- bb2 = bb5 = 0;
- bd2 = bd5 = e;
- }
- else {
- bb2 = bb5 = -e;
- bd2 = bd5 = 0;
- }
- if (bbe >= 0)
- bb2 += bbe;
- else
- bd2 -= bbe;
- bs2 = bb2;
-#ifdef Sudden_Underflow
-#ifdef IBM
- j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
-#else
- j = P + 1 - bbbits;
-#endif
-#else
- i = bbe + bbbits - 1; /* logb(rv) */
- if (i < Emin) /* denormal */
- j = bbe + (P-Emin);
- else
- j = P + 1 - bbbits;
-#endif
- bb2 += j;
- bd2 += j;
- i = bb2 < bd2 ? bb2 : bd2;
- if (i > bs2)
- i = bs2;
- if (i > 0) {
- bb2 -= i;
- bd2 -= i;
- bs2 -= i;
- }
- if (bb5 > 0) {
- bs = pow5mult(bs, bb5);
- bb1 = mult(bs, bb);
- Bfree(bb);
- bb = bb1;
- }
- if (bb2 > 0)
- bb = lshift(bb, bb2);
- if (bd5 > 0)
- bd = pow5mult(bd, bd5);
- if (bd2 > 0)
- bd = lshift(bd, bd2);
- if (bs2 > 0)
- bs = lshift(bs, bs2);
- delta = diff(bb, bd);
- dsign = delta->sign;
- delta->sign = 0;
- i = cmp(delta, bs);
- if (i < 0) {
- /* Error is less than half an ulp -- check for
- * special case of mantissa a power of two.
- */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask)
- break;
- delta = lshift(delta,Log2P);
- if (cmp(delta, bs) > 0)
- goto drop_down;
- break;
- }
- if (i == 0) {
- /* exactly half-way between */
- if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == 0xffffffff) {
- /*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
- + Exp_msk1
-#ifdef IBM
- | Exp_msk1 >> 4
-#endif
- ;
- word1(rv) = 0;
- break;
- }
- }
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
- drop_down:
- /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow
- L = word0(rv) & Exp_mask;
-#ifdef IBM
- if (L < Exp_msk1)
-#else
- if (L <= Exp_msk1)
-#endif
- goto undfl;
- L -= Exp_msk1;
-#else
- L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
-#ifdef IBM
- goto cont;
-#else
- break;
-#endif
- }
-#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
- break;
-#endif
- if (dsign)
- value(rv) += ulp(value(rv));
-#ifndef ROUND_BIASED
- else {
- value(rv) -= ulp(value(rv));
-#ifndef Sudden_Underflow
- if (!value(rv))
- goto undfl;
-#endif
- }
-#endif
- break;
- }
- if ((aadj = ratio(delta, bs)) <= 2.) {
- if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
- goto undfl;
-#endif
- aadj = 1.;
- aadj1 = -1.;
- }
- else {
- /* special case -- power of FLT_RADIX to be */
- /* rounded down... */
-
- if (aadj < 2./FLT_RADIX)
- aadj = 1./FLT_RADIX;
- else
- aadj *= 0.5;
- aadj1 = -aadj;
- }
- }
- else {
- aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
- switch(FLT_ROUNDS) {
- case 2: /* towards +infinity */
- aadj1 -= 0.5;
- break;
- case 0: /* towards 0 */
- case 3: /* towards -infinity */
- aadj1 += 0.5;
- }
-#else
- if (FLT_ROUNDS == 0)
- aadj1 += 0.5;
-#endif
- }
- y = word0(rv) & Exp_mask;
-
- /* Check for overflow */
-
- if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- value(rv0) = value(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(value(rv));
- value(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
- Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
- goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
- goto cont;
- }
- else
- word0(rv) += P*Exp_msk1;
- }
- else {
-#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- value(rv0) = value(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(value(rv));
- value(rv) += adj;
-#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
-#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
-#endif
- {
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
- goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
- goto cont;
- }
- else
- word0(rv) -= P*Exp_msk1;
- }
- else {
- adj = aadj1 * ulp(value(rv));
- value(rv) += adj;
- }
-#else
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
- * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
- * trouble from bits lost to denormalization;
- * example: 1.2e-307 .
- */
- if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
- if (!dsign)
- aadj1 = -aadj1;
- }
- adj = aadj1 * ulp(value(rv));
- value(rv) += adj;
-#endif
- }
- z = word0(rv) & Exp_mask;
- if (y == z) {
- /* Can we stop now? */
- L = aadj;
- aadj -= L;
- /* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
- if (aadj < .4999999 || aadj > .5000001)
- break;
- }
- else if (aadj < .4999999/FLT_RADIX)
- break;
- }
- cont:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(delta);
- }
- retfree:
- Bfree(bb);
- Bfree(bd);
- Bfree(bs);
- Bfree(bd0);
- Bfree(delta);
- ret:
- if (se)
- /* LINTED interface specification */
- *se = (char *)s;
- return sign ? -value(rv) : value(rv);
-}
-
- static int
-quorem
-#ifdef KR_headers
- (b, S) Bigint *b, *S;
-#else
- (Bigint *b, Bigint *S)
-#endif
-{
- int n;
- Long borrow, y;
- ULong carry, q, ys;
- ULong *bx, *bxe, *sx, *sxe;
-#ifdef Pack_32
- Long z;
- ULong si, zs;
-#endif
-
- if (b == BIGINT_INVALID || S == BIGINT_INVALID)
- return 0;
-
- n = S->wds;
-#ifdef DEBUG
- /*debug*/ if (b->wds > n)
- /*debug*/ Bug("oversize b in quorem");
-#endif
- if (b->wds < n)
- return 0;
- sx = S->x;
- sxe = sx + --n;
- bx = b->x;
- bxe = bx + n;
- q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
-#ifdef DEBUG
- /*debug*/ if (q > 9)
- /*debug*/ Bug("oversized quotient in quorem");
-#endif
- if (q) {
- borrow = 0;
- carry = 0;
- do {
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) * q + carry;
- zs = (si >> 16) * q + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
- borrow = (ULong)y >> 16;
- Sign_Extend(borrow, y);
- z = (*bx >> 16) - (zs & 0xffff) + borrow;
- borrow = (ULong)z >> 16;
- Sign_Extend(borrow, z);
- Storeinc(bx, z, y);
-#else
- ys = *sx++ * q + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) + borrow;
- borrow = y >> 16;
- Sign_Extend(borrow, y);
- *bx++ = y & 0xffff;
-#endif
- }
- while(sx <= sxe);
- if (!*bxe) {
- bx = b->x;
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- if (cmp(b, S) >= 0) {
- q++;
- borrow = 0;
- carry = 0;
- bx = b->x;
- sx = S->x;
- do {
-#ifdef Pack_32
- si = *sx++;
- ys = (si & 0xffff) + carry;
- zs = (si >> 16) + (ys >> 16);
- carry = zs >> 16;
- y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
- borrow = (ULong)y >> 16;
- Sign_Extend(borrow, y);
- z = (*bx >> 16) - (zs & 0xffff) + borrow;
- borrow = (ULong)z >> 16;
- Sign_Extend(borrow, z);
- Storeinc(bx, z, y);
-#else
- ys = *sx++ + carry;
- carry = ys >> 16;
- y = *bx - (ys & 0xffff) + borrow;
- borrow = y >> 16;
- Sign_Extend(borrow, y);
- *bx++ = y & 0xffff;
-#endif
- }
- while(sx <= sxe);
- bx = b->x;
- bxe = bx + n;
- if (!*bxe) {
- while(--bxe > bx && !*bxe)
- --n;
- b->wds = n;
- }
- }
- return q;
-}
-
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined. It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
-void
-#ifdef KR_headers
-freedtoa(s) char *s;
-#else
-freedtoa(char *s)
-#endif
-{
- free(s);
-}
-
-
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- * 1. Rather than iterating, we use a simple numeric overestimate
- * to determine k = floor(log10(d)). We scale relevant
- * quantities using O(log2(k)) rather than O(k) multiplications.
- * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- * try to generate digits strictly left to right. Instead, we
- * compute with fewer bits and propagate the carry if necessary
- * when rounding the final digit up. This is often faster.
- * 3. Under the assumption that input will be rounded nearest,
- * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- * That is, we allow equality in stopping tests when the
- * round-nearest rule will give the same floating-point value
- * as would satisfaction of the stopping test with strict
- * inequality.
- * 4. We remove common factors of powers of 2 from relevant
- * quantities.
- * 5. When converting floating-point integers less than 1e16,
- * we use floating-point arithmetic rather than resorting
- * to multiple-precision integers.
- * 6. When asked to produce fewer than 15 digits, we first try
- * to get by with floating-point arithmetic; we resort to
- * multiple-precision integer arithmetic only if we cannot
- * guarantee that the floating-point calculation has given
- * the correctly rounded result. For k requested digits and
- * "uniformly" distributed input, the probability is
- * something like 10^(k-15) that we must resort to the Long
- * calculation.
- */
-
-__LIBC_HIDDEN__ char *
-__dtoa
-#ifdef KR_headers
- (_d, mode, ndigits, decpt, sign, rve)
- double _d; int mode, ndigits, *decpt, *sign; char **rve;
-#else
- (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
-#endif
-{
- /* Arguments ndigits, decpt, sign are similar to those
- of ecvt and fcvt; trailing zeros are suppressed from
- the returned string. If not null, *rve is set to point
- to the end of the return value. If d is +-Infinity or NaN,
- then *decpt is set to 9999.
-
- mode:
- 0 ==> shortest string that yields d when read in
- and rounded to nearest.
- 1 ==> like 0, but with Steele & White stopping rule;
- e.g. with IEEE P754 arithmetic , mode 0 gives
- 1e23 whereas mode 1 gives 9.999999999999999e22.
- 2 ==> max(1,ndigits) significant digits. This gives a
- return value similar to that of ecvt, except
- that trailing zeros are suppressed.
- 3 ==> through ndigits past the decimal point. This
- gives a return value similar to that from fcvt,
- except that trailing zeros are suppressed, and
- ndigits can be negative.
- 4-9 should give the same return values as 2-3, i.e.,
- 4 <= mode <= 9 ==> same return as mode
- 2 + (mode & 1). These modes are mainly for
- debugging; often they run slower but sometimes
- faster than modes 2-3.
- 4,5,8,9 ==> left-to-right digit generation.
- 6-9 ==> don't try fast floating-point estimate
- (if applicable).
-
- Values of mode other than 0-9 are treated as mode 0.
-
- Sufficient space is allocated to the return value
- to hold the suppressed trailing zeros.
- */
-
- int bbits, b2, b5, be, dig, i, ieps, ilim0,
- j, jj1, k, k0, k_check, leftright, m2, m5, s2, s5,
- try_quick;
- int ilim = 0, ilim1 = 0, spec_case = 0; /* pacify gcc */
- Long L;
-#ifndef Sudden_Underflow
- int denorm;
- ULong x;
-#endif
- Bigint *b, *b1, *delta, *mhi, *S;
- Bigint *mlo = NULL; /* pacify gcc */
- double ds;
- char *s, *s0;
- Bigint *result = NULL;
- int result_k = 0;
- _double d, d2, eps;
-
- value(d) = _d;
-
- if (word0(d) & Sign_bit) {
- /* set sign for everything, including 0's and NaNs */
- *sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
- }
- else
- *sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
-#else
- if (word0(d) == 0x8000)
-#endif
- {
- /* Infinity or NaN */
- *decpt = 9999;
- s =
-#ifdef IEEE_Arith
- !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
-#endif
- "NaN";
- result = Balloc(strlen(s)+1);
- if (result == BIGINT_INVALID)
- return NULL;
- s0 = (char *)(void *)result;
- strcpy(s0, s);
- if (rve)
- *rve =
-#ifdef IEEE_Arith
- s0[3] ? s0 + 8 :
-#endif
- s0 + 3;
- return s0;
- }
-#endif
-#ifdef IBM
- value(d) += 0; /* normalize */
-#endif
- if (!value(d)) {
- *decpt = 1;
- result = Balloc(2);
- if (result == BIGINT_INVALID)
- return NULL;
- s0 = (char *)(void *)result;
- strcpy(s0, "0");
- if (rve)
- *rve = s0 + 1;
- return s0;
- }
-
- b = d2b(value(d), &be, &bbits);
-#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
- if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
-#endif
- value(d2) = value(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
-#ifdef IBM
- if (j = 11 - hi0bits(word0(d2) & Frac_mask))
- value(d2) /= 1 << j;
-#endif
-
- /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
- * log10(x) = log(x) / log(10)
- * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
- *
- * This suggests computing an approximation k to log10(d) by
- *
- * k = (i - Bias)*0.301029995663981
- * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
- *
- * We want k to be too large rather than too small.
- * The error in the first-order Taylor series approximation
- * is in our favor, so we just round up the constant enough
- * to compensate for any error in the multiplication of
- * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
- * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
- * adding 1e-13 to the constant term more than suffices.
- * Hence we adjust the constant term to 0.1760912590558.
- * (We could get a more accurate k by invoking log10,
- * but this is probably not worthwhile.)
- */
-
- i -= Bias;
-#ifdef IBM
- i <<= 2;
- i += j;
-#endif
-#ifndef Sudden_Underflow
- denorm = 0;
- }
- else {
- /* d is denormalized */
-
- i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
- : word1(d) << (32 - i);
- value(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
- i -= (Bias + (P-1) - 1) + 1;
- denorm = 1;
- }
-#endif
- ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
- i*0.301029995663981;
- k = (int)ds;
- if (ds < 0. && ds != k)
- k--; /* want k = floor(ds) */
- k_check = 1;
- if (k >= 0 && k <= Ten_pmax) {
- if (value(d) < tens[k])
- k--;
- k_check = 0;
- }
- j = bbits - i - 1;
- if (j >= 0) {
- b2 = 0;
- s2 = j;
- }
- else {
- b2 = -j;
- s2 = 0;
- }
- if (k >= 0) {
- b5 = 0;
- s5 = k;
- s2 += k;
- }
- else {
- b2 -= k;
- b5 = -k;
- s5 = 0;
- }
- if (mode < 0 || mode > 9)
- mode = 0;
- try_quick = 1;
- if (mode > 5) {
- mode -= 4;
- try_quick = 0;
- }
- leftright = 1;
- switch(mode) {
- case 0:
- case 1:
- ilim = ilim1 = -1;
- i = 18;
- ndigits = 0;
- break;
- case 2:
- leftright = 0;
- /* FALLTHROUGH */
- case 4:
- if (ndigits <= 0)
- ndigits = 1;
- ilim = ilim1 = i = ndigits;
- break;
- case 3:
- leftright = 0;
- /* FALLTHROUGH */
- case 5:
- i = ndigits + k + 1;
- ilim = i;
- ilim1 = i - 1;
- if (i <= 0)
- i = 1;
- }
- j = sizeof(ULong);
- for(result_k = 0; (int)(sizeof(Bigint) - sizeof(ULong)) + j <= i;
- j <<= 1) result_k++;
- // this is really a ugly hack, the code uses Balloc
- // instead of malloc, but casts the result into a char*
- // it seems the only reason to do that is due to the
- // complicated way the block size need to be computed
- // buuurk....
- result = Balloc(result_k);
- if (result == BIGINT_INVALID) {
- Bfree(b);
- return NULL;
- }
- s = s0 = (char *)(void *)result;
-
- if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
- /* Try to get by with floating-point arithmetic. */
-
- i = 0;
- value(d2) = value(d);
- k0 = k;
- ilim0 = ilim;
- ieps = 2; /* conservative */
- if (k > 0) {
- ds = tens[k&0xf];
- j = (unsigned int)k >> 4;
- if (j & Bletch) {
- /* prevent overflows */
- j &= Bletch - 1;
- value(d) /= bigtens[n_bigtens-1];
- ieps++;
- }
- for(; j; j = (unsigned int)j >> 1, i++)
- if (j & 1) {
- ieps++;
- ds *= bigtens[i];
- }
- value(d) /= ds;
- }
- else if ((jj1 = -k) != 0) {
- value(d) *= tens[jj1 & 0xf];
- for(j = (unsigned int)jj1 >> 4; j;
- j = (unsigned int)j >> 1, i++)
- if (j & 1) {
- ieps++;
- value(d) *= bigtens[i];
- }
- }
- if (k_check && value(d) < 1. && ilim > 0) {
- if (ilim1 <= 0)
- goto fast_failed;
- ilim = ilim1;
- k--;
- value(d) *= 10.;
- ieps++;
- }
- value(eps) = ieps*value(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
- if (ilim == 0) {
- S = mhi = 0;
- value(d) -= 5.;
- if (value(d) > value(eps))
- goto one_digit;
- if (value(d) < -value(eps))
- goto no_digits;
- goto fast_failed;
- }
-#ifndef No_leftright
- if (leftright) {
- /* Use Steele & White method of only
- * generating digits needed.
- */
- value(eps) = 0.5/tens[ilim-1] - value(eps);
- for(i = 0;;) {
- L = value(d);
- value(d) -= L;
- *s++ = '0' + (int)L;
- if (value(d) < value(eps))
- goto ret1;
- if (1. - value(d) < value(eps))
- goto bump_up;
- if (++i >= ilim)
- break;
- value(eps) *= 10.;
- value(d) *= 10.;
- }
- }
- else {
-#endif
- /* Generate ilim digits, then fix them up. */
- value(eps) *= tens[ilim-1];
- for(i = 1;; i++, value(d) *= 10.) {
- L = value(d);
- value(d) -= L;
- *s++ = '0' + (int)L;
- if (i == ilim) {
- if (value(d) > 0.5 + value(eps))
- goto bump_up;
- else if (value(d) < 0.5 - value(eps)) {
- while(*--s == '0');
- s++;
- goto ret1;
- }
- break;
- }
- }
-#ifndef No_leftright
- }
-#endif
- fast_failed:
- s = s0;
- value(d) = value(d2);
- k = k0;
- ilim = ilim0;
- }
-
- /* Do we have a "small" integer? */
-
- if (be >= 0 && k <= Int_max) {
- /* Yes. */
- ds = tens[k];
- if (ndigits < 0 && ilim <= 0) {
- S = mhi = 0;
- if (ilim < 0 || value(d) <= 5*ds)
- goto no_digits;
- goto one_digit;
- }
- for(i = 1;; i++) {
- L = value(d) / ds;
- value(d) -= L*ds;
-#ifdef Check_FLT_ROUNDS
- /* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (value(d) < 0) {
- L--;
- value(d) += ds;
- }
-#endif
- *s++ = '0' + (int)L;
- if (i == ilim) {
- value(d) += value(d);
- if (value(d) > ds || (value(d) == ds && L & 1)) {
- bump_up:
- while(*--s == '9')
- if (s == s0) {
- k++;
- *s = '0';
- break;
- }
- ++*s++;
- }
- break;
- }
- if (!(value(d) *= 10.))
- break;
- }
- goto ret1;
- }
-
- m2 = b2;
- m5 = b5;
- mhi = mlo = 0;
- if (leftright) {
- if (mode < 2) {
- i =
-#ifndef Sudden_Underflow
- denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
- 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
- 1 + P - bbits;
-#endif
- }
- else {
- j = ilim - 1;
- if (m5 >= j)
- m5 -= j;
- else {
- s5 += j -= m5;
- b5 += j;
- m5 = 0;
- }
- if ((i = ilim) < 0) {
- m2 -= i;
- i = 0;
- }
- }
- b2 += i;
- s2 += i;
- mhi = i2b(1);
- }
- if (m2 > 0 && s2 > 0) {
- i = m2 < s2 ? m2 : s2;
- b2 -= i;
- m2 -= i;
- s2 -= i;
- }
- if (b5 > 0) {
- if (leftright) {
- if (m5 > 0) {
- mhi = pow5mult(mhi, m5);
- b1 = mult(mhi, b);
- Bfree(b);
- b = b1;
- }
- if ((j = b5 - m5) != 0)
- b = pow5mult(b, j);
- }
- else
- b = pow5mult(b, b5);
- }
- S = i2b(1);
- if (s5 > 0)
- S = pow5mult(S, s5);
-
- /* Check for special case that d is a normalized power of 2. */
-
- if (mode < 2) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
- && word0(d) & Exp_mask
-#endif
- ) {
- /* The special case */
- b2 += Log2P;
- s2 += Log2P;
- spec_case = 1;
- }
- else
- spec_case = 0;
- }
-
- /* Arrange for convenient computation of quotients:
- * shift left if necessary so divisor has 4 leading 0 bits.
- *
- * Perhaps we should just compute leading 28 bits of S once
- * and for all and pass them and a shift to quorem, so it
- * can do shifts and ors to compute the numerator for q.
- */
- if (S == BIGINT_INVALID) {
- i = 0;
- } else {
-#ifdef Pack_32
- if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
- i = 32 - i;
-#else
- if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
- i = 16 - i;
-#endif
- }
-
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
- b = lshift(b, b2);
- if (s2 > 0)
- S = lshift(S, s2);
- if (k_check) {
- if (cmp(b,S) < 0) {
- k--;
- b = multadd(b, 10, 0); /* we botched the k estimate */
- if (leftright)
- mhi = multadd(mhi, 10, 0);
- ilim = ilim1;
- }
- }
- if (ilim <= 0 && mode > 2) {
- if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
- /* no digits, fcvt style */
- no_digits:
- k = -1 - ndigits;
- goto ret;
- }
- one_digit:
- *s++ = '1';
- k++;
- goto ret;
- }
- if (leftright) {
- if (m2 > 0)
- mhi = lshift(mhi, m2);
-
- /* Compute mlo -- check for special case
- * that d is a normalized power of 2.
- */
-
- mlo = mhi;
- if (spec_case) {
- mhi = Balloc(mhi->k);
- Bcopy(mhi, mlo);
- mhi = lshift(mhi, Log2P);
- }
-
- for(i = 1;;i++) {
- dig = quorem(b,S) + '0';
- /* Do we yet have the shortest decimal string
- * that will round to d?
- */
- j = cmp(b, mlo);
- delta = diff(S, mhi);
- jj1 = delta->sign ? 1 : cmp(b, delta);
- Bfree(delta);
-#ifndef ROUND_BIASED
- if (jj1 == 0 && !mode && !(word1(d) & 1)) {
- if (dig == '9')
- goto round_9_up;
- if (j > 0)
- dig++;
- *s++ = dig;
- goto ret;
- }
-#endif
- if (j < 0 || (j == 0 && !mode
-#ifndef ROUND_BIASED
- && !(word1(d) & 1)
-#endif
- )) {
- if (jj1 > 0) {
- b = lshift(b, 1);
- jj1 = cmp(b, S);
- if ((jj1 > 0 || (jj1 == 0 && dig & 1))
- && dig++ == '9')
- goto round_9_up;
- }
- *s++ = dig;
- goto ret;
- }
- if (jj1 > 0) {
- if (dig == '9') { /* possible if i == 1 */
- round_9_up:
- *s++ = '9';
- goto roundoff;
- }
- *s++ = dig + 1;
- goto ret;
- }
- *s++ = dig;
- if (i == ilim)
- break;
- b = multadd(b, 10, 0);
- if (mlo == mhi)
- mlo = mhi = multadd(mhi, 10, 0);
- else {
- mlo = multadd(mlo, 10, 0);
- mhi = multadd(mhi, 10, 0);
- }
- }
- }
- else
- for(i = 1;; i++) {
- *s++ = dig = quorem(b,S) + '0';
- if (i >= ilim)
- break;
- b = multadd(b, 10, 0);
- }
-
- /* Round off last digit */
-
- b = lshift(b, 1);
- j = cmp(b, S);
- if (j > 0 || (j == 0 && dig & 1)) {
- roundoff:
- while(*--s == '9')
- if (s == s0) {
- k++;
- *s++ = '1';
- goto ret;
- }
- ++*s++;
- }
- else {
- while(*--s == '0');
- s++;
- }
- ret:
- Bfree(S);
- if (mhi) {
- if (mlo && mlo != mhi)
- Bfree(mlo);
- Bfree(mhi);
- }
- ret1:
- Bfree(b);
- if (s == s0) { /* don't return empty string */
- *s++ = '0';
- k = 0;
- }
- *s = 0;
- *decpt = k + 1;
- if (rve)
- *rve = s;
- return s0;
-}
-#ifdef __cplusplus
-}
-#endif
diff --git a/libc/tools/genlibgcc_compat.py b/libc/tools/genlibgcc_compat.py
index f2ff7b0..cb5c3b3 100755
--- a/libc/tools/genlibgcc_compat.py
+++ b/libc/tools/genlibgcc_compat.py
@@ -71,23 +71,7 @@
import tempfile
import re
-libgcc_compat_header = "/* Generated by genlibgcc_compat.py */\n" + \
-"""
-#define COMPAT_FUNCTIONS_LIST \\
-"""
-
-libgcc_compat_footer = """
-
-#define XX(f) extern void f(void);
-COMPAT_FUNCTIONS_LIST
-#undef XX
-
-void __bionic_libgcc_compat_hooks(void) {
-#define XX(f) f();
-COMPAT_FUNCTIONS_LIST
-#undef XX
-}
-"""
+libgcc_compat_header = "/* Generated by genlibgcc_compat.py */\n\n"
class Generator:
def process(self):
@@ -114,29 +98,36 @@
print "* Build complete, logfile: " + build_output_file_path
- func_set = set()
+ symbol_set = set()
prog=re.compile("(?<=undefined reference to ')\w+")
fd = open(build_output_file_path, 'r')
for line in fd:
m = prog.search(line)
if m:
- func_set.add(m.group(0))
+ symbol_set.add(m.group(0))
fd.close()
- func_list = sorted(func_set)
+ symbol_list = sorted(symbol_set)
- print "* Found " + repr(len(func_list)) + " referenced functions: " + repr(func_list)
+ print "* Found " + repr(len(symbol_list)) + " referenced symbols: " + repr(symbol_list)
- if 0 == len(func_list):
- sys.exit("Error: function list is empty, please check the build log: " + build_output_file_path)
+ if 0 == len(symbol_list):
+ sys.exit("Error: symbol list is empty, please check the build log: " + build_output_file_path)
print "* Generating " + file_path
fres = open(file_path, 'w')
fres.write(libgcc_compat_header)
- for func_name in func_list:
- fres.write(" XX("+func_name+") \\\n")
- fres.write(libgcc_compat_footer)
+
+ for sym_name in symbol_list:
+ fres.write("extern char "+sym_name+";\n")
+ fres.write("\n");
+
+ fres.write("void* __bionic_libgcc_compat_symbols[] = {\n");
+ for sym_name in symbol_list:
+ fres.write(" &"+sym_name+",\n")
+ fres.write("};\n");
+
fres.close()
generator = Generator()
diff --git a/libc/upstream-freebsd/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
similarity index 100%
rename from libc/upstream-freebsd/freebsd-compat.h
rename to libc/upstream-freebsd/android/include/freebsd-compat.h
diff --git a/libc/upstream-freebsd/libc_private.h b/libc/upstream-freebsd/android/include/libc_private.h
similarity index 100%
rename from libc/upstream-freebsd/libc_private.h
rename to libc/upstream-freebsd/android/include/libc_private.h
diff --git a/libc/upstream-freebsd/namespace.h b/libc/upstream-freebsd/android/include/namespace.h
similarity index 100%
rename from libc/upstream-freebsd/namespace.h
rename to libc/upstream-freebsd/android/include/namespace.h
diff --git a/libc/upstream-freebsd/spinlock.h b/libc/upstream-freebsd/android/include/spinlock.h
similarity index 100%
rename from libc/upstream-freebsd/spinlock.h
rename to libc/upstream-freebsd/android/include/spinlock.h
diff --git a/libc/upstream-freebsd/un-namespace.h b/libc/upstream-freebsd/android/include/un-namespace.h
similarity index 100%
rename from libc/upstream-freebsd/un-namespace.h
rename to libc/upstream-freebsd/android/include/un-namespace.h
diff --git a/libc/upstream-netbsd/README.txt b/libc/upstream-netbsd/README.txt
index 86af6eb..e2d146e 100644
--- a/libc/upstream-netbsd/README.txt
+++ b/libc/upstream-netbsd/README.txt
@@ -2,8 +2,4 @@
files directly. Make fixes upstream and then pull down the new version of
the file.
-Note that code in the other 'netbsd' directory contains Android modifications.
-We should work towards getting as many of those changes as possible upstream
-and then losing those files in favor of pure upstream copies here instead.
-
TODO: write a script to make this process automated.
diff --git a/libc/upstream-netbsd/env.h b/libc/upstream-netbsd/android/include/env.h
similarity index 100%
rename from libc/upstream-netbsd/env.h
rename to libc/upstream-netbsd/android/include/env.h
diff --git a/libc/upstream-netbsd/extern.h b/libc/upstream-netbsd/android/include/extern.h
similarity index 100%
rename from libc/upstream-netbsd/extern.h
rename to libc/upstream-netbsd/android/include/extern.h
diff --git a/libc/upstream-netbsd/fd_setsize.h b/libc/upstream-netbsd/android/include/fd_setsize.h
similarity index 100%
rename from libc/upstream-netbsd/fd_setsize.h
rename to libc/upstream-netbsd/android/include/fd_setsize.h
diff --git a/libc/upstream-netbsd/namespace.h b/libc/upstream-netbsd/android/include/namespace.h
similarity index 100%
rename from libc/upstream-netbsd/namespace.h
rename to libc/upstream-netbsd/android/include/namespace.h
diff --git a/libc/upstream-netbsd/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h
similarity index 100%
rename from libc/upstream-netbsd/netbsd-compat.h
rename to libc/upstream-netbsd/android/include/netbsd-compat.h
diff --git a/libc/upstream-netbsd/port_after.h b/libc/upstream-netbsd/android/include/port_after.h
similarity index 100%
rename from libc/upstream-netbsd/port_after.h
rename to libc/upstream-netbsd/android/include/port_after.h
diff --git a/libc/upstream-netbsd/port_before.h b/libc/upstream-netbsd/android/include/port_before.h
similarity index 100%
rename from libc/upstream-netbsd/port_before.h
rename to libc/upstream-netbsd/android/include/port_before.h
diff --git a/libc/upstream-netbsd/rand48.h b/libc/upstream-netbsd/android/include/rand48.h
similarity index 100%
rename from libc/upstream-netbsd/rand48.h
rename to libc/upstream-netbsd/android/include/rand48.h
diff --git a/libc/upstream-netbsd/reentrant.h b/libc/upstream-netbsd/android/include/reentrant.h
similarity index 100%
rename from libc/upstream-netbsd/reentrant.h
rename to libc/upstream-netbsd/android/include/reentrant.h
diff --git a/libc/upstream-openbsd/README.txt b/libc/upstream-openbsd/README.txt
new file mode 100644
index 0000000..9db64ea
--- /dev/null
+++ b/libc/upstream-openbsd/README.txt
@@ -0,0 +1,5 @@
+This directory contains upstream OpenBSD source. You should not edit these
+files directly. Make fixes upstream and then pull down the new version of
+the file.
+
+TODO: write a script to make this process automated.
diff --git a/libc/upstream-openbsd/openbsd-compat.h b/libc/upstream-openbsd/android/gdtoa_support.cpp
similarity index 82%
copy from libc/upstream-openbsd/openbsd-compat.h
copy to libc/upstream-openbsd/android/gdtoa_support.cpp
index 2c3fe56..4e7bf3b 100644
--- a/libc/upstream-openbsd/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/gdtoa_support.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-#ifndef _BIONIC_OPENBSD_COMPAT_H_included
-#define _BIONIC_OPENBSD_COMPAT_H_included
+#include <pthread.h>
-#define _GNU_SOURCE
-#define __USE_BSD
-
-#endif
+__LIBC_HIDDEN__ pthread_mutex_t __dtoa_locks[] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
diff --git a/libc/upstream-openbsd/openbsd-compat.h b/libc/upstream-openbsd/android/include/arith.h
similarity index 83%
rename from libc/upstream-openbsd/openbsd-compat.h
rename to libc/upstream-openbsd/android/include/arith.h
index 2c3fe56..b262e4f 100644
--- a/libc/upstream-openbsd/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/arith.h
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#ifndef _BIONIC_OPENBSD_COMPAT_H_included
-#define _BIONIC_OPENBSD_COMPAT_H_included
+#define IEEE_8087
-#define _GNU_SOURCE
-#define __USE_BSD
-
+#if __LP64__
+#define Long int
#endif
+
+#define INFNAN_CHECK
+#define MULTIPLE_THREADS
diff --git a/libc/upstream-openbsd/android/include/gd_qnan.h b/libc/upstream-openbsd/android/include/gd_qnan.h
new file mode 100644
index 0000000..e8e907b
--- /dev/null
+++ b/libc/upstream-openbsd/android/include/gd_qnan.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#if __arm__
+
+#define f_QNAN 0xffffffff
+
+#define d_QNAN0 0xffffffff
+#define d_QNAN1 0xffffffff
+
+#elif __mips__
+
+#define f_QNAN 0x7fbfffff
+
+#define d_QNAN0 0x7ff7ffff
+#define d_QNAN1 0xffffffff
+
+#else
+
+#define f_QNAN 0xffc00000
+
+#define d_QNAN0 0x00000000
+#define d_QNAN1 0xfff80000
+
+#endif
+
+/* long double. */
+#if __LP64__
+#define ld_QNAN0 0x7fff8000
+#define ld_QNAN1 0x00000000
+#define ld_QNAN2 0x00000000
+#define ld_QNAN3 0x00000000
+#else
+/* sizeof(long double) == sizeof(double), so we shouldn't be trying to use these constants. */
+#endif
diff --git a/libc/upstream-openbsd/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
similarity index 70%
copy from libc/upstream-openbsd/openbsd-compat.h
copy to libc/upstream-openbsd/android/include/openbsd-compat.h
index 2c3fe56..b55f390 100644
--- a/libc/upstream-openbsd/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -20,4 +20,16 @@
#define _GNU_SOURCE
#define __USE_BSD
+/* OpenBSD's <ctype.h> uses these names, which conflicted with stlport.
+ * Additionally, we changed the numeric/digit type from N to D for libcxx.
+ */
+#define _U _CTYPE_U
+#define _L _CTYPE_L
+#define _N _CTYPE_D
+#define _S _CTYPE_S
+#define _P _CTYPE_P
+#define _C _CTYPE_C
+#define _X _CTYPE_X
+#define _B _CTYPE_B
+
#endif
diff --git a/libc/upstream-openbsd/openbsd-compat.h b/libc/upstream-openbsd/android/include/thread_private.h
similarity index 64%
copy from libc/upstream-openbsd/openbsd-compat.h
copy to libc/upstream-openbsd/android/include/thread_private.h
index 2c3fe56..10421e2 100644
--- a/libc/upstream-openbsd/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/thread_private.h
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-#ifndef _BIONIC_OPENBSD_COMPAT_H_included
-#define _BIONIC_OPENBSD_COMPAT_H_included
+#ifndef _THREAD_PRIVATE_H_
+#define _THREAD_PRIVATE_H_
-#define _GNU_SOURCE
-#define __USE_BSD
+#include <pthread.h>
-#endif
+/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
+#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
+#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+
+#endif /* _THREAD_PRIVATE_H_ */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c b/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c
new file mode 100644
index 0000000..a5795cf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/dmisc.c
@@ -0,0 +1,224 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+#ifndef MULTIPLE_THREADS
+ char *dtoa_result;
+#endif
+
+ char *
+#ifdef KR_headers
+rv_alloc(i) int i;
+#else
+rv_alloc(int i)
+#endif
+{
+ int j, k, *r;
+
+ j = sizeof(ULong);
+ for(k = 0;
+ sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
+ j <<= 1)
+ k++;
+ r = (int*)Balloc(k);
+ if (r == NULL)
+ return (
+#ifndef MULTIPLE_THREADS
+ dtoa_result =
+#endif
+ NULL);
+ *r = k;
+ return
+#ifndef MULTIPLE_THREADS
+ dtoa_result =
+#endif
+ (char *)(r+1);
+ }
+
+ char *
+#ifdef KR_headers
+nrv_alloc(s, rve, n) char *s, **rve; int n;
+#else
+nrv_alloc(char *s, char **rve, int n)
+#endif
+{
+ char *rv, *t;
+
+ t = rv = rv_alloc(n);
+ if (t == NULL)
+ return (NULL);
+ while((*t = *s++) !=0)
+ t++;
+ if (rve)
+ *rve = t;
+ return rv;
+ }
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined. It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+ void
+#ifdef KR_headers
+freedtoa(s) char *s;
+#else
+freedtoa(char *s)
+#endif
+{
+ Bigint *b = (Bigint *)((int *)s - 1);
+ b->maxwds = 1 << (b->k = *(int*)b);
+ Bfree(b);
+#ifndef MULTIPLE_THREADS
+ if (s == dtoa_result)
+ dtoa_result = 0;
+#endif
+ }
+
+ int
+quorem
+#ifdef KR_headers
+ (b, S) Bigint *b, *S;
+#else
+ (Bigint *b, Bigint *S)
+#endif
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+ ULLong borrow, carry, y, ys;
+#else
+ ULong borrow, carry, y, ys;
+#ifdef Pack_32
+ ULong si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+#ifdef DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef ULLong
+ ys = *sx++ * (ULLong)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & 1UL;
+ *bx++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef ULLong
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & 0xffffffffUL) - borrow;
+ borrow = y >> 32 & 1UL;
+ *bx++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c
new file mode 100644
index 0000000..668f7b5
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/dtoa.c
@@ -0,0 +1,839 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+#ifdef Honor_FLT_ROUNDS
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+ char *
+dtoa
+#ifdef KR_headers
+ (d0, mode, ndigits, decpt, sign, rve)
+ double d0; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+ (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
+#endif
+{
+ /* Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4,5 ==> similar to 2 and 3, respectively, but (in
+ round-nearest mode) with the tests of mode 0 to
+ possibly return a shorter string that rounds to d.
+ With IEEE arithmetic and compilation with
+ -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+ as modes 2 and 3 when FLT_ROUNDS != 1.
+ 6-9 ==> Debugging modes similar to mode - 4: don't try
+ fast floating-point estimate (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ Long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ ULong x;
+#endif
+ Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ U d, d2, eps;
+ double ds;
+ char *s, *s0;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+#ifdef Honor_FLT_ROUNDS /*{*/
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+#endif /*}*/
+
+#ifndef MULTIPLE_THREADS
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+ d.d = d0;
+ if (word0(&d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(&d) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((word0(&d) & Exp_mask) == Exp_mask)
+#else
+ if (word0(&d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+#ifdef IEEE_Arith
+ if (!word1(&d) && !(word0(&d) & 0xfffff))
+ return nrv_alloc("Infinity", rve, 8);
+#endif
+ return nrv_alloc("NaN", rve, 3);
+ }
+#endif
+#ifdef IBM
+ dval(&d) += 0; /* normalize */
+#endif
+ if (!dval(&d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if (Rounding >= 2) {
+ if (*sign)
+ Rounding = Rounding == 2 ? 0 : 2;
+ else
+ if (Rounding != 2)
+ Rounding = 0;
+ }
+#endif
+
+ b = d2b(dval(&d), &be, &bbits);
+ if (b == NULL)
+ return (NULL);
+#ifdef Sudden_Underflow
+ i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+ if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
+#endif
+ dval(&d2) = dval(&d);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
+#ifdef IBM
+ if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0)
+ dval(&d2) /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2)
+ *
+ * This suggests computing an approximation k to log10(&d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P-1) - 1);
+ x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
+ : word1(&d) << (32 - i);
+ dval(&d2) = x;
+ word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P-1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(&d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
+ /* silence erroneous "gcc -Wall" warning. */
+ switch(mode) {
+ case 0:
+ case 1:
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ s = s0 = rv_alloc(i);
+ if (s == NULL)
+ return (NULL);
+
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1 && Rounding != 1)
+ leftright = 0;
+#endif
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(&d2) = dval(&d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(&d) /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ dval(&d) /= ds;
+ }
+ else if (( j1 = -k )!=0) {
+ dval(&d) *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ dval(&d) *= bigtens[i];
+ }
+ }
+ if (k_check && dval(&d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(&d) *= 10.;
+ ieps++;
+ }
+ dval(&eps) = ieps*dval(&d) + 7.;
+ word0(&eps) -= (P-1)*Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
+ goto one_digit;
+ if (dval(&d) < -dval(&eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
+ for(i = 0;;) {
+ L = dval(&d);
+ dval(&d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(&d) < dval(&eps))
+ goto ret1;
+ if (1. - dval(&d) < dval(&eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(&eps) *= 10.;
+ dval(&d) *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(dval(&d));
+ if (!(dval(&d) -= L))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(&d) > 0.5 + dval(&eps))
+ goto bump_up;
+ else if (dval(&d) < 0.5 - dval(&eps)) {
+ while(*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ dval(&d) = dval(&d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(&d) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(dval(&d) / ds);
+ dval(&d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(&d) < 0) {
+ L--;
+ dval(&d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(&d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(Rounding) {
+ case 0: goto ret1;
+ case 2: goto bump_up;
+ }
+#endif
+ dval(&d) += dval(&d);
+#ifdef ROUND_BIASED
+ if (dval(&d) >= ds)
+#else
+ if (dval(&d) > ds || (dval(&d) == ds && L & 1))
+#endif
+ {
+ bump_up:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ if (mhi == NULL)
+ return (NULL);
+ b1 = mult(mhi, b);
+ if (b1 == NULL)
+ return (NULL);
+ Bfree(b);
+ b = b1;
+ }
+ if (( j = b5 - m5 )!=0) {
+ b = pow5mult(b, j);
+ if (b == NULL)
+ return (NULL);
+ }
+ }
+ else {
+ b = pow5mult(b, b5);
+ if (b == NULL)
+ return (NULL);
+ }
+ }
+ S = i2b(1);
+ if (S == NULL)
+ return (NULL);
+ if (s5 > 0) {
+ S = pow5mult(S, s5);
+ if (S == NULL)
+ return (NULL);
+ }
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+ && Rounding == 1
+#endif
+ ) {
+ if (!word1(&d) && !(word0(&d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(&d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f )!=0)
+ i = 32 - i;
+#else
+ if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf )!=0)
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0) {
+ b = lshift(b, b2);
+ if (b == NULL)
+ return (NULL);
+ }
+ if (s2 > 0) {
+ S = lshift(S, s2);
+ if (S == NULL)
+ return (NULL);
+ }
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (b == NULL)
+ return (NULL);
+ if (leftright) {
+ mhi = multadd(mhi, 10, 0);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && (mode == 3 || mode == 5)) {
+ S = multadd(S,5,0);
+ if (S == NULL)
+ return (NULL);
+ if (ilim < 0 || cmp(b,S) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ k = -1 - ndigits;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0) {
+ mhi = lshift(mhi, m2);
+ if (mhi == NULL)
+ return (NULL);
+ }
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ if (mhi == NULL)
+ return (NULL);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ if (mhi == NULL)
+ return (NULL);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ if (delta == NULL)
+ return (NULL);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && mode != 1 && !(word1(&d) & 1)
+#ifdef Honor_FLT_ROUNDS
+ && Rounding >= 1
+#endif
+ ) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && mode != 1
+#ifndef ROUND_BIASED
+ && !(word1(&d) & 1)
+#endif
+ )) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(Rounding) {
+ case 0: goto accept_dig;
+ case 2: goto keep_dig;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ if (b == NULL)
+ return (NULL);
+ j1 = cmp(b, S);
+#ifdef ROUND_BIASED
+ if (j1 >= 0 /*)*/
+#else
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+#endif
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+#ifdef Honor_FLT_ROUNDS
+ if (!Rounding)
+ goto accept_dig;
+#endif
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+#ifdef Honor_FLT_ROUNDS
+ keep_dig:
+#endif
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (b == NULL)
+ return (NULL);
+ if (mlo == mhi) {
+ mlo = mhi = multadd(mhi, 10, 0);
+ if (mlo == NULL)
+ return (NULL);
+ }
+ else {
+ mlo = multadd(mlo, 10, 0);
+ if (mlo == NULL)
+ return (NULL);
+ mhi = multadd(mhi, 10, 0);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (b == NULL)
+ return (NULL);
+ }
+
+ /* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+ switch(Rounding) {
+ case 0: goto trimzeros;
+ case 2: goto roundoff;
+ }
+#endif
+ b = lshift(b, 1);
+ if (b == NULL)
+ return (NULL);
+ j = cmp(b, S);
+#ifdef ROUND_BIASED
+ if (j >= 0)
+#else
+ if (j > 0 || (j == 0 && dig & 1))
+#endif
+ {
+ roundoff:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+#ifdef Honor_FLT_ROUNDS
+ trimzeros:
+#endif
+ while(*--s == '0');
+ s++;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(&d) = Exp_1 + (70 << Exp_shift);
+ word1(&d) = 0;
+ dval(&d) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c
new file mode 100644
index 0000000..fd11de5
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.c
@@ -0,0 +1,829 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ static Bigint *
+#ifdef KR_headers
+bitstob(bits, nbits, bbits) ULong *bits; int nbits; int *bbits;
+#else
+bitstob(ULong *bits, int nbits, int *bbits)
+#endif
+{
+ int i, k;
+ Bigint *b;
+ ULong *be, *x, *x0;
+
+ i = ULbits;
+ k = 0;
+ while(i < nbits) {
+ i <<= 1;
+ k++;
+ }
+#ifndef Pack_32
+ if (!k)
+ k = 1;
+#endif
+ b = Balloc(k);
+ if (b == NULL)
+ return (NULL);
+ be = bits + ((nbits - 1) >> kshift);
+ x = x0 = b->x;
+ do {
+ *x++ = *bits & ALL_ON;
+#ifdef Pack_16
+ *x++ = (*bits >> 16) & ALL_ON;
+#endif
+ } while(++bits <= be);
+ i = x - x0;
+ while(!x0[--i])
+ if (!i) {
+ b->wds = 0;
+ *bbits = 0;
+ goto ret;
+ }
+ b->wds = i + 1;
+ *bbits = i*ULbits + 32 - hi0bits(b->x[i]);
+ ret:
+ return b;
+ }
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+ char *
+gdtoa
+#ifdef KR_headers
+ (fpi, be, bits, kindp, mode, ndigits, decpt, rve)
+ FPI *fpi; int be; ULong *bits;
+ int *kindp, mode, ndigits, *decpt; char **rve;
+#else
+ (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)
+#endif
+{
+ /* Arguments ndigits and decpt are similar to the second and third
+ arguments of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+ be = exponent: value = (integer represented by bits) * (2 to the power of be).
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4-9 should give the same return values as 2-3, i.e.,
+ 4 <= mode <= 9 ==> same return as mode
+ 2 + (mode & 1). These modes are mainly for
+ debugging; often they run slower but sometimes
+ faster than modes 2-3.
+ 4,5,8,9 ==> left-to-right digit generation.
+ 6-9 ==> don't try fast floating-point estimate
+ (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex;
+ int j, j1, k, k0, k_check, kind, leftright, m2, m5, nbits;
+ int rdir, s2, s5, spec_case, try_quick;
+ Long L;
+ Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
+ double d2, ds;
+ char *s, *s0;
+ U d, eps;
+
+#ifndef MULTIPLE_THREADS
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+ inex = 0;
+ kind = *kindp &= ~STRTOG_Inexact;
+ switch(kind & STRTOG_Retmask) {
+ case STRTOG_Zero:
+ goto ret_zero;
+ case STRTOG_Normal:
+ case STRTOG_Denormal:
+ break;
+ case STRTOG_Infinite:
+ *decpt = -32768;
+ return nrv_alloc("Infinity", rve, 8);
+ case STRTOG_NaN:
+ *decpt = -32768;
+ return nrv_alloc("NaN", rve, 3);
+ default:
+ return 0;
+ }
+ b = bitstob(bits, nbits = fpi->nbits, &bbits);
+ if (b == NULL)
+ return (NULL);
+ be0 = be;
+ if ( (i = trailz(b)) !=0) {
+ rshift(b, i);
+ be += i;
+ bbits -= i;
+ }
+ if (!b->wds) {
+ Bfree(b);
+ ret_zero:
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+ dval(&d) = b2d(b, &i);
+ i = be + bbits - 1;
+ word0(&d) &= Frac_mask1;
+ word0(&d) |= Exp_11;
+#ifdef IBM
+ if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
+ dval(&d) /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(&d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+ ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+
+ /* correct assumption about exponent range */
+ if ((j = i) < 0)
+ j = -j;
+ if ((j -= 1077) > 0)
+ ds += j * 7e-17;
+
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+#ifdef IBM
+ j = be + bbits - 1;
+ if ( (j1 = j & 3) !=0)
+ dval(&d) *= 1 << j1;
+ word0(&d) += j << Exp_shift - 2 & Exp_mask;
+#else
+ word0(&d) += (be + bbits - 1) << Exp_shift;
+#endif
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(&d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+ try_quick = 1;
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ else if (i >= -4 - Emin || i < Emin)
+ try_quick = 0;
+ leftright = 1;
+ ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
+ /* silence erroneous "gcc -Wall" warning. */
+ switch(mode) {
+ case 0:
+ case 1:
+ i = (int)(nbits * .30103) + 3;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ s = s0 = rv_alloc(i);
+ if (s == NULL)
+ return (NULL);
+
+ if ( (rdir = fpi->rounding - 1) !=0) {
+ if (rdir < 0)
+ rdir = 2;
+ if (kind & STRTOG_Neg)
+ rdir = 3 - rdir;
+ }
+
+ /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir
+#ifndef IMPRECISE_INEXACT
+ && k == 0
+#endif
+ ) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ d2 = dval(&d);
+#ifdef IBM
+ if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
+ dval(&d) /= 1 << j;
+#endif
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(&d) /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ }
+ else {
+ ds = 1.;
+ if ( (j1 = -k) !=0) {
+ dval(&d) *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ dval(&d) *= bigtens[i];
+ }
+ }
+ }
+ if (k_check && dval(&d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(&d) *= 10.;
+ ieps++;
+ }
+ dval(&eps) = ieps*dval(&d) + 7.;
+ word0(&eps) -= (P-1)*Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
+ goto one_digit;
+ if (dval(&d) < -dval(&eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps);
+ for(i = 0;;) {
+ L = (Long)(dval(&d)/ds);
+ dval(&d) -= L*ds;
+ *s++ = '0' + (int)L;
+ if (dval(&d) < dval(&eps)) {
+ if (dval(&d))
+ inex = STRTOG_Inexlo;
+ goto ret1;
+ }
+ if (ds - dval(&d) < dval(&eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(&eps) *= 10.;
+ dval(&d) *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ if ( (L = (Long)(dval(&d)/ds)) !=0)
+ dval(&d) -= L*ds;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ ds *= 0.5;
+ if (dval(&d) > ds + dval(&eps))
+ goto bump_up;
+ else if (dval(&d) < ds - dval(&eps)) {
+ if (dval(&d))
+ inex = STRTOG_Inexlo;
+ goto clear_trailing0;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ dval(&d) = d2;
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(&d) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = dval(&d) / ds;
+ dval(&d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(&d) < 0) {
+ L--;
+ dval(&d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (dval(&d) == 0.)
+ break;
+ if (i == ilim) {
+ if (rdir) {
+ if (rdir == 1)
+ goto bump_up;
+ inex = STRTOG_Inexlo;
+ goto ret1;
+ }
+ dval(&d) += dval(&d);
+#ifdef ROUND_BIASED
+ if (dval(&d) >= ds)
+#else
+ if (dval(&d) > ds || (dval(&d) == ds && L & 1))
+#endif
+ {
+ bump_up:
+ inex = STRTOG_Inexhi;
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ else {
+ inex = STRTOG_Inexlo;
+ clear_trailing0:
+ while(*--s == '0'){}
+ ++s;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i = nbits - bbits;
+ if (be - i++ < fpi->emin && mode != 3 && mode != 5) {
+ /* denormal */
+ i = be - fpi->emin + 1;
+ if (mode >= 2 && ilim > 0 && ilim < i)
+ goto small_ilim;
+ }
+ else if (mode >= 2) {
+ small_ilim:
+ j = ilim - 1;
+ if (m5 >= j)
+ m5 -= j;
+ else {
+ s5 += j -= m5;
+ b5 += j;
+ m5 = 0;
+ }
+ if ((i = ilim) < 0) {
+ m2 -= i;
+ i = 0;
+ }
+ }
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ if (mhi == NULL)
+ return (NULL);
+ b1 = mult(mhi, b);
+ if (b1 == NULL)
+ return (NULL);
+ Bfree(b);
+ b = b1;
+ }
+ if ( (j = b5 - m5) !=0) {
+ b = pow5mult(b, j);
+ if (b == NULL)
+ return (NULL);
+ }
+ }
+ else {
+ b = pow5mult(b, b5);
+ if (b == NULL)
+ return (NULL);
+ }
+ }
+ S = i2b(1);
+ if (S == NULL)
+ return (NULL);
+ if (s5 > 0) {
+ S = pow5mult(S, s5);
+ if (S == NULL)
+ return (NULL);
+ }
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if (mode < 2) {
+ if (bbits == 1 && be0 > fpi->emin + 1) {
+ /* The special case */
+ b2++;
+ s2++;
+ spec_case = 1;
+ }
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+ i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
+ m2 += i;
+ if ((b2 += i) > 0) {
+ b = lshift(b, b2);
+ if (b == NULL)
+ return (NULL);
+ }
+ if ((s2 += i) > 0) {
+ S = lshift(S, s2);
+ if (S == NULL)
+ return (NULL);
+ }
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (b == NULL)
+ return (NULL);
+ if (leftright) {
+ mhi = multadd(mhi, 10, 0);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && mode > 2) {
+ S = multadd(S,5,0);
+ if (S == NULL)
+ return (NULL);
+ if (ilim < 0 || cmp(b,S) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ k = -1 - ndigits;
+ inex = STRTOG_Inexlo;
+ goto ret;
+ }
+ one_digit:
+ inex = STRTOG_Inexhi;
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0) {
+ mhi = lshift(mhi, m2);
+ if (mhi == NULL)
+ return (NULL);
+ }
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ if (mhi == NULL)
+ return (NULL);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, 1);
+ if (mhi == NULL)
+ return (NULL);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ if (delta == NULL)
+ return (NULL);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && !mode && !(bits[0] & 1) && !rdir) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j <= 0) {
+ if (b->wds > 1 || b->x[0])
+ inex = STRTOG_Inexlo;
+ }
+ else {
+ dig++;
+ inex = STRTOG_Inexhi;
+ }
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && !mode
+#ifndef ROUND_BIASED
+ && !(bits[0] & 1)
+#endif
+ )) {
+ if (rdir && (b->wds > 1 || b->x[0])) {
+ if (rdir == 2) {
+ inex = STRTOG_Inexlo;
+ goto accept;
+ }
+ while (cmp(S,mhi) > 0) {
+ *s++ = dig;
+ mhi1 = multadd(mhi, 10, 0);
+ if (mhi1 == NULL)
+ return (NULL);
+ if (mlo == mhi)
+ mlo = mhi1;
+ mhi = mhi1;
+ b = multadd(b, 10, 0);
+ if (b == NULL)
+ return (NULL);
+ dig = quorem(b,S) + '0';
+ }
+ if (dig++ == '9')
+ goto round_9_up;
+ inex = STRTOG_Inexhi;
+ goto accept;
+ }
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ if (b == NULL)
+ return (NULL);
+ j1 = cmp(b, S);
+#ifdef ROUND_BIASED
+ if (j1 >= 0 /*)*/
+#else
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+#endif
+ && dig++ == '9')
+ goto round_9_up;
+ inex = STRTOG_Inexhi;
+ }
+ if (b->wds > 1 || b->x[0])
+ inex = STRTOG_Inexlo;
+ accept:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0 && rdir != 2) {
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ inex = STRTOG_Inexhi;
+ goto roundoff;
+ }
+ inex = STRTOG_Inexhi;
+ *s++ = dig + 1;
+ goto ret;
+ }
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (b == NULL)
+ return (NULL);
+ if (mlo == mhi) {
+ mlo = mhi = multadd(mhi, 10, 0);
+ if (mlo == NULL)
+ return (NULL);
+ }
+ else {
+ mlo = multadd(mlo, 10, 0);
+ if (mlo == NULL)
+ return (NULL);
+ mhi = multadd(mhi, 10, 0);
+ if (mhi == NULL)
+ return (NULL);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (b == NULL)
+ return (NULL);
+ }
+
+ /* Round off last digit */
+
+ if (rdir) {
+ if (rdir == 2 || (b->wds <= 1 && !b->x[0]))
+ goto chopzeros;
+ goto roundoff;
+ }
+ b = lshift(b, 1);
+ if (b == NULL)
+ return (NULL);
+ j = cmp(b, S);
+#ifdef ROUND_BIASED
+ if (j >= 0)
+#else
+ if (j > 0 || (j == 0 && dig & 1))
+#endif
+ {
+ roundoff:
+ inex = STRTOG_Inexhi;
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+ chopzeros:
+ if (b->wds > 1 || b->x[0])
+ inex = STRTOG_Inexlo;
+ while(*--s == '0'){}
+ ++s;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ *kindp |= inex;
+ return s0;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h
new file mode 100644
index 0000000..9e1cea0
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h
@@ -0,0 +1,155 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#ifndef GDTOA_H_INCLUDED
+#define GDTOA_H_INCLUDED
+
+#include "arith.h"
+#include <stddef.h> /* for size_t */
+
+#ifndef Long
+#define Long int
+#endif
+#ifndef ULong
+typedef unsigned Long ULong;
+#endif
+#ifndef UShort
+typedef unsigned short UShort;
+#endif
+
+#ifndef ANSI
+#ifdef KR_headers
+#define ANSI(x) ()
+#define Void /*nothing*/
+#else
+#define ANSI(x) x
+#define Void void
+#endif
+#endif /* ANSI */
+
+#ifndef CONST
+#ifdef KR_headers
+#define CONST /* blank */
+#else
+#define CONST const
+#endif
+#endif /* CONST */
+
+ enum { /* return values from strtodg */
+ STRTOG_Zero = 0x000,
+ STRTOG_Normal = 0x001,
+ STRTOG_Denormal = 0x002,
+ STRTOG_Infinite = 0x003,
+ STRTOG_NaN = 0x004,
+ STRTOG_NaNbits = 0x005,
+ STRTOG_NoNumber = 0x006,
+ STRTOG_NoMemory = 0x007,
+ STRTOG_Retmask = 0x00f,
+
+ /* The following may be or-ed into one of the above values. */
+
+ STRTOG_Inexlo = 0x010, /* returned result rounded toward zero */
+ STRTOG_Inexhi = 0x020, /* returned result rounded away from zero */
+ STRTOG_Inexact = 0x030,
+ STRTOG_Underflow= 0x040,
+ STRTOG_Overflow = 0x080,
+ STRTOG_Neg = 0x100 /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */
+ };
+
+ typedef struct
+FPI {
+ int nbits;
+ int emin;
+ int emax;
+ int rounding;
+ int sudden_underflow;
+ } FPI;
+
+enum { /* FPI.rounding values: same as FLT_ROUNDS */
+ FPI_Round_zero = 0,
+ FPI_Round_near = 1,
+ FPI_Round_up = 2,
+ FPI_Round_down = 3
+ };
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char* __dtoa ANSI((double d, int mode, int ndigits, int *decpt,
+ int *sign, char **rve));
+extern char* __gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
+ int mode, int ndigits, int *decpt, char **rve));
+extern void __freedtoa ANSI((char*));
+extern float strtof ANSI((CONST char *, char **));
+extern double strtod ANSI((CONST char *, char **));
+extern int __strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
+
+extern char* __g_ddfmt ANSI((char*, double*, int, size_t));
+extern char* __g_dfmt ANSI((char*, double*, int, size_t));
+extern char* __g_ffmt ANSI((char*, float*, int, size_t));
+extern char* __g_Qfmt ANSI((char*, void*, int, size_t));
+extern char* __g_xfmt ANSI((char*, void*, int, size_t));
+extern char* __g_xLfmt ANSI((char*, void*, int, size_t));
+
+extern int __strtoId ANSI((CONST char*, char**, double*, double*));
+extern int __strtoIdd ANSI((CONST char*, char**, double*, double*));
+extern int __strtoIf ANSI((CONST char*, char**, float*, float*));
+extern int __strtoIQ ANSI((CONST char*, char**, void*, void*));
+extern int __strtoIx ANSI((CONST char*, char**, void*, void*));
+extern int __strtoIxL ANSI((CONST char*, char**, void*, void*));
+extern int __strtord ANSI((CONST char*, char**, int, double*));
+extern int __strtordd ANSI((CONST char*, char**, int, double*));
+extern int __strtorf ANSI((CONST char*, char**, int, float*));
+extern int __strtorQ ANSI((CONST char*, char**, int, void*));
+extern int __strtorx ANSI((CONST char*, char**, int, void*));
+extern int __strtorxL ANSI((CONST char*, char**, int, void*));
+#if 1
+extern int __strtodI ANSI((CONST char*, char**, double*));
+extern int __strtopd ANSI((CONST char*, char**, double*));
+extern int __strtopdd ANSI((CONST char*, char**, double*));
+extern int __strtopf ANSI((CONST char*, char**, float*));
+extern int __strtopQ ANSI((CONST char*, char**, void*));
+extern int __strtopx ANSI((CONST char*, char**, void*));
+extern int __strtopxL ANSI((CONST char*, char**, void*));
+#else
+#define __strtopd(s,se,x) strtord(s,se,1,x)
+#define __strtopdd(s,se,x) strtordd(s,se,1,x)
+#define __strtopf(s,se,x) strtorf(s,se,1,x)
+#define __strtopQ(s,se,x) strtorQ(s,se,1,x)
+#define __strtopx(s,se,x) strtorx(s,se,1,x)
+#define __strtopxL(s,se,x) strtorxL(s,se,1,x)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GDTOA_H_INCLUDED */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa_fltrnds.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa_fltrnds.h
new file mode 100644
index 0000000..33e5f9e
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa_fltrnds.h
@@ -0,0 +1,18 @@
+ FPI *fpi, fpi1;
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+ fpi = &fpi0;
+ if (Rounding != 1) {
+ fpi1 = fpi0;
+ fpi = &fpi1;
+ fpi1.rounding = Rounding;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
new file mode 100644
index 0000000..7a36967
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
@@ -0,0 +1,665 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* This is a variation on dtoa.c that converts arbitary binary
+ floating-point formats to and from decimal notation. It uses
+ double-precision arithmetic internally, so there are still
+ various #ifdefs that adapt the calculations to the native
+ double-precision arithmetic (any of IEEE, VAX D_floating,
+ or IBM mainframe arithmetic).
+
+ Please send bug reports to David M. Gay (dmg at acm dot org,
+ with " at " changed at "@" and " dot " changed to ".").
+ */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define Sudden_Underflow for IEEE-format machines without gradual
+ * underflow (i.e., that flush to zero on underflow).
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic (D_floating).
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa and gdtoa. This will cause modes 4 and 5 to be
+ * treated the same as modes 2 and 3 for some inputs.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic
+ * that rounds toward +Infinity.
+ * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased
+ * rounding when the underlying floating-point arithmetic uses
+ * unbiased rounding. This prevent using ordinary floating-point
+ * arithmetic when the result could be computed with one rounding error.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define NO_LONG_LONG on machines that do not have a "long long"
+ * integer type (of >= 64 bits). On such machines, you can
+ * #define Just_16 to store 16 bits per 32-bit Long when doing
+ * high-precision integer arithmetic. Whether this speeds things
+ * up or slows things down depends on the machine and the number
+ * being converted. If long long is available and the name is
+ * something other than "long long", #define Llong to be the name,
+ * and if "unsigned Llong" does not work as an unsigned version of
+ * Llong, #define #ULLong to be the corresponding unsigned type.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ * if memory is available and otherwise does something you deem
+ * appropriate. If MALLOC is undefined, malloc will be invoked
+ * directly -- and assumed always to succeed. Similarly, if you
+ * want something other than the system's free() to be called to
+ * recycle memory acquired from MALLOC, #define FREE to be the
+ * name of the alternate routine. (FREE or free is only called in
+ * pathological cases, e.g., in a gdtoa call after a gdtoa return in
+ * mode 3 with thousands of digits requested.)
+ * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
+ * memory allocations from a private pool of memory when possible.
+ * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
+ * unless #defined to be a different length. This default length
+ * suffices to get rid of MALLOC calls except for unusual cases,
+ * such as decimal-to-binary conversion of a very long string of
+ * digits. When converting IEEE double precision values, the
+ * longest string gdtoa can return is about 751 bytes long. For
+ * conversions by strtod of strings of 800 digits and all gdtoa
+ * conversions of IEEE doubles in single-threaded executions with
+ * 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
+ * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ * #defined automatically on IEEE systems. On such systems,
+ * when INFNAN_CHECK is #defined, strtod checks
+ * for Infinity and NaN (case insensitively).
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtodg also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits (optionally
+ * preceded by 0x or 0X) and spaces; if there is only one string
+ * of hexadecimal digits, it is taken for the fraction bits of the
+ * resulting NaN; if there are two or more strings of hexadecimal
+ * digits, each string is assigned to the next available sequence
+ * of 32-bit words of fractions bits (starting with the most
+ * significant), right-aligned in each sequence.
+ * Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)"
+ * is consumed even when ... has the wrong form (in which case the
+ * "(...)" is consumed but ignored).
+ * #define MULTIPLE_THREADS if the system offers preemptively scheduled
+ * multiple threads. In this case, you must provide (or suitably
+ * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
+ * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
+ * in pow5mult, ensures lazy evaluation of only one copy of high
+ * powers of 5; omitting this lock would introduce a small
+ * probability of wasting memory, but would otherwise be harmless.)
+ * You must also invoke freedtoa(s) to free the value s returned by
+ * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
+ * #define IMPRECISE_INEXACT if you do not care about the setting of
+ * the STRTOG_Inexact bits in the special case of doing IEEE double
+ * precision conversions (which could also be done by the strtod in
+ * dtoa.c).
+ * #define NO_HEX_FP to disable recognition of C9x's hexadecimal
+ * floating-point constants.
+ * #define -DNO_ERRNO to suppress setting errno (in strtod.c and
+ * strtodg.c).
+ * #define NO_STRING_H to use private versions of memcpy.
+ * On some K&R systems, it may also be necessary to
+ * #define DECLARE_SIZE_T in this case.
+ * #define USE_LOCALE to use the current locale's decimal_point value.
+ */
+
+#ifndef GDTOAIMP_H_INCLUDED
+#define GDTOAIMP_H_INCLUDED
+#include "gdtoa.h"
+#include "gd_qnan.h"
+#ifdef Honor_FLT_ROUNDS
+#include <fenv.h>
+#endif
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#include "stdlib.h"
+#include "string.h"
+
+#ifdef KR_headers
+#define Char char
+#else
+#define Char void
+#endif
+
+#ifdef MALLOC
+extern Char *MALLOC ANSI((size_t));
+#else
+#define MALLOC malloc
+#endif
+
+#undef IEEE_Arith
+#undef Avoid_Underflow
+#ifdef IEEE_MC68k
+#define IEEE_Arith
+#endif
+#ifdef IEEE_8087
+#define IEEE_Arith
+#endif
+
+#include "errno.h"
+#ifdef Bad_float_h
+
+#ifdef IEEE_Arith
+#define DBL_DIG 15
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define FLT_RADIX 2
+#define DBL_MAX 1.7976931348623157e+308
+#endif
+
+#ifdef IBM
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 75
+#define DBL_MAX_EXP 63
+#define FLT_RADIX 16
+#define DBL_MAX 7.2370055773322621e+75
+#endif
+
+#ifdef VAX
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 38
+#define DBL_MAX_EXP 127
+#define FLT_RADIX 2
+#define DBL_MAX 1.7014118346046923e+38
+#define n_bigtens 2
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#else /* ifndef Bad_float_h */
+#include "float.h"
+#endif /* Bad_float_h */
+
+#ifdef IEEE_Arith
+#define Scale_Bit 0x10
+#define n_bigtens 5
+#endif
+
+#ifdef IBM
+#define n_bigtens 3
+#endif
+
+#ifdef VAX
+#define n_bigtens 2
+#endif
+
+#ifndef __MATH_H__
+#include "math.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
+#endif
+
+typedef union { double d; ULong L[2]; } U;
+
+#ifdef IEEE_8087
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
+#else
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
+#endif
+#define dval(x) (x)->d
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#ifdef IEEE_Arith
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#else /* ifndef IEEE_Arith */
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#undef Flt_Rounds
+#define Flt_Rounds 0
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 0x1000000
+#define Exp_msk11 0x1000000
+#define Exp_mask 0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1 0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask 0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask 0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#undef Flt_Rounds
+#define Flt_Rounds 1
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 0x800000
+#define Exp_mask 0x7f80
+#define P 56
+#define Bias 129
+#define Emin (-127)
+#define Exp_1 0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask 0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask 0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif /* IBM, VAX */
+#endif /* IEEE_Arith */
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#else
+#ifdef ROUND_BIASED_without_Round_Up
+#undef ROUND_BIASED
+#define ROUND_BIASED
+#endif
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#undef Pack_16
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#ifdef NO_LONG_LONG
+#undef ULLong
+#ifdef Just_16
+#undef Pack_32
+#define Pack_16
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per Long.
+ */
+#endif
+#else /* long long available */
+#ifndef Llong
+#define Llong long long
+#endif
+#ifndef ULLong
+#define ULLong unsigned Llong
+#endif
+#endif /* NO_LONG_LONG */
+
+#ifdef Pack_32
+#define ULbits 32
+#define kshift 5
+#define kmask 31
+#define ALL_ON 0xffffffff
+#else
+#define ULbits 16
+#define kshift 4
+#define kmask 15
+#define ALL_ON 0xffff
+#endif
+
+#ifndef MULTIPLE_THREADS
+#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
+#define FREE_DTOA_LOCK(n) /*nothing*/
+#else
+#include "thread_private.h"
+extern void *__dtoa_locks[];
+#define ACQUIRE_DTOA_LOCK(n) _MUTEX_LOCK(&__dtoa_locks[n])
+#define FREE_DTOA_LOCK(n) _MUTEX_UNLOCK(&__dtoa_locks[n])
+#endif
+
+#define Kmax 9
+
+ struct
+Bigint {
+ struct Bigint *next;
+ int k, maxwds, sign, wds;
+ ULong x[1];
+ };
+
+ typedef struct Bigint Bigint;
+
+#ifdef NO_STRING_H
+#ifdef DECLARE_SIZE_T
+typedef unsigned int size_t;
+#endif
+extern void memcpy_D2A ANSI((void*, const void*, size_t));
+#define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
+#else /* !NO_STRING_H */
+#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
+#endif /* NO_STRING_H */
+
+#define dtoa __dtoa
+#define gdtoa __gdtoa
+#define freedtoa __freedtoa
+#define strtodg __strtodg
+#define g_ddfmt __g_ddfmt
+#define g_dfmt __g_dfmt
+#define g_ffmt __g_ffmt
+#define g_Qfmt __g_Qfmt
+#define g_xfmt __g_xfmt
+#define g_xLfmt __g_xLfmt
+#define strtoId __strtoId
+#define strtoIdd __strtoIdd
+#define strtoIf __strtoIf
+#define strtoIQ __strtoIQ
+#define strtoIx __strtoIx
+#define strtoIxL __strtoIxL
+#define strtord __strtord
+#define strtordd __strtordd
+#define strtorf __strtorf
+#define strtorQ __strtorQ
+#define strtorx __strtorx
+#define strtorxL __strtorxL
+#define strtodI __strtodI
+#define strtopd __strtopd
+#define strtopdd __strtopdd
+#define strtopf __strtopf
+#define strtopQ __strtopQ
+#define strtopx __strtopx
+#define strtopxL __strtopxL
+
+#define Balloc __Balloc_D2A
+#define Bfree __Bfree_D2A
+#define ULtoQ __ULtoQ_D2A
+#define ULtof __ULtof_D2A
+#define ULtod __ULtod_D2A
+#define ULtodd __ULtodd_D2A
+#define ULtox __ULtox_D2A
+#define ULtoxL __ULtoxL_D2A
+#define any_on __any_on_D2A
+#define b2d __b2d_D2A
+#define bigtens __bigtens_D2A
+#define cmp __cmp_D2A
+#define copybits __copybits_D2A
+#define d2b __d2b_D2A
+#define decrement __decrement_D2A
+#define diff __diff_D2A
+#define dtoa_result __dtoa_result_D2A
+#define g__fmt __g__fmt_D2A
+#define gethex __gethex_D2A
+#define hexdig __hexdig_D2A
+#define hexnan __hexnan_D2A
+#define hi0bits(x) __hi0bits_D2A((ULong)(x))
+#define hi0bits_D2A __hi0bits_D2A
+#define i2b __i2b_D2A
+#define increment __increment_D2A
+#define lo0bits __lo0bits_D2A
+#define lshift __lshift_D2A
+#define match __match_D2A
+#define mult __mult_D2A
+#define multadd __multadd_D2A
+#define nrv_alloc __nrv_alloc_D2A
+#define pow5mult __pow5mult_D2A
+#define quorem __quorem_D2A
+#define ratio __ratio_D2A
+#define rshift __rshift_D2A
+#define rv_alloc __rv_alloc_D2A
+#define s2b __s2b_D2A
+#define set_ones __set_ones_D2A
+#define strcp __strcp_D2A
+#define strtoIg __strtoIg_D2A
+#define sulp __sulp_D2A
+#define sum __sum_D2A
+#define tens __tens_D2A
+#define tinytens __tinytens_D2A
+#define tinytens __tinytens_D2A
+#define trailz __trailz_D2A
+#define ulp __ulp_D2A
+
+ extern char *dtoa_result;
+ extern CONST double bigtens[], tens[], tinytens[];
+ extern unsigned char hexdig[];
+
+ extern Bigint *Balloc ANSI((int));
+ extern void Bfree ANSI((Bigint*));
+ extern void ULtof ANSI((ULong*, ULong*, Long, int));
+ extern void ULtod ANSI((ULong*, ULong*, Long, int));
+ extern void ULtodd ANSI((ULong*, ULong*, Long, int));
+ extern void ULtoQ ANSI((ULong*, ULong*, Long, int));
+ extern void ULtox ANSI((UShort*, ULong*, Long, int));
+ extern void ULtoxL ANSI((ULong*, ULong*, Long, int));
+ extern ULong any_on ANSI((Bigint*, int));
+ extern double b2d ANSI((Bigint*, int*));
+ extern int cmp ANSI((Bigint*, Bigint*));
+ extern void copybits ANSI((ULong*, int, Bigint*));
+ extern Bigint *d2b ANSI((double, int*, int*));
+ extern void decrement ANSI((Bigint*));
+ extern Bigint *diff ANSI((Bigint*, Bigint*));
+ extern char *dtoa ANSI((double d, int mode, int ndigits,
+ int *decpt, int *sign, char **rve));
+ extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
+ extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
+ extern void hexdig_init_D2A(Void);
+ extern int hexnan ANSI((CONST char**, FPI*, ULong*));
+ extern int hi0bits_D2A ANSI((ULong));
+ extern Bigint *i2b ANSI((int));
+ extern Bigint *increment ANSI((Bigint*));
+ extern int lo0bits ANSI((ULong*));
+ extern Bigint *lshift ANSI((Bigint*, int));
+ extern int match ANSI((CONST char**, char*));
+ extern Bigint *mult ANSI((Bigint*, Bigint*));
+ extern Bigint *multadd ANSI((Bigint*, int, int));
+ extern char *nrv_alloc ANSI((char*, char **, int));
+ extern Bigint *pow5mult ANSI((Bigint*, int));
+ extern int quorem ANSI((Bigint*, Bigint*));
+ extern double ratio ANSI((Bigint*, Bigint*));
+ extern void rshift ANSI((Bigint*, int));
+ extern char *rv_alloc ANSI((int));
+ extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
+ extern Bigint *set_ones ANSI((Bigint*, int));
+ extern char *strcp ANSI((char*, const char*));
+ extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
+ extern double strtod ANSI((const char *s00, char **se));
+ extern Bigint *sum ANSI((Bigint*, Bigint*));
+ extern int trailz ANSI((Bigint*));
+ extern double ulp ANSI((U*));
+
+#ifdef __cplusplus
+}
+#endif
+/*
+ * NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c. Prior to
+ * 20050115, they used to be hard-wired here (to 0x7ff80000 and 0,
+ * respectively), but now are determined by compiling and running
+ * qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1.
+ * Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=...
+ * and -DNAN_WORD1=... values if necessary. This should still work.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ */
+#ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#ifndef NAN_WORD0
+#define NAN_WORD0 d_QNAN0
+#endif
+#ifndef NAN_WORD1
+#define NAN_WORD1 d_QNAN1
+#endif
+#else
+#define _0 1
+#define _1 0
+#ifndef NAN_WORD0
+#define NAN_WORD0 d_QNAN1
+#endif
+#ifndef NAN_WORD1
+#define NAN_WORD1 d_QNAN0
+#endif
+#endif
+#else
+#undef INFNAN_CHECK
+#endif
+
+#undef SI
+#ifdef Sudden_Underflow
+#define SI 1
+#else
+#define SI 0
+#endif
+
+#endif /* GDTOAIMP_H_INCLUDED */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
new file mode 100644
index 0000000..7ace0fa
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
@@ -0,0 +1,360 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+ int
+#ifdef KR_headers
+gethex(sp, fpi, exp, bp, sign)
+ CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
+#else
+gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
+#endif
+{
+ Bigint *b;
+ CONST unsigned char *decpt, *s0, *s, *s1;
+ int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
+ ULong L, lostbits, *x;
+ Long e, e1;
+#ifdef USE_LOCALE
+ int i;
+#ifdef NO_LOCALE_CACHE
+ const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point;
+#else
+ const unsigned char *decimalpoint;
+ static unsigned char *decimalpoint_cache;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = (unsigned char*)localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
+ strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = s0;
+#endif
+#endif
+
+ if (!hexdig['0'])
+ hexdig_init_D2A();
+ *bp = 0;
+ havedig = 0;
+ s0 = *(CONST unsigned char **)sp + 2;
+ while(s0[havedig] == '0')
+ havedig++;
+ s0 += havedig;
+ s = s0;
+ decpt = 0;
+ zret = 0;
+ e = 0;
+ if (hexdig[*s])
+ havedig++;
+ else {
+ zret = 1;
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s != '.')
+ goto pcheck;
+ decpt = ++s;
+#endif
+ if (!hexdig[*s])
+ goto pcheck;
+ while(*s == '0')
+ s++;
+ if (hexdig[*s])
+ zret = 0;
+ havedig = 1;
+ s0 = s;
+ }
+ while(hexdig[*s])
+ s++;
+#ifdef USE_LOCALE
+ if (*s == *decimalpoint && !decpt) {
+ for(i = 1; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s == '.' && !decpt) {
+ decpt = ++s;
+#endif
+ while(hexdig[*s])
+ s++;
+ }/*}*/
+ if (decpt)
+ e = -(((Long)(s-decpt)) << 2);
+ pcheck:
+ s1 = s;
+ big = esign = 0;
+ switch(*s) {
+ case 'p':
+ case 'P':
+ switch(*++s) {
+ case '-':
+ esign = 1;
+ /* no break */
+ case '+':
+ s++;
+ }
+ if ((n = hexdig[*s]) == 0 || n > 0x19) {
+ s = s1;
+ break;
+ }
+ e1 = n - 0x10;
+ while((n = hexdig[*++s]) !=0 && n <= 0x19) {
+ if (e1 & 0xf8000000)
+ big = 1;
+ e1 = 10*e1 + n - 0x10;
+ }
+ if (esign)
+ e1 = -e1;
+ e += e1;
+ }
+ *sp = (char*)s;
+ if (!havedig)
+ *sp = (char*)s0 - 1;
+ if (zret)
+ return STRTOG_Zero;
+ if (big) {
+ if (esign) {
+ switch(fpi->rounding) {
+ case FPI_Round_up:
+ if (sign)
+ break;
+ goto ret_tiny;
+ case FPI_Round_down:
+ if (!sign)
+ break;
+ goto ret_tiny;
+ }
+ goto retz;
+ ret_tiny:
+ b = Balloc(0);
+ if (b == NULL)
+ return (STRTOG_NoMemory);
+ b->wds = 1;
+ b->x[0] = 1;
+ goto dret;
+ }
+ switch(fpi->rounding) {
+ case FPI_Round_near:
+ goto ovfl1;
+ case FPI_Round_up:
+ if (!sign)
+ goto ovfl1;
+ goto ret_big;
+ case FPI_Round_down:
+ if (sign)
+ goto ovfl1;
+ goto ret_big;
+ }
+ ret_big:
+ nbits = fpi->nbits;
+ n0 = n = nbits >> kshift;
+ if (nbits & kmask)
+ ++n;
+ for(j = n, k = 0; j >>= 1; ++k);
+ *bp = b = Balloc(k);
+ if (*bp == NULL)
+ return (STRTOG_NoMemory);
+ b->wds = n;
+ for(j = 0; j < n0; ++j)
+ b->x[j] = ALL_ON;
+ if (n > n0)
+ b->x[j] = ULbits >> (ULbits - (nbits & kmask));
+ *exp = fpi->emin;
+ return STRTOG_Normal | STRTOG_Inexlo;
+ }
+ n = s1 - s0 - 1;
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
+ k++;
+ b = Balloc(k);
+ if (b == NULL)
+ return (STRTOG_NoMemory);
+ x = b->x;
+ n = 0;
+ L = 0;
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i+1]; ++i);
+#endif
+ while(s1 > s0) {
+#ifdef USE_LOCALE
+ if (*--s1 == decimalpoint[i]) {
+ s1 -= i;
+ continue;
+ }
+#else
+ if (*--s1 == '.')
+ continue;
+#endif
+ if (n == ULbits) {
+ *x++ = L;
+ L = 0;
+ n = 0;
+ }
+ L |= (hexdig[*s1] & 0x0f) << n;
+ n += 4;
+ }
+ *x++ = L;
+ b->wds = n = x - b->x;
+ n = ULbits*n - hi0bits(L);
+ nbits = fpi->nbits;
+ lostbits = 0;
+ x = b->x;
+ if (n > nbits) {
+ n -= nbits;
+ if (any_on(b,n)) {
+ lostbits = 1;
+ k = n - 1;
+ if (x[k>>kshift] & 1 << (k & kmask)) {
+ lostbits = 2;
+ if (k > 0 && any_on(b,k))
+ lostbits = 3;
+ }
+ }
+ rshift(b, n);
+ e += n;
+ }
+ else if (n < nbits) {
+ n = nbits - n;
+ b = lshift(b, n);
+ if (b == NULL)
+ return (STRTOG_NoMemory);
+ e -= n;
+ x = b->x;
+ }
+ if (e > fpi->emax) {
+ ovfl:
+ Bfree(b);
+ ovfl1:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+ }
+ irv = STRTOG_Normal;
+ if (e < fpi->emin) {
+ irv = STRTOG_Denormal;
+ n = fpi->emin - e;
+ if (n >= nbits) {
+ switch (fpi->rounding) {
+ case FPI_Round_near:
+ if (n == nbits && (n < 2 || any_on(b,n-1)))
+ goto one_bit;
+ break;
+ case FPI_Round_up:
+ if (!sign)
+ goto one_bit;
+ break;
+ case FPI_Round_down:
+ if (sign) {
+ one_bit:
+ x[0] = b->wds = 1;
+ dret:
+ *bp = b;
+ *exp = fpi->emin;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ return STRTOG_Denormal | STRTOG_Inexhi
+ | STRTOG_Underflow;
+ }
+ }
+ Bfree(b);
+ retz:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
+ }
+ k = n - 1;
+ if (lostbits)
+ lostbits = 1;
+ else if (k > 0)
+ lostbits = any_on(b,k);
+ if (x[k>>kshift] & 1 << (k & kmask))
+ lostbits |= 2;
+ nbits -= n;
+ rshift(b,n);
+ e = fpi->emin;
+ }
+ if (lostbits) {
+ up = 0;
+ switch(fpi->rounding) {
+ case FPI_Round_zero:
+ break;
+ case FPI_Round_near:
+ if (lostbits & 2
+ && (lostbits | x[0]) & 1)
+ up = 1;
+ break;
+ case FPI_Round_up:
+ up = 1 - sign;
+ break;
+ case FPI_Round_down:
+ up = sign;
+ }
+ if (up) {
+ k = b->wds;
+ b = increment(b);
+ if (b == NULL)
+ return (STRTOG_NoMemory);
+ x = b->x;
+ if (irv == STRTOG_Denormal) {
+ if (nbits == fpi->nbits - 1
+ && x[nbits >> kshift] & 1 << (nbits & kmask))
+ irv = STRTOG_Normal;
+ }
+ else if (b->wds > k
+ || ((n = nbits & kmask) !=0
+ && hi0bits(x[k-1]) < 32-n)) {
+ rshift(b,1);
+ if (++e > fpi->emax)
+ goto ovfl;
+ }
+ irv |= STRTOG_Inexhi;
+ }
+ else
+ irv |= STRTOG_Inexlo;
+ }
+ *bp = b;
+ *exp = e;
+ return irv;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gmisc.c b/libc/upstream-openbsd/lib/libc/gdtoa/gmisc.c
new file mode 100644
index 0000000..8270ef9
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gmisc.c
@@ -0,0 +1,86 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+rshift(b, k) Bigint *b; int k;
+#else
+rshift(Bigint *b, int k)
+#endif
+{
+ ULong *x, *x1, *xe, y;
+ int n;
+
+ x = x1 = b->x;
+ n = k >> kshift;
+ if (n < b->wds) {
+ xe = x + b->wds;
+ x += n;
+ if (k &= kmask) {
+ n = ULbits - k;
+ y = *x++ >> k;
+ while(x < xe) {
+ *x1++ = (y | (*x << n)) & ALL_ON;
+ y = *x++ >> k;
+ }
+ if ((*x1 = y) !=0)
+ x1++;
+ }
+ else
+ while(x < xe)
+ *x1++ = *x++;
+ }
+ if ((b->wds = x1 - b->x) == 0)
+ b->x[0] = 0;
+ }
+
+ int
+#ifdef KR_headers
+trailz(b) Bigint *b;
+#else
+trailz(Bigint *b)
+#endif
+{
+ ULong L, *x, *xe;
+ int n = 0;
+
+ x = b->x;
+ xe = x + b->wds;
+ for(n = 0; x < xe && !*x; x++)
+ n += ULbits;
+ if (x < xe) {
+ L = *x;
+ n += lo0bits(&L);
+ }
+ return n;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c b/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c
new file mode 100644
index 0000000..fa6e18d
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hd_init.c
@@ -0,0 +1,55 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ unsigned char hexdig[256];
+
+ static void
+#ifdef KR_headers
+htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc;
+#else
+htinit(unsigned char *h, unsigned char *s, int inc)
+#endif
+{
+ int i, j;
+ for(i = 0; (j = s[i]) !=0; i++)
+ h[j] = i + inc;
+ }
+
+ void
+hexdig_init_D2A(Void)
+{
+#define USC (unsigned char *)
+ htinit(hexdig, USC "0123456789", 0x10);
+ htinit(hexdig, USC "abcdef", 0x10 + 10);
+ htinit(hexdig, USC "ABCDEF", 0x10 + 10);
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
new file mode 100644
index 0000000..c62f6d5
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
@@ -0,0 +1,332 @@
+/* $OpenBSD: hdtoa.c,v 1.2 2009/10/16 12:15:03 martynas Exp $ */
+/*-
+ * Copyright (c) 2004, 2005 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.
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+#include "gdtoaimp.h"
+
+/* Strings values used by dtoa() */
+#define INFSTR "Infinity"
+#define NANSTR "NaN"
+
+#define DBL_ADJ (DBL_MAX_EXP - 2 + ((DBL_MANT_DIG - 1) % 4))
+#define LDBL_ADJ (LDBL_MAX_EXP - 2 + ((LDBL_MANT_DIG - 1) % 4))
+
+/*
+ * Round up the given digit string. If the digit string is fff...f,
+ * this procedure sets it to 100...0 and returns 1 to indicate that
+ * the exponent needs to be bumped. Otherwise, 0 is returned.
+ */
+static int
+roundup(char *s0, int ndigits)
+{
+ char *s;
+
+ for (s = s0 + ndigits - 1; *s == 0xf; s--) {
+ if (s == s0) {
+ *s = 1;
+ return (1);
+ }
+ *s = 0;
+ }
+ ++*s;
+ return (0);
+}
+
+/*
+ * Round the given digit string to ndigits digits according to the
+ * current rounding mode. Note that this could produce a string whose
+ * value is not representable in the corresponding floating-point
+ * type. The exponent pointed to by decpt is adjusted if necessary.
+ */
+static void
+dorounding(char *s0, int ndigits, int sign, int *decpt)
+{
+ int adjust = 0; /* do we need to adjust the exponent? */
+
+ switch (FLT_ROUNDS) {
+ case 0: /* toward zero */
+ default: /* implementation-defined */
+ break;
+ case 1: /* to nearest, halfway rounds to even */
+ if ((s0[ndigits] > 8) ||
+ (s0[ndigits] == 8 && s0[ndigits + 1] & 1))
+ adjust = roundup(s0, ndigits);
+ break;
+ case 2: /* toward +inf */
+ if (sign == 0)
+ adjust = roundup(s0, ndigits);
+ break;
+ case 3: /* toward -inf */
+ if (sign != 0)
+ adjust = roundup(s0, ndigits);
+ break;
+ }
+
+ if (adjust)
+ *decpt += 4;
+}
+
+/*
+ * This procedure converts a double-precision number in IEEE format
+ * into a string of hexadecimal digits and an exponent of 2. Its
+ * behavior is bug-for-bug compatible with dtoa() in mode 2, with the
+ * following exceptions:
+ *
+ * - An ndigits < 0 causes it to use as many digits as necessary to
+ * represent the number exactly.
+ * - The additional xdigs argument should point to either the string
+ * "0123456789ABCDEF" or the string "0123456789abcdef", depending on
+ * which case is desired.
+ * - This routine does not repeat dtoa's mistake of setting decpt
+ * to 9999 in the case of an infinity or NaN. INT_MAX is used
+ * for this purpose instead.
+ *
+ * Note that the C99 standard does not specify what the leading digit
+ * should be for non-zero numbers. For instance, 0x1.3p3 is the same
+ * as 0x2.6p2 is the same as 0x4.cp3. This implementation chooses the
+ * first digit so that subsequent digits are aligned on nibble
+ * boundaries (before rounding).
+ *
+ * Inputs: d, xdigs, ndigits
+ * Outputs: decpt, sign, rve
+ */
+char *
+__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ static const int sigfigs = (DBL_MANT_DIG + 3) / 4;
+ struct ieee_double *p = (struct ieee_double *)&d;
+ char *s, *s0;
+ int bufsize;
+
+ *sign = p->dbl_sign;
+
+ switch (fpclassify(d)) {
+ case FP_NORMAL:
+ *decpt = p->dbl_exp - DBL_ADJ;
+ break;
+ case FP_ZERO:
+ *decpt = 1;
+ return (nrv_alloc("0", rve, 1));
+ case FP_SUBNORMAL:
+ d *= 0x1p514;
+ *decpt = p->dbl_exp - (514 + DBL_ADJ);
+ break;
+ case FP_INFINITE:
+ *decpt = INT_MAX;
+ return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+ case FP_NAN:
+ *decpt = INT_MAX;
+ return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+ default:
+ abort();
+ }
+
+ /* FP_NORMAL or FP_SUBNORMAL */
+
+ if (ndigits == 0) /* dtoa() compatibility */
+ ndigits = 1;
+
+ /*
+ * For simplicity, we generate all the digits even if the
+ * caller has requested fewer.
+ */
+ bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
+ s0 = rv_alloc(bufsize);
+ if (s0 == NULL)
+ return (NULL);
+
+ /*
+ * We work from right to left, first adding any requested zero
+ * padding, then the least significant portion of the
+ * mantissa, followed by the most significant. The buffer is
+ * filled with the byte values 0x0 through 0xf, which are
+ * converted to xdigs[0x0] through xdigs[0xf] after the
+ * rounding phase.
+ */
+ for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
+ *s = 0;
+ for (; s > s0 + sigfigs - (DBL_FRACLBITS / 4) - 1 && s > s0; s--) {
+ *s = p->dbl_fracl & 0xf;
+ p->dbl_fracl >>= 4;
+ }
+ for (; s > s0; s--) {
+ *s = p->dbl_frach & 0xf;
+ p->dbl_frach >>= 4;
+ }
+
+ /*
+ * At this point, we have snarfed all the bits in the
+ * mantissa, with the possible exception of the highest-order
+ * (partial) nibble, which is dealt with by the next
+ * statement. We also tack on the implicit normalization bit.
+ */
+ *s = p->dbl_frach | (1U << ((DBL_MANT_DIG - 1) % 4));
+
+ /* If ndigits < 0, we are expected to auto-size the precision. */
+ if (ndigits < 0) {
+ for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
+ ;
+ }
+
+ if (sigfigs > ndigits && s0[ndigits] != 0)
+ dorounding(s0, ndigits, p->dbl_sign, decpt);
+
+ s = s0 + ndigits;
+ if (rve != NULL)
+ *rve = s;
+ *s-- = '\0';
+ for (; s >= s0; s--)
+ *s = xdigs[(unsigned int)*s];
+
+ return (s0);
+}
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG)
+
+/*
+ * This is the long double version of __hdtoa().
+ */
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ static const int sigfigs = (LDBL_MANT_DIG + 3) / 4;
+ struct ieee_ext *p = (struct ieee_ext *)&e;
+ char *s, *s0;
+ int bufsize;
+
+ *sign = p->ext_sign;
+
+ switch (fpclassify(e)) {
+ case FP_NORMAL:
+ *decpt = p->ext_exp - LDBL_ADJ;
+ break;
+ case FP_ZERO:
+ *decpt = 1;
+ return (nrv_alloc("0", rve, 1));
+ case FP_SUBNORMAL:
+ e *= 0x1p514L;
+ *decpt = p->ext_exp - (514 + LDBL_ADJ);
+ break;
+ case FP_INFINITE:
+ *decpt = INT_MAX;
+ return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+ case FP_NAN:
+ *decpt = INT_MAX;
+ return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+ default:
+ abort();
+ }
+
+ /* FP_NORMAL or FP_SUBNORMAL */
+
+ if (ndigits == 0) /* dtoa() compatibility */
+ ndigits = 1;
+
+ /*
+ * For simplicity, we generate all the digits even if the
+ * caller has requested fewer.
+ */
+ bufsize = (sigfigs > ndigits) ? sigfigs : ndigits;
+ s0 = rv_alloc(bufsize);
+ if (s0 == NULL)
+ return (NULL);
+
+ /*
+ * We work from right to left, first adding any requested zero
+ * padding, then the least significant portion of the
+ * mantissa, followed by the most significant. The buffer is
+ * filled with the byte values 0x0 through 0xf, which are
+ * converted to xdigs[0x0] through xdigs[0xf] after the
+ * rounding phase.
+ */
+ for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
+ *s = 0;
+ for (; s > s0 + sigfigs - (EXT_FRACLBITS / 4) - 1 && s > s0; s--) {
+ *s = p->ext_fracl & 0xf;
+ p->ext_fracl >>= 4;
+ }
+#ifdef EXT_FRACHMBITS
+ for (; s > s0; s--) {
+ *s = p->ext_frachm & 0xf;
+ p->ext_frachm >>= 4;
+ }
+#endif
+#ifdef EXT_FRACLMBITS
+ for (; s > s0; s--) {
+ *s = p->ext_fraclm & 0xf;
+ p->ext_fraclm >>= 4;
+ }
+#endif
+ for (; s > s0; s--) {
+ *s = p->ext_frach & 0xf;
+ p->ext_frach >>= 4;
+ }
+
+ /*
+ * At this point, we have snarfed all the bits in the
+ * mantissa, with the possible exception of the highest-order
+ * (partial) nibble, which is dealt with by the next
+ * statement. We also tack on the implicit normalization bit.
+ */
+ *s = p->ext_frach | (1U << ((LDBL_MANT_DIG - 1) % 4));
+
+ /* If ndigits < 0, we are expected to auto-size the precision. */
+ if (ndigits < 0) {
+ for (ndigits = sigfigs; s0[ndigits - 1] == 0; ndigits--)
+ ;
+ }
+
+ if (sigfigs > ndigits && s0[ndigits] != 0)
+ dorounding(s0, ndigits, p->ext_sign, decpt);
+
+ s = s0 + ndigits;
+ if (rve != NULL)
+ *rve = s;
+ *s-- = '\0';
+ for (; s >= s0; s--)
+ *s = xdigs[(unsigned int)*s];
+
+ return (s0);
+}
+
+#else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
+
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ return (__hdtoa((double)e, xdigs, ndigits, decpt, sign, rve));
+}
+
+#endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c b/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c
new file mode 100644
index 0000000..a443721
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hexnan.c
@@ -0,0 +1,150 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ static void
+#ifdef KR_headers
+L_shift(x, x1, i) ULong *x; ULong *x1; int i;
+#else
+L_shift(ULong *x, ULong *x1, int i)
+#endif
+{
+ int j;
+
+ i = 8 - i;
+ i <<= 2;
+ j = ULbits - i;
+ do {
+ *x |= x[1] << j;
+ x[1] >>= i;
+ } while(++x < x1);
+ }
+
+ int
+#ifdef KR_headers
+hexnan(sp, fpi, x0)
+ CONST char **sp; FPI *fpi; ULong *x0;
+#else
+hexnan( CONST char **sp, FPI *fpi, ULong *x0)
+#endif
+{
+ ULong c, h, *x, *x1, *xe;
+ CONST char *s;
+ int havedig, hd0, i, nbits;
+
+ if (!hexdig['0'])
+ hexdig_init_D2A();
+ nbits = fpi->nbits;
+ x = x0 + (nbits >> kshift);
+ if (nbits & kmask)
+ x++;
+ *--x = 0;
+ x1 = xe = x;
+ havedig = hd0 = i = 0;
+ s = *sp;
+ /* allow optional initial 0x or 0X */
+ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
+ && *(CONST unsigned char*)(s+3) > ' ')
+ s += 2;
+ while((c = *(CONST unsigned char*)++s)) {
+ if (!(h = hexdig[c])) {
+ if (c <= ' ') {
+ if (hd0 < havedig) {
+ if (x < x1 && i < 8)
+ L_shift(x, x1, i);
+ if (x <= x0) {
+ i = 8;
+ continue;
+ }
+ hd0 = havedig;
+ *--x = 0;
+ x1 = x;
+ i = 0;
+ }
+ while(*(CONST unsigned char*)(s+1) <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
+ && *(CONST unsigned char*)(s+3) > ' ')
+ s += 2;
+ continue;
+ }
+ if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ }
+#ifndef GDTOA_NON_PEDANTIC_NANCHECK
+ do {
+ if (/*(*/ c == ')') {
+ *sp = s + 1;
+ break;
+ }
+ } while((c = *++s));
+#endif
+ return STRTOG_NaN;
+ }
+ havedig++;
+ if (++i > 8) {
+ if (x <= x0)
+ continue;
+ i = 1;
+ *--x = 0;
+ }
+ *x = (*x << 4) | (h & 0xf);
+ }
+ if (!havedig)
+ return STRTOG_NaN;
+ if (x < x1 && i < 8)
+ L_shift(x, x1, i);
+ if (x > x0) {
+ x1 = x0;
+ do *x1++ = *x++;
+ while(x <= xe);
+ do *x1++ = 0;
+ while(x1 <= xe);
+ }
+ else {
+ /* truncate high-order word if necessary */
+ if ( (i = nbits & (ULbits-1)) !=0)
+ *xe &= ((ULong)0xffffffff) >> (ULbits - i);
+ }
+ for(x1 = xe;; --x1) {
+ if (*x1 != 0)
+ break;
+ if (x1 == x0) {
+ *x1 = 1;
+ break;
+ }
+ }
+ return STRTOG_NaNbits;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
new file mode 100644
index 0000000..793d71c
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/ldtoa.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: ldtoa.c,v 1.1 2008/09/07 20:36:08 martynas Exp $ */
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+#ifndef __vax__
+#include <machine/ieee.h>
+#endif /* !__vax__ */
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include "gdtoaimp.h"
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG)
+
+/*
+ * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
+ * except that the floating point argument is passed by reference.
+ * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
+ * However, a long double could have a valid exponent of 9999, so we
+ * use INT_MAX in ldtoa() instead.
+ */
+char *
+__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ FPI fpi = {
+ LDBL_MANT_DIG, /* nbits */
+ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */
+ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */
+ FLT_ROUNDS, /* rounding */
+#ifdef Sudden_Underflow /* unused, but correct anyway */
+ 1
+#else
+ 0
+#endif
+ };
+ int be, kind;
+ char *ret;
+ struct ieee_ext *p = (struct ieee_ext *)ld;
+ uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
+ void *vbits = bits;
+
+ /*
+ * gdtoa doesn't know anything about the sign of the number, so
+ * if the number is negative, we need to swap rounding modes of
+ * 2 (upwards) and 3 (downwards).
+ */
+ *sign = p->ext_sign;
+ fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign;
+
+ be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
+ EXT_TO_ARRAY32(p, bits);
+
+ switch (fpclassify(*ld)) {
+ case FP_NORMAL:
+ kind = STRTOG_Normal;
+#ifdef EXT_IMPLICIT_NBIT
+ bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
+#endif /* EXT_IMPLICIT_NBIT */
+ break;
+ case FP_ZERO:
+ kind = STRTOG_Zero;
+ break;
+ case FP_SUBNORMAL:
+ kind = STRTOG_Denormal;
+ be++;
+ break;
+ case FP_INFINITE:
+ kind = STRTOG_Infinite;
+ break;
+ case FP_NAN:
+ kind = STRTOG_NaN;
+ break;
+ default:
+ abort();
+ }
+
+ ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
+ if (*decpt == -32768)
+ *decpt = INT_MAX;
+ return ret;
+}
+
+#else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
+
+char *
+__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ char *ret;
+
+ ret = dtoa((double)*ld, mode, ndigits, decpt, sign, rve);
+ if (*decpt == 9999)
+ *decpt = INT_MAX;
+ return ret;
+}
+
+#endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
new file mode 100644
index 0000000..6ad706b
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
@@ -0,0 +1,907 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ static Bigint *freelist[Kmax+1];
+#ifndef Omit_Private_Memory
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
+#endif
+
+ Bigint *
+Balloc
+#ifdef KR_headers
+ (k) int k;
+#else
+ (int k)
+#endif
+{
+ int x;
+ Bigint *rv;
+#ifndef Omit_Private_Memory
+ unsigned int len;
+#endif
+
+ ACQUIRE_DTOA_LOCK(0);
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
+ if (k <= Kmax && (rv = freelist[k]) !=0) {
+ freelist[k] = rv->next;
+ }
+ else {
+ x = 1 << k;
+#ifdef Omit_Private_Memory
+ rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+ if (rv == NULL)
+ return (NULL);
+#else
+ len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+ /sizeof(double);
+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
+ rv = (Bigint*)pmem_next;
+ pmem_next += len;
+ }
+ else {
+ rv = (Bigint*)MALLOC(len*sizeof(double));
+ if (rv == NULL)
+ return (NULL);
+ }
+#endif
+ rv->k = k;
+ rv->maxwds = x;
+ }
+ FREE_DTOA_LOCK(0);
+ rv->sign = rv->wds = 0;
+ return rv;
+ }
+
+ void
+Bfree
+#ifdef KR_headers
+ (v) Bigint *v;
+#else
+ (Bigint *v)
+#endif
+{
+ if (v) {
+ if (v->k > Kmax)
+#ifdef FREE
+ FREE((void*)v);
+#else
+ free((void*)v);
+#endif
+ else {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
+ }
+ }
+
+ int
+lo0bits
+#ifdef KR_headers
+ (y) ULong *y;
+#else
+ (ULong *y)
+#endif
+{
+ int k;
+ ULong x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x)
+ return 32;
+ }
+ *y = x;
+ return k;
+ }
+
+ Bigint *
+multadd
+#ifdef KR_headers
+ (b, m, a) Bigint *b; int m, a;
+#else
+ (Bigint *b, int m, int a) /* multiply by m and add a */
+#endif
+{
+ int i, wds;
+#ifdef ULLong
+ ULong *x;
+ ULLong carry, y;
+#else
+ ULong carry, *x, y;
+#ifdef Pack_32
+ ULong xi, z;
+#endif
+#endif
+ Bigint *b1;
+
+ wds = b->wds;
+ x = b->x;
+ i = 0;
+ carry = a;
+ do {
+#ifdef ULLong
+ y = *x * (ULLong)m + carry;
+ carry = y >> 32;
+ *x++ = y & 0xffffffffUL;
+#else
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + carry;
+ z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(++i < wds);
+ if (carry) {
+ if (wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ if (b1 == NULL)
+ return (NULL);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = carry;
+ b->wds = wds;
+ }
+ return b;
+ }
+
+ int
+hi0bits_D2A
+#ifdef KR_headers
+ (x) ULong x;
+#else
+ (ULong x)
+#endif
+{
+ int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+ }
+
+ Bigint *
+i2b
+#ifdef KR_headers
+ (i) int i;
+#else
+ (int i)
+#endif
+{
+ Bigint *b;
+
+ b = Balloc(1);
+ if (b == NULL)
+ return (NULL);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+ }
+
+ Bigint *
+mult
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ ULong y;
+#ifdef ULLong
+ ULLong carry, z;
+#else
+ ULong carry, z;
+#ifdef Pack_32
+ ULong z2;
+#endif
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ if (c == NULL)
+ return (NULL);
+ for(x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef ULLong
+ for(; xb < xbe; xc0++) {
+ if ( (y = *xb++) !=0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (ULLong)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = z & 0xffffffffUL;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for(; xb < xbe; xb++, xc0++) {
+ if ( (y = *xb & 0xffff) !=0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ if ( (y = *xb >> 16) !=0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while(x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if ( (y = *xb++) !=0) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds = wc;
+ return c;
+ }
+
+ static Bigint *p5s;
+
+ Bigint *
+pow5mult
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ Bigint *b1, *p5, *p51;
+ int i;
+ static int p05[3] = { 5, 25, 125 };
+
+ if ( (i = k & 3) !=0) {
+ b = multadd(b, p05[i-1], 0);
+ if (b == NULL)
+ return (NULL);
+ }
+
+ if (!(k >>= 2))
+ return b;
+ if ((p5 = p5s) == 0) {
+ /* first time */
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p5 = p5s)) {
+ p5 = p5s = i2b(625);
+ if (p5 == NULL)
+ return (NULL);
+ p5->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p5 = p5s = i2b(625);
+ if (p5 == NULL)
+ return (NULL);
+ p5->next = 0;
+#endif
+ }
+ for(;;) {
+ if (k & 1) {
+ b1 = mult(b, p5);
+ if (b1 == NULL)
+ return (NULL);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if ((p51 = p5->next) == 0) {
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p51 = p5->next)) {
+ p51 = p5->next = mult(p5,p5);
+ if (p51 == NULL)
+ return (NULL);
+ p51->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p51 = p5->next = mult(p5,p5);
+ if (p51 == NULL)
+ return (NULL);
+ p51->next = 0;
+#endif
+ }
+ p5 = p51;
+ }
+ return b;
+ }
+
+ Bigint *
+lshift
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+ n = k >> kshift;
+ k1 = b->k;
+ n1 = n + b->wds + 1;
+ for(i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc(k1);
+ if (b1 == NULL)
+ return (NULL);
+ x1 = b1->x;
+ for(i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->x;
+ xe = x + b->wds;
+ if (k &= kmask) {
+#ifdef Pack_32
+ k1 = 32 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if ((*x1 = z) !=0)
+ ++n1;
+#else
+ k1 = 16 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+#endif
+ }
+ else do
+ *x1++ = *x++;
+ while(x < xe);
+ b1->wds = n1 - 1;
+ Bfree(b);
+ return b1;
+ }
+
+ int
+cmp
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+#ifdef DEBUG
+ if (i > 1 && !a->x[i-1])
+ Bug("cmp called with a->x[a->wds-1] == 0");
+ if (j > 1 && !b->x[j-1])
+ Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for(;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+ }
+
+ Bigint *
+diff
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int i, wa, wb;
+ ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef ULLong
+ ULLong borrow, y;
+#else
+ ULong borrow, y;
+#ifdef Pack_32
+ ULong z;
+#endif
+#endif
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ if (c == NULL)
+ return (NULL);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc(a->k);
+ if (c == NULL)
+ return (NULL);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+ borrow = 0;
+#ifdef ULLong
+ do {
+ y = (ULLong)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & 1UL;
+ *xc++ = y & 0xffffffffUL;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = y >> 32 & 1UL;
+ *xc++ = y & 0xffffffffUL;
+ }
+#else
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while(!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+ }
+
+ double
+b2d
+#ifdef KR_headers
+ (a, e) Bigint *a; int *e;
+#else
+ (Bigint *a, int *e)
+#endif
+{
+ ULong *xa, *xa0, w, y, z;
+ int k;
+ U d;
+#ifdef VAX
+ ULong d0, d1;
+#else
+#define d0 word0(&d)
+#define d1 word1(&d)
+#endif
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+#ifdef DEBUG
+ if (!y) Bug("zero y in b2d");
+#endif
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ d0 = Exp_1 | y >> (Ebits - k);
+ w = xa > xa0 ? *--xa : 0;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ d0 = Exp_1 | y << k | z >> (32 - k);
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> (32 - k);
+ }
+ else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ ret_d:
+#ifdef VAX
+ word0(&d) = d0 >> 16 | d0 << 16;
+ word1(&d) = d1 >> 16 | d1 << 16;
+#endif
+ return dval(&d);
+ }
+#undef d0
+#undef d1
+
+ Bigint *
+d2b
+#ifdef KR_headers
+ (dd, e, bits) double dd; int *e, *bits;
+#else
+ (double dd, int *e, int *bits)
+#endif
+{
+ Bigint *b;
+ U d;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+ int de, k;
+ ULong *x, y, z;
+#ifdef VAX
+ ULong d0, d1;
+#else
+#define d0 word0(&d)
+#define d1 word1(&d)
+#endif
+ d.d = dd;
+#ifdef VAX
+ d0 = word0(&d) >> 16 | word0(&d) << 16;
+ d1 = word1(&d) >> 16 | word1(&d) << 16;
+#endif
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ if (b == NULL)
+ return (NULL);
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if ( (de = (int)(d0 >> Exp_shift)) !=0)
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ( (y = d1) !=0) {
+ if ( (k = lo0bits(&y)) !=0) {
+ x[0] = y | z << (32 - k);
+ z >>= k;
+ }
+ else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) !=0 ? 2 : 1;
+ }
+ else {
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if ( (y = d1) !=0) {
+ if ( (k = lo0bits(&y)) !=0)
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k+16;
+ i = 3;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ }
+ else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while(!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P-1) << 2) + k;
+ *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
+#else
+ *e = de - Bias - (P-1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else {
+ *e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32*i - hi0bits(x[i-1]);
+#else
+ *bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+ }
+#undef d0
+#undef d1
+
+ CONST double
+#ifdef IEEE_Arith
+bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
+ };
+#else
+#ifdef IBM
+bigtens[] = { 1e16, 1e32, 1e64 };
+CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#else
+bigtens[] = { 1e16, 1e32 };
+CONST double tinytens[] = { 1e-16, 1e-32 };
+#endif
+#endif
+
+ CONST double
+tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+#ifdef VAX
+ , 1e23, 1e24
+#endif
+ };
+
+ char *
+#ifdef KR_headers
+strcp_D2A(a, b) char *a; char *b;
+#else
+strcp_D2A(char *a, CONST char *b)
+#endif
+{
+ while((*a = *b++))
+ a++;
+ return a;
+ }
+
+#ifdef NO_STRING_H
+
+ Char *
+#ifdef KR_headers
+memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
+#else
+memcpy_D2A(void *a1, void *b1, size_t len)
+#endif
+{
+ char *a = (char*)a1, *ae = a + len;
+ char *b = (char*)b1, *a0 = a;
+ while(a < ae)
+ *a++ = *b++;
+ return a0;
+ }
+
+#endif /* NO_STRING_H */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/smisc.c b/libc/upstream-openbsd/lib/libc/gdtoa/smisc.c
new file mode 100644
index 0000000..d063a38
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/smisc.c
@@ -0,0 +1,201 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ Bigint *
+s2b
+#ifdef KR_headers
+ (s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9;
+#else
+ (CONST char *s, int nd0, int nd, ULong y9, int dplen)
+#endif
+{
+ Bigint *b;
+ int i, k;
+ Long x, y;
+
+ x = (nd + 8) / 9;
+ for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+ b = Balloc(k);
+ if (b == NULL)
+ return (NULL);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ b = Balloc(k+1);
+ if (b == NULL)
+ return (NULL);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do {
+ b = multadd(b, 10, *s++ - '0');
+ if (b == NULL)
+ return (NULL);
+ } while(++i < nd0);
+ s += dplen;
+ }
+ else
+ s += dplen + 9;
+ for(; i < nd; i++) {
+ b = multadd(b, 10, *s++ - '0');
+ if (b == NULL)
+ return (NULL);
+ }
+ return b;
+ }
+
+ double
+ratio
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ U da, db;
+ int k, ka, kb;
+
+ dval(&da) = b2d(a, &ka);
+ dval(&db) = b2d(b, &kb);
+ k = ka - kb + ULbits*(a->wds - b->wds);
+#ifdef IBM
+ if (k > 0) {
+ word0(&da) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(&da) *= 1 << k;
+ }
+ else {
+ k = -k;
+ word0(&db) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(&db) *= 1 << k;
+ }
+#else
+ if (k > 0)
+ word0(&da) += k*Exp_msk1;
+ else {
+ k = -k;
+ word0(&db) += k*Exp_msk1;
+ }
+#endif
+ return dval(&da) / dval(&db);
+ }
+
+#ifdef INFNAN_CHECK
+
+ int
+match
+#ifdef KR_headers
+ (sp, t) char **sp, *t;
+#else
+ (CONST char **sp, char *t)
+#endif
+{
+ int c, d;
+ CONST char *s = *sp;
+
+ while( (d = *t++) !=0) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+ }
+#endif /* INFNAN_CHECK */
+
+ void
+#ifdef KR_headers
+copybits(c, n, b) ULong *c; int n; Bigint *b;
+#else
+copybits(ULong *c, int n, Bigint *b)
+#endif
+{
+ ULong *ce, *x, *xe;
+#ifdef Pack_16
+ int nw, nw1;
+#endif
+
+ ce = c + ((n-1) >> kshift) + 1;
+ x = b->x;
+#ifdef Pack_32
+ xe = x + b->wds;
+ while(x < xe)
+ *c++ = *x++;
+#else
+ nw = b->wds;
+ nw1 = nw & 1;
+ for(xe = x + (nw - nw1); x < xe; x += 2)
+ Storeinc(c, x[1], x[0]);
+ if (nw1)
+ *c++ = *x;
+#endif
+ while(c < ce)
+ *c++ = 0;
+ }
+
+ ULong
+#ifdef KR_headers
+any_on(b, k) Bigint *b; int k;
+#else
+any_on(Bigint *b, int k)
+#endif
+{
+ int n, nwds;
+ ULong *x, *x0, x1, x2;
+
+ x = b->x;
+ nwds = b->wds;
+ n = k >> kshift;
+ if (n > nwds)
+ n = nwds;
+ else if (n < nwds && (k &= kmask)) {
+ x1 = x2 = x[n];
+ x1 >>= k;
+ x1 <<= k;
+ if (x1 != x2)
+ return 1;
+ }
+ x0 = x;
+ x += n;
+ while(x > x0)
+ if (*--x)
+ return 1;
+ return 0;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
new file mode 100644
index 0000000..ded47d8
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
@@ -0,0 +1,1105 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+#ifndef NO_FENV_H
+#include <fenv.h>
+#endif
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+#ifdef IEEE_Arith
+#ifndef NO_IEEE_Scale
+#define Avoid_Underflow
+#undef tinytens
+/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+ 9007199254740992.*9007199254740992.e-256
+ };
+#endif
+#endif
+
+#ifdef Honor_FLT_ROUNDS
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+#ifdef Avoid_Underflow /*{*/
+ static double
+sulp
+#ifdef KR_headers
+ (x, scale) U *x; int scale;
+#else
+ (U *x, int scale)
+#endif
+{
+ U u;
+ double rv;
+ int i;
+
+ rv = ulp(x);
+ if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0)
+ return rv; /* Is there an example where i <= 0 ? */
+ word0(&u) = Exp_1 + (i << Exp_shift);
+ word1(&u) = 0;
+ return rv * u.d;
+ }
+#endif /*}*/
+
+ double
+strtod
+#ifdef KR_headers
+ (s00, se) CONST char *s00; char **se;
+#else
+ (CONST char *s00, char **se)
+#endif
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ CONST char *s, *s0, *s1;
+ double aadj;
+ Long L;
+ U adj, aadj1, rv, rv0;
+ ULong y, z;
+ Bigint *bb = NULL, *bb1, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;
+#ifdef Avoid_Underflow
+ ULong Lsb, Lsb1;
+#endif
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+#ifdef USE_LOCALE /*{{*/
+#ifdef NO_LOCALE_CACHE
+ char *decimalpoint = localeconv()->decimal_point;
+ int dplen = strlen(decimalpoint);
+#else
+ char *decimalpoint;
+ static char *decimalpoint_cache;
+ static int dplen;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
+ strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
+ s0 = decimalpoint_cache;
+ }
+ dplen = strlen(s0);
+ }
+ decimalpoint = (char*)s0;
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
+
+#ifdef Honor_FLT_ROUNDS /*{*/
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+#endif /*}*/
+
+ sign = nz0 = nz = decpt = 0;
+ dval(&rv) = 0.;
+ for(s = s00;;s++) switch(*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+ break2:
+ if (*s == '0') {
+#ifndef NO_HEX_FP /*{*/
+ {
+ static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+ Long exp;
+ ULong bits[2];
+ switch(s[1]) {
+ case 'x':
+ case 'X':
+ {
+#ifdef Honor_FLT_ROUNDS
+ FPI fpi1 = fpi;
+ fpi1.rounding = Rounding;
+#else
+#define fpi1 fpi
+#endif
+ switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
+ case STRTOG_NoMemory:
+ goto ovfl;
+ case STRTOG_NoNumber:
+ s = s00;
+ sign = 0;
+ case STRTOG_Zero:
+ break;
+ default:
+ if (bb) {
+ copybits(bits, fpi.nbits, bb);
+ Bfree(bb);
+ }
+ ULtod(((U*)&rv)->L, bits, exp, i);
+ }}
+ goto ret;
+ }
+ }
+#endif /*}*/
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+#ifdef USE_LOCALE
+ if (c == *decimalpoint) {
+ for(i = 1; decimalpoint[i]; ++i)
+ if (s[i] != decimalpoint[i])
+ goto dig_done;
+ s += i;
+ c = *s;
+#else
+ if (c == '.') {
+ c = *++s;
+#endif
+ decpt = 1;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }/*}*/
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ ULong bits[2];
+ static FPI fpinan = /* only 52 explicit bits */
+ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+ if (!decpt)
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ word0(&rv) = 0x7ff00000;
+ word1(&rv) = 0;
+ goto ret;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+#ifndef No_Hex_NaN
+ if (*s == '(' /*)*/
+ && hexnan(&s, &fpinan, bits)
+ == STRTOG_NaNbits) {
+ word0(&rv) = 0x7ff00000 | bits[1];
+ word1(&rv) = bits[0];
+ }
+ else {
+#endif
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
+#ifndef No_Hex_NaN
+ }
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(&rv) = y;
+ if (k > 9) {
+#ifdef SET_INEXACT
+ if (k > DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
+ }
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+#ifndef Honor_FLT_ROUNDS
+ && Flt_Rounds == 1
+#endif
+#endif
+ ) {
+ if (!e)
+ goto ret;
+#ifndef ROUND_BIASED_without_Round_Up
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv.d = -rv.d;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv.d = -rv.d;
+ sign = 0;
+ }
+#endif
+ e -= i;
+ dval(&rv) *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ word0(&rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if ((word0(&rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto ovfl;
+ word0(&rv) += P*Exp_msk1;
+#else
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv.d = -rv.d;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+ goto ret;
+ }
+#endif
+#endif /* ROUND_BIASED_without_Round_Up */
+ }
+ e1 += nd - k;
+
+#ifdef IEEE_Arith
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if (Rounding >= 2) {
+ if (sign)
+ Rounding = Rounding == 2 ? 0 : 2;
+ else
+ if (Rounding != 2)
+ Rounding = 0;
+ }
+#endif
+#endif /*IEEE_Arith*/
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ( (i = e1 & 15) !=0)
+ dval(&rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+ /* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+#ifdef Honor_FLT_ROUNDS
+ switch(Rounding) {
+ case 0: /* toward 0 */
+ case 3: /* toward -infinity */
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
+ break;
+ default:
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
+ }
+#else /*Honor_FLT_ROUNDS*/
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
+#endif /*Honor_FLT_ROUNDS*/
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ dval(&rv0) = 1e300;
+ dval(&rv0) *= dval(&rv0);
+#endif
+#else /*IEEE_Arith*/
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
+#endif /*IEEE_Arith*/
+ range_err:
+ if (bd0) {
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ }
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ goto ret;
+ }
+ e1 >>= 4;
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(&rv) *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0(&rv) -= P*Exp_msk1;
+ dval(&rv) *= bigtens[j];
+ if ((z = word0(&rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+ goto ovfl;
+ if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
+ }
+ else
+ word0(&rv) += P*Exp_msk1;
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if ( (i = e1 & 15) !=0)
+ dval(&rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ scale = 2*P;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(&rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
+ >> Exp_shift)) > 0) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(&rv) = 0;
+ if (j >= 53)
+ word0(&rv) = (P+2)*Exp_msk1;
+ else
+ word0(&rv) &= 0xffffffff << (j-32);
+ }
+ else
+ word1(&rv) &= 0xffffffff << j;
+ }
+#else
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(&rv) *= tinytens[j];
+ /* The last multiplication could underflow. */
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2.*dval(&rv0);
+ dval(&rv) *= tinytens[j];
+#endif
+ if (!dval(&rv)) {
+ undfl:
+ dval(&rv) = 0.;
+ goto range_err;
+ }
+#ifndef Avoid_Underflow
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y, dplen);
+ if (bd0 == NULL)
+ goto ovfl;
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ if (bd == NULL)
+ goto ovfl;
+ Bcopy(bd, bd0);
+ bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ if (bb == NULL)
+ goto ovfl;
+ bs = i2b(1);
+ if (bs == NULL)
+ goto ovfl;
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Honor_FLT_ROUNDS
+ if (Rounding != 1)
+ bs2++;
+#endif
+#ifdef Avoid_Underflow
+ Lsb = LSB;
+ Lsb1 = 0;
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ j = P + 1 - bbbits;
+ if (i < Emin) { /* denormal */
+ i = Emin - i;
+ j -= i;
+ if (i < 32)
+ Lsb <<= i;
+ else
+ Lsb1 = Lsb << (i-32);
+ }
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(&rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ if (bs == NULL)
+ goto ovfl;
+ bb1 = mult(bs, bb);
+ if (bb1 == NULL)
+ goto ovfl;
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0) {
+ bb = lshift(bb, bb2);
+ if (bb == NULL)
+ goto ovfl;
+ }
+ if (bd5 > 0) {
+ bd = pow5mult(bd, bd5);
+ if (bd == NULL)
+ goto ovfl;
+ }
+ if (bd2 > 0) {
+ bd = lshift(bd, bd2);
+ if (bd == NULL)
+ goto ovfl;
+ }
+ if (bs2 > 0) {
+ bs = lshift(bs, bs2);
+ if (bs == NULL)
+ goto ovfl;
+ }
+ delta = diff(bb, bd);
+ if (delta == NULL)
+ goto ovfl;
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+#ifdef Honor_FLT_ROUNDS
+ if (Rounding != 1) {
+ if (i < 0) {
+ /* Error is less than an ulp */
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (Rounding) {
+ if (dsign) {
+ dval(&adj) = 1.;
+ goto apply_adj;
+ }
+ }
+ else if (!dsign) {
+ dval(&adj) = -1.;
+ if (!word1(&rv)
+ && !(word0(&rv) & Frac_mask)) {
+ y = word0(&rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (!scale || y > 2*P*Exp_msk1)
+#else
+ if (y)
+#endif
+ {
+ delta = lshift(delta,Log2P);
+ if (delta == NULL)
+ goto ovfl;
+ if (cmp(delta, bs) <= 0)
+ dval(&adj) = -0.5;
+ }
+ }
+ apply_adj:
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(&rv) & Exp_mask)
+ <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(&rv) & Exp_mask) <=
+ P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ dval(&rv) += adj*ulp(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ }
+ else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ dval(&rv) += adj.d*ulp(&rv);
+ }
+ break;
+ }
+ dval(&adj) = ratio(delta, bs);
+ if (adj.d < 1.)
+ dval(&adj) = 1.;
+ if (adj.d <= 0x7ffffffe) {
+ /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
+ y = adj.d;
+ if (y != adj.d) {
+ if (!((Rounding>>1) ^ dsign))
+ y++;
+ dval(&adj) = y;
+ }
+ }
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) *= ulp(&rv);
+ if (dsign)
+ dval(&rv) += adj;
+ else
+ dval(&rv) -= adj;
+ word0(&rv) -= P*Exp_msk1;
+ goto cont;
+ }
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ dval(&adj) *= ulp(&rv);
+ if (dsign) {
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
+ goto ovfl;
+ dval(&rv) += adj.d;
+ }
+ else
+ dval(&rv) -= adj.d;
+ goto cont;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
+#ifdef IEEE_Arith
+#ifdef Avoid_Underflow
+ || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+#else
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
+#endif
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (delta == NULL)
+ goto ovfl;
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
+#ifdef Avoid_Underflow
+ (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
+#endif
+ 0xffffffff)) {
+ /*boundary case -- increment exponent*/
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
+ goto ovfl;
+ word0(&rv) = (word0(&rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ ;
+ word1(&rv) = 0;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ }
+ else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(&rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+#endif /*IBM*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(&rv) & Exp_mask;
+ if (L <= (2*P+1)*Exp_msk1) {
+ if (L > (P+2)*Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+#ifdef Avoid_Underflow
+ if (Lsb1) {
+ if (!(word0(&rv) & Lsb1))
+ break;
+ }
+ else if (!(word1(&rv) & Lsb))
+ break;
+#else
+ if (!(word1(&rv) & LSB))
+ break;
+#endif
+#endif
+ if (dsign)
+#ifdef Avoid_Underflow
+ dval(&rv) += sulp(&rv, scale);
+#else
+ dval(&rv) += ulp(&rv);
+#endif
+#ifndef ROUND_BIASED
+ else {
+#ifdef Avoid_Underflow
+ dval(&rv) -= sulp(&rv, scale);
+#else
+ dval(&rv) -= ulp(&rv);
+#endif
+#ifndef Sudden_Underflow
+ if (!dval(&rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = dval(&aadj1) = 1.;
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(&rv) == Tiny1 && !word0(&rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ dval(&aadj1) = -1.;
+ }
+ else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2./FLT_RADIX)
+ aadj = 1./FLT_RADIX;
+ else
+ aadj *= 0.5;
+ dval(&aadj1) = -aadj;
+ }
+ }
+ else {
+ aadj *= 0.5;
+ dval(&aadj1) = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch(Rounding) {
+ case 2: /* towards +infinity */
+ dval(&aadj1) -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ dval(&aadj1) += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ dval(&aadj1) += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ y = word0(&rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+ if ((word0(&rv) & Exp_mask) >=
+ Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+ if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
+ goto ovfl;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
+ goto cont;
+ }
+ else
+ word0(&rv) += P*Exp_msk1;
+ }
+ else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2*P*Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = aadj) <= 0)
+ z = 1;
+ aadj = z;
+ dval(&aadj1) = dsign ? aadj : -aadj;
+ }
+ word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
+ }
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+#else
+#ifdef Sudden_Underflow
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+#ifdef IBM
+ if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
+#else
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+ {
+ if (word0(&rv0) == Tiny0
+ && word1(&rv0) == Tiny1)
+ goto undfl;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(&rv) -= P*Exp_msk1;
+ }
+ else {
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+ }
+#else /*Sudden_Underflow*/
+ /* Compute dval(&adj) so that the IEEE rounding rules will
+ * correctly round rv + dval(&adj) in some half-way cases.
+ * If rv * ulp(&rv) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
+ dval(&aadj1) = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ dval(&aadj1) = -dval(&aadj1);
+ }
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(&rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (Long)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999/FLT_RADIX)
+ break;
+ }
+#endif
+ cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(&rv0) = Exp_1 + (70 << Exp_shift);
+ word1(&rv0) = 0;
+ dval(&rv0) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+ if (scale) {
+ word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(&rv0) = 0;
+ dval(&rv) *= dval(&rv0);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+#ifdef IEEE_Arith
+ if (!(word0(&rv) & Exp_mask))
+#else
+ if (word0(&rv) == 0 && word1(&rv) == 0)
+#endif
+ errno = ERANGE;
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(&rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(&rv0) = 1e-300;
+ dval(&rv0) *= dval(&rv0);
+ }
+#endif
+ ret:
+ if (se)
+ *se = (char *)s;
+ return sign ? -dval(&rv) : dval(&rv);
+ }
+
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c
new file mode 100644
index 0000000..753f6bf
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c
@@ -0,0 +1,1154 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998-2001 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+ static CONST int
+fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
+ 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
+ 47, 49, 52
+#ifdef VAX
+ , 54, 56
+#endif
+ };
+
+ Bigint *
+#ifdef KR_headers
+increment(b) Bigint *b;
+#else
+increment(Bigint *b)
+#endif
+{
+ ULong *x, *xe;
+ Bigint *b1;
+#ifdef Pack_16
+ ULong carry = 1, y;
+#endif
+
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ do {
+ if (*x < (ULong)0xffffffffL) {
+ ++*x;
+ return b;
+ }
+ *x++ = 0;
+ } while(x < xe);
+#else
+ do {
+ y = *x + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+ if (!carry)
+ return b;
+ } while(x < xe);
+ if (carry)
+#endif
+ {
+ if (b->wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ if (b1 == NULL)
+ return (NULL);
+ Bcopy(b1,b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[b->wds++] = 1;
+ }
+ return b;
+ }
+
+ void
+#ifdef KR_headers
+decrement(b) Bigint *b;
+#else
+decrement(Bigint *b)
+#endif
+{
+ ULong *x, *xe;
+#ifdef Pack_16
+ ULong borrow = 1, y;
+#endif
+
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ do {
+ if (*x) {
+ --*x;
+ break;
+ }
+ *x++ = 0xffffffffL;
+ }
+ while(x < xe);
+#else
+ do {
+ y = *x - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *x++ = y & 0xffff;
+ } while(borrow && x < xe);
+#endif
+ }
+
+ static int
+#ifdef KR_headers
+all_on(b, n) Bigint *b; int n;
+#else
+all_on(Bigint *b, int n)
+#endif
+{
+ ULong *x, *xe;
+
+ x = b->x;
+ xe = x + (n >> kshift);
+ while(x < xe)
+ if ((*x++ & ALL_ON) != ALL_ON)
+ return 0;
+ if (n &= kmask)
+ return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
+ return 1;
+ }
+
+ Bigint *
+#ifdef KR_headers
+set_ones(b, n) Bigint *b; int n;
+#else
+set_ones(Bigint *b, int n)
+#endif
+{
+ int k;
+ ULong *x, *xe;
+
+ k = (n + ((1 << kshift) - 1)) >> kshift;
+ if (b->k < k) {
+ Bfree(b);
+ b = Balloc(k);
+ if (b == NULL)
+ return (NULL);
+ }
+ k = n >> kshift;
+ if (n &= kmask)
+ k++;
+ b->wds = k;
+ x = b->x;
+ xe = x + k;
+ while(x < xe)
+ *x++ = ALL_ON;
+ if (n)
+ x[-1] >>= ULbits - n;
+ return b;
+ }
+
+ static int
+rvOK
+#ifdef KR_headers
+ (d, fpi, exp, bits, exact, rd, irv)
+ U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
+#else
+ (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+#endif
+{
+ Bigint *b;
+ ULong carry, inex, lostbits;
+ int bdif, e, j, k, k1, nb, rv;
+
+ carry = rv = 0;
+ b = d2b(dval(d), &e, &bdif);
+ if (b == NULL) {
+ *irv = STRTOG_NoMemory;
+ return (1);
+ }
+ bdif -= nb = fpi->nbits;
+ e += bdif;
+ if (bdif <= 0) {
+ if (exact)
+ goto trunc;
+ goto ret;
+ }
+ if (P == nb) {
+ if (
+#ifndef IMPRECISE_INEXACT
+ exact &&
+#endif
+ fpi->rounding ==
+#ifdef RND_PRODQUOT
+ FPI_Round_near
+#else
+ Flt_Rounds
+#endif
+ ) goto trunc;
+ goto ret;
+ }
+ switch(rd) {
+ case 1: /* round down (toward -Infinity) */
+ goto trunc;
+ case 2: /* round up (toward +Infinity) */
+ break;
+ default: /* round near */
+ k = bdif - 1;
+ if (k < 0)
+ goto trunc;
+ if (!k) {
+ if (!exact)
+ goto ret;
+ if (b->x[0] & 2)
+ break;
+ goto trunc;
+ }
+ if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
+ break;
+ goto trunc;
+ }
+ /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
+ carry = 1;
+ trunc:
+ inex = lostbits = 0;
+ if (bdif > 0) {
+ if ( (lostbits = any_on(b, bdif)) !=0)
+ inex = STRTOG_Inexlo;
+ rshift(b, bdif);
+ if (carry) {
+ inex = STRTOG_Inexhi;
+ b = increment(b);
+ if (b == NULL) {
+ *irv = STRTOG_NoMemory;
+ return (1);
+ }
+ if ( (j = nb & kmask) !=0)
+ j = ULbits - j;
+ if (hi0bits(b->x[b->wds - 1]) != j) {
+ if (!lostbits)
+ lostbits = b->x[0] & 1;
+ rshift(b, 1);
+ e++;
+ }
+ }
+ }
+ else if (bdif < 0) {
+ b = lshift(b, -bdif);
+ if (b == NULL) {
+ *irv = STRTOG_NoMemory;
+ return (1);
+ }
+ }
+ if (e < fpi->emin) {
+ k = fpi->emin - e;
+ e = fpi->emin;
+ if (k > nb || fpi->sudden_underflow) {
+ b->wds = inex = 0;
+ *irv = STRTOG_Underflow | STRTOG_Inexlo;
+ }
+ else {
+ k1 = k - 1;
+ if (k1 > 0 && !lostbits)
+ lostbits = any_on(b, k1);
+ if (!lostbits && !exact)
+ goto ret;
+ lostbits |=
+ carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
+ rshift(b, k);
+ *irv = STRTOG_Denormal;
+ if (carry) {
+ b = increment(b);
+ if (b == NULL) {
+ *irv = STRTOG_NoMemory;
+ return (1);
+ }
+ inex = STRTOG_Inexhi | STRTOG_Underflow;
+ }
+ else if (lostbits)
+ inex = STRTOG_Inexlo | STRTOG_Underflow;
+ }
+ }
+ else if (e > fpi->emax) {
+ e = fpi->emax + 1;
+ *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ b->wds = inex = 0;
+ }
+ *exp = e;
+ copybits(bits, nb, b);
+ *irv |= inex;
+ rv = 1;
+ ret:
+ Bfree(b);
+ return rv;
+ }
+
+ static int
+#ifdef KR_headers
+mantbits(d) U *d;
+#else
+mantbits(U *d)
+#endif
+{
+ ULong L;
+#ifdef VAX
+ L = word1(d) << 16 | word1(d) >> 16;
+ if (L)
+#else
+ if ( (L = word1(d)) !=0)
+#endif
+ return P - lo0bits(&L);
+#ifdef VAX
+ L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
+#else
+ L = word0(d) | Exp_msk1;
+#endif
+ return P - 32 - lo0bits(&L);
+ }
+
+ int
+strtodg
+#ifdef KR_headers
+ (s00, se, fpi, exp, bits)
+ CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
+#else
+ (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
+#endif
+{
+ int abe, abits, asub;
+ int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
+ int dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
+ int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
+ int sudden_underflow;
+ CONST char *s, *s0, *s1;
+ double adj0, tol;
+ Long L;
+ U adj, rv;
+ ULong *b, *be, y, z;
+ Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
+#ifdef USE_LOCALE /*{{*/
+#ifdef NO_LOCALE_CACHE
+ char *decimalpoint = localeconv()->decimal_point;
+ int dplen = strlen(decimalpoint);
+#else
+ char *decimalpoint;
+ static char *decimalpoint_cache;
+ static int dplen;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
+ strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
+ s0 = decimalpoint_cache;
+ }
+ dplen = strlen(s0);
+ }
+ decimalpoint = (char*)s0;
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
+
+ irv = STRTOG_Zero;
+ denorm = sign = nz0 = nz = 0;
+ dval(&rv) = 0.;
+ rvb = 0;
+ nbits = fpi->nbits;
+ for(s = s00;;s++) switch(*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ sign = 0;
+ irv = STRTOG_NoNumber;
+ s = s00;
+ goto ret;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+ break2:
+ if (*s == '0') {
+#ifndef NO_HEX_FP
+ switch(s[1]) {
+ case 'x':
+ case 'X':
+ irv = gethex(&s, fpi, exp, &rvb, sign);
+ if (irv == STRTOG_NoMemory)
+ return (STRTOG_NoMemory);
+ if (irv == STRTOG_NoNumber) {
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+#endif
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ sudden_underflow = fpi->sudden_underflow;
+ s0 = s;
+ y = z = 0;
+ for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+#ifdef USE_LOCALE
+ if (c == *decimalpoint) {
+ for(i = 1; decimalpoint[i]; ++i)
+ if (s[i] != decimalpoint[i])
+ goto dig_done;
+ s += i;
+ c = *s;
+#else
+ if (c == '.') {
+ c = *++s;
+#endif
+ decpt = 1;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }/*}*/
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ irv = STRTOG_NoNumber;
+ s = s00;
+ goto ret;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ if (!decpt)
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ irv = STRTOG_Infinite;
+ goto infnanexp;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+ irv = STRTOG_NaN;
+ *exp = fpi->emax + 1;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ irv = hexnan(&s, fpi, bits);
+#endif
+ goto infnanexp;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ irv = STRTOG_NoNumber;
+ s = s00;
+ }
+ goto ret;
+ }
+
+ irv = STRTOG_Normal;
+ e1 = e -= nf;
+ rd = 0;
+ switch(fpi->rounding & 3) {
+ case FPI_Round_up:
+ rd = 2 - sign;
+ break;
+ case FPI_Round_zero:
+ rd = 1;
+ break;
+ case FPI_Round_down:
+ rd = 1 + sign;
+ }
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(&rv) = y;
+ if (k > 9)
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
+ bd0 = 0;
+ if (nbits <= P && nd <= DBL_DIG) {
+ if (!e) {
+ if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) {
+ if (irv == STRTOG_NoMemory)
+ return (STRTOG_NoMemory);
+ goto ret;
+ }
+ }
+ else if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+ i = fivesbits[e] + mantbits(&rv) <= P;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) {
+ if (irv == STRTOG_NoMemory)
+ return (STRTOG_NoMemory);
+ goto ret;
+ }
+ e1 -= e;
+ goto rv_notOK;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+ e2 = e - i;
+ e1 -= i;
+ dval(&rv) *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ dval(&adj) = dval(&rv);
+ word0(&adj) -= P*Exp_msk1;
+ /* adj = */ rounded_product(dval(&adj), tens[e2]);
+ if ((word0(&adj) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto rv_notOK;
+ word0(&adj) += P*Exp_msk1;
+ dval(&rv) = dval(&adj);
+#else
+ /* rv = */ rounded_product(dval(&rv), tens[e2]);
+#endif
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
+ if (irv == STRTOG_NoMemory)
+ return (STRTOG_NoMemory);
+ goto ret;
+ }
+ e1 -= e2;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) {
+ if (irv == STRTOG_NoMemory)
+ return (STRTOG_NoMemory);
+ goto ret;
+ }
+ e1 -= e;
+ }
+#endif
+ }
+ rv_notOK:
+ e1 += nd - k;
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ e2 = 0;
+ if (e1 > 0) {
+ if ( (i = e1 & 15) !=0)
+ dval(&rv) *= tens[i];
+ if (e1 &= ~15) {
+ e1 >>= 4;
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
+ >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= bigtens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
+ }
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(&rv) *= bigtens[j];
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if ( (i = e1 & 15) !=0)
+ dval(&rv) /= tens[i];
+ if (e1 &= ~15) {
+ e1 >>= 4;
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
+ >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= tinytens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
+ }
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(&rv) *= tinytens[j];
+ }
+ }
+#ifdef IBM
+ /* e2 is a correction to the (base 2) exponent of the return
+ * value, reflecting adjustments above to avoid overflow in the
+ * native arithmetic. For native IBM (base 16) arithmetic, we
+ * must multiply e2 by 4 to change from base 16 to 2.
+ */
+ e2 <<= 2;
+#endif
+ rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ rve += e2;
+ if ((j = rvbits - nbits) > 0) {
+ rshift(rvb, j);
+ rvbits = nbits;
+ rve += j;
+ }
+ bb0 = 0; /* trailing zero bits in rvb */
+ e2 = rve + rvbits - nbits;
+ if (e2 > fpi->emax + 1)
+ goto huge;
+ rve1 = rve + rvbits - nbits;
+ if (e2 < (emin = fpi->emin)) {
+ denorm = 1;
+ j = rve - emin;
+ if (j > 0) {
+ rvb = lshift(rvb, j);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ rvbits += j;
+ }
+ else if (j < 0) {
+ rvbits += j;
+ if (rvbits <= 0) {
+ if (rvbits < -1) {
+ ufl:
+ rvb->wds = 0;
+ rvb->x[0] = 0;
+ *exp = emin;
+ irv = STRTOG_Underflow | STRTOG_Inexlo;
+ goto ret;
+ }
+ rvb->x[0] = rvb->wds = rvbits = 1;
+ }
+ else
+ rshift(rvb, -j);
+ }
+ rve = rve1 = emin;
+ if (sudden_underflow && e2 + 1 < emin)
+ goto ufl;
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y, dplen);
+ if (bd0 == NULL)
+ return (STRTOG_NoMemory);
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ if (bd == NULL)
+ return (STRTOG_NoMemory);
+ Bcopy(bd, bd0);
+ bb = Balloc(rvb->k);
+ if (bb == NULL)
+ return (STRTOG_NoMemory);
+ Bcopy(bb, rvb);
+ bbbits = rvbits - bb0;
+ bbe = rve + bb0;
+ bs = i2b(1);
+ if (bs == NULL)
+ return (STRTOG_NoMemory);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+ j = nbits + 1 - bbbits;
+ i = bbe + bbbits - nbits;
+ if (i < emin) /* denormal */
+ j += i - emin;
+ bb2 += j;
+ bd2 += j;
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ if (bs == NULL)
+ return (STRTOG_NoMemory);
+ bb1 = mult(bs, bb);
+ if (bb1 == NULL)
+ return (STRTOG_NoMemory);
+ Bfree(bb);
+ bb = bb1;
+ }
+ bb2 -= bb0;
+ if (bb2 > 0) {
+ bb = lshift(bb, bb2);
+ if (bb == NULL)
+ return (STRTOG_NoMemory);
+ }
+ else if (bb2 < 0)
+ rshift(bb, -bb2);
+ if (bd5 > 0) {
+ bd = pow5mult(bd, bd5);
+ if (bd == NULL)
+ return (STRTOG_NoMemory);
+ }
+ if (bd2 > 0) {
+ bd = lshift(bd, bd2);
+ if (bd == NULL)
+ return (STRTOG_NoMemory);
+ }
+ if (bs2 > 0) {
+ bs = lshift(bs, bs2);
+ if (bs == NULL)
+ return (STRTOG_NoMemory);
+ }
+ asub = 1;
+ inex = STRTOG_Inexhi;
+ delta = diff(bb, bd);
+ if (delta == NULL)
+ return (STRTOG_NoMemory);
+ if (delta->wds <= 1 && !delta->x[0])
+ break;
+ dsign = delta->sign;
+ delta->sign = finished = 0;
+ L = 0;
+ i = cmp(delta, bs);
+ if (rd && i <= 0) {
+ irv = STRTOG_Normal;
+ if ( (finished = dsign ^ (rd&1)) !=0) {
+ if (dsign != 0) {
+ irv |= STRTOG_Inexhi;
+ goto adj1;
+ }
+ irv |= STRTOG_Inexlo;
+ if (rve1 == emin)
+ goto adj1;
+ for(i = 0, j = nbits; j >= ULbits;
+ i++, j -= ULbits) {
+ if (rvb->x[i] & ALL_ON)
+ goto adj1;
+ }
+ if (j > 1 && lo0bits(rvb->x + i) < j - 1)
+ goto adj1;
+ rve = rve1 - 1;
+ rvb = set_ones(rvb, rvbits = nbits);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ break;
+ }
+ irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
+ break;
+ }
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ irv = dsign
+ ? STRTOG_Normal | STRTOG_Inexlo
+ : STRTOG_Normal | STRTOG_Inexhi;
+ if (dsign || bbbits > 1 || denorm || rve1 == emin)
+ break;
+ delta = lshift(delta,1);
+ if (delta == NULL)
+ return (STRTOG_NoMemory);
+ if (cmp(delta, bs) > 0) {
+ irv = STRTOG_Normal | STRTOG_Inexlo;
+ goto drop_down;
+ }
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if (denorm && all_on(rvb, rvbits)) {
+ /*boundary case -- increment exponent*/
+ rvb->wds = 1;
+ rvb->x[0] = 1;
+ rve = emin + nbits - (rvbits = 1);
+ irv = STRTOG_Normal | STRTOG_Inexhi;
+ denorm = 0;
+ break;
+ }
+ irv = STRTOG_Normal | STRTOG_Inexlo;
+ }
+ else if (bbbits == 1) {
+ irv = STRTOG_Normal;
+ drop_down:
+ /* boundary case -- decrement exponent */
+ if (rve1 == emin) {
+ irv = STRTOG_Normal | STRTOG_Inexhi;
+ if (rvb->wds == 1 && rvb->x[0] == 1)
+ sudden_underflow = 1;
+ break;
+ }
+ rve -= nbits;
+ rvb = set_ones(rvb, rvbits = nbits);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ break;
+ }
+ else
+ irv = STRTOG_Normal | STRTOG_Inexhi;
+ if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
+ break;
+ if (dsign) {
+ rvb = increment(rvb);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ j = kmask & (ULbits - (rvbits & kmask));
+ if (hi0bits(rvb->x[rvb->wds - 1]) != j)
+ rvbits++;
+ irv = STRTOG_Normal | STRTOG_Inexhi;
+ }
+ else {
+ if (bbbits == 1)
+ goto undfl;
+ decrement(rvb);
+ irv = STRTOG_Normal | STRTOG_Inexlo;
+ }
+ break;
+ }
+ if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
+ adj1:
+ inex = STRTOG_Inexlo;
+ if (dsign) {
+ asub = 0;
+ inex = STRTOG_Inexhi;
+ }
+ else if (denorm && bbbits <= 1) {
+ undfl:
+ rvb->wds = 0;
+ rve = emin;
+ irv = STRTOG_Underflow | STRTOG_Inexlo;
+ break;
+ }
+ adj0 = dval(&adj) = 1.;
+ }
+ else {
+ adj0 = dval(&adj) *= 0.5;
+ if (dsign) {
+ asub = 0;
+ inex = STRTOG_Inexlo;
+ }
+ if (dval(&adj) < 2147483647.) {
+ L = adj0;
+ adj0 -= L;
+ switch(rd) {
+ case 0:
+ if (adj0 >= .5)
+ goto inc_L;
+ break;
+ case 1:
+ if (asub && adj0 > 0.)
+ goto inc_L;
+ break;
+ case 2:
+ if (!asub && adj0 > 0.) {
+ inc_L:
+ L++;
+ inex = STRTOG_Inexact - inex;
+ }
+ }
+ dval(&adj) = L;
+ }
+ }
+ y = rve + rvbits;
+
+ /* adj *= ulp(dval(&rv)); */
+ /* if (asub) rv -= adj; else rv += adj; */
+
+ if (!denorm && rvbits < nbits) {
+ rvb = lshift(rvb, j = nbits - rvbits);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ rve -= j;
+ rvbits = nbits;
+ }
+ ab = d2b(dval(&adj), &abe, &abits);
+ if (ab == NULL)
+ return (STRTOG_NoMemory);
+ if (abe < 0)
+ rshift(ab, -abe);
+ else if (abe > 0) {
+ ab = lshift(ab, abe);
+ if (ab == NULL)
+ return (STRTOG_NoMemory);
+ }
+ rvb0 = rvb;
+ if (asub) {
+ /* rv -= adj; */
+ j = hi0bits(rvb->x[rvb->wds-1]);
+ rvb = diff(rvb, ab);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ k = rvb0->wds - 1;
+ if (denorm)
+ /* do nothing */;
+ else if (rvb->wds <= k
+ || hi0bits( rvb->x[k]) >
+ hi0bits(rvb0->x[k])) {
+ /* unlikely; can only have lost 1 high bit */
+ if (rve1 == emin) {
+ --rvbits;
+ denorm = 1;
+ }
+ else {
+ rvb = lshift(rvb, 1);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ --rve;
+ --rve1;
+ L = finished = 0;
+ }
+ }
+ }
+ else {
+ rvb = sum(rvb, ab);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ k = rvb->wds - 1;
+ if (k >= rvb0->wds
+ || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
+ if (denorm) {
+ if (++rvbits == nbits)
+ denorm = 0;
+ }
+ else {
+ rshift(rvb, 1);
+ rve++;
+ rve1++;
+ L = 0;
+ }
+ }
+ }
+ Bfree(ab);
+ Bfree(rvb0);
+ if (finished)
+ break;
+
+ z = rve + rvbits;
+ if (y == z && L) {
+ /* Can we stop now? */
+ tol = dval(&adj) * 5e-16; /* > max rel error */
+ dval(&adj) = adj0 - .5;
+ if (dval(&adj) < -tol) {
+ if (adj0 > tol) {
+ irv |= inex;
+ break;
+ }
+ }
+ else if (dval(&adj) > tol && adj0 < 1. - tol) {
+ irv |= inex;
+ break;
+ }
+ }
+ bb0 = denorm ? 0 : trailz(rvb);
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+ if (!denorm && (j = nbits - rvbits)) {
+ if (j > 0) {
+ rvb = lshift(rvb, j);
+ if (rvb == NULL)
+ return (STRTOG_NoMemory);
+ }
+ else
+ rshift(rvb, -j);
+ rve -= j;
+ }
+ *exp = rve;
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ if (rve > fpi->emax) {
+ switch(fpi->rounding & 3) {
+ case FPI_Round_near:
+ goto huge;
+ case FPI_Round_up:
+ if (!sign)
+ goto huge;
+ break;
+ case FPI_Round_down:
+ if (sign)
+ goto huge;
+ }
+ /* Round to largest representable magnitude */
+ Bfree(rvb);
+ rvb = 0;
+ irv = STRTOG_Normal | STRTOG_Inexlo;
+ *exp = fpi->emax;
+ b = bits;
+ be = b + ((fpi->nbits + 31) >> 5);
+ while(b < be)
+ *b++ = -1;
+ if ((j = fpi->nbits & 0x1f))
+ *--be >>= (32 - j);
+ goto ret;
+ huge:
+ rvb->wds = 0;
+ irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ infnanexp:
+ *exp = fpi->emax + 1;
+ }
+ ret:
+ if (denorm) {
+ if (sudden_underflow) {
+ rvb->wds = 0;
+ irv = STRTOG_Underflow | STRTOG_Inexlo;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ }
+ else {
+ irv = (irv & ~STRTOG_Retmask) |
+ (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
+ if (irv & STRTOG_Inexact) {
+ irv |= STRTOG_Underflow;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ }
+ }
+ }
+ if (se)
+ *se = (char *)s;
+ if (sign)
+ irv |= STRTOG_Neg;
+ if (rvb) {
+ copybits(bits, nbits, rvb);
+ Bfree(rvb);
+ }
+ return irv;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c
new file mode 100644
index 0000000..224491b
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtof.c
@@ -0,0 +1,81 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ float
+#ifdef KR_headers
+strtof(s, sp) CONST char *s; char **sp;
+#else
+strtof(CONST char *s, char **sp)
+#endif
+{
+ static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
+ ULong bits[1];
+ Long exp;
+ int k;
+ union { ULong L[1]; float f; } u;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
+
+ k = strtodg(s, sp, fpi, &exp, bits);
+ switch(k & STRTOG_Retmask) {
+ case STRTOG_NoNumber:
+ case STRTOG_Zero:
+ u.L[0] = 0;
+ break;
+
+ case STRTOG_Normal:
+ case STRTOG_NaNbits:
+ u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
+ break;
+
+ case STRTOG_Denormal:
+ u.L[0] = bits[0];
+ break;
+
+ case STRTOG_NoMemory:
+ errno = ERANGE;
+ /* FALLTHROUGH */
+ case STRTOG_Infinite:
+ u.L[0] = 0x7f800000;
+ break;
+
+ case STRTOG_NaN:
+ u.L[0] = f_QNAN;
+ }
+ if (k & STRTOG_Neg)
+ u.L[0] |= 0x80000000L;
+ return u.f;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtorQ.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtorQ.c
new file mode 100644
index 0000000..715cb08
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtorQ.c
@@ -0,0 +1,120 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+#undef _0
+#undef _1
+
+/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
+
+#ifdef IEEE_MC68k
+#define _0 0
+#define _1 1
+#define _2 2
+#define _3 3
+#endif
+#ifdef IEEE_8087
+#define _0 3
+#define _1 2
+#define _2 1
+#define _3 0
+#endif
+
+ void
+#ifdef KR_headers
+ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtoQ(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+ switch(k & STRTOG_Retmask) {
+ case STRTOG_NoNumber:
+ case STRTOG_Zero:
+ L[0] = L[1] = L[2] = L[3] = 0;
+ break;
+
+ case STRTOG_Normal:
+ case STRTOG_NaNbits:
+ L[_3] = bits[0];
+ L[_2] = bits[1];
+ L[_1] = bits[2];
+ L[_0] = (bits[3] & ~0x10000) | ((exp + 0x3fff + 112) << 16);
+ break;
+
+ case STRTOG_Denormal:
+ L[_3] = bits[0];
+ L[_2] = bits[1];
+ L[_1] = bits[2];
+ L[_0] = bits[3];
+ break;
+
+ case STRTOG_NoMemory:
+ errno = ERANGE;
+ /* FALLTHROUGH */
+ case STRTOG_Infinite:
+ L[_0] = 0x7fff0000;
+ L[_1] = L[_2] = L[_3] = 0;
+ break;
+
+ case STRTOG_NaN:
+ L[0] = ld_QNAN0;
+ L[1] = ld_QNAN1;
+ L[2] = ld_QNAN2;
+ L[3] = ld_QNAN3;
+ }
+ if (k & STRTOG_Neg)
+ L[_0] |= 0x80000000L;
+ }
+
+ int
+#ifdef KR_headers
+strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L;
+#else
+strtorQ(CONST char *s, char **sp, int rounding, void *L)
+#endif
+{
+ static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI };
+ FPI *fpi, fpi1;
+ ULong bits[4];
+ Long exp;
+ int k;
+
+ fpi = &fpi0;
+ if (rounding != FPI_Round_near) {
+ fpi1 = fpi0;
+ fpi1.rounding = rounding;
+ fpi = &fpi1;
+ }
+ k = strtodg(s, sp, fpi, &exp, bits);
+ ULtoQ((ULong*)L, bits, exp, k);
+ return k;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtord.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtord.c
new file mode 100644
index 0000000..966d264
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtord.c
@@ -0,0 +1,96 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 2000 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ void
+#ifdef KR_headers
+ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k;
+#else
+ULtod(ULong *L, ULong *bits, Long exp, int k)
+#endif
+{
+ switch(k & STRTOG_Retmask) {
+ case STRTOG_NoNumber:
+ case STRTOG_Zero:
+ L[0] = L[1] = 0;
+ break;
+
+ case STRTOG_Denormal:
+ L[_1] = bits[0];
+ L[_0] = bits[1];
+ break;
+
+ case STRTOG_Normal:
+ case STRTOG_NaNbits:
+ L[_1] = bits[0];
+ L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20);
+ break;
+
+ case STRTOG_NoMemory:
+ errno = ERANGE;
+ /* FALLTHROUGH */
+ case STRTOG_Infinite:
+ L[_0] = 0x7ff00000;
+ L[_1] = 0;
+ break;
+
+ case STRTOG_NaN:
+ L[0] = d_QNAN0;
+ L[1] = d_QNAN1;
+ }
+ if (k & STRTOG_Neg)
+ L[_0] |= 0x80000000L;
+ }
+
+ int
+#ifdef KR_headers
+strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d;
+#else
+strtord(CONST char *s, char **sp, int rounding, double *d)
+#endif
+{
+ static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
+ FPI *fpi, fpi1;
+ ULong bits[2];
+ Long exp;
+ int k;
+
+ fpi = &fpi0;
+ if (rounding != FPI_Round_near) {
+ fpi1 = fpi0;
+ fpi1.rounding = rounding;
+ fpi = &fpi1;
+ }
+ k = strtodg(s, sp, fpi, &exp, bits);
+ ULtod((ULong*)d, bits, exp, k);
+ return k;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/sum.c b/libc/upstream-openbsd/lib/libc/gdtoa/sum.c
new file mode 100644
index 0000000..c6eb954
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/sum.c
@@ -0,0 +1,102 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ Bigint *
+#ifdef KR_headers
+sum(a, b) Bigint *a; Bigint *b;
+#else
+sum(Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ ULong carry, *xc, *xa, *xb, *xe, y;
+#ifdef Pack_32
+ ULong z;
+#endif
+
+ if (a->wds < b->wds) {
+ c = b; b = a; a = c;
+ }
+ c = Balloc(a->k);
+ if (c == NULL)
+ return (NULL);
+ c->wds = a->wds;
+ carry = 0;
+ xa = a->x;
+ xb = b->x;
+ xc = c->x;
+ xe = xc + b->wds;
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) + (*xb & 0xffff) + carry;
+ carry = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) + (*xb++ >> 16) + carry;
+ carry = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+ while(xc < xe);
+ xe += a->wds - b->wds;
+ while(xc < xe) {
+ y = (*xa & 0xffff) + carry;
+ carry = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) + carry;
+ carry = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ + *xb++ + carry;
+ carry = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+ while(xc < xe);
+ xe += a->wds - b->wds;
+ while(xc < xe) {
+ y = *xa++ + carry;
+ carry = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+ if (carry) {
+ if (c->wds == c->maxwds) {
+ b = Balloc(c->k + 1);
+ if (b == NULL)
+ return (NULL);
+ Bcopy(b, c);
+ Bfree(c);
+ c = b;
+ }
+ c->x[c->wds++] = 1;
+ }
+ return c;
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/ulp.c b/libc/upstream-openbsd/lib/libc/gdtoa/ulp.c
new file mode 100644
index 0000000..17e9f86
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/ulp.c
@@ -0,0 +1,70 @@
+/****************************************************************
+
+The author of this software is David M. Gay.
+
+Copyright (C) 1998, 1999 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+
+****************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+#include "gdtoaimp.h"
+
+ double
+ulp
+#ifdef KR_headers
+ (x) U *x;
+#else
+ (U *x)
+#endif
+{
+ Long L;
+ U a;
+
+ L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ word0(&a) = L;
+ word1(&a) = 0;
+#ifndef Sudden_Underflow
+ }
+ else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(&a) = 0x80000 >> L;
+ word1(&a) = 0;
+ }
+ else {
+ word0(&a) = 0;
+ L -= Exp_shift;
+ word1(&a) = L >= 31 ? 1 : 1 << (31 - L);
+ }
+ }
+#endif
+ return dval(&a);
+ }
diff --git a/libc/upstream-openbsd/lib/libc/gen/ctype_.c b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
new file mode 100644
index 0000000..89c8257
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: ctype_.c,v 1.10 2011/09/22 09:06:10 stsp Exp $ */
+/*
+ * Copyright (c) 1989 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
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include "ctype_private.h"
+
+const char _C_ctype_[1 + CTYPE_NUM_CHARS] = {
+ 0,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S|(char)_B, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _P, _P, _P, _P, _C,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 88 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 98 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* A0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* A8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* B0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* B8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* C0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* C8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* D0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* D8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* E0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* E8 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* F0 */
+ 0, 0, 0, 0, 0, 0, 0, 0 /* F8 */
+};
+
+const char *_ctype_ = _C_ctype_;
diff --git a/libc/upstream-openbsd/lib/libc/gen/isctype.c b/libc/upstream-openbsd/lib/libc/gen/isctype.c
new file mode 100644
index 0000000..970b5e2
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/gen/isctype.c
@@ -0,0 +1,150 @@
+/* $OpenBSD: isctype.c,v 1.11 2005/08/08 08:05:34 espie Exp $ */
+/*
+ * Copyright (c) 1989 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
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, 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.
+ * 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.
+ */
+
+#define _ANSI_LIBRARY
+#include <ctype.h>
+#include <stdio.h>
+
+#undef isalnum
+int
+isalnum(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L|_N)));
+}
+
+#undef isalpha
+int
+isalpha(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L)));
+}
+
+#undef isblank
+int
+isblank(int c)
+{
+ return (c == ' ' || c == '\t');
+}
+
+#undef iscntrl
+int
+iscntrl(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _C));
+}
+
+#undef isdigit
+int
+isdigit(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _N));
+}
+
+#undef isgraph
+int
+isgraph(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N)));
+}
+
+#undef islower
+int
+islower(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _L));
+}
+
+#undef isprint
+int
+isprint(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N|_B)));
+}
+
+#undef ispunct
+int
+ispunct(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _P));
+}
+
+#undef isspace
+int
+isspace(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _S));
+}
+
+#undef isupper
+int
+isupper(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _U));
+}
+
+#undef isxdigit
+int
+isxdigit(int c)
+{
+ return (c == EOF ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_N|_X)));
+}
+
+#undef isascii
+int
+isascii(int c)
+{
+ return ((unsigned int)c <= 0177);
+}
+
+#undef toascii
+int
+toascii(int c)
+{
+ return (c & 0177);
+}
+
+#undef _toupper
+int
+_toupper(int c)
+{
+ return (c - 'a' + 'A');
+}
+
+#undef _tolower
+int
+_tolower(int c)
+{
+ return (c - 'A' + 'a');
+}
diff --git a/libc/stdlib/ctype_private.h b/libc/upstream-openbsd/lib/libc/include/ctype_private.h
similarity index 100%
rename from libc/stdlib/ctype_private.h
rename to libc/upstream-openbsd/lib/libc/include/ctype_private.h
diff --git a/libc/upstream-openbsd/lib/libc/include/langinfo.h b/libc/upstream-openbsd/lib/libc/include/langinfo.h
new file mode 100644
index 0000000..a871ab8
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/include/langinfo.h
@@ -0,0 +1,3 @@
+/* Hack to build "vfprintf.c". */
+#define RADIXCHAR 1
+#define nl_langinfo(i) ((i == RADIXCHAR) ? (char*) "." : NULL)
diff --git a/libc/stdio/floatio.h b/libc/upstream-openbsd/lib/libc/stdio/floatio.h
similarity index 72%
rename from libc/stdio/floatio.h
rename to libc/upstream-openbsd/lib/libc/stdio/floatio.h
index 20f9801..9769030 100644
--- a/libc/stdio/floatio.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/floatio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: floatio.h,v 1.3 2003/06/02 20:18:37 millert Exp $ */
+/* $OpenBSD: floatio.h,v 1.4 2008/09/07 20:36:08 martynas Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -40,3 +40,19 @@
#define MAXEXP 308
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
#define MAXFRACT 39
+
+/*
+ * MAXEXPDIG is the maximum number of decimal digits needed to store a
+ * floating point exponent in the largest supported format. It should
+ * be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point
+ * conversions are supported, ceil(log10(LDBL_MAX_EXP)). But since it
+ * is presently never greater than 5 in practice, we fudge it.
+ */
+#define MAXEXPDIG 6
+#if LDBL_MAX_EXP > 999999
+#error "floating point buffers too small"
+#endif
+
+char *__hdtoa(double, const char *, int, int *, int *, char **);
+char *__hldtoa(long double, const char *, int, int *, int *, char **);
+char *__ldtoa(long double *, int, int, int *, int *, char **);
diff --git a/libc/stdio/floatio.h b/libc/upstream-openbsd/lib/libc/stdio/fread.c
similarity index 65%
copy from libc/stdio/floatio.h
copy to libc/upstream-openbsd/lib/libc/stdio/fread.c
index 20f9801..430865d 100644
--- a/libc/stdio/floatio.h
+++ b/libc/upstream-openbsd/lib/libc/stdio/fread.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: floatio.h,v 1.3 2003/06/02 20:18:37 millert Exp $ */
-
+/* $OpenBSD: fread.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,11 +31,44 @@
* SUCH DAMAGE.
*/
-/*
- * Floating point scanf/printf (input/output) definitions.
- */
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
-/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
-#define MAXEXP 308
-/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
-#define MAXFRACT 39
+size_t
+fread(void *buf, size_t size, size_t count, FILE *fp)
+{
+ size_t resid;
+ char *p;
+ int r;
+ size_t total;
+
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ if ((resid = count * size) == 0)
+ return (0);
+ FLOCKFILE(fp);
+ _SET_ORIENTATION(fp, -1);
+ if (fp->_r < 0)
+ fp->_r = 0;
+ total = resid;
+ p = buf;
+ while (resid > (r = fp->_r)) {
+ (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
+ fp->_p += r;
+ /* fp->_r = 0 ... done in __srefill */
+ p += r;
+ resid -= r;
+ if (__srefill(fp)) {
+ /* no more input: return partial result */
+ FUNLOCKFILE(fp);
+ return ((total - resid) / size);
+ }
+ }
+ (void)memcpy((void *)p, (void *)fp->_p, resid);
+ fp->_r -= resid;
+ fp->_p += resid;
+ FUNLOCKFILE(fp);
+ return (count);
+}
diff --git a/libc/stdio/fvwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
similarity index 89%
rename from libc/stdio/fvwrite.c
rename to libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
index 39d0604..1088991 100644
--- a/libc/stdio/fvwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fvwrite.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
+/* $OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -44,11 +44,11 @@
* This routine is large and unsightly, but most of the ugliness due
* to the three different kinds of output buffering is handled here.
*/
-__LIBC_HIDDEN__ int
+int
__sfvwrite(FILE *fp, struct __suio *uio)
{
size_t len;
- const char *p;
+ char *p;
struct __siov *iov;
int w, s;
char *nl;
@@ -82,11 +82,7 @@
*/
do {
GETIOV(;);
-#if 1 /* BIONIC: don't limit to 1KB writes */
- w = (*fp->_write)(fp->_cookie, p, len);
-#else
- w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ2));
-#endif
+ w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
if (w <= 0)
goto err;
p += w;
@@ -107,7 +103,7 @@
do {
GETIOV(;);
if ((fp->_flags & (__SALC | __SSTR)) ==
- (__SALC | __SSTR) && fp->_w < (int)len) {
+ (__SALC | __SSTR) && fp->_w < len) {
size_t blen = fp->_p - fp->_bf._base;
unsigned char *_base;
int _size;
@@ -116,7 +112,7 @@
_size = fp->_bf._size;
do {
_size = (_size << 1) + 1;
- } while (_size < (int)(blen + len));
+ } while (_size < blen + len);
_base = realloc(fp->_bf._base, _size + 1);
if (_base == NULL)
goto err;
@@ -127,20 +123,20 @@
}
w = fp->_w;
if (fp->_flags & __SSTR) {
- if ((int)len < w)
+ if (len < w)
w = len;
COPY(w); /* copy MIN(fp->_w,len), */
fp->_w -= w;
fp->_p += w;
w = len; /* but pretend copied all */
- } else if (fp->_p > fp->_bf._base && (int)len > w) {
+ } else if (fp->_p > fp->_bf._base && len > w) {
/* fill and flush */
COPY(w);
/* fp->_w -= w; */ /* unneeded */
fp->_p += w;
- if (fflush(fp))
+ if (__sflush(fp))
goto err;
- } else if ((int)len >= (w = fp->_bf._size)) {
+ } else if (len >= (w = fp->_bf._size)) {
/* write directly */
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
@@ -169,21 +165,21 @@
GETIOV(nlknown = 0);
if (!nlknown) {
nl = memchr((void *)p, '\n', len);
- nldist = nl ? nl + 1 - p : (int)len + 1;
+ nldist = nl ? nl + 1 - p : len + 1;
nlknown = 1;
}
- s = MIN((int)len, nldist);
+ s = MIN(len, nldist);
w = fp->_w + fp->_bf._size;
if (fp->_p > fp->_bf._base && s > w) {
COPY(w);
/* fp->_w -= w; */
fp->_p += w;
- if (fflush(fp))
+ if (__sflush(fp))
goto err;
} else if (s >= (w = fp->_bf._size)) {
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
- goto err;
+ goto err;
} else {
w = s;
COPY(w);
@@ -192,7 +188,7 @@
}
if ((nldist -= w) == 0) {
/* copied the newline: flush and forget */
- if (fflush(fp))
+ if (__sflush(fp))
goto err;
nlknown = 0;
}
diff --git a/libc/stdio/vfprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
similarity index 69%
rename from libc/stdio/vfprintf.c
rename to libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
index e33c105..b4f8f29 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfprintf.c,v 1.37 2006/01/13 17:56:18 millert Exp $ */
+/* $OpenBSD: vfprintf.c,v 1.63 2013/03/02 19:40:08 guenther Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
@@ -41,12 +41,16 @@
#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 <wchar.h>
#include "local.h"
#include "fvwrite.h"
@@ -60,7 +64,7 @@
unsigned long long ulonglongarg;
ptrdiff_t ptrdiffarg;
size_t sizearg;
- size_t ssizearg;
+ ssize_t ssizearg;
intmax_t intmaxarg;
uintmax_t uintmaxarg;
void *pvoidarg;
@@ -71,12 +75,16 @@
long *plongarg;
long long *plonglongarg;
ptrdiff_t *pptrdiffarg;
- size_t *pssizearg;
+ ssize_t *pssizearg;
intmax_t *pintmaxarg;
#ifdef FLOATING_POINT
double doublearg;
long double longdoublearg;
#endif
+#ifdef PRINTF_WIDE_CHAR
+ wint_t wintarg;
+ wchar_t *pwchararg;
+#endif
};
static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
@@ -136,24 +144,98 @@
return (ret);
}
+#ifdef PRINTF_WIDE_CHAR
+/*
+ * Convert a wide character string argument for the %ls format to a multibyte
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char
+ * string is null-terminated.
+ */
+static char *
+__wcsconv(wchar_t *wcsarg, int prec)
+{
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ wchar_t *p;
+ char *convbuf;
+ size_t clen, nbytes;
+
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
+ memset(&mbs, 0, sizeof(mbs));
+ p = wcsarg;
+ nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
+ if (nbytes == (size_t)-1) {
+ errno = EILSEQ;
+ return (NULL);
+ }
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ memset(&mbs, 0, sizeof(mbs));
+ for (;;) {
+ clen = wcrtomb(buf, *p++, &mbs);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > (size_t)prec)
+ break;
+ nbytes += clen;
+ }
+ if (clen == (size_t)-1) {
+ errno = EILSEQ;
+ return (NULL);
+ }
+ }
+ }
+ if ((convbuf = malloc(nbytes + 1)) == NULL)
+ return (NULL);
+
+ /* Fill the output buffer. */
+ p = wcsarg;
+ memset(&mbs, 0, sizeof(mbs));
+ if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs)) == (size_t)-1) {
+ free(convbuf);
+ errno = EILSEQ;
+ return (NULL);
+ }
+ convbuf[nbytes] = '\0';
+ return (convbuf);
+}
+#endif
#ifdef FLOATING_POINT
+#include <float.h>
#include <locale.h>
#include <math.h>
#include "floatio.h"
-#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
#define DEFPREC 6
-static char *cvt(double, int, int, char *, int *, int, int *);
-extern void freedtoa(char *);
+extern char *__dtoa(double, int, int, int *, int *, char **);
+extern void __freedtoa(char *);
static int exponent(char *, int, int);
-#else /* no FLOATING_POINT */
-#define BUF 40
#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
*/
@@ -165,9 +247,8 @@
* Flags used during conversion.
*/
#define ALT 0x0001 /* alternate form */
-#define HEXPREFIX 0x0002 /* add 0x or 0X prefix */
#define LADJUST 0x0004 /* left adjustment */
-#define LONGDBL 0x0008 /* long double; unimplemented */
+#define LONGDBL 0x0008 /* long double */
#define LONGINT 0x0010 /* long integer */
#define LLONGINT 0x0020 /* long long integer */
#define SHORTINT 0x0040 /* short integer */
@@ -194,54 +275,81 @@
{
char *fmt; /* format string */
int ch; /* character from fmt */
- int n, m, n2; /* handy integers (short term usage) */
+ int n, n2; /* handy integers (short term usage) */
char *cp; /* handy char pointer (short term usage) */
struct __siov *iovp; /* for PRINT macro */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
- int prec; /* precision from format (%.3d), or -1 */
+ int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
wchar_t wc;
- void* ps;
+ mbstate_t ps;
#ifdef FLOATING_POINT
- char *decimal_point = ".";
- char softsign; /* temporary negative sign for floats */
- double _double = 0.; /* double precision arguments %[eEfgG] */
+ /*
+ * 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 */
- int expsize = 0; /* character count for expstr */
- int ndig; /* actual number of digits returned by cvt */
- char expstr[7]; /* buffer for exponent string */
+ 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 */
+ char 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 */
+ 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 */
- char* xdigs = NULL; /* digits for [xX] conversion */
+ const char *xdigs; /* digits for %[xX] conversion */
#define NIOV 8
struct __suio uio; /* output information: summary */
struct __siov iov[NIOV];/* ... and individual io vectors */
- char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
- char ox[2]; /* space for 0x hex-prefix */
+ char buf[BUF]; /* buffer with space for digits of uintmax_t */
+ char 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 */
+#ifdef PRINTF_WIDE_CHAR
+ char *convbuf; /* buffer for wide to multi-byte conversion */
+#endif
+
/*
* 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 const char blanks[PADSIZE] =
+ static char blanks[PADSIZE] =
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static const char zeroes[PADSIZE] =
+ static char 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, and PAD uses `n'.
*/
@@ -265,6 +373,14 @@
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)
#define FLUSH() do { \
if (uio.uio_resid && __sprint(fp, &uio)) \
goto error; \
@@ -295,6 +411,18 @@
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.
@@ -303,7 +431,7 @@
n2 = 0; \
cp = fmt; \
while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
+ APPEND_DIGIT(n2, *cp); \
cp++; \
} \
if (*cp == '$') { \
@@ -349,6 +477,9 @@
uio.uio_resid = 0;
uio.uio_iovcnt = 0;
ret = 0;
+#ifdef PRINTF_WIDE_CHAR
+ convbuf = NULL;
+#endif
memset(&ps, 0, sizeof(ps));
/*
@@ -356,16 +487,6 @@
*/
for (;;) {
cp = fmt;
-#if 1 /* BIONIC */
- n = -1;
- while ( (wc = *fmt) != 0 ) {
- if (wc == '%') {
- n = 1;
- break;
- }
- fmt++;
- }
-#else
while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
fmt += n;
if (wc == '%') {
@@ -373,8 +494,10 @@
break;
}
}
-#endif
- if ((m = fmt - cp) != 0) {
+ if (fmt != cp) {
+ ptrdiff_t m = fmt - cp;
+ if (m < 0 || m > INT_MAX - ret)
+ goto overflow;
PRINT(cp, m);
ret += m;
}
@@ -387,6 +510,7 @@
width = 0;
prec = -1;
sign = '\0';
+ ox[1] = '\0';
rflag: ch = *fmt++;
reswitch: switch (ch) {
@@ -402,6 +526,9 @@
case '#':
flags |= ALT;
goto rflag;
+ case '\'':
+ /* grouping not implemented */
+ goto rflag;
case '*':
/*
* ``A negative field width argument is taken as a
@@ -412,6 +539,8 @@
GETASTER(width);
if (width >= 0)
goto rflag;
+ if (width == INT_MIN)
+ goto overflow;
width = -width;
/* FALLTHROUGH */
case '-':
@@ -428,7 +557,7 @@
}
n = 0;
while (is_digit(ch)) {
- n = 10 * n + to_digit(ch);
+ APPEND_DIGIT(n, ch);
ch = *fmt++;
}
if (ch == '$') {
@@ -440,7 +569,7 @@
}
goto rflag;
}
- prec = n < 0 ? -1 : n;
+ prec = n;
goto reswitch;
case '0':
/*
@@ -454,7 +583,7 @@
case '5': case '6': case '7': case '8': case '9':
n = 0;
do {
- n = 10 * n + to_digit(ch);
+ APPEND_DIGIT(n, ch);
ch = *fmt++;
} while (is_digit(ch));
if (ch == '$') {
@@ -502,8 +631,28 @@
flags |= SIZEINT;
goto rflag;
case 'c':
- *(cp = buf) = GETARG(int);
- size = 1;
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT) {
+ mbstate_t mbs;
+ size_t mbseqlen;
+
+ memset(&mbs, 0, sizeof(mbs));
+ mbseqlen = wcrtomb(buf,
+ (wchar_t)GETARG(wint_t), &mbs);
+ if (mbseqlen == (size_t)-1) {
+ fp->_flags |= __SERR;
+ errno = EILSEQ;
+ goto error;
+ }
+ cp = buf;
+ size = (int)mbseqlen;
+ } else {
+#endif
+ *(cp = buf) = GETARG(int);
+ size = 1;
+#ifdef PRINTF_WIDE_CHAR
+ }
+#endif
sign = '\0';
break;
case 'D':
@@ -519,79 +668,140 @@
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 = cp =
+ __hldtoa(fparg.ldbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ __hdtoa(fparg.dbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+ }
+ if (prec < 0)
+ prec = dtoaend - cp;
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ 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':
- if (prec == -1) {
+ expchar = ch - ('g' - 'e');
+ if (prec == 0)
+ prec = 1;
+fp_begin:
+ if (prec < 0)
prec = DEFPREC;
- } else if ((ch == 'g' || ch == 'G') && prec == 0) {
- prec = 1;
- }
-
+ if (dtoaresult)
+ __freedtoa(dtoaresult);
if (flags & LONGDBL) {
- _double = (double) GETARG(long double);
- } else {
- _double = GETARG(double);
- }
-
- /* do this before tricky precision changes */
- if (isinf(_double)) {
- if (_double < 0)
- sign = '-';
- cp = "Inf";
- size = 3;
- break;
- }
- if (isnan(_double)) {
- cp = "NaN";
- size = 3;
- break;
- }
-
- if (dtoaresult != NULL) freedtoa(dtoaresult);
- flags |= FPT;
- dtoaresult = cp = cvt(_double, prec, flags, &softsign,
- &expt, ch, &ndig);
- if (ch == 'g' || ch == 'G') {
- if (expt <= -4 || expt > prec)
- ch = (ch == 'g') ? 'e' : 'E';
- else
- ch = 'g';
- }
- if (ch <= 'e') { /* 'e' or 'E' fmt */
- --expt;
- expsize = exponent(expstr, expt, ch);
- size = expsize + ndig;
- if (ndig > 1 || flags & ALT)
- ++size;
- } else if (ch == 'f') { /* f fmt */
- if (expt > 0) {
- size = expt;
- if (prec || flags & ALT)
- size += prec + 1;
- } else { /* "0.X" */
- size = prec + 2;
+ fparg.ldbl = GETARG(long double);
+ dtoaresult = cp =
+ __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto error;
}
- } else if (expt >= ndig) { /* fixed g fmt */
- size = expt;
- if (flags & ALT)
- ++size;
} else {
- size = ndig + (expt > 0 ? 1 : 2 - expt);
- }
-
- if (softsign)
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+ if (expt == 9999)
+ expt = INT_MAX;
+ }
+fp_common:
+ if (signflag)
sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*cp == 'N') {
+ cp = (ch >= 'a') ? "nan" : "NAN";
+ sign = '\0';
+ } else
+ cp = (ch >= 'a') ? "inf" : "INF";
+ size = 3;
+ flags &= ~ZEROPAD;
+ break;
+ }
+ flags |= FPT;
+ ndig = dtoaend - cp;
+ 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 */
-/* the Android security team suggests removing support for %n
- * since it has no real practical value, and could lead to
- * running malicious code (for really buggy programs that
- * send to printf() user-generated formatting strings).
- */
-#if 0
case 'n':
if (flags & LLONGINT)
*GETARG(long long *) = ret;
@@ -610,7 +820,6 @@
else
*GETARG(int *) = ret;
continue; /* no output */
-#endif
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
@@ -629,11 +838,30 @@
/* NOSTRICT */
_umax = (u_long)GETARG(void *);
base = HEX;
- xdigs = "0123456789abcdef";
- flags |= HEXPREFIX;
- ch = 'x';
+ xdigs = xdigs_lower;
+ ox[1] = 'x';
goto nosign;
case 's':
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT) {
+ wchar_t *wcp;
+
+ if (convbuf != NULL) {
+ free(convbuf);
+ convbuf = NULL;
+ }
+ if ((wcp = GETARG(wchar_t *)) == NULL) {
+ cp = "(null)";
+ } else {
+ convbuf = __wcsconv(wcp, prec);
+ if (convbuf == NULL) {
+ fp->_flags = __SERR;
+ goto error;
+ }
+ cp = convbuf;
+ }
+ } else
+#endif /* PRINTF_WIDE_CHAR */
if ((cp = GETARG(char *)) == NULL)
cp = "(null)";
if (prec >= 0) {
@@ -644,15 +872,13 @@
*/
char *p = memchr(cp, 0, prec);
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else {
- size = prec;
- }
+ size = p ? (p - cp) : prec;
} else {
- size = strlen(cp);
+ size_t len;
+
+ if ((len = strlen(cp)) > INT_MAX)
+ goto overflow;
+ size = (int)len;
}
sign = '\0';
break;
@@ -664,15 +890,15 @@
base = DEC;
goto nosign;
case 'X':
- xdigs = "0123456789ABCDEF";
+ xdigs = xdigs_upper;
goto hex;
case 'x':
- xdigs = "0123456789abcdef";
+ xdigs = xdigs_lower;
hex: _umax = UARG();
base = HEX;
/* leading 0x/X only if non-zero */
if (flags & ALT && _umax != 0)
- flags |= HEXPREFIX;
+ ox[1] = ch;
/* unsigned conversions */
nosign: sign = '\0';
@@ -730,6 +956,8 @@
}
}
size = buf + BUF - cp;
+ if (size > BUF) /* should never happen */
+ abort();
skipsize:
break;
default: /* "%?" prints ?, unless ? is NUL */
@@ -750,7 +978,7 @@
* 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
+ * 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.
*
@@ -760,7 +988,7 @@
realsz = dprec > size ? dprec : size;
if (sign)
realsz++;
- else if (flags & HEXPREFIX)
+ if (ox[1])
realsz+= 2;
/* right-adjusting blank padding */
@@ -768,11 +996,10 @@
PAD(width - realsz, blanks);
/* prefix */
- if (sign) {
+ if (sign)
PRINT(&sign, 1);
- } else if (flags & HEXPREFIX) {
+ if (ox[1]) { /* ox[1] is either x, X, or \0 */
ox[0] = '0';
- ox[1] = ch;
PRINT(ox, 2);
}
@@ -788,41 +1015,30 @@
if ((flags & FPT) == 0) {
PRINT(cp, size);
} else { /* glue together f_p fragments */
- if (ch >= 'f') { /* 'f' or 'g' */
- if (_double == 0) {
- /* kludge for __dtoa irregularity */
- PRINT("0", 1);
- if (expt < ndig || (flags & ALT) != 0) {
+ 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(ndig - 1, zeroes);
- }
- } else if (expt <= 0) {
- PRINT("0", 1);
- PRINT(decimal_point, 1);
PAD(-expt, zeroes);
- PRINT(cp, ndig);
- } else if (expt >= ndig) {
- PRINT(cp, ndig);
- PAD(expt - ndig, zeroes);
- if (flags & ALT)
- PRINT(".", 1);
- } else {
- PRINT(cp, expt);
- cp += expt;
- PRINT(".", 1);
- PRINT(cp, ndig-expt);
+ /* already handled initial 0's */
+ prec += expt;
+ } else {
+ PRINTANDPAD(cp, dtoaend, lead, zeroes);
+ cp += lead;
+ if (prec || flags & ALT)
+ PRINT(decimal_point, 1);
}
- } else { /* 'e' or 'E' */
- if (ndig > 1 || flags & ALT) {
- ox[0] = *cp++;
- ox[1] = '.';
- PRINT(ox, 2);
- if (_double) {
- PRINT(cp, ndig-1);
- } else {/* 0.[0..] */
- /* __dtoa irregularity */
- PAD(ndig - 1, zeroes);
- }
+ PRINTANDPAD(cp, dtoaend, 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);
}
@@ -837,25 +1053,40 @@
PAD(width - realsz, blanks);
/* finally, adjust ret */
- ret += width > realsz ? width : realsz;
+ if (width < realsz)
+ width = realsz;
+ if (width > INT_MAX - ret)
+ goto overflow;
+ ret += width;
FLUSH(); /* copy out the I/O vectors */
}
done:
FLUSH();
error:
+ va_end(orgap);
+ if (__sferror(fp))
+ ret = -1;
+ goto finish;
+
+overflow:
+ errno = ENOMEM;
+ ret = -1;
+
+finish:
+#ifdef PRINTF_WIDE_CHAR
+ if (convbuf)
+ free(convbuf);
+#endif
#ifdef FLOATING_POINT
- if (dtoaresult != NULL) {
- freedtoa(dtoaresult);
- }
+ if (dtoaresult)
+ __freedtoa(dtoaresult);
#endif
if (argtable != NULL && argtable != statargtable) {
munmap(argtable, argtablesiz);
argtable = NULL;
}
- va_end(orgap);
- return (__sferror(fp) ? EOF : ret);
- /* NOTREACHED */
+ return (ret);
}
/*
@@ -886,6 +1117,10 @@
#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
@@ -909,8 +1144,9 @@
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 */
wchar_t wc;
- void* ps;
+ mbstate_t ps;
/*
* Add an argument type to the table, expanding if necessary.
@@ -927,7 +1163,8 @@
((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
((flags&LONGINT) ? ADDTYPE(T_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))))))
+ ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
+ ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
#define ADDUARG() \
((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
@@ -935,7 +1172,8 @@
((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))))))
+ ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
+ ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
/*
* Add * arguments to the type array.
@@ -944,7 +1182,7 @@
n2 = 0; \
cp = fmt; \
while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
+ APPEND_DIGIT(n2, *cp); \
cp++; \
} \
if (*cp == '$') { \
@@ -969,16 +1207,6 @@
*/
for (;;) {
cp = fmt;
-#if 1 /* BIONIC */
- n = -1;
- while ((wc = *fmt) != 0) {
- if (wc == '%') {
- n = 1;
- break;
- }
- fmt++;
- }
-#else
while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
fmt += n;
if (wc == '%') {
@@ -986,7 +1214,6 @@
break;
}
}
-#endif
if (n <= 0)
goto done;
fmt++; /* skip over '%' */
@@ -997,6 +1224,7 @@
reswitch: switch (ch) {
case ' ':
case '#':
+ case '\'':
goto rflag;
case '*':
ADDASTER();
@@ -1019,7 +1247,7 @@
case '5': case '6': case '7': case '8': case '9':
n = 0;
do {
- n = 10 * n + to_digit(ch);
+ APPEND_DIGIT(n ,ch);
ch = *fmt++;
} while (is_digit(ch));
if (ch == '$') {
@@ -1040,6 +1268,9 @@
flags |= SHORTINT;
}
goto rflag;
+ case 'j':
+ flags |= MAXINT;
+ goto rflag;
case 'l':
if (*fmt == 'l') {
fmt++;
@@ -1058,7 +1289,12 @@
flags |= SIZEINT;
goto rflag;
case 'c':
- ADDTYPE(T_INT);
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT)
+ ADDTYPE(T_WINT);
+ else
+#endif
+ ADDTYPE(T_INT);
break;
case 'D':
flags |= LONGINT;
@@ -1068,9 +1304,12 @@
ADDSARG();
break;
#ifdef FLOATING_POINT
+ case 'a':
+ case 'A':
case 'e':
case 'E':
case 'f':
+ case 'F':
case 'g':
case 'G':
if (flags & LONGDBL)
@@ -1105,7 +1344,12 @@
ADDTYPE(TP_VOID);
break;
case 's':
- ADDTYPE(TP_CHAR);
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT)
+ ADDTYPE(TP_WCHAR);
+ else
+#endif
+ ADDTYPE(TP_CHAR);
break;
case 'U':
flags |= LONGINT;
@@ -1140,20 +1384,16 @@
for (n = 1; n <= tablemax; n++) {
switch (typetable[n]) {
case T_UNUSED:
- (*argtable)[n].intarg = va_arg(ap, int);
- break;
+ case T_CHAR:
+ case T_U_CHAR:
case T_SHORT:
- (*argtable)[n].intarg = va_arg(ap, int);
- break;
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_INT:
- (*argtable)[n].intarg = va_arg(ap, int);
- break;
case T_U_INT:
(*argtable)[n].uintarg = va_arg(ap, unsigned int);
break;
@@ -1207,17 +1447,37 @@
case TP_SSIZEINT:
(*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
break;
- case TP_MAXINT:
+ case T_MAXINT:
(*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
break;
+ case T_MAXUINT:
+ (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
+ break;
+ case TP_MAXINT:
+ (*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);
+ break;
+#ifdef PRINTF_WIDE_CHAR
+ case T_WINT:
+ (*argtable)[n].wintarg = va_arg(ap, wint_t);
+ break;
+ case TP_WCHAR:
+ (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
+ break;
+#endif
}
}
+ goto finish;
+overflow:
+ errno = ENOMEM;
+ ret = -1;
+
+finish:
if (typetable != NULL && typetable != stattypetable) {
munmap(typetable, *argtablesiz);
typetable = NULL;
}
- return (0);
+ return (ret);
}
/*
@@ -1229,12 +1489,15 @@
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);
- memcpy( *typetable, oldtable, *tablesize);
+ bcopy(oldtable, *typetable, *tablesize);
} else {
unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
MAP_ANON|MAP_PRIVATE, -1, 0);
@@ -1250,58 +1513,13 @@
return (0);
}
-
+
#ifdef FLOATING_POINT
-
-extern char *__dtoa(double, int, int, int *, int *, char **);
-
-static char *
-cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch,
- int *length)
-{
- int mode, dsgn;
- char *digits, *bp, *rve;
-
- if (ch == 'f') {
- mode = 3; /* ndigits after the decimal point */
- } else {
- /* To obtain ndigits after the decimal point for the 'e'
- * and 'E' formats, round to ndigits + 1 significant
- * figures.
- */
- if (ch == 'e' || ch == 'E') {
- ndigits++;
- }
- mode = 2; /* ndigits significant digits */
- }
-
- if (value < 0) {
- value = -value;
- *sign = '-';
- } else
- *sign = '\000';
- digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
- if ((ch != 'g' && ch != 'G') || flags & ALT) {/* Print trailing zeros */
- bp = digits + ndigits;
- if (ch == 'f') {
- if (*digits == '0' && value)
- *decpt = -ndigits + 1;
- bp += *decpt;
- }
- if (value == 0) /* kludge for __dtoa irregularity */
- rve = bp;
- while (rve < bp)
- *rve++ = '0';
- }
- *length = rve - digits;
- return (digits);
-}
-
static int
exponent(char *p0, int exp, int fmtch)
{
char *p, *t;
- char expbuf[MAXEXP];
+ char expbuf[MAXEXPDIG];
p = p0;
*p++ = fmtch;
@@ -1310,19 +1528,25 @@
*p++ = '-';
} else
*p++ = '+';
- t = expbuf + MAXEXP;
+ t = expbuf + MAXEXPDIG;
if (exp > 9) {
do {
*--t = to_char(exp % 10);
} while ((exp /= 10) > 9);
*--t = to_char(exp);
- for (; t < expbuf + MAXEXP; *p++ = *t++)
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
/* nothing */;
} else {
- *p++ = '0';
+ /*
+ * 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/stdlib/getenv.c b/libc/upstream-openbsd/lib/libc/stdlib/getenv.c
similarity index 83%
rename from libc/stdlib/getenv.c
rename to libc/upstream-openbsd/lib/libc/stdlib/getenv.c
index 72367b3..fd8482e 100644
--- a/libc/stdlib/getenv.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/getenv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getenv.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
+/* $OpenBSD: getenv.c,v 1.10 2010/08/23 22:31:50 millert Exp $ */
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,31 +31,29 @@
#include <stdlib.h>
#include <string.h>
-char *__findenv(const char *name, int *offset);
+char *__findenv(const char *name, int len, int *offset);
/*
* __findenv --
* Returns pointer to value associated with name, if any, else NULL.
+ * Starts searching within the environmental array at offset.
* Sets offset to be the offset of the name/value combination in the
- * environmental array, for use by setenv(3) and unsetenv(3).
+ * environmental array, for use by putenv(3), setenv(3) and unsetenv(3).
* Explicitly removes '=' in argument name.
*
* This routine *should* be a static; don't use it.
*/
char *
-__findenv(const char *name, int *offset)
+__findenv(const char *name, int len, int *offset)
{
extern char **environ;
- int len, i;
+ int i;
const char *np;
char **p, *cp;
if (name == NULL || environ == NULL)
return (NULL);
- for (np = name; *np && *np != '='; ++np)
- ;
- len = np - name;
- for (p = environ; (cp = *p) != NULL; ++p) {
+ for (p = environ + *offset; (cp = *p) != NULL; ++p) {
for (np = name, i = len; i && *cp; i--)
if (*cp++ != *np++)
break;
@@ -74,7 +72,10 @@
char *
getenv(const char *name)
{
- int offset;
+ int offset = 0;
+ const char *np;
- return (__findenv(name, &offset));
+ for (np = name; *np && *np != '='; ++np)
+ ;
+ return (__findenv(name, (int)(np - name), &offset));
}
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/setenv.c b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
new file mode 100644
index 0000000..9060fdb
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
@@ -0,0 +1,180 @@
+/* $OpenBSD: setenv.c,v 1.14 2012/09/23 16:08:04 jeremy Exp $ */
+/*
+ * Copyright (c) 1987 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *__findenv(const char *name, int len, int *offset);
+
+extern char **environ;
+static char **lastenv; /* last value of environ */
+
+/*
+ * putenv --
+ * Add a name=value string directly to the environmental, replacing
+ * any current value.
+ */
+int
+putenv(char *str)
+{
+ char **P, *cp;
+ size_t cnt;
+ int offset = 0;
+
+ for (cp = str; *cp && *cp != '='; ++cp)
+ ;
+ if (*cp != '=') {
+ errno = EINVAL;
+ return (-1); /* missing `=' in string */
+ }
+
+ if (__findenv(str, (int)(cp - str), &offset) != NULL) {
+ environ[offset++] = str;
+ /* could be set multiple times */
+ while (__findenv(str, (int)(cp - str), &offset)) {
+ for (P = &environ[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+ }
+ return (0);
+ }
+
+ /* create new slot for string */
+ for (P = environ; *P != NULL; P++)
+ ;
+ cnt = P - environ;
+ P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
+ if (!P)
+ return (-1);
+ if (lastenv != environ)
+ memcpy(P, environ, cnt * sizeof(char *));
+ lastenv = environ = P;
+ environ[cnt] = str;
+ environ[cnt + 1] = NULL;
+ return (0);
+}
+
+/*
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ */
+int
+setenv(const char *name, const char *value, int rewrite)
+{
+ char *C, **P;
+ const char *np;
+ int l_value, offset = 0;
+
+ if (!name || !*name) {
+ errno = EINVAL;
+ return (-1);
+ }
+ for (np = name; *np && *np != '='; ++np)
+ ;
+ if (*np) {
+ errno = EINVAL;
+ return (-1); /* has `=' in name */
+ }
+
+ l_value = strlen(value);
+ if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
+ int tmpoff = offset + 1;
+ if (!rewrite)
+ return (0);
+#if 0 /* XXX - existing entry may not be writable */
+ if (strlen(C) >= l_value) { /* old larger; copy over */
+ while ((*C++ = *value++))
+ ;
+ return (0);
+ }
+#endif
+ /* could be set multiple times */
+ while (__findenv(name, (int)(np - name), &tmpoff)) {
+ for (P = &environ[tmpoff];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+ }
+ } else { /* create new slot */
+ size_t cnt;
+
+ for (P = environ; *P != NULL; P++)
+ ;
+ cnt = P - environ;
+ P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
+ if (!P)
+ return (-1);
+ if (lastenv != environ)
+ memcpy(P, environ, cnt * sizeof(char *));
+ lastenv = environ = P;
+ offset = cnt;
+ environ[cnt + 1] = NULL;
+ }
+ if (!(environ[offset] = /* name + `=' + value */
+ malloc((size_t)((int)(np - name) + l_value + 2))))
+ return (-1);
+ for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
+ ;
+ for (*C++ = '='; (*C++ = *value++); )
+ ;
+ return (0);
+}
+
+/*
+ * unsetenv(name) --
+ * Delete environmental variable "name".
+ */
+int
+unsetenv(const char *name)
+{
+ char **P;
+ const char *np;
+ int offset = 0;
+
+ if (!name || !*name) {
+ errno = EINVAL;
+ return (-1);
+ }
+ for (np = name; *np && *np != '='; ++np)
+ ;
+ if (*np) {
+ errno = EINVAL;
+ return (-1); /* has `=' in name */
+ }
+
+ /* could be set multiple times */
+ while (__findenv(name, (int)(np - name), &offset)) {
+ for (P = &environ[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+ }
+ return (0);
+}
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 310db54..dca51b0 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -17,6 +17,7 @@
#include <dlfcn.h>
#include <link.h>
#include <stdlib.h>
+#include <android/dlext.h>
// These are stubs for functions that are actually defined
// in the dynamic linker and hijacked at runtime.
@@ -27,11 +28,13 @@
int dladdr(const void* addr __unused, Dl_info* info __unused) { return 0; }
int dlclose(void* handle __unused) { return 0; }
-void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unused) { }
-void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
-
#if defined(__arm__)
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) { return 0; }
#endif
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused, void* data __unused) { return 0; }
+
+void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unused) { }
+void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
+
+void* android_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
diff --git a/libm/Android.mk b/libm/Android.mk
index 1bd428d..5f69d1e 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -8,6 +8,7 @@
# TODO: this is not in the BSDs.
libm_common_src_files += \
+ significandl.c \
sincos.c \
libm_common_src_files += \
@@ -64,6 +65,7 @@
upstream-freebsd/lib/msun/src/e_sinhf.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \
+ upstream-freebsd/lib/msun/src/imprecise.c \
upstream-freebsd/lib/msun/src/k_cos.c \
upstream-freebsd/lib/msun/src/k_cosf.c \
upstream-freebsd/lib/msun/src/k_exp.c \
@@ -128,8 +130,6 @@
upstream-freebsd/lib/msun/src/s_frexpf.c \
upstream-freebsd/lib/msun/src/s_ilogb.c \
upstream-freebsd/lib/msun/src/s_ilogbf.c \
- upstream-freebsd/lib/msun/src/s_isfinite.c \
- upstream-freebsd/lib/msun/src/s_isnormal.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_llround.c \
@@ -148,7 +148,6 @@
upstream-freebsd/lib/msun/src/s_nearbyint.c \
upstream-freebsd/lib/msun/src/s_nextafter.c \
upstream-freebsd/lib/msun/src/s_nextafterf.c \
- upstream-freebsd/lib/msun/src/s_nexttowardf.c \
upstream-freebsd/lib/msun/src/s_remquo.c \
upstream-freebsd/lib/msun/src/s_remquof.c \
upstream-freebsd/lib/msun/src/s_rint.c \
@@ -158,7 +157,6 @@
upstream-freebsd/lib/msun/src/s_scalbln.c \
upstream-freebsd/lib/msun/src/s_scalbn.c \
upstream-freebsd/lib/msun/src/s_scalbnf.c \
- upstream-freebsd/lib/msun/src/s_signbit.c \
upstream-freebsd/lib/msun/src/s_signgam.c \
upstream-freebsd/lib/msun/src/s_significand.c \
upstream-freebsd/lib/msun/src/s_significandf.c \
@@ -178,6 +176,7 @@
libm_common_src_files += \
fake_long_double.c \
+ signbit.c \
libm_ld_src_files = \
upstream-freebsd/lib/msun/src/e_acosl.c \
@@ -210,6 +209,7 @@
upstream-freebsd/lib/msun/src/s_lroundl.c \
upstream-freebsd/lib/msun/src/s_nextafterl.c \
upstream-freebsd/lib/msun/src/s_nexttoward.c \
+ upstream-freebsd/lib/msun/src/s_nexttowardf.c \
upstream-freebsd/lib/msun/src/s_remquol.c \
upstream-freebsd/lib/msun/src/s_rintl.c \
upstream-freebsd/lib/msun/src/s_roundl.c \
@@ -255,21 +255,20 @@
LOCAL_C_INCLUDES_arm := $(LOCAL_PATH)/arm
LOCAL_SRC_FILES_arm := arm/fenv.c
-LOCAL_C_INCLUDES_arm64 := $(LOCAL_PATH)/arm64 $(libm_ld_includes)
+LOCAL_C_INCLUDES_arm64 := $(libm_ld_includes)
LOCAL_SRC_FILES_arm64 := arm64/fenv.c $(libm_ld_src_files)
-LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i386 $(LOCAL_PATH)/i387
+LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i387
LOCAL_SRC_FILES_x86 := i387/fenv.c
-LOCAL_C_INCLUDES_x86_64 := $(LOCAL_PATH)/amd64 $(libm_ld_includes)
+LOCAL_C_INCLUDES_x86_64 := $(libm_ld_includes)
LOCAL_SRC_FILES_x86_64 := amd64/fenv.c $(libm_ld_src_files)
LOCAL_CFLAGS_mips := -fno-builtin-rintf -fno-builtin-rint
-LOCAL_C_INCLUDES_mips := $(LOCAL_PATH)/mips
LOCAL_SRC_FILES_mips := mips/fenv.c
LOCAL_CFLAGS_mips64 := -fno-builtin-rintf -fno-builtin-rint
-LOCAL_C_INCLUDES_mips64 := $(LOCAL_PATH)/mips $(libm_ld_includes)
+LOCAL_C_INCLUDES_mips64 := $(libm_ld_includes)
LOCAL_SRC_FILES_mips64 := mips/fenv.c $(libm_ld_src_files)
include $(BUILD_STATIC_LIBRARY)
diff --git a/libm/NOTICE b/libm/NOTICE
index 1229447..5a8e139 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -46,6 +46,31 @@
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
+
+-------------------------------------------------------------------
+
+====================================================
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
+====================================================
+
+Optimized by Bruce D. Evans.
+
+-------------------------------------------------------------------
+
+====================================================
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
Developed at SunPro, a Sun Microsystems, Inc. business.
@@ -78,6 +103,16 @@
-------------------------------------------------------------------
+====================================================
+Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
+
+-------------------------------------------------------------------
+
Copyright (C) 2010 The Android Open Source Project
All rights reserved.
@@ -384,33 +419,6 @@
-------------------------------------------------------------------
-Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
-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, Steven G. Kargl
All rights reserved.
@@ -810,6 +818,32 @@
-------------------------------------------------------------------
+Copyright (c) 2007-2013 Bruce D. Evans
+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 unmodified, 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 ``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) 2008 David Schultz <das@FreeBSD.ORG>
All rights reserved.
@@ -836,6 +870,34 @@
-------------------------------------------------------------------
+Copyright (c) 2009-2013 Steven G. Kargl
+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 unmodified, 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 ``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.
+
+Optimized by Bruce D. Evans.
+
+-------------------------------------------------------------------
+
Copyright (c) 2010 The NetBSD Foundation, Inc.
All rights reserved.
diff --git a/libm/amd64/_fpmath.h b/libm/amd64/_fpmath.h
deleted file mode 100755
index f8d5c85..0000000
--- a/libm/amd64/_fpmath.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * 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.
- *
- * $FreeBSD$
- */
-
-// ANDROID changed
-// Android uses 128 bits long doubles for LP64, so the structure and macros
-// were reworked for the quad precision ieee representation.
-
-union IEEEl2bits {
- long double e;
- struct {
- unsigned long manl :64;
- unsigned long manh :48;
- unsigned int exp :15;
- unsigned int sign :1;
- } bits;
- struct {
- unsigned long manl :64;
- unsigned long manh :48;
- unsigned int expsign :16;
- } xbits;
-};
-
-#define LDBL_NBIT 0
-#define LDBL_IMPLICIT_NBIT
-#define mask_nbit_l(u) ((void)0)
-
-#define LDBL_MANH_SIZE 48
-#define LDBL_MANL_SIZE 64
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)((u).bits.manl >> 32); \
- (a)[2] = (uint32_t)(u).bits.manh; \
- (a)[3] = (uint32_t)((u).bits.manh >> 32); \
-} while(0)
diff --git a/libm/arm/_fpmath.h b/libm/arm/_fpmath.h
deleted file mode 100644
index 4c18945..0000000
--- a/libm/arm/_fpmath.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * 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.
- *
- * $FreeBSD$
- */
-
-#if defined(__VFP_FP__)
-#define _IEEE_WORD_ORDER _BYTE_ORDER
-#else
-#define _IEEE_WORD_ORDER _BIG_ENDIAN
-#endif
-
-union IEEEl2bits {
- long double e;
- struct {
-#if _BYTE_ORDER == _LITTLE_ENDIAN
-#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
- unsigned int manl :32;
-#endif
- unsigned int manh :20;
- unsigned int exp :11;
- unsigned int sign :1;
-#if _IEEE_WORD_ORDER == _BIG_ENDIAN
- unsigned int manl :32;
-#endif
-#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
- unsigned int sign :1;
- unsigned int exp :11;
- unsigned int manh :20;
- unsigned int manl :32;
-#endif
- } bits;
-};
-
-#define LDBL_NBIT 0
-#define LDBL_IMPLICIT_NBIT
-#define mask_nbit_l(u) ((void)0)
-
-#define LDBL_MANH_SIZE 20
-#define LDBL_MANL_SIZE 32
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)(u).bits.manh; \
-} while(0)
diff --git a/libm/arm64/_fpmath.h b/libm/arm64/_fpmath.h
deleted file mode 100644
index 560d53a..0000000
--- a/libm/arm64/_fpmath.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * 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.
- *
- * $FreeBSD: src/lib/libc/aarch64/_fpmath.h $
- */
-
-// ANDROID changed
-// Android uses 128 bits long doubles for LP64, so the structure and the macros
-// were reworked for the quad precision ieee representation.
-
-union IEEEl2bits {
- long double e;
- struct {
- unsigned long manl :64;
- unsigned long manh :48;
- unsigned int exp :15;
- unsigned int sign :1;
- } bits;
- struct {
- unsigned long manl :64;
- unsigned long manh :48;
- unsigned int expsign :16;
- } xbits;
-};
-
-#define LDBL_NBIT 0
-#define LDBL_IMPLICIT_NBIT
-#define mask_nbit_l(u) ((void)0)
-
-#define LDBL_MANH_SIZE 48
-#define LDBL_MANL_SIZE 64
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)((u).bits.manl >> 32); \
- (a)[2] = (uint32_t)(u).bits.manh; \
- (a)[3] = (uint32_t)((u).bits.manh >> 32); \
-} while(0)
diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c
index 611512a..317a115 100644
--- a/libm/fake_long_double.c
+++ b/libm/fake_long_double.c
@@ -17,35 +17,6 @@
#include <float.h>
#include <math.h>
-/*
- * On LP64 sizeof(long double) > sizeof(double) so functions which fall back
- * to their double variants lose precision. Emit a warning whenever something
- * links against such functions.
- * On LP32 sizeof(long double) == sizeof(double) so we don't need to warn.
- */
-#ifdef __LP64__
-#define WARN_IMPRECISE(x) \
- __warn_references(x, # x " has lower than advertised precision");
-#else
-#define WARN_IMPRECISE(x)
-#endif //__LP64__
-
-#define DECLARE_IMPRECISE(f) \
- long double f ## l(long double v) { return f(v); } \
- WARN_IMPRECISE(x)
-
-DECLARE_IMPRECISE(cosh);
-DECLARE_IMPRECISE(erfc);
-DECLARE_IMPRECISE(erf);
-DECLARE_IMPRECISE(lgamma);
-DECLARE_IMPRECISE(sinh);
-DECLARE_IMPRECISE(tanh);
-DECLARE_IMPRECISE(tgamma);
-DECLARE_IMPRECISE(significand);
-
-long double powl(long double a1, long double a2) { return pow(a1, a2); }
-WARN_IMPRECISE(powl)
-
#ifndef __LP64__
/*
* The BSD "long double" functions are broken when sizeof(long double) == sizeof(double).
@@ -53,56 +24,18 @@
* that call the regular "double" function.
*/
-int __isfinitel(long double a1) { return __isfinite(a1); }
-int __isnormall(long double a1) { return __isnormal(a1); }
-int __signbitl(long double a1) { return __signbit(a1); }
-
-long double acoshl(long double a1) { return acosh(a1); }
-long double acosl(long double a1) { return acos(a1); }
-long double asinhl(long double a1) { return asinh(a1); }
-long double asinl(long double a1) { return asin(a1); }
-long double atan2l(long double a1, long double a2) { return atan2(a1, a2); }
-long double atanhl(long double a1) { return atanh(a1); }
-long double atanl(long double a1) { return atan(a1); }
-long double cbrtl(long double a1) { return cbrt(a1); }
-long double ceill(long double a1) { return ceil(a1); }
long double copysignl(long double a1, long double a2) { return copysign(a1, a2); }
-
-long double cosl(long double a1) { return cos(a1); }
-
-long double exp2l(long double a1) { return exp2(a1); }
-long double expl(long double a1) { return exp(a1); }
-long double expm1l(long double a1) { return expm1(a1); }
long double fabsl(long double a1) { return fabs(a1); }
-long double floorl(long double a1) { return floor(a1); }
-long double fmal(long double a1, long double a2, long double a3) { return fma(a1, a2, a3); }
long double fmaxl(long double a1, long double a2) { return fmax(a1, a2); }
long double fmodl(long double a1, long double a2) { return fmod(a1, a2); }
long double fminl(long double a1, long double a2) { return fmin(a1, a2); }
-long double frexpl(long double a1, int* a2) { return frexp(a1, a2); }
-long double hypotl(long double a1, long double a2) { return hypot(a1, a2); }
int ilogbl(long double a1) { return ilogb(a1); }
-long double ldexpl(long double a1, int a2) { return ldexp(a1, a2); }
long long llrintl(long double a1) { return llrint(a1); }
-long double log10l(long double a1) { return log10(a1); }
-long double log1pl(long double a1) { return log1p(a1); }
-long double log2l(long double a1) { return log2(a1); }
-long double logbl(long double a1) { return logb(a1); }
-long double logl(long double a1) { return log(a1); }
long lrintl(long double a1) { return lrint(a1); }
long long llroundl(long double a1) { return llround(a1); }
long lroundl(long double a1) { return lround(a1); }
long double modfl(long double a1, long double* a2) { double i; double f = modf(a1, &i); *a2 = i; return f; }
-long double nanl(const char* a1) { return nan(a1); }
-long double nextafterl(long double a1, long double a2) { return nextafter(a1, a2); }
-long double remainderl(long double a1, long double a2) { return remainder(a1, a2); }
-long double remquol(long double a1, long double a2, int* a3) { return remquo(a1, a2, a3); }
-long double rintl(long double a1) { return rint(a1); }
+float nexttowardf(float a1, long double a2) { return nextafterf(a1, (float) a2); }
long double roundl(long double a1) { return round(a1); }
-long double scalbnl(long double a1, int a2) { return scalbn(a1, a2); }
-long double sinl(long double a1) { return sin(a1); }
-long double sqrtl(long double a1) { return sqrt(a1); }
-long double tanl(long double a1) { return tan(a1); }
-long double truncl(long double a1) { return trunc(a1); }
#endif // __LP64__
diff --git a/libm/fpmath.h b/libm/fpmath.h
index e76771d..80420e5 100644
--- a/libm/fpmath.h
+++ b/libm/fpmath.h
@@ -27,69 +27,69 @@
* $FreeBSD$
*/
+// ANDROID changed:
+// - keep only little endian variants as they're the only one supported.
+// - add long double structures here instead of _fpmath.h.
+// - android uses 128 bits long doubles for LP64, so the structure and macros
+// were reworked for the quad precision ieee representation.
+
#ifndef _FPMATH_
#define _FPMATH_
#include <endian.h>
-#include "_fpmath.h"
-
-#ifndef _IEEE_WORD_ORDER
-#define _IEEE_WORD_ORDER _BYTE_ORDER
-#endif
union IEEEf2bits {
- float f;
- struct {
-#if _BYTE_ORDER == _LITTLE_ENDIAN
- unsigned int man :23;
- unsigned int exp :8;
- unsigned int sign :1;
-#else /* _BIG_ENDIAN */
- unsigned int sign :1;
- unsigned int exp :8;
- unsigned int man :23;
-#endif
- } bits;
+ float f;
+ struct {
+ unsigned int man :23;
+ unsigned int exp :8;
+ unsigned int sign :1;
+ } bits;
};
-#define DBL_MANH_SIZE 20
-#define DBL_MANL_SIZE 32
+#define DBL_MANH_SIZE 20
+#define DBL_MANL_SIZE 32
union IEEEd2bits {
- double d;
- struct {
-#if _BYTE_ORDER == _LITTLE_ENDIAN
-#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
- unsigned int manl :32;
-#endif
- unsigned int manh :20;
- unsigned int exp :11;
- unsigned int sign :1;
-#if _IEEE_WORD_ORDER == _BIG_ENDIAN
- unsigned int manl :32;
-#endif
-#else /* _BIG_ENDIAN */
- unsigned int sign :1;
- unsigned int exp :11;
- unsigned int manh :20;
- unsigned int manl :32;
-#endif
- } bits;
+ double d;
+ struct {
+ unsigned int manl :32;
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+ } bits;
};
-/*
- * The BSD "long double" functions are broken when sizeof(long double) == sizeof(double).
- * Android works around those cases by replacing the broken functions with our own trivial stubs
- * that call the regular "double" function.
- */
-#ifndef __LP64__
+#ifdef __LP64__
-#define __fpclassifyl __broken__fpclassify
-#define __isfinitel __broken__isfinitel
-#define __isinfl __broken__isinfl
-#define __isnanl __broken__isnanl
-#define __isnormall __broken__isnormall
-#define __signbitl __broken_signbitl
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned long manl :64;
+ unsigned long manh :48;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ } bits;
+ struct {
+ unsigned long manl :64;
+ unsigned long manh :48;
+ unsigned int expsign :16;
+ } xbits;
+};
+
+#define LDBL_NBIT 0
+#define LDBL_IMPLICIT_NBIT
+#define mask_nbit_l(u) ((void)0)
+
+#define LDBL_MANH_SIZE 48
+#define LDBL_MANL_SIZE 64
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)((u).bits.manl >> 32); \
+ (a)[2] = (uint32_t)(u).bits.manh; \
+ (a)[3] = (uint32_t)((u).bits.manh >> 32); \
+} while(0)
#endif // __LP64__
diff --git a/libm/freebsd-compat.h b/libm/freebsd-compat.h
index c63d407..1481cc2 100644
--- a/libm/freebsd-compat.h
+++ b/libm/freebsd-compat.h
@@ -17,8 +17,11 @@
#ifndef _BIONIC_LIBM_FREEBSD_COMPAT_H_included
#define _BIONIC_LIBM_FREEBSD_COMPAT_H_included
-#define __weak_reference(sym,alias) \
- /* We don't use __weak_reference; see "fake_long_double.c". */
+#include <float.h>
+
+#define __weak_reference(sym,alias) \
+ __asm__(".weak " #alias); \
+ __asm__(".equ " #alias ", " #sym)
#define __strong_reference(sym,aliassym) \
extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)))
diff --git a/libm/i386/_fpmath.h b/libm/i386/_fpmath.h
deleted file mode 100644
index 4f1f5f4..0000000
--- a/libm/i386/_fpmath.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * 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.
- *
- * $FreeBSD$
- */
-
-union IEEEl2bits {
- long double e;
- struct {
- unsigned int manl :32;
- unsigned int manh :32;
- unsigned int exp :15;
- unsigned int sign :1;
- unsigned int junk :16;
- } bits;
- struct {
- unsigned long long man :64;
- unsigned int expsign :16;
- unsigned int junk :16;
- } xbits;
-};
-
-#define LDBL_NBIT 0x80000000
-#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
-
-#define LDBL_MANH_SIZE 32
-#define LDBL_MANL_SIZE 32
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)(u).bits.manh; \
-} while (0)
diff --git a/libm/mips/_fpmath.h b/libm/mips/_fpmath.h
deleted file mode 100644
index f759639..0000000
--- a/libm/mips/_fpmath.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * 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.
- *
- * $FreeBSD$
- */
-
-union IEEEl2bits {
- long double e;
- struct {
-#ifndef __MIPSEB__
-#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32)
- unsigned long manl :64;
- unsigned long manh :48;
- unsigned int exp :15;
- unsigned int sign :1;
-#else
- unsigned int manl :32;
- unsigned int manh :20;
- unsigned int exp :11;
- unsigned int sign :1;
-#endif
-#else
-#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32)
- unsigned int sign :1;
- unsigned int exp :15;
- unsigned long manh :48;
- unsigned long manl :64;
-#else
- unsigned int sign :1;
- unsigned int exp :11;
- unsigned int manh :20;
- unsigned int manl :32;
-#endif
-#endif
- } bits;
-
-};
-
-#define LDBL_NBIT 0
-#define mask_nbit_l(u) ((void)0)
-#define LDBL_IMPLICIT_NBIT
-
-#if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32)
-#define LDBL_MANH_SIZE 48
-#define LDBL_MANL_SIZE 64
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)((u).bits.manl >> 32); \
- (a)[2] = (uint32_t)(u).bits.manh; \
- (a)[3] = (uint32_t)((u).bits.manh >> 32); \
-} while(0)
-#else
-#define LDBL_MANH_SIZE 20
-#define LDBL_MANL_SIZE 32
-
-#define LDBL_TO_ARRAY32(u, a) do { \
- (a)[0] = (uint32_t)(u).bits.manl; \
- (a)[1] = (uint32_t)(u).bits.manh; \
-} while(0)
-#endif
diff --git a/libm/upstream-freebsd/lib/msun/src/s_signbit.c b/libm/signbit.c
similarity index 80%
rename from libm/upstream-freebsd/lib/msun/src/s_signbit.c
rename to libm/signbit.c
index 01eb3ab..b98bf45 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_signbit.c
+++ b/libm/signbit.c
@@ -30,29 +30,30 @@
#include "fpmath.h"
-int
-__signbit(double d)
+int __signbit(double d)
{
- union IEEEd2bits u;
+ union IEEEd2bits u;
- u.d = d;
- return (u.bits.sign);
+ u.d = d;
+ return (u.bits.sign);
}
-int
-__signbitf(float f)
+int __signbitf(float f)
{
- union IEEEf2bits u;
+ union IEEEf2bits u;
- u.f = f;
- return (u.bits.sign);
+ u.f = f;
+ return (u.bits.sign);
}
-int
-__signbitl(long double e)
+#ifdef __LP64__
+int __signbitl(long double e)
{
- union IEEEl2bits u;
+ union IEEEl2bits u;
- u.e = e;
- return (u.bits.sign);
+ u.e = e;
+ return (u.bits.sign);
}
+#else // __LP32__
+__weak_reference(__signbit, __signbitl);
+#endif // __LP64__
diff --git a/libm/upstream-freebsd/lib/msun/src/s_signbit.c b/libm/significandl.c
similarity index 78%
copy from libm/upstream-freebsd/lib/msun/src/s_signbit.c
copy to libm/significandl.c
index 01eb3ab..c5d7dd4 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_signbit.c
+++ b/libm/significandl.c
@@ -1,5 +1,5 @@
-/*-
- * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+/*
+ * Copyright (C) 2014 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,36 +23,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
*/
#include <math.h>
-#include "fpmath.h"
-
-int
-__signbit(double d)
-{
- union IEEEd2bits u;
-
- u.d = d;
- return (u.bits.sign);
-}
-
-int
-__signbitf(float f)
-{
- union IEEEf2bits u;
-
- u.f = f;
- return (u.bits.sign);
-}
-
-int
-__signbitl(long double e)
-{
- union IEEEl2bits u;
-
- u.e = e;
- return (u.bits.sign);
+long double significandl(long double x) {
+ return scalbnl(x, -ilogbl(x));
}
diff --git a/libm/upstream-freebsd/lib/msun/src/imprecise.c b/libm/upstream-freebsd/lib/msun/src/imprecise.c
new file mode 100644
index 0000000..a7503bf
--- /dev/null
+++ b/libm/upstream-freebsd/lib/msun/src/imprecise.c
@@ -0,0 +1,69 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <float.h>
+#include <math.h>
+
+/*
+ * If long double is not the same size as double, then these will lose
+ * precision and we should emit a warning whenever something links against
+ * them.
+ */
+#if (LDBL_MANT_DIG > 53)
+#define WARN_IMPRECISE(x) \
+ __warn_references(x, # x " has lower than advertised precision");
+#else
+#define WARN_IMPRECISE(x)
+#endif
+/*
+ * Declare the functions as weak variants so that other libraries providing
+ * real versions can override them.
+ */
+#define DECLARE_WEAK(x)\
+ __weak_reference(imprecise_## x, x);\
+ WARN_IMPRECISE(x)
+
+long double
+imprecise_powl(long double x, long double y)
+{
+
+ return pow(x, y);
+}
+DECLARE_WEAK(powl);
+
+#define DECLARE_IMPRECISE(f) \
+ long double imprecise_ ## f ## l(long double v) { return f(v); }\
+ DECLARE_WEAK(f ## l)
+
+DECLARE_IMPRECISE(cosh);
+DECLARE_IMPRECISE(erfc);
+DECLARE_IMPRECISE(erf);
+DECLARE_IMPRECISE(lgamma);
+DECLARE_IMPRECISE(sinh);
+DECLARE_IMPRECISE(tanh);
+DECLARE_IMPRECISE(tgamma);
diff --git a/libm/upstream-freebsd/lib/msun/src/s_isfinite.c b/libm/upstream-freebsd/lib/msun/src/s_isfinite.c
deleted file mode 100644
index c9d1bd7..0000000
--- a/libm/upstream-freebsd/lib/msun/src/s_isfinite.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * Copyright (c) 2004 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.
- *
- * $FreeBSD$
- */
-
-#include <math.h>
-
-#include "fpmath.h"
-
-int
-__isfinite(double d)
-{
- union IEEEd2bits u;
-
- u.d = d;
- return (u.bits.exp != 2047);
-}
-
-int
-__isfinitef(float f)
-{
- union IEEEf2bits u;
-
- u.f = f;
- return (u.bits.exp != 255);
-}
-
-int
-__isfinitel(long double e)
-{
- union IEEEl2bits u;
-
- u.e = e;
- return (u.bits.exp != 32767);
-}
diff --git a/libm/upstream-freebsd/lib/msun/src/s_isnormal.c b/libm/upstream-freebsd/lib/msun/src/s_isnormal.c
deleted file mode 100644
index 49f2a74..0000000
--- a/libm/upstream-freebsd/lib/msun/src/s_isnormal.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * Copyright (c) 2004 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.
- *
- * $FreeBSD$
- */
-
-#include <math.h>
-
-#include "fpmath.h"
-
-int
-__isnormal(double d)
-{
- union IEEEd2bits u;
-
- u.d = d;
- return (u.bits.exp != 0 && u.bits.exp != 2047);
-}
-
-int
-__isnormalf(float f)
-{
- union IEEEf2bits u;
-
- u.f = f;
- return (u.bits.exp != 0 && u.bits.exp != 255);
-}
-
-int
-__isnormall(long double e)
-{
- union IEEEl2bits u;
-
- u.e = e;
- return (u.bits.exp != 0 && u.bits.exp != 32767);
-}
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index aee9aa9..a44380c 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -29,6 +29,7 @@
#include "linker.h"
#include <errno.h>
+#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,12 +48,12 @@
#endif
enum debugger_action_t {
- // dump a crash
- DEBUGGER_ACTION_CRASH,
- // dump a tombstone file
- DEBUGGER_ACTION_DUMP_TOMBSTONE,
- // dump a backtrace only back to the socket
- DEBUGGER_ACTION_DUMP_BACKTRACE,
+ // dump a crash
+ DEBUGGER_ACTION_CRASH,
+ // dump a tombstone file
+ DEBUGGER_ACTION_DUMP_TOMBSTONE,
+ // dump a backtrace only back to the socket
+ DEBUGGER_ACTION_DUMP_BACKTRACE,
};
/* message sent over the socket */
@@ -69,40 +70,39 @@
#define MAX_TASK_NAME_LEN (16)
static int socket_abstract_client(const char* name, int type) {
- sockaddr_un addr;
+ sockaddr_un addr;
- // Test with length +1 for the *initial* '\0'.
- size_t namelen = strlen(name);
- if ((namelen + 1) > sizeof(addr.sun_path)) {
- errno = EINVAL;
- return -1;
- }
+ // Test with length +1 for the *initial* '\0'.
+ size_t namelen = strlen(name);
+ if ((namelen + 1) > sizeof(addr.sun_path)) {
+ errno = EINVAL;
+ return -1;
+ }
- /* This is used for abstract socket namespace, we need
- * an initial '\0' at the start of the Unix socket path.
- *
- * Note: The path in this case is *not* supposed to be
- * '\0'-terminated. ("man 7 unix" for the gory details.)
- */
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_LOCAL;
- addr.sun_path[0] = 0;
- memcpy(addr.sun_path + 1, name, namelen);
+ // This is used for abstract socket namespace, we need
+ // an initial '\0' at the start of the Unix socket path.
+ //
+ // Note: The path in this case is *not* supposed to be
+ // '\0'-terminated. ("man 7 unix" for the gory details.)
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ addr.sun_path[0] = 0;
+ memcpy(addr.sun_path + 1, name, namelen);
- socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
+ socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
- int s = socket(AF_LOCAL, type, 0);
- if (s == -1) {
- return -1;
- }
+ int s = socket(AF_LOCAL, type, 0);
+ if (s == -1) {
+ return -1;
+ }
- int rc = TEMP_FAILURE_RETRY(connect(s, reinterpret_cast<sockaddr*>(&addr), alen));
- if (rc == -1) {
- close(s);
- return -1;
- }
+ int rc = TEMP_FAILURE_RETRY(connect(s, reinterpret_cast<sockaddr*>(&addr), alen));
+ if (rc == -1) {
+ close(s);
+ return -1;
+ }
- return s;
+ return s;
}
/*
@@ -115,65 +115,88 @@
* could allocate memory or hold a lock.
*/
static void log_signal_summary(int signum, const siginfo_t* info) {
- const char* signal_name;
- switch (signum) {
- case SIGILL: signal_name = "SIGILL"; break;
- case SIGABRT: signal_name = "SIGABRT"; break;
- case SIGBUS: signal_name = "SIGBUS"; break;
- case SIGFPE: signal_name = "SIGFPE"; break;
- case SIGSEGV: signal_name = "SIGSEGV"; break;
+ const char* signal_name = "???";
+ bool has_address = false;
+ switch (signum) {
+ case SIGILL:
+ signal_name = "SIGILL";
+ has_address = true;
+ break;
+ case SIGABRT:
+ signal_name = "SIGABRT";
+ break;
+ case SIGBUS:
+ signal_name = "SIGBUS";
+ has_address = true;
+ break;
+ case SIGFPE:
+ signal_name = "SIGFPE";
+ has_address = true;
+ break;
+ case SIGSEGV:
+ signal_name = "SIGSEGV";
+ has_address = true;
+ break;
#if defined(SIGSTKFLT)
- case SIGSTKFLT: signal_name = "SIGSTKFLT"; break;
+ case SIGSTKFLT:
+ signal_name = "SIGSTKFLT";
+ break;
#endif
- case SIGPIPE: signal_name = "SIGPIPE"; break;
- default: signal_name = "???"; break;
- }
+ case SIGPIPE:
+ signal_name = "SIGPIPE";
+ break;
+ }
- char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
- if (prctl(PR_GET_NAME, (unsigned long)thread_name, 0, 0, 0) != 0) {
- strcpy(thread_name, "<name unknown>");
- } else {
- // short names are null terminated by prctl, but the man page
- // implies that 16 byte names are not.
- thread_name[MAX_TASK_NAME_LEN] = 0;
- }
+ char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
+ if (prctl(PR_GET_NAME, (unsigned long)thread_name, 0, 0, 0) != 0) {
+ strcpy(thread_name, "<name unknown>");
+ } else {
+ // short names are null terminated by prctl, but the man page
+ // implies that 16 byte names are not.
+ thread_name[MAX_TASK_NAME_LEN] = 0;
+ }
- // "info" will be NULL if the siginfo_t information was not available.
- if (info != NULL) {
- __libc_format_log(ANDROID_LOG_FATAL, "libc",
- "Fatal signal %d (%s) at %p (code=%d), thread %d (%s)",
- signum, signal_name, info->si_addr, info->si_code,
- gettid(), thread_name);
- } else {
- __libc_format_log(ANDROID_LOG_FATAL, "libc",
- "Fatal signal %d (%s), thread %d (%s)",
- signum, signal_name, gettid(), thread_name);
+ // "info" will be NULL if the siginfo_t information was not available.
+ // Many signals don't have an address or a code.
+ char code_desc[32]; // ", code -6"
+ char addr_desc[32]; // ", fault addr 0x1234"
+ addr_desc[0] = code_desc[0] = 0;
+ if (info != NULL) {
+ // For a rethrown signal, this si_code will be right and the one debuggerd shows will
+ // always be SI_TKILL.
+ snprintf(code_desc, sizeof(code_desc), ", code %d", info->si_code);
+ if (has_address) {
+ snprintf(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
}
+ }
+ __libc_format_log(ANDROID_LOG_FATAL, "libc",
+ "Fatal signal %d (%s)%s%s in tid %d (%s)",
+ signum, signal_name, code_desc, addr_desc, gettid(), thread_name);
}
/*
* Returns true if the handler for signal "signum" has SA_SIGINFO set.
*/
static bool have_siginfo(int signum) {
- struct sigaction old_action, new_action;
+ struct sigaction old_action, new_action;
- memset(&new_action, 0, sizeof(new_action));
- new_action.sa_handler = SIG_DFL;
- new_action.sa_flags = SA_RESTART;
- sigemptyset(&new_action.sa_mask);
+ memset(&new_action, 0, sizeof(new_action));
+ new_action.sa_handler = SIG_DFL;
+ new_action.sa_flags = SA_RESTART;
+ sigemptyset(&new_action.sa_mask);
- if (sigaction(signum, &new_action, &old_action) < 0) {
- __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
- strerror(errno));
- return false;
- }
- bool result = (old_action.sa_flags & SA_SIGINFO) != 0;
+ if (sigaction(signum, &new_action, &old_action) < 0) {
+ __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
+ strerror(errno));
+ return false;
+ }
+ bool result = (old_action.sa_flags & SA_SIGINFO) != 0;
- if (sigaction(signum, &old_action, NULL) == -1) {
- __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
- strerror(errno));
- }
- return result;
+ if (sigaction(signum, &old_action, NULL) == -1) {
+ __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
+ strerror(errno));
+ }
+ return result;
}
/*
@@ -181,87 +204,87 @@
* we crash.
*/
void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
- // It's possible somebody cleared the SA_SIGINFO flag, which would mean
- // our "info" arg holds an undefined value.
- if (!have_siginfo(signal_number)) {
- info = NULL;
+ // It's possible somebody cleared the SA_SIGINFO flag, which would mean
+ // our "info" arg holds an undefined value.
+ if (!have_siginfo(signal_number)) {
+ info = NULL;
+ }
+
+ log_signal_summary(signal_number, info);
+
+ int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
+ if (s != -1) {
+ // debuggerd knows our pid from the credentials on the
+ // local socket but we need to tell it the tid of the crashing thread.
+ // debuggerd will be paranoid and verify that we sent a tid
+ // that's actually in our process.
+ debugger_msg_t msg;
+ msg.action = DEBUGGER_ACTION_CRASH;
+ msg.tid = gettid();
+ msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
+ int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
+ if (ret == sizeof(msg)) {
+ // If the write failed, there is no point trying to read a response.
+ char debuggerd_ack;
+ ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
+ int saved_errno = errno;
+ notify_gdb_of_libraries();
+ errno = saved_errno;
}
- log_signal_summary(signal_number, info);
-
- int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
- if (s != -1) {
- // debuggerd knows our pid from the credentials on the
- // local socket but we need to tell it the tid of the crashing thread.
- // debuggerd will be paranoid and verify that we sent a tid
- // that's actually in our process.
- debugger_msg_t msg;
- msg.action = DEBUGGER_ACTION_CRASH;
- msg.tid = gettid();
- msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
- int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
- if (ret == sizeof(msg)) {
- // If the write failed, there is no point trying to read a response.
- char debuggerd_ack;
- ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
- int saved_errno = errno;
- notify_gdb_of_libraries();
- errno = saved_errno;
- }
-
- if (ret < 0) {
- // read or write failed -- broken connection?
- __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
- strerror(errno));
- }
-
- close(s);
- } else {
- // socket failed; maybe process ran out of fds?
- __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
- strerror(errno));
+ if (ret < 0) {
+ // read or write failed -- broken connection?
+ __libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
+ strerror(errno));
}
- // Remove our net so we fault for real when we return.
- signal(signal_number, SIG_DFL);
+ close(s);
+ } else {
+ // socket failed; maybe process ran out of fds?
+ __libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
+ strerror(errno));
+ }
- // These signals are not re-thrown when we resume. This means that
- // crashing due to (say) SIGPIPE doesn't work the way you'd expect it
- // to. We work around this by throwing them manually. We don't want
- // to do this for *all* signals because it'll screw up the address for
- // faults like SIGSEGV.
- switch (signal_number) {
- case SIGABRT:
- case SIGFPE:
- case SIGPIPE:
+ // Remove our net so we fault for real when we return.
+ signal(signal_number, SIG_DFL);
+
+ // These signals are not re-thrown when we resume. This means that
+ // crashing due to (say) SIGPIPE doesn't work the way you'd expect it
+ // to. We work around this by throwing them manually. We don't want
+ // to do this for *all* signals because it'll screw up the address for
+ // faults like SIGSEGV.
+ switch (signal_number) {
+ case SIGABRT:
+ case SIGFPE:
+ case SIGPIPE:
#if defined(SIGSTKFLT)
- case SIGSTKFLT:
+ case SIGSTKFLT:
#endif
- tgkill(getpid(), gettid(), signal_number);
- break;
- default: // SIGILL, SIGBUS, SIGSEGV
- break;
- }
+ tgkill(getpid(), gettid(), signal_number);
+ break;
+ default: // SIGILL, SIGBUS, SIGSEGV
+ break;
+ }
}
void debuggerd_init() {
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_sigaction = debuggerd_signal_handler;
- action.sa_flags = SA_RESTART | SA_SIGINFO;
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ action.sa_sigaction = debuggerd_signal_handler;
+ action.sa_flags = SA_RESTART | SA_SIGINFO;
- // Use the alternate signal stack if available so we can catch stack overflows.
- action.sa_flags |= SA_ONSTACK;
+ // Use the alternate signal stack if available so we can catch stack overflows.
+ action.sa_flags |= SA_ONSTACK;
- sigaction(SIGABRT, &action, NULL);
- sigaction(SIGBUS, &action, NULL);
- sigaction(SIGFPE, &action, NULL);
- sigaction(SIGILL, &action, NULL);
- sigaction(SIGPIPE, &action, NULL);
- sigaction(SIGSEGV, &action, NULL);
+ sigaction(SIGABRT, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
+ sigaction(SIGFPE, &action, NULL);
+ sigaction(SIGILL, &action, NULL);
+ sigaction(SIGPIPE, &action, NULL);
+ sigaction(SIGSEGV, &action, NULL);
#if defined(SIGSTKFLT)
- sigaction(SIGSTKFLT, &action, NULL);
+ sigaction(SIGSTKFLT, &action, NULL);
#endif
- sigaction(SIGTRAP, &action, NULL);
+ sigaction(SIGTRAP, &action, NULL);
}
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6e70808..0292bdf 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -20,6 +20,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include <android/dlext.h>
#include <bionic/pthread_internal.h>
#include "private/bionic_tls.h"
@@ -64,9 +65,10 @@
do_android_update_LD_LIBRARY_PATH(ld_library_path);
}
-void* dlopen(const char* filename, int flags) {
+void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo)
+{
ScopedPthreadMutexLocker locker(&gDlMutex);
- soinfo* result = do_dlopen(filename, flags);
+ soinfo* result = do_dlopen(filename, flags, extinfo);
if (result == NULL) {
__bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
return NULL;
@@ -74,6 +76,10 @@
return result;
}
+void* dlopen(const char* filename, int flags) {
+ return android_dlopen_ext(filename, flags, NULL);
+}
+
void* dlsym(void* handle, const char* symbol) {
ScopedPthreadMutexLocker locker(&gDlMutex);
@@ -168,15 +174,15 @@
}
#if defined(__arm__)
- // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1
- // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1
+ // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222 333333333344444444445
+ // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789 012345678901234567890
# define ANDROID_LIBDL_STRTAB \
- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0dl_unwind_find_exidx\0"
+ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0dl_unwind_find_exidx\0"
#elif defined(__aarch64__) || defined(__i386__) || defined(__mips__) || defined(__x86_64__)
- // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1
- // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1
+ // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222
+ // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789
# define ANDROID_LIBDL_STRTAB \
- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0"
+ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0"
#else
# error Unsupported architecture. Only arm, arm64, mips, mips64, x86 and x86_64 are presently supported.
#endif
@@ -195,8 +201,9 @@
ELFW(SYM_INITIALIZER)( 36, &android_update_LD_LIBRARY_PATH, 1),
ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1),
ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1),
+ ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
#if defined(__arm__)
- ELFW(SYM_INITIALIZER)(111, &dl_unwind_find_exidx, 1),
+ ELFW(SYM_INITIALIZER)(130, &dl_unwind_find_exidx, 1),
#endif
};
@@ -213,9 +220,9 @@
// Note that adding any new symbols here requires stubbing them out in libdl.
static unsigned gLibDlBuckets[1] = { 1 };
#if defined(__arm__)
-static unsigned gLibDlChains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+static unsigned gLibDlChains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
#else
-static unsigned gLibDlChains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 0 };
+static unsigned gLibDlChains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
#endif
// This is used by the dynamic linker. Every process gets these symbols for free.
diff --git a/linker/linker.cpp b/linker/linker.cpp
index de7b04d..4d8563e 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -65,7 +65,7 @@
* and NOEXEC
*/
-static bool soinfo_link_image(soinfo* si);
+static bool soinfo_link_image(soinfo* si, const android_dlextinfo* extinfo);
static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
// We can't use malloc(3) in the dynamic linker. We use a linked list of anonymous
@@ -690,7 +690,7 @@
return fd;
}
-static soinfo* load_library(const char* name) {
+static soinfo* load_library(const char* name, const android_dlextinfo* extinfo) {
// Open the file.
int fd = open_library(name);
if (fd == -1) {
@@ -700,7 +700,7 @@
// Read the ELF header and load the segments.
ElfReader elf_reader(name, fd);
- if (!elf_reader.Load()) {
+ if (!elf_reader.Load(extinfo)) {
return NULL;
}
@@ -735,7 +735,7 @@
return NULL;
}
-static soinfo* find_library_internal(const char* name) {
+static soinfo* find_library_internal(const char* name, const android_dlextinfo* extinfo) {
if (name == NULL) {
return somain;
}
@@ -750,7 +750,7 @@
}
TRACE("[ '%s' has not been loaded yet. Locating...]", name);
- si = load_library(name);
+ si = load_library(name, extinfo);
if (si == NULL) {
return NULL;
}
@@ -760,7 +760,7 @@
TRACE("[ find_library_internal base=%p size=%zu name='%s' ]",
reinterpret_cast<void*>(si->base), si->size, si->name);
- if (!soinfo_link_image(si)) {
+ if (!soinfo_link_image(si, extinfo)) {
munmap(reinterpret_cast<void*>(si->base), si->size);
soinfo_free(si);
return NULL;
@@ -769,8 +769,8 @@
return si;
}
-static soinfo* find_library(const char* name) {
- soinfo* si = find_library_internal(name);
+static soinfo* find_library(const char* name, const android_dlextinfo* extinfo) {
+ soinfo* si = find_library_internal(name, extinfo);
if (si != NULL) {
si->ref_count++;
}
@@ -811,13 +811,17 @@
}
}
-soinfo* do_dlopen(const char* name, int flags) {
+soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL)) != 0) {
DL_ERR("invalid flags to dlopen: %x", flags);
return NULL;
}
+ if (extinfo != NULL && ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0)) {
+ DL_ERR("invalid extended flags to android_dlopen_ext: %x", extinfo->flags);
+ return NULL;
+ }
set_soinfo_pool_protection(PROT_READ | PROT_WRITE);
- soinfo* si = find_library(name);
+ soinfo* si = find_library(name, extinfo);
if (si != NULL) {
si->CallConstructors();
}
@@ -1562,7 +1566,7 @@
return return_value;
}
-static bool soinfo_link_image(soinfo* si) {
+static bool soinfo_link_image(soinfo* si, const android_dlextinfo* extinfo) {
/* "base" might wrap around UINT32_MAX. */
ElfW(Addr) base = si->load_bias;
const ElfW(Phdr)* phdr = si->phdr;
@@ -1799,7 +1803,7 @@
memset(gLdPreloads, 0, sizeof(gLdPreloads));
size_t preload_count = 0;
for (size_t i = 0; gLdPreloadNames[i] != NULL; i++) {
- soinfo* lsi = find_library(gLdPreloadNames[i]);
+ soinfo* lsi = find_library(gLdPreloadNames[i], NULL);
if (lsi != NULL) {
gLdPreloads[preload_count++] = lsi;
} else {
@@ -1817,7 +1821,7 @@
if (d->d_tag == DT_NEEDED) {
const char* library_name = si->strtab + d->d_un.d_val;
DEBUG("%s needs %s", si->name, library_name);
- soinfo* lsi = find_library(library_name);
+ soinfo* lsi = find_library(library_name, NULL);
if (lsi == NULL) {
strlcpy(tmp_err_buf, linker_get_error_buffer(), sizeof(tmp_err_buf));
DL_ERR("could not load library \"%s\" needed by \"%s\"; caused by %s",
@@ -1833,8 +1837,10 @@
if (si->has_text_relocations) {
// Make segments writable to allow text relocations to work properly. We will later call
// phdr_table_protect_segments() after all of them are applied and all constructors are run.
+#if !defined(__i386__) // The platform itself has too many text relocations on x86.
DL_WARN("%s has text relocations. This is wasting memory and prevents "
"security hardening. Please fix.", si->name);
+#endif
if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
si->name, strerror(errno));
@@ -1898,6 +1904,23 @@
return false;
}
+ /* Handle serializing/sharing the RELRO segment */
+ if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
+ if (phdr_table_serialize_gnu_relro(si->phdr, si->phnum, si->load_bias,
+ extinfo->relro_fd) < 0) {
+ DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
+ si->name, strerror(errno));
+ return false;
+ }
+ } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
+ if (phdr_table_map_gnu_relro(si->phdr, si->phnum, si->load_bias,
+ extinfo->relro_fd) < 0) {
+ DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
+ si->name, strerror(errno));
+ return false;
+ }
+ }
+
notify_gdb_of_load(si);
return true;
}
@@ -1923,7 +1946,7 @@
si->flags = 0;
si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
- soinfo_link_image(si);
+ soinfo_link_image(si, NULL);
#endif
}
@@ -2051,7 +2074,7 @@
somain = si;
- if (!soinfo_link_image(si)) {
+ if (!soinfo_link_image(si, NULL)) {
__libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
exit(EXIT_FAILURE);
}
@@ -2168,7 +2191,7 @@
linker_so.phnum = elf_hdr->e_phnum;
linker_so.flags |= FLAG_LINKER;
- if (!soinfo_link_image(&linker_so)) {
+ if (!soinfo_link_image(&linker_so, NULL)) {
// It would be nice to print an error message, but if the linker
// can't link itself, there's no guarantee that we'll be able to
// call write() (because it involves a GOT reference). We may as
diff --git a/linker/linker.h b/linker/linker.h
index b8d0587..93ab51d 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -32,6 +32,7 @@
#include <elf.h>
#include <link.h>
#include <unistd.h>
+#include <android/dlext.h>
#include "private/libc_logging.h"
@@ -192,7 +193,7 @@
void do_android_get_LD_LIBRARY_PATH(char*, size_t);
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
-soinfo* do_dlopen(const char* name, int flags);
+soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
int do_dlclose(soinfo* si);
ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 7c5d3f6..cfeab96 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -31,6 +31,9 @@
#include <errno.h>
#include <machine/exec.h>
#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include "linker.h"
#include "linker_debug.h"
@@ -132,11 +135,11 @@
}
}
-bool ElfReader::Load() {
+bool ElfReader::Load(const android_dlextinfo* extinfo) {
return ReadElfHeader() &&
VerifyElfHeader() &&
ReadProgramHeader() &&
- ReserveAddressSpace() &&
+ ReserveAddressSpace(extinfo) &&
LoadSegments() &&
FindPhdr();
}
@@ -291,7 +294,7 @@
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
-bool ElfReader::ReserveAddressSpace() {
+bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
ElfW(Addr) min_vaddr;
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
if (load_size_ == 0) {
@@ -300,11 +303,33 @@
}
uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
- int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
- void* start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
- if (start == MAP_FAILED) {
- DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
- return false;
+ void* start;
+ size_t reserved_size = 0;
+ bool reserved_hint = true;
+
+ if (extinfo != NULL) {
+ if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
+ reserved_size = extinfo->reserved_size;
+ reserved_hint = false;
+ } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
+ reserved_size = extinfo->reserved_size;
+ }
+ }
+
+ if (load_size_ > reserved_size) {
+ if (!reserved_hint) {
+ DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
+ reserved_size - load_size_, load_size_, name_);
+ return false;
+ }
+ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
+ if (start == MAP_FAILED) {
+ DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
+ return false;
+ }
+ } else {
+ start = extinfo->reserved_addr;
}
load_start_ = start;
@@ -501,6 +526,129 @@
return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
}
+/* Serialize the GNU relro segments to the given file descriptor. This can be
+ * performed after relocations to allow another process to later share the
+ * relocated segment, if it was loaded at the same address.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * fd -> writable file descriptor to use
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
+ int fd) {
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+ ssize_t file_offset = 0;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO) {
+ continue;
+ }
+
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+ ssize_t size = seg_page_end - seg_page_start;
+
+ ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size));
+ if (written != size) {
+ return -1;
+ }
+ void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
+ MAP_PRIVATE|MAP_FIXED, fd, file_offset);
+ if (map == MAP_FAILED) {
+ return -1;
+ }
+ file_offset += size;
+ }
+ return 0;
+}
+
+/* Where possible, replace the GNU relro segments with mappings of the given
+ * file descriptor. This can be performed after relocations to allow a file
+ * previously created by phdr_table_serialize_gnu_relro in another process to
+ * replace the dirty relocated pages, saving memory, if it was loaded at the
+ * same address. We have to compare the data before we map over it, since some
+ * parts of the relro segment may not be identical due to other libraries in
+ * the process being loaded at different addresses.
+ *
+ * Input:
+ * phdr_table -> program header table
+ * phdr_count -> number of entries in tables
+ * load_bias -> load bias
+ * fd -> readable file descriptor to use
+ * Return:
+ * 0 on error, -1 on failure (error code in errno).
+ */
+int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
+ int fd) {
+ // Map the file at a temporary location so we can compare its contents.
+ struct stat file_stat;
+ if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
+ return -1;
+ }
+ off_t file_size = file_stat.st_size;
+ void* temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (temp_mapping == MAP_FAILED) {
+ return -1;
+ }
+ size_t file_offset = 0;
+
+ // Iterate over the relro segments and compare/remap the pages.
+ const ElfW(Phdr)* phdr = phdr_table;
+ const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
+
+ for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_GNU_RELRO) {
+ continue;
+ }
+
+ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+
+ char* file_base = static_cast<char*>(temp_mapping) + file_offset;
+ char* mem_base = reinterpret_cast<char*>(seg_page_start);
+ size_t match_offset = 0;
+ size_t size = seg_page_end - seg_page_start;
+
+ while (match_offset < size) {
+ // Skip over dissimilar pages.
+ while (match_offset < size &&
+ memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
+ match_offset += PAGE_SIZE;
+ }
+
+ // Count similar pages.
+ size_t mismatch_offset = match_offset;
+ while (mismatch_offset < size &&
+ memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
+ mismatch_offset += PAGE_SIZE;
+ }
+
+ // Map over similar pages.
+ if (mismatch_offset > match_offset) {
+ void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
+ PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
+ if (map == MAP_FAILED) {
+ munmap(temp_mapping, file_size);
+ return -1;
+ }
+ }
+
+ match_offset = mismatch_offset;
+ }
+
+ // Add to the base file offset in case there are multiple relro segments.
+ file_offset += size;
+ }
+ munmap(temp_mapping, file_size);
+ return 0;
+}
+
+
#if defined(__arm__)
# ifndef PT_ARM_EXIDX
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 6b72caf..611f1a7 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -42,7 +42,7 @@
ElfReader(const char* name, int fd);
~ElfReader();
- bool Load();
+ bool Load(const android_dlextinfo* extinfo);
size_t phdr_count() { return phdr_num_; }
ElfW(Addr) load_start() { return reinterpret_cast<ElfW(Addr)>(load_start_); }
@@ -54,7 +54,7 @@
bool ReadElfHeader();
bool VerifyElfHeader();
bool ReadProgramHeader();
- bool ReserveAddressSpace();
+ bool ReserveAddressSpace(const android_dlextinfo* extinfo);
bool LoadSegments();
bool FindPhdr();
bool CheckPhdr(ElfW(Addr));
@@ -89,6 +89,11 @@
int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias);
+int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
+ int fd);
+
+int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
+ int fd);
#if defined(__arm__)
int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 33e0a0b..5a53685 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -18,6 +18,11 @@
LOCAL_MODULE := $(module)
LOCAL_MODULE_TAGS := $(module_tag)
+LOCAL_MULTILIB := $(multilib)
+ifeq ($(multilib),both)
+ LOCAL_MODULE_STEM_32 := $(module)32
+ LOCAL_MODULE_STEM_64 := $(module)64
+endif
LOCAL_CLANG := $($(module)_clang_$(build_type))
diff --git a/tests/Android.mk b/tests/Android.mk
index b32d8d4..0014af6 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -40,6 +40,7 @@
libBionicStandardTests_src_files := \
buffer_tests.cpp \
+ ctype_test.cpp \
dirent_test.cpp \
eventfd_test.cpp \
fcntl_test.cpp \
@@ -189,6 +190,18 @@
endif
# -----------------------------------------------------------------------------
+# Library used by dlext tests.
+# -----------------------------------------------------------------------------
+libdlext_test_src_files := \
+ dlext_test_library.cpp \
+
+module := libdlext_test
+module_tag := optional
+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
# -----------------------------------------------------------------------------
@@ -196,6 +209,7 @@
libBionicTests \
bionic-unit-tests_src_files := \
+ dlext_test.cpp \
dlfcn_test.cpp \
bionic-unit-tests_ldflags := \
@@ -207,6 +221,7 @@
module := bionic-unit-tests
module_tag := optional
+multilib := both
build_type := target
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
@@ -228,6 +243,7 @@
module := bionic-unit-tests-static
module_tag := optional
+multilib := both
build_type := target
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
@@ -236,6 +252,9 @@
# Tests to run on the host and linked against glibc. Run with:
# cd bionic/tests; mm bionic-unit-tests-glibc-run
# -----------------------------------------------------------------------------
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+
bionic-unit-tests-glibc_whole_static_libraries := \
libBionicStandardTests \
@@ -248,6 +267,14 @@
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
+ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
+LINKER = linker64
+NATIVE_TEST_SUFFIX=64
+else
+LINKER = linker
+NATIVE_TEST_SUFFIX=32
+endif
+
# gtest needs ANDROID_DATA/local/tmp for death test output.
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
# Use the current target out directory as ANDROID_DATA.
@@ -256,18 +283,13 @@
mkdir -p $(TARGET_OUT_DATA)/local/tmp
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
- $(HOST_OUT_EXECUTABLES)/bionic-unit-tests-glibc $(BIONIC_TEST_FLAGS)
+ $(HOST_OUT_EXECUTABLES)/bionic-unit-tests-glibc$(NATIVE_TEST_SUFFIX) $(BIONIC_TEST_FLAGS)
# -----------------------------------------------------------------------------
# Run the unit tests built against x86 bionic on an x86 host.
# -----------------------------------------------------------------------------
-ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
-ifeq ($(TARGET_ARCH),x86)
-LINKER = linker
-else
-LINKER = linker64
-endif
# gtest needs ANDROID_DATA/local/tmp for death test output.
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
@@ -283,8 +305,9 @@
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
- $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests $(BIONIC_TEST_FLAGS)
+ $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests$(NATIVE_TEST_SUFFIX) $(BIONIC_TEST_FLAGS)
endif
-endif
+
+endif # linux-x86
endif # !BUILD_TINY_ANDROID
diff --git a/tests/ctype_test.cpp b/tests/ctype_test.cpp
new file mode 100644
index 0000000..7b27d64
--- /dev/null
+++ b/tests/ctype_test.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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 <ctype.h>
+
+TEST(ctype, isalnum) {
+ EXPECT_TRUE(isalnum('1'));
+ EXPECT_TRUE(isalnum('a'));
+ EXPECT_TRUE(isalnum('A'));
+ EXPECT_FALSE(isalnum('!'));
+ EXPECT_FALSE(isalnum(' '));
+}
+
+TEST(ctype, isalpha) {
+ EXPECT_FALSE(isalpha('1'));
+ EXPECT_TRUE(isalpha('a'));
+ EXPECT_TRUE(isalpha('A'));
+ EXPECT_FALSE(isalpha('!'));
+ EXPECT_FALSE(isalpha(' '));
+}
+
+TEST(ctype, isascii) {
+ EXPECT_TRUE(isascii('\x7f'));
+ EXPECT_FALSE(isascii('\x80'));
+}
+
+TEST(ctype, isblank) {
+ EXPECT_FALSE(isblank('1'));
+ EXPECT_TRUE(isblank(' '));
+ EXPECT_TRUE(isblank('\t'));
+}
+
+TEST(ctype, iscntrl) {
+ EXPECT_FALSE(iscntrl('1'));
+ EXPECT_TRUE(iscntrl('\b'));
+}
+
+TEST(ctype, isdigit) {
+ EXPECT_TRUE(isdigit('1'));
+ EXPECT_FALSE(isdigit('a'));
+ EXPECT_FALSE(isdigit('x'));
+}
+
+TEST(ctype, isgraph) {
+ EXPECT_TRUE(isgraph('a'));
+ EXPECT_TRUE(isgraph('A'));
+ EXPECT_TRUE(isgraph('1'));
+ EXPECT_TRUE(isgraph('!'));
+ EXPECT_FALSE(isgraph(' '));
+}
+
+TEST(ctype, islower) {
+ EXPECT_TRUE(islower('a'));
+ EXPECT_FALSE(islower('A'));
+ EXPECT_FALSE(islower('!'));
+}
+
+TEST(ctype, isprint) {
+ EXPECT_TRUE(isprint('a'));
+ EXPECT_TRUE(isprint(' '));
+ EXPECT_FALSE(isprint('\b'));
+}
+
+TEST(ctype, ispunct) {
+ EXPECT_TRUE(ispunct('!'));
+ EXPECT_FALSE(ispunct('a'));
+ EXPECT_FALSE(ispunct(' '));
+ EXPECT_FALSE(ispunct('\b'));
+}
+
+TEST(ctype, isspace) {
+ EXPECT_TRUE(isspace(' '));
+ EXPECT_TRUE(isspace('\f'));
+ EXPECT_TRUE(isspace('\n'));
+ EXPECT_TRUE(isspace('\r'));
+ EXPECT_TRUE(isspace('\t'));
+ EXPECT_TRUE(isspace('\v'));
+ EXPECT_FALSE(isspace('a'));
+ EXPECT_FALSE(isspace('!'));
+}
+
+TEST(ctype, isupper) {
+ EXPECT_TRUE(isupper('A'));
+ EXPECT_FALSE(isupper('a'));
+ EXPECT_FALSE(isupper('!'));
+}
+
+TEST(ctype, isxdigit) {
+ EXPECT_TRUE(isxdigit('0'));
+ EXPECT_FALSE(isxdigit('x'));
+ EXPECT_TRUE(isxdigit('1'));
+ EXPECT_TRUE(isxdigit('a'));
+ EXPECT_TRUE(isxdigit('A'));
+ EXPECT_FALSE(isxdigit('g'));
+ EXPECT_FALSE(isxdigit(' '));
+}
+
+TEST(ctype, toascii) {
+ EXPECT_EQ('a', toascii('a'));
+ EXPECT_EQ('a', toascii(0x80 | 'a'));
+}
+
+TEST(ctype, tolower) {
+ EXPECT_EQ('!', tolower('!'));
+ EXPECT_EQ('a', tolower('a'));
+ EXPECT_EQ('a', tolower('A'));
+}
+
+TEST(ctype, _tolower) {
+ // _tolower may mangle characters for which isupper is false.
+ EXPECT_EQ('a', _tolower('A'));
+}
+
+TEST(ctype, toupper) {
+ EXPECT_EQ('!', toupper('!'));
+ EXPECT_EQ('A', toupper('a'));
+ EXPECT_EQ('A', toupper('A'));
+}
+
+TEST(ctype, _toupper) {
+ // _toupper may mangle characters for which islower is false.
+ EXPECT_EQ('A', _toupper('a'));
+}
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
new file mode 100644
index 0000000..872cc5b
--- /dev/null
+++ b/tests/dlext_test.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <android/dlext.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+#define ASSERT_DL_NOTNULL(ptr) \
+ ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror()
+
+#define ASSERT_DL_ZERO(i) \
+ ASSERT_EQ(0, i) << "dlerror: " << dlerror()
+
+#define ASSERT_NOERROR(i) \
+ ASSERT_NE(-1, i) << "errno: " << strerror(errno)
+
+
+typedef int (*fn)(void);
+#define LIBNAME "libdlext_test.so"
+#define LIBSIZE 1024*1024 // how much address space to reserve for it
+
+
+class DlExtTest : public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ handle_ = NULL;
+ // verify that we don't have the library loaded already
+ ASSERT_EQ(NULL, dlsym(RTLD_DEFAULT, "getRandomNumber"));
+ // call dlerror() to swallow the error, and check it was the one we wanted
+ ASSERT_STREQ("undefined symbol: getRandomNumber", dlerror());
+ }
+
+ virtual void TearDown() {
+ if (handle_ != NULL) {
+ ASSERT_DL_ZERO(dlclose(handle_));
+ }
+ }
+
+ void* handle_;
+};
+
+TEST_F(DlExtTest, ExtInfoNull) {
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, ExtInfoNoFlags) {
+ android_dlextinfo extinfo;
+ extinfo.flags = 0;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, Reserved) {
+ void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
+ extinfo.reserved_addr = start;
+ extinfo.reserved_size = LIBSIZE;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_GE(f, start);
+ EXPECT_LT(reinterpret_cast<void*>(f),
+ reinterpret_cast<char*>(start) + LIBSIZE);
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, ReservedTooSmall) {
+ void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
+ extinfo.reserved_addr = start;
+ extinfo.reserved_size = PAGE_SIZE;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ EXPECT_EQ(NULL, handle_);
+}
+
+TEST_F(DlExtTest, ReservedHint) {
+ void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
+ extinfo.reserved_addr = start;
+ extinfo.reserved_size = LIBSIZE;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_GE(f, start);
+ EXPECT_LT(reinterpret_cast<void*>(f),
+ reinterpret_cast<char*>(start) + LIBSIZE);
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, ReservedHintTooSmall) {
+ void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS_HINT;
+ extinfo.reserved_addr = start;
+ extinfo.reserved_size = PAGE_SIZE;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_TRUE(f < start || (reinterpret_cast<void*>(f) >=
+ reinterpret_cast<char*>(start) + PAGE_SIZE));
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, RelroShareChildWrites) {
+ void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ android_dlextinfo extinfo;
+ extinfo.reserved_addr = start;
+ extinfo.reserved_size = LIBSIZE;
+
+ int relro_fd;
+ char relro_file[PATH_MAX];
+ const char* android_data = getenv("ANDROID_DATA");
+ ASSERT_TRUE(android_data != NULL);
+ snprintf(relro_file, sizeof(relro_file), "%s/local/tmp/libdlext_test.relro", android_data);
+ relro_fd = open(relro_file, O_CREAT | O_RDWR | O_TRUNC, 0644);
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
+ ASSERT_NOERROR(relro_fd);
+ extinfo.relro_fd = relro_fd;
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // child process
+ void* handle = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ if (handle == NULL) {
+ fprintf(stderr, "in child: %s\n", dlerror());
+ exit(1);
+ }
+ exit(0);
+ }
+
+ // continuing in parent
+ ASSERT_NOERROR(close(relro_fd));
+ ASSERT_NOERROR(pid);
+ int status;
+ ASSERT_EQ(pid, waitpid(pid, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(0, WEXITSTATUS(status));
+
+ relro_fd = open(relro_file, O_RDONLY);
+ ASSERT_NOERROR(relro_fd);
+ extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_USE_RELRO;
+ extinfo.relro_fd = relro_fd;
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_NOERROR(close(relro_fd));
+
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(4, f());
+}
diff --git a/tests/dlext_test_library.cpp b/tests/dlext_test_library.cpp
new file mode 100644
index 0000000..5c04329
--- /dev/null
+++ b/tests/dlext_test_library.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+class A {
+public:
+ virtual int getRandomNumber() {
+ return 4; // chosen by fair dice roll.
+ // guaranteed to be random.
+ }
+
+ virtual ~A() {}
+};
+
+A a;
+
+// nested macros to make it easy to define a large amount of read-only data
+// which will require relocation.
+#define A_16 &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a, &a,
+#define A_128 A_16 A_16 A_16 A_16 A_16 A_16 A_16 A_16
+#define A_1024 A_128 A_128 A_128 A_128 A_128 A_128 A_128 A_128
+
+extern "C" A* const lots_of_relro[] = {
+ A_1024 A_1024 A_1024 A_1024 A_1024 A_1024 A_1024 A_1024
+};
+
+extern "C" int getRandomNumber() {
+ // access the relro section (twice, in fact, once for the pointer, and once
+ // for the vtable of A) to check it's actually there.
+ return lots_of_relro[0]->getRandomNumber();
+}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index d80b2f7..e0d055e 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -668,10 +668,12 @@
}
TEST(DEATHTEST, FD_ISSET_fortified) {
+#ifdef __BIONIC__ // glibc catches this at compile-time.
::testing::FLAGS_gtest_death_test_style = "threadsafe";
fd_set set;
memset(&set, 0, sizeof(set));
ASSERT_EXIT(FD_ISSET(-1, &set), testing::KilledBySignal(SIGABRT), "");
+#endif
}
TEST(DEATHTEST, FD_ISSET_2_fortified) {
@@ -681,11 +683,14 @@
ASSERT_EXIT(FD_ISSET(0, set), testing::KilledBySignal(SIGABRT), "");
}
+// gtest's ASSERT_EXIT needs a valid expression, but glibc has a do-while macro.
+static void FD_ZERO_function(fd_set* s) { FD_ZERO(s); }
+
TEST(DEATHTEST, FD_ZERO_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char buf[1];
fd_set* set = (fd_set*) buf;
- ASSERT_EXIT(FD_ZERO(set), testing::KilledBySignal(SIGABRT), "");
+ ASSERT_EXIT(FD_ZERO_function(set), testing::KilledBySignal(SIGABRT), "");
}
TEST(DEATHTEST, read_fortified) {
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 6758af1..0b98e40 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -1015,9 +1015,26 @@
ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, -1.0L));
}
-// TODO: nexttoward
-// TODO: nexttowardf
-// TODO: nexttowardl
+TEST(math, nexttoward) {
+ ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, 0.0L));
+ ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nexttoward(0.0, 1.0L));
+ ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, -1.0L));
+}
+
+TEST(math, nexttowardf) {
+ ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, 0.0L));
+ ASSERT_FLOAT_EQ(1.4012985e-45f, nexttowardf(0.0f, 1.0L));
+ ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, -1.0L));
+}
+
+TEST(math, nexttowardl) {
+ ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, 0.0L));
+ // Use a runtime value to accomodate the case when
+ // sizeof(double) == sizeof(long double)
+ long double smallest_positive = ldexpl(1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG);
+ ASSERT_DOUBLE_EQ(smallest_positive, nexttowardl(0.0L, 1.0L));
+ ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, -1.0L));
+}
TEST(math, copysign) {
ASSERT_DOUBLE_EQ(0.0, copysign(0.0, 1.0));
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 0aa1d15..d825c14 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <wchar.h>
TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) {
FILE* fp = tmpfile();
@@ -192,18 +193,38 @@
snprintf(buf, sizeof(buf), "%zd", v);
}
-TEST(stdio, snprintf_n_format_specifier_not_implemented) {
-#if defined(__BIONIC__)
+// https://code.google.com/p/android/issues/detail?id=64886
+TEST(stdio, snprintf_a) {
+ char buf[BUFSIZ];
+ EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
+ EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
+}
+
+TEST(stdio, snprintf_lc) {
+ char buf[BUFSIZ];
+ wint_t wc = L'a';
+ EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
+ EXPECT_STREQ("<a>", buf);
+}
+
+TEST(stdio, snprintf_ls) {
+ char buf[BUFSIZ];
+ wchar_t* ws = NULL;
+ EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
+ EXPECT_STREQ("<(null)>", buf);
+
+ wchar_t chars[] = { L'h', L'i', 0 };
+ ws = chars;
+ EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
+ EXPECT_STREQ("<hi>", buf);
+}
+
+TEST(stdio, snprintf_n) {
char buf[32];
int i = 0;
- // We deliberately don't implement %n, so it's treated like
- // any other unrecognized format specifier.
- EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
- EXPECT_EQ(0, i);
- EXPECT_STREQ("a n b", buf);
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+ EXPECT_EQ(4, snprintf(buf, sizeof(buf), "a %n b", &i));
+ EXPECT_EQ(2, i);
+ EXPECT_STREQ("a b", buf);
}
TEST(stdio, snprintf_smoke) {
@@ -306,19 +327,19 @@
TEST(stdio, snprintf_f_special) {
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "%f", nanf(""));
- EXPECT_STREQ("NaN", buf);
+ EXPECT_STRCASEEQ("NaN", buf);
snprintf(buf, sizeof(buf), "%f", HUGE_VALF);
- EXPECT_STREQ("Inf", buf);
+ EXPECT_STRCASEEQ("Inf", buf);
}
TEST(stdio, snprintf_g_special) {
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "%g", nan(""));
- EXPECT_STREQ("NaN", buf);
+ EXPECT_STRCASEEQ("NaN", buf);
snprintf(buf, sizeof(buf), "%g", HUGE_VAL);
- EXPECT_STREQ("Inf", buf);
+ EXPECT_STRCASEEQ("Inf", buf);
}
TEST(stdio, snprintf_d_INT_MAX) {
@@ -365,6 +386,16 @@
EXPECT_STREQ("-9223372036854775808", buf);
}
+TEST(stdio, snprintf_e) {
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof(buf), "%e", 1.5);
+ EXPECT_STREQ("1.500000e+00", buf);
+
+ snprintf(buf, sizeof(buf), "%Le", 1.5l);
+ EXPECT_STREQ("1.500000e+00", buf);
+}
+
TEST(stdio, popen) {
FILE* fp = popen("cat /proc/version", "r");
ASSERT_TRUE(fp != NULL);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f56c5da..70b23bd 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -132,3 +132,111 @@
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(99, WEXITSTATUS(status));
}
+
+TEST(unistd, getenv_unsetenv) {
+ ASSERT_EQ(0, setenv("test-variable", "hello", 1));
+ ASSERT_STREQ("hello", getenv("test-variable"));
+ ASSERT_EQ(0, unsetenv("test-variable"));
+ ASSERT_TRUE(getenv("test-variable") == NULL);
+}
+
+TEST(unistd, unsetenv_EINVAL) {
+ EXPECT_EQ(-1, unsetenv(NULL));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, unsetenv(""));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, unsetenv("a=b"));
+ EXPECT_EQ(EINVAL, errno);
+}
+
+TEST(unistd, setenv_EINVAL) {
+ EXPECT_EQ(-1, setenv(NULL, "value", 0));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, setenv(NULL, "value", 1));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, setenv("", "value", 0));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, setenv("", "value", 1));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, setenv("a=b", "value", 0));
+ EXPECT_EQ(EINVAL, errno);
+ EXPECT_EQ(-1, setenv("a=b", "value", 1));
+ EXPECT_EQ(EINVAL, errno);
+}
+
+TEST(unistd, setenv) {
+ ASSERT_EQ(0, unsetenv("test-variable"));
+
+ char a[] = "a";
+ char b[] = "b";
+ char c[] = "c";
+
+ // New value.
+ EXPECT_EQ(0, setenv("test-variable", a, 0));
+ EXPECT_STREQ(a, getenv("test-variable"));
+
+ // Existing value, no overwrite.
+ EXPECT_EQ(0, setenv("test-variable", b, 0));
+ EXPECT_STREQ(a, getenv("test-variable"));
+
+ // Existing value, overwrite.
+ EXPECT_EQ(0, setenv("test-variable", c, 1));
+ EXPECT_STREQ(c, getenv("test-variable"));
+ // But the arrays backing the values are unchanged.
+ EXPECT_EQ('a', a[0]);
+ EXPECT_EQ('b', b[0]);
+ EXPECT_EQ('c', c[0]);
+
+ ASSERT_EQ(0, unsetenv("test-variable"));
+}
+
+TEST(unistd, putenv) {
+ ASSERT_EQ(0, unsetenv("a"));
+
+ char* s1 = strdup("a=b");
+ ASSERT_EQ(0, putenv(s1));
+
+ ASSERT_STREQ("b", getenv("a"));
+ s1[2] = 'c';
+ ASSERT_STREQ("c", getenv("a"));
+
+ char* s2 = strdup("a=b");
+ ASSERT_EQ(0, putenv(s2));
+
+ ASSERT_STREQ("b", getenv("a"));
+ ASSERT_EQ('c', s1[2]);
+
+ ASSERT_EQ(0, unsetenv("a"));
+ free(s1);
+ free(s2);
+}
+
+TEST(unistd, clearenv) {
+ extern char** environ;
+
+ // Guarantee that environ is not initially empty...
+ ASSERT_EQ(0, setenv("test-variable", "a", 1));
+
+ // Stash a copy.
+ std::vector<char*> old_environ;
+ for (size_t i = 0; environ[i] != NULL; ++i) {
+ old_environ.push_back(strdup(environ[i]));
+ }
+
+ ASSERT_EQ(0, clearenv());
+
+ EXPECT_TRUE(environ == NULL || environ[0] == NULL);
+ EXPECT_EQ(NULL, getenv("test-variable"));
+ EXPECT_EQ(0, setenv("test-variable", "post-clear", 1));
+ EXPECT_STREQ("post-clear", getenv("test-variable"));
+
+ // Put the old environment back.
+ for (size_t i = 0; i < old_environ.size(); ++i) {
+ EXPECT_EQ(0, putenv(old_environ[i]));
+ }
+
+ // Check it wasn't overwritten.
+ EXPECT_STREQ("a", getenv("test-variable"));
+
+ EXPECT_EQ(0, unsetenv("test-variable"));
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 20566f2..be451c1 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -16,6 +16,7 @@
#include <gtest/gtest.h>
+#include <errno.h>
#include <limits.h>
#include <wchar.h>
@@ -55,3 +56,106 @@
EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
EXPECT_EQ('h', bytes[0]);
}
+
+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* src;
+ char bytes[BUFSIZ];
+
+ // Given a NULL destination, these functions count valid characters.
+ EXPECT_EQ(5U, wcstombs(NULL, chars, 0));
+ EXPECT_EQ(5U, wcstombs(NULL, chars, 4));
+ EXPECT_EQ(5U, wcstombs(NULL, chars, 256));
+ src = chars;
+ EXPECT_EQ(5U, wcsrtombs(NULL, &src, 0, NULL));
+ EXPECT_EQ(&chars[0], src);
+ src = chars;
+ EXPECT_EQ(5U, wcsrtombs(NULL, &src, 4, NULL));
+ EXPECT_EQ(&chars[0], src);
+ src = chars;
+ EXPECT_EQ(5U, wcsrtombs(NULL, &src, 256, NULL));
+ EXPECT_EQ(&chars[0], src);
+
+ // An unrepresentable char just returns an error from wcstombs...
+ errno = 0;
+ EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 0));
+ EXPECT_EQ(EILSEQ, errno);
+ errno = 0;
+ EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 256));
+ EXPECT_EQ(EILSEQ, errno);
+
+ // And wcsrtombs doesn't tell us where it got stuck because we didn't ask it
+ // to actually convert anything...
+ errno = 0;
+ src = bad_chars;
+ EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, NULL));
+ EXPECT_EQ(&bad_chars[0], src);
+ EXPECT_EQ(EILSEQ, errno);
+ errno = 0;
+ src = bad_chars;
+ EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 256, NULL));
+ EXPECT_EQ(&bad_chars[0], src);
+ EXPECT_EQ(EILSEQ, errno);
+
+ // Okay, now let's test actually converting something...
+ memset(bytes, 'x', sizeof(bytes));
+ EXPECT_EQ(0U, wcstombs(bytes, chars, 0));
+ memset(bytes, 'x', sizeof(bytes));
+ EXPECT_EQ(4U, wcstombs(bytes, chars, 4));
+ bytes[5] = 0;
+ EXPECT_STREQ("hellx", bytes);
+ memset(bytes, 'x', sizeof(bytes));
+ EXPECT_EQ(5U, wcstombs(bytes, chars, 256));
+ EXPECT_STREQ("hello", bytes);
+ memset(bytes, 'x', sizeof(bytes));
+ EXPECT_EQ(5U, wcstombs(bytes, chars, 6));
+ EXPECT_STREQ("hello", bytes);
+ errno = 0;
+ memset(bytes, 'x', sizeof(bytes));
+ EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256));
+ EXPECT_EQ(EILSEQ, errno);
+ bytes[3] = 0;
+ EXPECT_STREQ("hix", bytes);
+
+ // wcsrtombs is a bit more informative...
+ memset(bytes, 'x', sizeof(bytes));
+ src = chars;
+ EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, NULL));
+ EXPECT_EQ(&chars[0], src); // No input consumed.
+ EXPECT_EQ(EILSEQ, errno);
+
+ memset(bytes, 'x', sizeof(bytes));
+ src = chars;
+ EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, NULL));
+ EXPECT_EQ(&chars[4], src); // Some input consumed.
+ EXPECT_EQ(EILSEQ, errno);
+ bytes[5] = 0;
+ EXPECT_STREQ("hellx", bytes);
+
+ memset(bytes, 'x', sizeof(bytes));
+ src = chars;
+ EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, NULL));
+ EXPECT_EQ(NULL, src); // All input consumed!
+ EXPECT_EQ(EILSEQ, errno);
+ EXPECT_STREQ("hello", bytes);
+
+ memset(bytes, 'x', sizeof(bytes));
+ src = chars;
+ EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, NULL));
+ EXPECT_EQ(NULL, src); // All input consumed.
+ EXPECT_EQ(EILSEQ, errno);
+ EXPECT_STREQ("hello", bytes);
+
+ memset(bytes, 'x', sizeof(bytes));
+ src = bad_chars;
+ EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, NULL));
+ EXPECT_EQ(&bad_chars[2], src);
+ EXPECT_EQ(EILSEQ, errno);
+ bytes[3] = 0;
+ EXPECT_STREQ("hix", bytes);
+}
+
+TEST(wchar, limits) {
+ ASSERT_LT(WCHAR_MIN, WCHAR_MAX);
+}