summaryrefslogtreecommitdiff
path: root/modules/m4.c
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2007-05-24 20:13:44 +0000
committerEric Blake <ebb9@byu.net>2007-10-06 07:08:30 -0600
commitfa8768bc7aa3153979a6a5295baa84f138fd0d9c (patch)
tree9372f8b15431934b431f6690e1e80043dfe203d1 /modules/m4.c
parent65bedc1cbd322db74e0f81f73d6a246ba709d97c (diff)
downloadm4-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/m4.c')
-rw-r--r--modules/m4.c29
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