summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2018-08-01 18:53:31 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2018-08-01 19:01:51 -0700
commitd216d7d248199aa6c99cd642116717c5b301ae6d (patch)
tree687b9efadbb87fa1095fb0a2e0569e625856e15a
parent2f37ecaefcc61b0bf389f1c1eb3ac1b15105f056 (diff)
downloademacs-d216d7d248199aa6c99cd642116717c5b301ae6d.tar.gz
Substitute a <ieee754.h> on hosts lacking it
* .gitignore: Add lib/ieee754.h. * admin/merge-gnulib (GNULIB_MODULES): Add ieee754-h. * configure.ac: Remove ieee754.h check, as Gnulib now does that. * etc/NEWS: Mention this. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/ieee754.in.h, m4/ieee754-h.m4: New files, from Gnulib. * src/lisp.h (IEEE_FLOATING_POINT): Now a macro so that it can be used in #if. * src/lread.c, src/print.c: Include <ieee754.h> if IEEE_FLOATING_POINT, not if HAVE_IEEE754_H. * src/lread.c (string_to_number): * src/print.c (float_to_string): Process NaNs only on IEEE hosts, and assume <ieee754.h> in that case.
-rw-r--r--.gitignore1
-rwxr-xr-xadmin/merge-gnulib2
-rw-r--r--configure.ac1
-rw-r--r--etc/NEWS6
-rw-r--r--lib/gnulib.mk.in29
-rw-r--r--lib/ieee754.in.h222
-rw-r--r--m4/gnulib-comp.m44
-rw-r--r--m4/ieee754-h.m421
-rw-r--r--src/lisp.h11
-rw-r--r--src/lread.c9
-rw-r--r--src/print.c25
11 files changed, 291 insertions, 40 deletions
diff --git a/.gitignore b/.gitignore
index d3712b0d6cf..26fe4bb34e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ lib/execinfo.h
lib/fcntl.h
lib/getopt.h
lib/getopt-cdefs.h
+lib/ieee754.h
lib/inttypes.h
lib/libgnu.a
lib/limits.h
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 39dfaee8f4d..1397ecfb9f7 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -35,7 +35,7 @@ GNULIB_MODULES='
fcntl fcntl-h fdatasync fdopendir
filemode filevercmp flexmember fpieee fstatat fsusage fsync
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
- ignore-value intprops largefile lstat
+ ieee754-h ignore-value intprops largefile lstat
manywarnings memrchr minmax mkostemp mktime nstrftime
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
diff --git a/configure.ac b/configure.ac
index dbdcce7c8d8..b6918671e40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1668,7 +1668,6 @@ fi
dnl checks for header files
AC_CHECK_HEADERS_ONCE(
- ieee754.h
linux/fs.h
malloc.h
sys/systeminfo.h
diff --git a/etc/NEWS b/etc/NEWS
index 9e7a765dc61..6c79a46f243 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -880,9 +880,9 @@ Formerly, some of these functions ignored signs and significands of
NaNs. Now, all these functions treat NaN signs and significands as
significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil
because the two NaNs have different signs; formerly it returned t.
-Also, on platforms that have <ieee754.h> Emacs now reads and prints
-NaN significands; e.g., if X is a NaN, (format "%s" X) now returns
-"0.0e+NaN", "1.0e+NaN", etc., depending on X's significand.
+Also, Emacs now reads and prints NaN significands; e.g., if X is a
+NaN, (format "%s" X) now returns "0.0e+NaN", "1.0e+NaN", etc.,
+depending on X's significand.
+++
** The function 'make-string' accepts an additional optional argument.
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index e623921091f..7d28dcc62b8 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -95,6 +95,7 @@
# gettime \
# gettimeofday \
# gitlog-to-changelog \
+# ieee754-h \
# ignore-value \
# intprops \
# largefile \
@@ -220,6 +221,7 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
+GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
@@ -646,6 +648,7 @@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
HAVE_XSERVER = @HAVE_XSERVER@
HAVE__EXIT = @HAVE__EXIT@
HYBRID_MALLOC = @HYBRID_MALLOC@
+IEEE754_H = @IEEE754_H@
IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
INCLUDE_NEXT = @INCLUDE_NEXT@
@@ -1787,6 +1790,32 @@ EXTRA_libgnu_a_SOURCES += group-member.c
endif
## end gnulib module group-member
+## begin gnulib module ieee754-h
+ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
+
+BUILT_SOURCES += $(IEEE754_H)
+
+# We need the following in order to create <ieee754.h> when the system
+# doesn't have one that works with the given compiler.
+ifneq (,$(GL_GENERATE_IEEE754_H))
+ieee754.h: ieee754.in.h $(top_builddir)/config.status
+ $(AM_V_GEN)rm -f $@-t && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \
+ $(srcdir)/ieee754.in.h; \
+ } > $@-t && \
+ mv -f $@-t $@
+else
+ieee754.h: $(top_builddir)/config.status
+ rm -f $@
+endif
+MOSTLYCLEANFILES += ieee754.h ieee754.h-t
+
+EXTRA_DIST += ieee754.in.h
+
+endif
+## end gnulib module ieee754-h
+
## begin gnulib module ignore-value
ifeq (,$(OMIT_GNULIB_MODULE_ignore-value))
diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h
new file mode 100644
index 00000000000..316ac039afe
--- /dev/null
+++ b/lib/ieee754.in.h
@@ -0,0 +1,222 @@
+/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _IEEE754_H
+
+#define _IEEE754_H 1
+
+#ifndef _GL_GNULIB_HEADER
+/* Ordinary glibc usage. */
+# include <features.h>
+# include <endian.h>
+#else
+/* Gnulib usage. */
+# ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# endif
+# ifndef __FLOAT_WORD_ORDER
+# define __LITTLE_ENDIAN 1234
+# define __BIG_ENDIAN 4321
+# ifdef WORDS_BIGENDIAN
+# define __BYTE_ORDER __BIG_ENDIAN
+# else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+# endif
+# define __FLOAT_WORD_ORDER __BYTE_ORDER
+# endif
+#endif
+
+__BEGIN_DECLS
+
+union ieee754_float
+ {
+ float f;
+
+ /* This is the IEEE 754 single-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa:22;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int mantissa:22;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee_nan;
+ };
+
+#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
+
+
+union ieee754_double
+ {
+ double d;
+
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:20;
+ unsigned int mantissa1:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:20;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:11;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:19;
+ unsigned int mantissa1:32;
+#else
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+ unsigned int mantissa1:32;
+# else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:19;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:11;
+ unsigned int negative:1;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
+
+
+union ieee854_long_double
+ {
+ long double d;
+
+ /* This is the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:32;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:32;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee;
+
+ /* This is for NaNs in the IEEE 854 double-extended-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int empty:16;
+ unsigned int one:1;
+ unsigned int quiet_nan:1;
+ unsigned int mantissa0:30;
+ unsigned int mantissa1:32;
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int mantissa1:32;
+# else
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:30;
+ unsigned int quiet_nan:1;
+ unsigned int one:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+ unsigned int empty:16;
+# endif
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
+
+__END_DECLS
+
+#endif /* ieee754.h */
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index a6e3be3815d..494c77c7c4e 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -101,6 +101,7 @@ AC_DEFUN([gl_EARLY],
# Code from module gettimeofday:
# Code from module gitlog-to-changelog:
# Code from module group-member:
+ # Code from module ieee754-h:
# Code from module ignore-value:
# Code from module include_next:
# Code from module intprops:
@@ -295,6 +296,7 @@ AC_DEFUN([gl_INIT],
gl_PREREQ_GETTIMEOFDAY
fi
gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
+ gl_IEEE754_H
gl_INTTYPES_INCOMPLETE
AC_REQUIRE([gl_LARGEFILE])
gl_LIMITS_H
@@ -895,6 +897,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/gettimeofday.c
lib/gl_openssl.h
lib/group-member.c
+ lib/ieee754.in.h
lib/ignore-value.h
lib/intprops.h
lib/inttypes.in.h
@@ -1017,6 +1020,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/gl-openssl.m4
m4/gnulib-common.m4
m4/group-member.m4
+ m4/ieee754-h.m4
m4/include_next.m4
m4/inttypes.m4
m4/largefile.m4
diff --git a/m4/ieee754-h.m4 b/m4/ieee754-h.m4
new file mode 100644
index 00000000000..bf7c332e48e
--- /dev/null
+++ b/m4/ieee754-h.m4
@@ -0,0 +1,21 @@
+# Configure ieee754-h module
+
+dnl Copyright 2018 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_IEEE754_H],
+[
+ AC_REQUIRE([AC_C_BIGENDIAN])
+ AC_CHECK_HEADERS_ONCE([ieee754.h])
+ if test $ac_cv_header_ieee754_h = yes; then
+ IEEE754_H=
+ else
+ IEEE754_H=ieee754.h
+ AC_DEFINE([_GL_REPLACE_IEEE754_H], 1,
+ [Define to 1 if <ieee754.h> is missing.])
+ fi
+ AC_SUBST([IEEE754_H])
+ AM_CONDITIONAL([GL_GENERATE_IEEE754_H], [test -n "$IEEE754_H"])
+])
diff --git a/src/lisp.h b/src/lisp.h
index 96de60e4670..bdece817bd6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2670,17 +2670,14 @@ XFLOAT_DATA (Lisp_Object f)
/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
representations, have infinities and NaNs, and do not trap on
- exceptions. Define IEEE_FLOATING_POINT if this host is one of the
+ exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the
typical ones. The C11 macro __STDC_IEC_559__ is close to what is
wanted here, but is not quite right because Emacs does not require
all the features of C11 Annex F (and does not require C11 at all,
for that matter). */
-enum
- {
- IEEE_FLOATING_POINT
- = (FLT_RADIX == 2 && FLT_MANT_DIG == 24
- && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
- };
+
+#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
+ && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
/* A character, declared with the following typedef, is a member
of some character set associated with the current buffer. */
diff --git a/src/lread.c b/src/lread.c
index 290b0f6bbe9..9a025d8664d 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -72,7 +72,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define file_tell ftell
#endif
-#if HAVE_IEEE754_H
+#if IEEE_FLOATING_POINT
# include <ieee754.h>
#endif
@@ -3756,21 +3756,18 @@ string_to_number (char const *string, int base, int flags)
cp += 3;
value = INFINITY;
}
+#if IEEE_FLOATING_POINT
else if (cp[-1] == '+'
&& cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N')
{
state |= E_EXP;
cp += 3;
-#if HAVE_IEEE754_H
union ieee754_double u
= { .ieee_nan = { .exponent = -1, .quiet_nan = 1,
.mantissa0 = n >> 31 >> 1, .mantissa1 = n }};
value = u.d;
-#else
- /* NAN is a "positive" NaN on all known Emacs hosts. */
- value = NAN;
-#endif
}
+#endif
else
cp = ecp;
}
diff --git a/src/print.c b/src/print.c
index add21609cc5..34c7fa12b6e 100644
--- a/src/print.c
+++ b/src/print.c
@@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <ftoastr.h>
#include <math.h>
-#if HAVE_IEEE754_H
+#if IEEE_FLOATING_POINT
# include <ieee754.h>
#endif
@@ -1013,34 +1013,15 @@ float_to_string (char *buf, double data)
strcpy (buf, minus_infinity_string + positive);
return sizeof minus_infinity_string - 1 - positive;
}
+#if IEEE_FLOATING_POINT
if (isnan (data))
{
-#if HAVE_IEEE754_H
union ieee754_double u = { .d = data };
uprintmax_t hi = u.ieee_nan.mantissa0;
return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative],
(hi << 31 << 1) + u.ieee_nan.mantissa1);
-#else
- /* Prepend "-" if the NaN's sign bit is negative.
- The sign bit of a double is the bit that is 1 in -0.0. */
- static char const NaN_string[] = "0.0e+NaN";
- int i;
- union { double d; char c[sizeof (double)]; } u_data, u_minus_zero;
- bool negative = 0;
- u_data.d = data;
- u_minus_zero.d = - 0.0;
- for (i = 0; i < sizeof (double); i++)
- if (u_data.c[i] & u_minus_zero.c[i])
- {
- *buf = '-';
- negative = 1;
- break;
- }
-
- strcpy (buf + negative, NaN_string);
- return negative + sizeof NaN_string - 1;
-#endif
}
+#endif
if (NILP (Vfloat_output_format)
|| !STRINGP (Vfloat_output_format))