Merge "Add android_dlopen_ext() interface to linker."
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/libc/Android.mk b/libc/Android.mk
index b94e573..507126e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -75,17 +75,12 @@
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.
@@ -208,7 +203,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 +305,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 +361,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 +394,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 \
@@ -523,7 +549,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 +573,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 +600,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 +626,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 +641,34 @@
# ========================================================
+# 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) \
+ -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 +730,7 @@
libc_bionic \
libc_dns \
libc_freebsd \
+ libc_gdtoa \
libc_netbsd \
libc_openbsd \
libc_stack_protector \
@@ -773,7 +828,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 +841,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 +889,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 +920,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/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-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_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/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..82e1b03 100644
--- a/libc/bionic/fpclassify.cpp
+++ b/libc/bionic/fpclassify.cpp
@@ -96,22 +96,19 @@
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;
}
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/strtof.cpp b/libc/bionic/strtof.cpp
deleted file mode 100644
index a41e4d4..0000000
--- a/libc/bionic/strtof.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-
-float strtof(const char* s, char** end_ptr) {
- // TODO: upgrade to a non-hack implementation.
- return strtod(s, end_ptr);
-}
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/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/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/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/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/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/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/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/linker.cpp b/linker/linker.cpp
index ba50d5c..2e145b5 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1837,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));
diff --git a/tests/Android.mk b/tests/Android.mk
index b32d8d4..723d7cf 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 \
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/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/wchar_test.cpp b/tests/wchar_test.cpp
index 20566f2..d5d27ed 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,102 @@
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);
+}