mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 13:11:14 -08:00
Arithmetic overflows now return float rather than wrapping around.
* data.c: Include <intprops.h>. (arith_driver): Use floating point if the accumulator would otherwise go out of EMACS_INT range. (arith_driver, Fadd1, Fsub1): Use floating point if the result is out of Emacs fixnum range. * bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate.
This commit is contained in:
parent
fed14fd752
commit
7fc4768c45
3 changed files with 91 additions and 49 deletions
|
|
@ -1,5 +1,13 @@
|
|||
2011-05-03 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Arithmetic overflows now return float rather than wrapping around.
|
||||
* data.c: Include <intprops.h>.
|
||||
(arith_driver): Use floating point if the accumulator would otherwise
|
||||
go out of EMACS_INT range.
|
||||
(arith_driver, Fadd1, Fsub1): Use floating point if the result is
|
||||
out of Emacs fixnum range.
|
||||
* bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate.
|
||||
|
||||
* callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering.
|
||||
|
||||
* process.c (Fformat_network_address): Fix typo: args2 -> *args2.
|
||||
|
|
|
|||
|
|
@ -1186,7 +1186,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1))
|
||||
if (INTEGERP (v1) && MOST_NEGATIVE_FIXNUM < XINT (v1))
|
||||
{
|
||||
XSETINT (v1, XINT (v1) - 1);
|
||||
TOP = v1;
|
||||
|
|
@ -1204,7 +1204,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1))
|
||||
if (INTEGERP (v1) && XINT (v1) < MOST_POSITIVE_FIXNUM)
|
||||
{
|
||||
XSETINT (v1, XINT (v1) + 1);
|
||||
TOP = v1;
|
||||
|
|
@ -1290,7 +1290,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1))
|
||||
if (INTEGERP (v1) && - MOST_POSITIVE_FIXNUM <= XINT (v1))
|
||||
{
|
||||
XSETINT (v1, - XINT (v1));
|
||||
TOP = v1;
|
||||
|
|
|
|||
126
src/data.c
126
src/data.c
|
|
@ -22,6 +22,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include <intprops.h>
|
||||
|
||||
#include "lisp.h"
|
||||
#include "puresize.h"
|
||||
#include "character.h"
|
||||
|
|
@ -2426,10 +2429,8 @@ static Lisp_Object float_arith_driver (double, size_t, enum arithop,
|
|||
static Lisp_Object
|
||||
arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
|
||||
{
|
||||
register Lisp_Object val;
|
||||
register size_t argnum;
|
||||
register EMACS_INT accum = 0;
|
||||
register EMACS_INT next;
|
||||
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
{
|
||||
|
|
@ -2451,58 +2452,89 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
|
|||
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
EMACS_INT a = accum;
|
||||
int use_float = 0;
|
||||
|
||||
/* Using args[argnum] as argument to CHECK_NUMBER_... */
|
||||
val = args[argnum];
|
||||
Lisp_Object val = args[argnum];
|
||||
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val);
|
||||
args[argnum] = val;
|
||||
|
||||
if (FLOATP (val))
|
||||
return float_arith_driver ((double) accum, argnum, code,
|
||||
nargs, args);
|
||||
args[argnum] = val;
|
||||
next = XINT (args[argnum]);
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
use_float = 1;
|
||||
else
|
||||
{
|
||||
case Aadd:
|
||||
accum += next;
|
||||
break;
|
||||
case Asub:
|
||||
accum = argnum ? accum - next : nargs == 1 ? - next : next;
|
||||
break;
|
||||
case Amult:
|
||||
accum *= next;
|
||||
break;
|
||||
case Adiv:
|
||||
if (!argnum)
|
||||
accum = next;
|
||||
else
|
||||
EMACS_INT next = XINT (val);
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
{
|
||||
if (next == 0)
|
||||
xsignal0 (Qarith_error);
|
||||
accum /= next;
|
||||
case Aadd:
|
||||
if (next < 0
|
||||
? a < TYPE_MINIMUM (EMACS_INT) - next
|
||||
: TYPE_MAXIMUM (EMACS_INT) - next < a)
|
||||
use_float = 1;
|
||||
else
|
||||
a += next;
|
||||
break;
|
||||
case Asub:
|
||||
if (argnum == 0 && nargs != 1)
|
||||
a = next;
|
||||
else if (next < 0
|
||||
? TYPE_MAXIMUM (EMACS_INT) + next < a
|
||||
: a < TYPE_MINIMUM (EMACS_INT) + next)
|
||||
use_float = 1;
|
||||
else
|
||||
a -= next;
|
||||
break;
|
||||
case Amult:
|
||||
if (next < 0
|
||||
? (a < 0
|
||||
? a < TYPE_MAXIMUM (EMACS_INT) / next
|
||||
: next != -1 && TYPE_MINIMUM (EMACS_INT) / next < a)
|
||||
: (next != 0
|
||||
&& (a < 0
|
||||
? a < TYPE_MINIMUM (EMACS_INT) / next
|
||||
: TYPE_MAXIMUM (EMACS_INT) / next < a)))
|
||||
use_float = 1;
|
||||
else
|
||||
a *= next;
|
||||
break;
|
||||
case Adiv:
|
||||
if (!argnum)
|
||||
a = next;
|
||||
else
|
||||
{
|
||||
if (next == 0)
|
||||
xsignal0 (Qarith_error);
|
||||
a /= next;
|
||||
}
|
||||
break;
|
||||
case Alogand:
|
||||
a &= next;
|
||||
break;
|
||||
case Alogior:
|
||||
a |= next;
|
||||
break;
|
||||
case Alogxor:
|
||||
a ^= next;
|
||||
break;
|
||||
case Amax:
|
||||
if (!argnum || a < next)
|
||||
a = next;
|
||||
break;
|
||||
case Amin:
|
||||
if (!argnum || next < a)
|
||||
a = next;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Alogand:
|
||||
accum &= next;
|
||||
break;
|
||||
case Alogior:
|
||||
accum |= next;
|
||||
break;
|
||||
case Alogxor:
|
||||
accum ^= next;
|
||||
break;
|
||||
case Amax:
|
||||
if (!argnum || next > accum)
|
||||
accum = next;
|
||||
break;
|
||||
case Amin:
|
||||
if (!argnum || next < accum)
|
||||
accum = next;
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_float)
|
||||
return float_arith_driver (accum, argnum, code, nargs, args);
|
||||
|
||||
accum = a;
|
||||
}
|
||||
|
||||
XSETINT (val, accum);
|
||||
return val;
|
||||
return make_fixnum_or_float (accum);
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
|
|
@ -2777,7 +2809,8 @@ Markers are converted to integers. */)
|
|||
|
||||
if (FLOATP (number))
|
||||
return (make_float (1.0 + XFLOAT_DATA (number)));
|
||||
|
||||
if (XINT (number) + 1 == MOST_POSITIVE_FIXNUM + 1)
|
||||
return make_float (XINT (number) + 1);
|
||||
XSETINT (number, XINT (number) + 1);
|
||||
return number;
|
||||
}
|
||||
|
|
@ -2791,7 +2824,8 @@ Markers are converted to integers. */)
|
|||
|
||||
if (FLOATP (number))
|
||||
return (make_float (-1.0 + XFLOAT_DATA (number)));
|
||||
|
||||
if (XINT (number) - 1 == MOST_NEGATIVE_FIXNUM - 1)
|
||||
return make_float (XINT (number) - 1);
|
||||
XSETINT (number, XINT (number) - 1);
|
||||
return number;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue