diff options
author | Eric Blake <ebb9@byu.net> | 2007-05-24 20:13:44 +0000 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2007-10-06 07:08:30 -0600 |
commit | fa8768bc7aa3153979a6a5295baa84f138fd0d9c (patch) | |
tree | 9372f8b15431934b431f6690e1e80043dfe203d1 /modules | |
parent | 65bedc1cbd322db74e0f81f73d6a246ba709d97c (diff) | |
download | m4-fa8768bc7aa3153979a6a5295baa84f138fd0d9c.tar.gz |
Provide consistent shift semantics regardless of hardware.
* modules/m4.c (numb_lshift, numb_rshift, numb_urshift): Mask
before shifting.
(number, unumber): Always use [u]intmax_t.
Reported by Gary V. Vaughan.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/m4.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/modules/m4.c b/modules/m4.c index 22835b70..90e5eb87 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -100,14 +100,8 @@ extern void m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, BUILTIN (undivert, false, false, false, 0, -1 ) \ -#if defined(SIZEOF_LONG_LONG_INT) && SIZEOF_LONG_LONG_INT > 0 -/* Use GNU long long int if available. */ -typedef long long int number; -typedef unsigned long long int unumber; -#else -typedef long int number; -typedef unsigned long int unumber; -#endif +typedef intmax_t number; +typedef uintmax_t unumber; static void include (m4 *context, int argc, m4_symbol_value **argv, bool silent); @@ -1103,10 +1097,21 @@ M4BUILTIN_HANDLER (translit) does not support. */ #define numb_invert(x) return NEGATIVE_EXPONENT -#define numb_lshift(c, x, y) (*(x) = (*(x) << *(y))) -#define numb_rshift(c, x, y) (*(x) = (*(x) >> *(y))) -#define numb_urshift(c, x, y) \ - (*(x) = (number) ((unumber) *(x) >> (unumber) *(y))) +/* Minimize undefined C behavior (shifting by a negative number, + shifting by the width or greater, left shift overflow, or right + shift of a negative number). Implement Java wrap-around semantics, + with implicit masking of shift amount. This code assumes that the + implementation-defined overflow when casting unsigned to signed is + a silent twos-complement wrap-around. */ +#define shift_mask (sizeof (number) * CHAR_BIT - 1) +#define numb_lshift(c, x, y) \ + (*(x) = (number) ((unumber) *(x) << (*(y) & shift_mask))) +#define numb_rshift(c, x, y) \ + (*(x) = (number) (*(x) < 0 \ + ? ~(~(unumber) *(x) >> (*(y) & shift_mask)) \ + : (unumber) *(x) >> (*(y) & shift_mask))) +#define numb_urshift(c, x, y) \ + (*(x) = (number) ((unumber) *(x) >> (*(y) & shift_mask))) /* The function ntoa () converts VALUE to a signed ascii representation in |