Port NaN, infinity handling better to VAX
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.
This commit is contained in:
parent
b94e7e6334
commit
0cd519971d
5 changed files with 44 additions and 9 deletions
|
@ -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
|
||||
|
|
8
etc/NEWS
8
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
29
src/lread.c
29
src/lread.c
|
@ -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)
|
|||
}
|
||||
|
||||
|
||||
#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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue