diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index 3e45aa90fda..bcf89fc9ab1 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -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 diff --git a/etc/NEWS b/etc/NEWS index 5d5ea990b92..997f7e82c2b 100644 --- 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. * Lisp Changes in Emacs 30.1 diff --git a/src/data.c b/src/data.c index 6de8e0cf1a1..5a31462d8ca 100644 --- a/src/data.c +++ b/src/data.c @@ -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); } enum arithop diff --git a/src/lread.c b/src/lread.c index 51d0d2a3c24..6792ef27206 100644 --- a/src/lread.c +++ b/src/lread.c @@ -75,6 +75,10 @@ along with GNU Emacs. If not, see . */ # 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) } +#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 (¬_a_number[negative]); + } +#endif + DEFSYM (Qinhibit_file_name_operation, "inhibit-file-name-operation"); DEFSYM (Qascii_character, "ascii-character"); DEFSYM (Qfunction, "function"); diff --git a/src/process.c b/src/process.c index 67d1d3e425f..2d6e08f16b5 100644 --- a/src/process.c +++ b/src/process.c @@ -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;