]> git.eshelyaron.com Git - emacs.git/commitdiff
Port NaN, infinity handling better to VAX
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 13 Jul 2023 21:26:29 +0000 (14:26 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 13 Jul 2023 21:43:03 +0000 (14:43 -0700)
Nowadays .elc files routinely contain tokens like 1.0e+INF and
0.0e+NaN that do not work on antiques like the VAX that lack IEEE fp.
Port Emacs to these platforms, by treating infinities as extreme
values and NaNs as strings that trap if used numerically.
* src/lread.c (INFINITY): Default to HUGE_VAL if non-IEEE.
(not_a_number) [!IEEE_FLOATING_POINT]: New static array.
(syms_of_lread) [!IEEE_FLOATING_POINT]: Initialize it.
(read0): Report invalid syntax for +0.0e+NaN on platforms
that lack NaNs.
(string_to_number): On non-IEEE platforms, return HUGE_VAL
for infinity and a string for NaN.  All callers changed.

doc/lispref/numbers.texi
etc/NEWS
src/data.c
src/lread.c
src/process.c

index 3e45aa90fda1f9697f2811bd424658a2c302b4f0..bcf89fc9ab1b197c47a613e36bc91602e6a2bbfc 100644 (file)
@@ -270,10 +270,6 @@ two NaNs as equal when their
 signs and significands agree.  Significands of NaNs are
 machine-dependent, as are the digits in their string representation.
 
-  NaNs are not available on systems which do not use IEEE
-floating-point arithmetic; if the read syntax for a NaN is used on a
-VAX, for example, the reader signals an error.
-
   When NaNs and signed zeros are involved, non-numeric functions like
 @code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and
 @code{gethash} determine whether values are indistinguishable, not
@@ -283,6 +279,12 @@ whether they are numerically equal.  For example, when @var{x} and
 conversely, @code{(equal 0.0 -0.0)} returns @code{nil} whereas
 @code{(= 0.0 -0.0)} returns @code{t}.
 
+  Infinities and NaNs are not available on legacy systems that lack
+IEEE floating-point arithmetic.  On a circa 1980 VAX, for example, the
+Lisp reader approximates an infinity with the nearest finite value,
+and a NaN with some other non-numeric Lisp object that provokes an
+error if used numerically.
+
 Here are read syntaxes for these special floating-point values:
 
 @table @asis
index 5d5ea990b92b47a6a56e5042476241e9e76bf975..997f7e82c2bd77f100cefa01c6315ec318f1c22a 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -585,6 +585,14 @@ behavior back for any other reason, you can do that using the
 previous behavior of showing 'U' in the mode line for 'koi8-u':
 
      (coding-system-put 'koi8-u :mnemonic ?U)
+
++++
+** Infinities and NaNs no longer act as symbols on non-IEEE platforms.
+On old platforms like the VAX that do not support IEEE floating-point,
+tokens like 0.0e+NaN and 1.0e+INF are no longer read as symbols.
+Instead, the Lisp reader approximates an infinity with the nearest
+finite value, and a NaN with some other non-numeric object that
+provokes an error if used numerically.
 \f
 * Lisp Changes in Emacs 30.1
 
index 6de8e0cf1a1c5c524755d7525376fe5c5f93ed83..5a31462d8ca79c695d79a059d7d97188f2352bc5 100644 (file)
@@ -3033,7 +3033,8 @@ If the base used is not 10, STRING is always parsed as an integer.  */)
     p++;
 
   Lisp_Object val = string_to_number (p, b, 0);
-  return NILP (val) ? make_fixnum (0) : val;
+  return ((IEEE_FLOATING_POINT ? NILP (val) : !NUMBERP (val))
+         ? make_fixnum (0) : val);
 }
 \f
 enum arithop
index 51d0d2a3c24e3e113f3bc80c7a65967187560bb4..6792ef27206d442a75ca4153fc07229bea8cdce0 100644 (file)
@@ -75,6 +75,10 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 # ifndef INFINITY
 #  define INFINITY ((union ieee754_double) {.ieee = {.exponent = -1}}.d)
 # endif
+#else
+# ifndef INFINITY
+#  define INFINITY HUGE_VAL
+# endif
 #endif
 
 /* The objects or placeholders read with the #n=object form.
@@ -4477,10 +4481,17 @@ substitute_in_interval (INTERVAL interval, void *arg)
 }
 
 \f
+#if !IEEE_FLOATING_POINT
+/* Strings that stand in for +NaN, -NaN, respectively.  */
+static Lisp_Object not_a_number[2];
+#endif
+
 /* Convert the initial prefix of STRING to a number, assuming base BASE.
    If the prefix has floating point syntax and BASE is 10, return a
    nearest float; otherwise, if the prefix has integer syntax, return
-   the integer; otherwise, return nil.  If PLEN, set *PLEN to the
+   the integer; otherwise, return nil.  (On antique platforms that lack
+   support for NaNs, if the prefix has NaN syntax return a Lisp object that
+   will provoke an error if used as a number.)  If PLEN, set *PLEN to the
    length of the numeric prefix if there is one, otherwise *PLEN is
    unspecified.  */
 
@@ -4545,7 +4556,6 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
                cp++;
              while ('0' <= *cp && *cp <= '9');
            }
-#if IEEE_FLOATING_POINT
          else if (cp[-1] == '+'
                   && cp[0] == 'I' && cp[1] == 'N' && cp[2] == 'F')
            {
@@ -4558,12 +4568,17 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
            {
              state |= E_EXP;
              cp += 3;
+#if IEEE_FLOATING_POINT
              union ieee754_double u
                = { .ieee_nan = { .exponent = 0x7ff, .quiet_nan = 1,
                                  .mantissa0 = n >> 31 >> 1, .mantissa1 = n }};
              value = u.d;
-           }
+#else
+             if (plen)
+               *plen = cp - string;
+             return not_a_number[negative];
 #endif
+           }
          else
            cp = ecp;
        }
@@ -5707,6 +5722,14 @@ that are loaded before your customizations are read!  */);
   DEFSYM (Qcomma, ",");
   DEFSYM (Qcomma_at, ",@");
 
+#if !IEEE_FLOATING_POINT
+  for (int negative = 0; negative < 2; negative++)
+    {
+      not_a_number[negative] = build_pure_c_string (&"-0.0e+NaN"[!negative]);
+      staticpro (&not_a_number[negative]);
+    }
+#endif
+
   DEFSYM (Qinhibit_file_name_operation, "inhibit-file-name-operation");
   DEFSYM (Qascii_character, "ascii-character");
   DEFSYM (Qfunction, "function");
index 67d1d3e425f45cff95dd3a73138b64012f82e8a1..2d6e08f16b5ff158aae75905f9b14979845d0d0a 100644 (file)
@@ -7130,7 +7130,8 @@ See function `signal-process' for more details on usage.  */)
        {
          ptrdiff_t len;
          tem = string_to_number (SSDATA (process), 10, &len);
-         if (NILP (tem) || len != SBYTES (process))
+         if ((IEEE_FLOATING_POINT ? NILP (tem) : !NUMBERP (tem))
+             || len != SBYTES (process))
            return Qnil;
        }
       process = tem;