diff options
| author | Paul Eggert | 2011-05-03 00:51:38 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-05-03 00:51:38 -0700 |
| commit | 7fc4768c45bce52d34f183eb4734d9f58745ea3d (patch) | |
| tree | b7414afb75c1fc941f8a9dd9e6b900cbd1eb9f23 /src | |
| parent | fed14fd75201f3c313293432e58de8f860979a3e (diff) | |
| download | emacs-7fc4768c45bce52d34f183eb4734d9f58745ea3d.tar.gz emacs-7fc4768c45bce52d34f183eb4734d9f58745ea3d.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/bytecode.c | 6 | ||||
| -rw-r--r-- | src/data.c | 126 |
3 files changed, 91 insertions, 49 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index ccf1fea9514..435f90abad9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | 2011-05-03 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-05-03 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Arithmetic overflows now return float rather than wrapping around. | ||
| 4 | * data.c: Include <intprops.h>. | ||
| 5 | (arith_driver): Use floating point if the accumulator would otherwise | ||
| 6 | go out of EMACS_INT range. | ||
| 7 | (arith_driver, Fadd1, Fsub1): Use floating point if the result is | ||
| 8 | out of Emacs fixnum range. | ||
| 9 | * bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate. | ||
| 10 | |||
| 3 | * callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering. | 11 | * callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering. |
| 4 | 12 | ||
| 5 | * process.c (Fformat_network_address): Fix typo: args2 -> *args2. | 13 | * process.c (Fformat_network_address): Fix typo: args2 -> *args2. |
diff --git a/src/bytecode.c b/src/bytecode.c index c3cd3d43072..ce79b011bbb 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1186,7 +1186,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1186 | { | 1186 | { |
| 1187 | Lisp_Object v1; | 1187 | Lisp_Object v1; |
| 1188 | v1 = TOP; | 1188 | v1 = TOP; |
| 1189 | if (INTEGERP (v1)) | 1189 | if (INTEGERP (v1) && MOST_NEGATIVE_FIXNUM < XINT (v1)) |
| 1190 | { | 1190 | { |
| 1191 | XSETINT (v1, XINT (v1) - 1); | 1191 | XSETINT (v1, XINT (v1) - 1); |
| 1192 | TOP = v1; | 1192 | TOP = v1; |
| @@ -1204,7 +1204,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1204 | { | 1204 | { |
| 1205 | Lisp_Object v1; | 1205 | Lisp_Object v1; |
| 1206 | v1 = TOP; | 1206 | v1 = TOP; |
| 1207 | if (INTEGERP (v1)) | 1207 | if (INTEGERP (v1) && XINT (v1) < MOST_POSITIVE_FIXNUM) |
| 1208 | { | 1208 | { |
| 1209 | XSETINT (v1, XINT (v1) + 1); | 1209 | XSETINT (v1, XINT (v1) + 1); |
| 1210 | TOP = v1; | 1210 | TOP = v1; |
| @@ -1290,7 +1290,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1290 | { | 1290 | { |
| 1291 | Lisp_Object v1; | 1291 | Lisp_Object v1; |
| 1292 | v1 = TOP; | 1292 | v1 = TOP; |
| 1293 | if (INTEGERP (v1)) | 1293 | if (INTEGERP (v1) && - MOST_POSITIVE_FIXNUM <= XINT (v1)) |
| 1294 | { | 1294 | { |
| 1295 | XSETINT (v1, - XINT (v1)); | 1295 | XSETINT (v1, - XINT (v1)); |
| 1296 | TOP = v1; | 1296 | TOP = v1; |
diff --git a/src/data.c b/src/data.c index 577ae777d89..beff570d552 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -22,6 +22,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 22 | #include <signal.h> | 22 | #include <signal.h> |
| 23 | #include <stdio.h> | 23 | #include <stdio.h> |
| 24 | #include <setjmp.h> | 24 | #include <setjmp.h> |
| 25 | |||
| 26 | #include <intprops.h> | ||
| 27 | |||
| 25 | #include "lisp.h" | 28 | #include "lisp.h" |
| 26 | #include "puresize.h" | 29 | #include "puresize.h" |
| 27 | #include "character.h" | 30 | #include "character.h" |
| @@ -2426,10 +2429,8 @@ static Lisp_Object float_arith_driver (double, size_t, enum arithop, | |||
| 2426 | static Lisp_Object | 2429 | static Lisp_Object |
| 2427 | arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | 2430 | arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) |
| 2428 | { | 2431 | { |
| 2429 | register Lisp_Object val; | ||
| 2430 | register size_t argnum; | 2432 | register size_t argnum; |
| 2431 | register EMACS_INT accum = 0; | 2433 | register EMACS_INT accum = 0; |
| 2432 | register EMACS_INT next; | ||
| 2433 | 2434 | ||
| 2434 | switch (SWITCH_ENUM_CAST (code)) | 2435 | switch (SWITCH_ENUM_CAST (code)) |
| 2435 | { | 2436 | { |
| @@ -2451,58 +2452,89 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | |||
| 2451 | 2452 | ||
| 2452 | for (argnum = 0; argnum < nargs; argnum++) | 2453 | for (argnum = 0; argnum < nargs; argnum++) |
| 2453 | { | 2454 | { |
| 2455 | EMACS_INT a = accum; | ||
| 2456 | int use_float = 0; | ||
| 2457 | |||
| 2454 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ | 2458 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ |
| 2455 | val = args[argnum]; | 2459 | Lisp_Object val = args[argnum]; |
| 2456 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); | 2460 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); |
| 2461 | args[argnum] = val; | ||
| 2457 | 2462 | ||
| 2458 | if (FLOATP (val)) | 2463 | if (FLOATP (val)) |
| 2459 | return float_arith_driver ((double) accum, argnum, code, | 2464 | use_float = 1; |
| 2460 | nargs, args); | 2465 | else |
| 2461 | args[argnum] = val; | ||
| 2462 | next = XINT (args[argnum]); | ||
| 2463 | switch (SWITCH_ENUM_CAST (code)) | ||
| 2464 | { | 2466 | { |
| 2465 | case Aadd: | 2467 | EMACS_INT next = XINT (val); |
| 2466 | accum += next; | 2468 | switch (SWITCH_ENUM_CAST (code)) |
| 2467 | break; | ||
| 2468 | case Asub: | ||
| 2469 | accum = argnum ? accum - next : nargs == 1 ? - next : next; | ||
| 2470 | break; | ||
| 2471 | case Amult: | ||
| 2472 | accum *= next; | ||
| 2473 | break; | ||
| 2474 | case Adiv: | ||
| 2475 | if (!argnum) | ||
| 2476 | accum = next; | ||
| 2477 | else | ||
| 2478 | { | 2469 | { |
| 2479 | if (next == 0) | 2470 | case Aadd: |
| 2480 | xsignal0 (Qarith_error); | 2471 | if (next < 0 |
| 2481 | accum /= next; | 2472 | ? a < TYPE_MINIMUM (EMACS_INT) - next |
| 2473 | : TYPE_MAXIMUM (EMACS_INT) - next < a) | ||
| 2474 | use_float = 1; | ||
| 2475 | else | ||
| 2476 | a += next; | ||
| 2477 | break; | ||
| 2478 | case Asub: | ||
| 2479 | if (argnum == 0 && nargs != 1) | ||
| 2480 | a = next; | ||
| 2481 | else if (next < 0 | ||
| 2482 | ? TYPE_MAXIMUM (EMACS_INT) + next < a | ||
| 2483 | : a < TYPE_MINIMUM (EMACS_INT) + next) | ||
| 2484 | use_float = 1; | ||
| 2485 | else | ||
| 2486 | a -= next; | ||
| 2487 | break; | ||
| 2488 | case Amult: | ||
| 2489 | if (next < 0 | ||
| 2490 | ? (a < 0 | ||
| 2491 | ? a < TYPE_MAXIMUM (EMACS_INT) / next | ||
| 2492 | : next != -1 && TYPE_MINIMUM (EMACS_INT) / next < a) | ||
| 2493 | : (next != 0 | ||
| 2494 | && (a < 0 | ||
| 2495 | ? a < TYPE_MINIMUM (EMACS_INT) / next | ||
| 2496 | : TYPE_MAXIMUM (EMACS_INT) / next < a))) | ||
| 2497 | use_float = 1; | ||
| 2498 | else | ||
| 2499 | a *= next; | ||
| 2500 | break; | ||
| 2501 | case Adiv: | ||
| 2502 | if (!argnum) | ||
| 2503 | a = next; | ||
| 2504 | else | ||
| 2505 | { | ||
| 2506 | if (next == 0) | ||
| 2507 | xsignal0 (Qarith_error); | ||
| 2508 | a /= next; | ||
| 2509 | } | ||
| 2510 | break; | ||
| 2511 | case Alogand: | ||
| 2512 | a &= next; | ||
| 2513 | break; | ||
| 2514 | case Alogior: | ||
| 2515 | a |= next; | ||
| 2516 | break; | ||
| 2517 | case Alogxor: | ||
| 2518 | a ^= next; | ||
| 2519 | break; | ||
| 2520 | case Amax: | ||
| 2521 | if (!argnum || a < next) | ||
| 2522 | a = next; | ||
| 2523 | break; | ||
| 2524 | case Amin: | ||
| 2525 | if (!argnum || next < a) | ||
| 2526 | a = next; | ||
| 2527 | break; | ||
| 2482 | } | 2528 | } |
| 2483 | break; | ||
| 2484 | case Alogand: | ||
| 2485 | accum &= next; | ||
| 2486 | break; | ||
| 2487 | case Alogior: | ||
| 2488 | accum |= next; | ||
| 2489 | break; | ||
| 2490 | case Alogxor: | ||
| 2491 | accum ^= next; | ||
| 2492 | break; | ||
| 2493 | case Amax: | ||
| 2494 | if (!argnum || next > accum) | ||
| 2495 | accum = next; | ||
| 2496 | break; | ||
| 2497 | case Amin: | ||
| 2498 | if (!argnum || next < accum) | ||
| 2499 | accum = next; | ||
| 2500 | break; | ||
| 2501 | } | 2529 | } |
| 2530 | |||
| 2531 | if (use_float) | ||
| 2532 | return float_arith_driver (accum, argnum, code, nargs, args); | ||
| 2533 | |||
| 2534 | accum = a; | ||
| 2502 | } | 2535 | } |
| 2503 | 2536 | ||
| 2504 | XSETINT (val, accum); | 2537 | return make_fixnum_or_float (accum); |
| 2505 | return val; | ||
| 2506 | } | 2538 | } |
| 2507 | 2539 | ||
| 2508 | #undef isnan | 2540 | #undef isnan |
| @@ -2777,7 +2809,8 @@ Markers are converted to integers. */) | |||
| 2777 | 2809 | ||
| 2778 | if (FLOATP (number)) | 2810 | if (FLOATP (number)) |
| 2779 | return (make_float (1.0 + XFLOAT_DATA (number))); | 2811 | return (make_float (1.0 + XFLOAT_DATA (number))); |
| 2780 | 2812 | if (XINT (number) + 1 == MOST_POSITIVE_FIXNUM + 1) | |
| 2813 | return make_float (XINT (number) + 1); | ||
| 2781 | XSETINT (number, XINT (number) + 1); | 2814 | XSETINT (number, XINT (number) + 1); |
| 2782 | return number; | 2815 | return number; |
| 2783 | } | 2816 | } |
| @@ -2791,7 +2824,8 @@ Markers are converted to integers. */) | |||
| 2791 | 2824 | ||
| 2792 | if (FLOATP (number)) | 2825 | if (FLOATP (number)) |
| 2793 | return (make_float (-1.0 + XFLOAT_DATA (number))); | 2826 | return (make_float (-1.0 + XFLOAT_DATA (number))); |
| 2794 | 2827 | if (XINT (number) - 1 == MOST_NEGATIVE_FIXNUM - 1) | |
| 2828 | return make_float (XINT (number) - 1); | ||
| 2795 | XSETINT (number, XINT (number) - 1); | 2829 | XSETINT (number, XINT (number) - 1); |
| 2796 | return number; | 2830 | return number; |
| 2797 | } | 2831 | } |