]> git.eshelyaron.com Git - emacs.git/commitdiff
Substitute a <ieee754.h> on hosts lacking it
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 2 Aug 2018 01:53:31 +0000 (18:53 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 2 Aug 2018 02:01:51 +0000 (19:01 -0700)
* .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.

.gitignore
admin/merge-gnulib
configure.ac
etc/NEWS
lib/gnulib.mk.in
lib/ieee754.in.h [new file with mode: 0644]
m4/gnulib-comp.m4
m4/ieee754-h.m4 [new file with mode: 0644]
src/lisp.h
src/lread.c
src/print.c

index d3712b0d6cf521058a54797b9a25da7a2eb26b69..26fe4bb34e8fed467fe78c72db211d3bdcb24c54 100644 (file)
@@ -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
index 39dfaee8f4de0b0ecfc5c935a441ba99d9d9f8c5..1397ecfb9f7c896be091d41df9db86dd9a6cc366 100755 (executable)
@@ -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
index dbdcce7c8d85246a54be05c1221d9e3059cedd96..b6918671e409b767364c0db27cd7f9764d8da4cd 100644 (file)
@@ -1668,7 +1668,6 @@ fi
 
 dnl checks for header files
 AC_CHECK_HEADERS_ONCE(
-  ieee754.h
   linux/fs.h
   malloc.h
   sys/systeminfo.h
index 9e7a765dc61ccc878844e5a6da1895cb07eaf47e..6c79a46f243c020148237a4ae42ca41b7cfb04ad 100644 (file)
--- 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.
index e623921091fc4f57e81d99187a98058924debb09..7d28dcc62b877a879299c4d8072142e7f8828b32 100644 (file)
@@ -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 (file)
index 0000000..316ac03
--- /dev/null
@@ -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 */
index a6e3be3815db88239d473b57957f097e2008bd07..494c77c7c4e0d809700adcbd488f9c9a969b7a0b 100644 (file)
@@ -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 (file)
index 0000000..bf7c332
--- /dev/null
@@ -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"])
+])
index 96de60e4670df4da913275422759245ef62f7ed3..bdece817bd6756cc015e7e468d97a04648b70d39 100644 (file)
@@ -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.  */
index 290b0f6bbe93c4b874036b9420c0c156a5105ca6..9a025d8664dd98ec4d5b36bd6d6836c453e2f408 100644 (file)
@@ -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;
        }
index add21609cc58c600ade377ae6313a6b53c28ee64..34c7fa12b6eadf8deb194d8a48a2f1d6235de139 100644 (file)
@@ -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))