* lisp.h (UNSIGNED_CMP): New macro.
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 12 Jun 2011 23:25:12 +0000 (16:25 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 12 Jun 2011 23:25:12 +0000 (16:25 -0700)
This fixes comparison bugs on 64-bit hosts.
(ASCII_CHAR_P): Use it.
* casefiddle.c (casify_object):
* character.h (ASCII_BYTE_P, CHAR_VALID_P):
(SINGLE_BYTE_CHAR_P, CHAR_STRING):
* composite.h (COMPOSITION_ENCODE_RULE_VALID):
* dispextern.h (FACE_FROM_ID):
* keyboard.c (read_char): Use UNSIGNED_CMP.

src/ChangeLog
src/casefiddle.c
src/character.h
src/composite.h
src/dispextern.h
src/keyboard.c
src/lisp.h

index 82fd352..cb3ed50 100644 (file)
@@ -1,3 +1,15 @@
+2011-06-12  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * lisp.h (UNSIGNED_CMP): New macro.
+       This fixes comparison bugs on 64-bit hosts.
+       (ASCII_CHAR_P): Use it.
+       * casefiddle.c (casify_object):
+       * character.h (ASCII_BYTE_P, CHAR_VALID_P):
+       (SINGLE_BYTE_CHAR_P, CHAR_STRING):
+       * composite.h (COMPOSITION_ENCODE_RULE_VALID):
+       * dispextern.h (FACE_FROM_ID):
+       * keyboard.c (read_char): Use UNSIGNED_CMP.
+
 2011-06-11  Paul Eggert  <eggert@cs.ucla.edu>
 
        * xmenu.c (dialog_selection_callback) [!USE_GTK]: Cast to intptr_t,
index 9f286d7..1a0a62f 100644 (file)
@@ -52,7 +52,7 @@ casify_object (enum case_action flag, Lisp_Object obj)
       /* If the character has higher bits set
         above the flags, return it unchanged.
         It is not a real character.  */
-      if ((unsigned) XFASTINT (obj) > (unsigned) flagbits)
+      if (UNSIGNED_CMP (XFASTINT (obj), >, flagbits))
        return obj;
 
       c1 = XFASTINT (obj) & ~flagbits;
index 8848337..695a55b 100644 (file)
@@ -102,13 +102,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define make_char(c) make_number (c)
 
 /* Nonzero iff C is an ASCII byte.  */
-#define ASCII_BYTE_P(c) ((unsigned) (c) < 0x80)
+#define ASCII_BYTE_P(c) UNSIGNED_CMP (c, <, 0x80)
 
 /* Nonzero iff X is a character.  */
 #define CHARACTERP(x) (NATNUMP (x) && XFASTINT (x) <= MAX_CHAR)
 
 /* Nonzero iff C is valid as a character code.  GENERICP is not used.  */
-#define CHAR_VALID_P(c, genericp) ((unsigned) (c) <= MAX_CHAR)
+#define CHAR_VALID_P(c, genericp) UNSIGNED_CMP (c, <=, MAX_CHAR)
 
 /* Check if Lisp object X is a character or not.  */
 #define CHECK_CHARACTER(x) \
@@ -129,7 +129,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
   } while (0)
 
 /* Nonzero iff C is a character of code less than 0x100.  */
-#define SINGLE_BYTE_CHAR_P(c) ((unsigned) (c) < 0x100)
+#define SINGLE_BYTE_CHAR_P(c) UNSIGNED_CMP (c, <, 0x100)
 
 /* Nonzero if character C has a printable glyph.  */
 #define CHAR_PRINTABLE_P(c)    \
@@ -161,14 +161,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    Returns the length of the multibyte form.  */
 
 #define CHAR_STRING(c, p)                      \
-  ((unsigned) (c) <= MAX_1_BYTE_CHAR           \
+  (UNSIGNED_CMP (c, <=, MAX_1_BYTE_CHAR)       \
    ? ((p)[0] = (c),                            \
       1)                                       \
-   : (unsigned) (c) <= MAX_2_BYTE_CHAR         \
+   : UNSIGNED_CMP (c, <=, MAX_2_BYTE_CHAR)     \
    ? ((p)[0] = (0xC0 | ((c) >> 6)),            \
       (p)[1] = (0x80 | ((c) & 0x3F)),          \
       2)                                       \
-   : (unsigned) (c) <= MAX_3_BYTE_CHAR         \
+   : UNSIGNED_CMP (c, <=, MAX_3_BYTE_CHAR)     \
    ? ((p)[0] = (0xE0 | ((c) >> 12)),           \
       (p)[1] = (0x80 | (((c) >> 6) & 0x3F)),   \
       (p)[2] = (0x80 | ((c) & 0x3F)),          \
index 0f81911..8cedfdb 100644 (file)
@@ -151,7 +151,7 @@ extern Lisp_Object composition_temp;
 /* Nonzero if the global reference point GREF and new reference point NREF are
    valid.  */
 #define COMPOSITION_ENCODE_RULE_VALID(gref, nref)      \
-  ((unsigned) (gref) < 12 && (unsigned) (nref) < 12)
+  (UNSIGNED_CMP (gref, <, 12) && UNSIGNED_CMP (nref, <, 12))
 
 /* Return encoded composition rule for the pair of global reference
    point GREF and new reference point NREF.  Arguments must be valid.  */
index 211a1b0..75ebc46 100644 (file)
@@ -1729,7 +1729,7 @@ struct face_cache
    face doesn't exist.  */
 
 #define FACE_FROM_ID(F, ID)                            \
-     (((unsigned) (ID) < FRAME_FACE_CACHE (F)->used)   \
+     (UNSIGNED_CMP (ID, <, FRAME_FACE_CACHE (F)->used) \
       ? FRAME_FACE_CACHE (F)->faces_by_id[ID]          \
       : NULL)
 
index 8948397..0bacc2f 100644 (file)
@@ -2906,9 +2906,13 @@ read_char (int commandflag, int nmaps, Lisp_Object *maps, Lisp_Object prev_event
        goto exit;
 
       if ((STRINGP (KVAR (current_kboard, Vkeyboard_translate_table))
-          && SCHARS (KVAR (current_kboard, Vkeyboard_translate_table)) > (unsigned) XFASTINT (c))
+          && UNSIGNED_CMP (XFASTINT (c), <,
+                           SCHARS (KVAR (current_kboard,
+                                         Vkeyboard_translate_table))))
          || (VECTORP (KVAR (current_kboard, Vkeyboard_translate_table))
-             && ASIZE (KVAR (current_kboard, Vkeyboard_translate_table)) > (unsigned) XFASTINT (c))
+             && UNSIGNED_CMP (XFASTINT (c), <,
+                              ASIZE (KVAR (current_kboard,
+                                           Vkeyboard_translate_table))))
          || (CHAR_TABLE_P (KVAR (current_kboard, Vkeyboard_translate_table))
              && CHARACTERP (c)))
        {
index 6003dae..4dfed31 100644 (file)
@@ -911,8 +911,18 @@ struct Lisp_Vector
 
 #endif /* not __GNUC__ */
 
+/* Compute A OP B, using the unsigned comparison operator OP.  A and B
+   should be integer expressions.  This is not the same as
+   mathemeatical comparison; for example, UNSIGNED_CMP (0, <, -1)
+   returns 1.  For efficiency, prefer plain unsigned comparison if A
+   and B's sizes both fit (after integer promotion).  */
+#define UNSIGNED_CMP(a, op, b)                                         \
+  (max (sizeof ((a) + 0), sizeof ((b) + 0)) <= sizeof (unsigned)       \
+   ? ((a) + (unsigned) 0) op ((b) + (unsigned) 0)                      \
+   : ((a) + (uintmax_t) 0) op ((b) + (uintmax_t) 0))
+
 /* Nonzero iff C is an ASCII character.  */
-#define ASCII_CHAR_P(c) ((unsigned) (c) < 0x80)
+#define ASCII_CHAR_P(c) UNSIGNED_CMP (c, <, 0x80)
 
 /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
    characters.  Do not check validity of CT.  */