]> git.eshelyaron.com Git - emacs.git/commitdiff
Check for overflow when converting integer to cons and back.
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 6 Jun 2011 08:29:01 +0000 (01:29 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 6 Jun 2011 08:29:01 +0000 (01:29 -0700)
* charset.c (Fdefine_charset_internal, Fdecode_char):
Use cons_to_unsigned to catch overflow.
(Fencode_char): Use INTEGER_TO_CONS.
* composite.h (LGLYPH_CODE): Use cons_to_unsigned.
(LGLYPH_SET_CODE): Use INTEGER_TO_CONS.
* data.c (long_to_cons, cons_to_long): Remove.
(cons_to_unsigned, cons_to_signed): New functions.
These signal an error for invalid or out-of-range values.
* dired.c (Ffile_attributes): Use INTEGER_TO_CONS.
* fileio.c (Fset_visited_file_modtime): Use CONS_TO_INTEGER.
* font.c (Ffont_variation_glyphs):
* fontset.c (Finternal_char_font): Use INTEGER_TO_CONS.
* lisp.h: Include <intprops.h>.
(INTEGER_TO_CONS, CONS_TO_INTEGER): New macros.
(cons_to_signed, cons_to_unsigned): New decls.
(long_to_cons, cons_to_long): Remove decls.
* undo.c (record_first_change): Use INTEGER_TO_CONS.
(Fprimitive_undo): Use CONS_TO_INTEGER.
* xfns.c (Fx_window_property): Likewise.
* xselect.c: Include <limits.h>.
(x_own_selection, selection_data_to_lisp_data):
Use INTEGER_TO_CONS.
(x_handle_selection_request, x_handle_selection_clear)
(x_get_foreign_selection, Fx_disown_selection_internal)
(Fx_get_atom_name, x_send_client_event): Use CONS_TO_INTEGER.
(lisp_data_to_selection_data): Use cons_to_unsigned.
(x_fill_property_data): Use cons_to_signed.
Report values out of range.

12 files changed:
src/ChangeLog
src/charset.c
src/composite.h
src/data.c
src/dired.c
src/fileio.c
src/font.c
src/fontset.c
src/lisp.h
src/undo.c
src/xfns.c
src/xselect.c

index bf81533460a1efb05b458508b663f8120affca4e..c9c739dde9abcfeef15201999b7e95baf05bf390 100644 (file)
@@ -1,5 +1,35 @@
 2011-06-06  Paul Eggert  <eggert@cs.ucla.edu>
 
+       Check for overflow when converting integer to cons and back.
+       * charset.c (Fdefine_charset_internal, Fdecode_char):
+       Use cons_to_unsigned to catch overflow.
+       (Fencode_char): Use INTEGER_TO_CONS.
+       * composite.h (LGLYPH_CODE): Use cons_to_unsigned.
+       (LGLYPH_SET_CODE): Use INTEGER_TO_CONS.
+       * data.c (long_to_cons, cons_to_long): Remove.
+       (cons_to_unsigned, cons_to_signed): New functions.
+       These signal an error for invalid or out-of-range values.
+       * dired.c (Ffile_attributes): Use INTEGER_TO_CONS.
+       * fileio.c (Fset_visited_file_modtime): Use CONS_TO_INTEGER.
+       * font.c (Ffont_variation_glyphs):
+       * fontset.c (Finternal_char_font): Use INTEGER_TO_CONS.
+       * lisp.h: Include <intprops.h>.
+       (INTEGER_TO_CONS, CONS_TO_INTEGER): New macros.
+       (cons_to_signed, cons_to_unsigned): New decls.
+       (long_to_cons, cons_to_long): Remove decls.
+       * undo.c (record_first_change): Use INTEGER_TO_CONS.
+       (Fprimitive_undo): Use CONS_TO_INTEGER.
+       * xfns.c (Fx_window_property): Likewise.
+       * xselect.c: Include <limits.h>.
+       (x_own_selection, selection_data_to_lisp_data):
+       Use INTEGER_TO_CONS.
+       (x_handle_selection_request, x_handle_selection_clear)
+       (x_get_foreign_selection, Fx_disown_selection_internal)
+       (Fx_get_atom_name, x_send_client_event): Use CONS_TO_INTEGER.
+       (lisp_data_to_selection_data): Use cons_to_unsigned.
+       (x_fill_property_data): Use cons_to_signed.
+       Report values out of range.
+
        Check for buffer and string overflow more precisely.
        * buffer.h (BUF_BYTES_MAX): New macro.
        * lisp.h (STRING_BYTES_MAX): New macro.
index bfebe02f52ef3009adfef0175102d1dfee5769a3..770e98c99e131c05e808305b7758b8880e9ce81a 100644 (file)
@@ -932,17 +932,8 @@ usage: (define-charset-internal ...)  */)
   val = args[charset_arg_min_code];
   if (! NILP (val))
     {
-      unsigned code;
+      unsigned code = cons_to_unsigned (val, UINT_MAX);
 
-      if (INTEGERP (val))
-       code = XINT (val);
-      else
-       {
-         CHECK_CONS (val);
-         CHECK_NUMBER_CAR (val);
-         CHECK_NUMBER_CDR (val);
-         code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
-       }
       if (code < charset.min_code
          || code > charset.max_code)
        args_out_of_range_3 (make_number (charset.min_code),
@@ -954,17 +945,8 @@ usage: (define-charset-internal ...)  */)
   val = args[charset_arg_max_code];
   if (! NILP (val))
     {
-      unsigned code;
+      unsigned code = cons_to_unsigned (val, UINT_MAX);
 
-      if (INTEGERP (val))
-       code = XINT (val);
-      else
-       {
-         CHECK_CONS (val);
-         CHECK_NUMBER_CAR (val);
-         CHECK_NUMBER_CDR (val);
-         code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
-       }
       if (code < charset.min_code
          || code > charset.max_code)
        args_out_of_range_3 (make_number (charset.min_code),
@@ -1865,17 +1847,7 @@ and CODE-POINT to a character.  Currently not supported and just ignored.  */)
   struct charset *charsetp;
 
   CHECK_CHARSET_GET_ID (charset, id);
-  if (CONSP (code_point))
-    {
-      CHECK_NATNUM_CAR (code_point);
-      CHECK_NATNUM_CDR (code_point);
-      code = (XINT (XCAR (code_point)) << 16) | (XINT (XCDR (code_point)));
-    }
-  else
-    {
-      CHECK_NATNUM (code_point);
-      code = XINT (code_point);
-    }
+  code = cons_to_unsigned (code_point, UINT_MAX);
   charsetp = CHARSET_FROM_ID (id);
   c = DECODE_CHAR (charsetp, code);
   return (c >= 0 ? make_number (c) : Qnil);
@@ -1900,9 +1872,7 @@ code-point in CCS.  Currently not supported and just ignored.  */)
   code = ENCODE_CHAR (charsetp, XINT (ch));
   if (code == CHARSET_INVALID_CODE (charsetp))
     return Qnil;
-  if (code > 0x7FFFFFF)
-    return Fcons (make_number (code >> 16), make_number (code & 0xFFFF));
-  return make_number (code);
+  return INTEGER_TO_CONS (code);
 }
 
 
index cc8ca10a1394ee4916c5c7063fd83743c7105aa5..0f81911f0b02bc80a90b8513bed22e2007136dba 100644 (file)
@@ -265,10 +265,7 @@ enum lglyph_indices
 #define LGLYPH_CODE(g)                                         \
   (NILP (AREF ((g), LGLYPH_IX_CODE))                           \
    ? FONT_INVALID_CODE                                         \
-   : CONSP (AREF ((g), LGLYPH_IX_CODE))                                \
-   ? ((XFASTINT (XCAR (AREF ((g), LGLYPH_IX_CODE))) << 16)     \
-      | (XFASTINT (XCDR (AREF ((g), LGLYPH_IX_CODE)))))                \
-   : XFASTINT (AREF ((g), LGLYPH_IX_CODE)))
+   : cons_to_unsigned (AREF (g, LGLYPH_IX_CODE), TYPE_MAXIMUM (unsigned)))
 #define LGLYPH_WIDTH(g) XINT (AREF ((g), LGLYPH_IX_WIDTH))
 #define LGLYPH_LBEARING(g) XINT (AREF ((g), LGLYPH_IX_LBEARING))
 #define LGLYPH_RBEARING(g) XINT (AREF ((g), LGLYPH_IX_RBEARING))
@@ -280,15 +277,8 @@ enum lglyph_indices
 #define LGLYPH_SET_CHAR(g, val) ASET ((g), LGLYPH_IX_CHAR, make_number (val))
 /* Callers must assure that VAL is not negative!  */
 #define LGLYPH_SET_CODE(g, val)                                                \
-  do {                                                                 \
-    if (val == FONT_INVALID_CODE)                                      \
-      ASET ((g), LGLYPH_IX_CODE, Qnil);                                        \
-    else if ((EMACS_INT)val > MOST_POSITIVE_FIXNUM)                    \
-      ASET ((g), LGLYPH_IX_CODE, Fcons (make_number ((val) >> 16),     \
-                                       make_number ((val) & 0xFFFF))); \
-    else                                                               \
-      ASET ((g), LGLYPH_IX_CODE, make_number (val));                   \
-  } while (0)
+  ASET (g, LGLYPH_IX_CODE,                                             \
+       val == FONT_INVALID_CODE ? Qnil : INTEGER_TO_CONS (val))
 
 #define LGLYPH_SET_WIDTH(g, val) ASET ((g), LGLYPH_IX_WIDTH, make_number (val))
 #define LGLYPH_SET_LBEARING(g, val) ASET ((g), LGLYPH_IX_LBEARING, make_number (val))
index 78bd454056d3298b36557d5164b79172303b494c..a41ffe7a1f6fd091a0e8e1201b3a3e7d82517eed 100644 (file)
@@ -2326,33 +2326,110 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0,
   return Qnil;
 }
 \f
-/* Convert between long values and pairs of Lisp integers.
-   Note that long_to_cons returns a single Lisp integer
-   when the value fits in one.  */
+/* Convert the cons-of-integers, integer, or float value C to an
+   unsigned value with maximum value MAX.  Signal an error if C does not
+   have a valid format or is out of range.  */
+uintmax_t
+cons_to_unsigned (Lisp_Object c, uintmax_t max)
+{
+  int valid = 0;
+  uintmax_t val IF_LINT (= 0);
+  if (INTEGERP (c))
+    {
+      valid = 0 <= XINT (c);
+      val = XINT (c);
+    }
+  else if (FLOATP (c))
+    {
+      double d = XFLOAT_DATA (c);
+      if (0 <= d
+         && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1))
+       {
+         val = d;
+         valid = 1;
+       }
+    }
+  else if (CONSP (c) && NATNUMP (XCAR (c)))
+    {
+      uintmax_t top = XFASTINT (XCAR (c));
+      Lisp_Object rest = XCDR (c);
+      if (top <= UINTMAX_MAX >> 24 >> 16
+         && CONSP (rest)
+         && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
+         && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
+       {
+         uintmax_t mid = XFASTINT (XCAR (rest));
+         val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
+         valid = 1;
+       }
+      else if (top <= UINTMAX_MAX >> 16)
+       {
+         if (CONSP (rest))
+           rest = XCAR (rest);
+         if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
+           {
+             val = top << 16 | XFASTINT (rest);
+             valid = 1;
+           }
+       }
+    }
 
-Lisp_Object
-long_to_cons (long unsigned int i)
-{
-  unsigned long top = i >> 16;
-  unsigned int bot = i & 0xFFFF;
-  if (top == 0)
-    return make_number (bot);
-  if (top == (unsigned long)-1 >> 16)
-    return Fcons (make_number (-1), make_number (bot));
-  return Fcons (make_number (top), make_number (bot));
+  if (! (valid && val <= max))
+    error ("Not an in-range integer, float, or cons of integers");
+  return val;
 }
 
-unsigned long
-cons_to_long (Lisp_Object c)
+/* Convert the cons-of-integers, integer, or float value C to a signed
+   value with extrema MIN and MAX.  Signal an error if C does not have
+   a valid format or is out of range.  */
+intmax_t
+cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
 {
-  Lisp_Object top, bot;
+  int valid = 0;
+  intmax_t val IF_LINT (= 0);
   if (INTEGERP (c))
-    return XINT (c);
-  top = XCAR (c);
-  bot = XCDR (c);
-  if (CONSP (bot))
-    bot = XCAR (bot);
-  return ((XINT (top) << 16) | XINT (bot));
+    {
+      val = XINT (c);
+      valid = 1;
+    }
+  else if (FLOATP (c))
+    {
+      double d = XFLOAT_DATA (c);
+      if (min <= d
+         && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1))
+       {
+         val = d;
+         valid = 1;
+       }
+    }
+  else if (CONSP (c) && INTEGERP (XCAR (c)))
+    {
+      intmax_t top = XINT (XCAR (c));
+      Lisp_Object rest = XCDR (c);
+      if (INTMAX_MIN >> 24 >> 16 <= top && top <= INTMAX_MAX >> 24 >> 16
+         && CONSP (rest)
+         && NATNUMP (XCAR (rest)) && XFASTINT (XCAR (rest)) < 1 << 24
+         && NATNUMP (XCDR (rest)) && XFASTINT (XCDR (rest)) < 1 << 16)
+       {
+         intmax_t mid = XFASTINT (XCAR (rest));
+         val = top << 24 << 16 | mid << 16 | XFASTINT (XCDR (rest));
+         valid = 1;
+       }
+      else if (INTMAX_MIN >> 16 <= top && top <= INTMAX_MAX >> 16)
+       {
+         if (CONSP (rest))
+           rest = XCAR (rest);
+         if (NATNUMP (rest) && XFASTINT (rest) < 1 << 16)
+           {
+             val = top << 16 | XFASTINT (rest);
+             valid = 1;
+           }
+       }
+    }
+
+  if (! (valid && min <= val && val <= max))
+    error ("Not an in-range integer, float, or cons of integers");
+  return val;
 }
 \f
 DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,
index 1e587353f6d61d1d1a77718560767c5fe776991c..a95882060fbd2e3725a47c51292a3ae01e7ef386 100644 (file)
@@ -900,11 +900,10 @@ Elements of the attribute list are:
   This is a floating point number if the size is too large for an integer.
  8. File modes, as a string of ten letters or dashes as in ls -l.
  9. t if file's gid would change if file were deleted and recreated.
-10. inode number.  If inode number is larger than what Emacs integer
-  can hold, but still fits into a 32-bit number, this is a cons cell
-  containing two integers: first the high part, then the low 16 bits.
-  If the inode number is wider than 32 bits, this is of the form
-  (HIGH MIDDLE . LOW): first the high 24 bits, then middle 24 bits,
+10. inode number.  If it is larger than what an Emacs integer can hold,
+  this is of the form (HIGH . LOW): first the high bits, then the low 16 bits.
+  If even HIGH is too large for an Emacs integer, this is instead of the form
+  (HIGH MIDDLE . LOW): first the high bits, then the middle 24 bits,
   and finally the low 16 bits.
 11. Filesystem device number.  If it is larger than what the Emacs
   integer can hold, this is a cons cell, similar to the inode number.
@@ -998,34 +997,8 @@ so last access time will always be midnight of that day.  */)
 #else                                  /* file gid will be egid */
   values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
 #endif /* not BSD4_2 */
-  if (!FIXNUM_OVERFLOW_P (s.st_ino))
-    /* Keep the most common cases as integers.  */
-    values[10] = make_number (s.st_ino);
-  else if (!FIXNUM_OVERFLOW_P (s.st_ino >> 16))
-    /* To allow inode numbers larger than VALBITS, separate the bottom
-       16 bits.  */
-    values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
-                       make_number ((EMACS_INT)(s.st_ino & 0xffff)));
-  else
-    {
-      /* To allow inode numbers beyond 32 bits, separate into 2 24-bit
-        high parts and a 16-bit bottom part.
-        The code on the next line avoids a compiler warning on
-        systems where st_ino is 32 bit wide. (bug#766).  */
-      EMACS_INT high_ino = s.st_ino >> 31 >> 1;
-
-      values[10] = Fcons (make_number (high_ino >> 8),
-                         Fcons (make_number (((high_ino & 0xff) << 16)
-                                             + (s.st_ino >> 16 & 0xffff)),
-                                make_number (s.st_ino & 0xffff)));
-    }
-
-  /* Likewise for device.  */
-  if (FIXNUM_OVERFLOW_P (s.st_dev))
-    values[11] = Fcons (make_number (s.st_dev >> 16),
-                       make_number (s.st_dev & 0xffff));
-  else
-    values[11] = make_number (s.st_dev);
+  values[10] = INTEGER_TO_CONS (s.st_ino);
+  values[11] = INTEGER_TO_CONS (s.st_dev);
 
   return Flist (sizeof(values) / sizeof(values[0]), values);
 }
index 82b31036fb9a13abdde2236b5c5ae2b473320730..d9bc28d8c37957bbd8c9cb8c353910db1f2d2a52 100644 (file)
@@ -5005,7 +5005,7 @@ An argument specifies the modification time value to use
 {
   if (!NILP (time_list))
     {
-      current_buffer->modtime = cons_to_long (time_list);
+      CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
       current_buffer->modtime_size = -1;
     }
   else
index 398198324a451b57927a42a23ba3185a88603d22..326c9d80e44b6a9ca212b321d3067c82ce9c057b 100644 (file)
@@ -4388,16 +4388,8 @@ where
   for (i = 0; i < 255; i++)
     if (variations[i])
       {
-       Lisp_Object code;
        int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
-       /* Stops GCC whining about limited range of data type.  */
-       EMACS_INT var = variations[i];
-
-       if (var > MOST_POSITIVE_FIXNUM)
-         code = Fcons (make_number ((variations[i]) >> 16),
-                       make_number ((variations[i]) & 0xFFFF));
-       else
-         code = make_number (variations[i]);
+       Lisp_Object code = INTEGER_TO_CONS (variations[i]);
        val = Fcons (Fcons (make_number (vs), code), val);
       }
   return val;
index 46637b53b3e0dc85bc4fbeaca7ef4e4f5040102d..fec3c56b03675f4e666a309e24c73177dbf441f0 100644 (file)
@@ -1859,17 +1859,11 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
     {
       unsigned code = face->font->driver->encode_char (face->font, c);
       Lisp_Object font_object;
-      /* Assignment to EMACS_INT stops GCC whining about limited range
-        of data type.  */
-      EMACS_INT cod = code;
 
       if (code == FONT_INVALID_CODE)
        return Qnil;
       XSETFONT (font_object, face->font);
-      if (cod <= MOST_POSITIVE_FIXNUM)
-       return Fcons (font_object, make_number (code));
-      return Fcons (font_object, Fcons (make_number (code >> 16),
-                                    make_number (code & 0xFFFF)));
+      return Fcons (font_object, INTEGER_TO_CONS (code));
     }
   return Qnil;
 }
index a46436e718b9a63a87ba1f82a208e75f670a204b..1c1e3ec37082180ef9040591221c94655c614914 100644 (file)
@@ -24,6 +24,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stddef.h>
 #include <inttypes.h>
 
+#include <intprops.h>
+
 /* Use the configure flag --enable-checking[=LIST] to enable various
    types of run time checks for Lisp objects.  */
 
@@ -2408,9 +2410,35 @@ EXFUN (Fadd1, 1);
 EXFUN (Fsub1, 1);
 EXFUN (Fmake_variable_buffer_local, 1);
 
+/* Convert the integer I to an Emacs representation, either the integer
+   itself, or a cons of two or three integers, or if all else fails a float.
+   I should not have side effects.  */
+#define INTEGER_TO_CONS(i)                                         \
+  (! FIXNUM_OVERFLOW_P (i)                                         \
+   ? make_number (i)                                               \
+   : ! ((FIXNUM_OVERFLOW_P (INTMAX_MIN >> 16)                      \
+        || FIXNUM_OVERFLOW_P (UINTMAX_MAX >> 16))                  \
+       && FIXNUM_OVERFLOW_P ((i) >> 16))                           \
+   ? Fcons (make_number ((i) >> 16), make_number ((i) & 0xffff))    \
+   : ! ((FIXNUM_OVERFLOW_P (INTMAX_MIN >> 16 >> 24)                \
+        || FIXNUM_OVERFLOW_P (UINTMAX_MAX >> 16 >> 24))            \
+       && FIXNUM_OVERFLOW_P ((i) >> 16 >> 24))                     \
+   ? Fcons (make_number ((i) >> 16 >> 24),                         \
+           Fcons (make_number ((i) >> 16 & 0xffffff),              \
+                  make_number ((i) & 0xffff)))                     \
+   : make_float (i))
+
+/* Convert the Emacs representation CONS back to an integer of type
+   TYPE, storing the result the variable VAR.  Signal an error if CONS
+   is not a valid representation or is out of range for TYPE.  */
+#define CONS_TO_INTEGER(cons, type, var)                               \
+ (TYPE_SIGNED (type)                                                   \
+  ? ((var) = cons_to_signed (cons, TYPE_MINIMUM (type), TYPE_MAXIMUM (type))) \
+  : ((var) = cons_to_unsigned (cons, TYPE_MAXIMUM (type))))
+extern intmax_t cons_to_signed (Lisp_Object, intmax_t, intmax_t);
+extern uintmax_t cons_to_unsigned (Lisp_Object, uintmax_t);
+
 extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
-extern Lisp_Object long_to_cons (unsigned long);
-extern unsigned long cons_to_long (Lisp_Object);
 extern void args_out_of_range (Lisp_Object, Lisp_Object) NO_RETURN;
 extern void args_out_of_range_3 (Lisp_Object, Lisp_Object,
                                  Lisp_Object) NO_RETURN;
index 142960545a79d3a68d6048c317bee66a1b69715a..e7e9ae5632e5925a65708210272518ea817e5c3a 100644 (file)
@@ -212,7 +212,6 @@ record_change (EMACS_INT beg, EMACS_INT length)
 void
 record_first_change (void)
 {
-  Lisp_Object high, low;
   struct buffer *base_buffer = current_buffer;
 
   if (EQ (BVAR (current_buffer, undo_list), Qt))
@@ -225,9 +224,9 @@ record_first_change (void)
   if (base_buffer->base_buffer)
     base_buffer = base_buffer->base_buffer;
 
-  XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff);
-  XSETFASTINT (low, base_buffer->modtime & 0xffff);
-  BVAR (current_buffer, undo_list) = Fcons (Fcons (Qt, Fcons (high, low)), BVAR (current_buffer, undo_list));
+  BVAR (current_buffer, undo_list) =
+    Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)),
+          BVAR (current_buffer, undo_list));
 }
 
 /* Record a change in property PROP (whose old value was VAL)
@@ -499,13 +498,9 @@ Return what remains of the list.  */)
              if (EQ (car, Qt))
                {
                  /* Element (t high . low) records previous modtime.  */
-                 Lisp_Object high, low;
-                 time_t mod_time;
                  struct buffer *base_buffer = current_buffer;
-
-                 high = Fcar (cdr);
-                 low = Fcdr (cdr);
-                 mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
+                 time_t mod_time;
+                 CONS_TO_INTEGER (cdr, time_t, mod_time);
 
                  if (current_buffer->base_buffer)
                    base_buffer = current_buffer->base_buffer;
index 34ffdbffbfe665d4f3b9f4e4a411f244730b156f..c307cc345e3243fd16e65c78001b343a026d69cc 100644 (file)
@@ -4299,18 +4299,9 @@ no value of TYPE (always string in the MS Windows case).  */)
 
   if (! NILP (source))
     {
-      if (NUMBERP (source))
-        {
-          if (FLOATP (source))
-            target_window = (Window) XFLOAT (source);
-          else
-            target_window = XFASTINT (source);
-
-          if (target_window == 0)
-            target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
-        }
-      else if (CONSP (source))
-        target_window = cons_to_long (source);
+      CONS_TO_INTEGER (source, Window, target_window);
+      if (! target_window)
+       target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
     }
 
   BLOCK_INPUT;
index 00d70eee4777d7a20a1414c73ef50ad82e43963d..5b01fc22a42e99b7fb4d5d364ed2ddb121f8d512 100644 (file)
@@ -20,6 +20,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Rewritten by jwz */
 
 #include <config.h>
+#include <limits.h>
 #include <stdio.h>      /* termhooks.h needs this */
 #include <setjmp.h>
 
@@ -335,7 +336,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
     Lisp_Object prev_value;
 
     selection_data = list4 (selection_name, selection_value,
-                           long_to_cons (timestamp), frame);
+                           INTEGER_TO_CONS (timestamp), frame);
     prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
 
     dpyinfo->terminal->Vselection_alist
@@ -419,7 +420,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
       || INTEGERP (check)
       || NILP (value))
     return value;
-  /* Check for a value that cons_to_long could handle.  */
+  /* Check for a value that CONS_TO_INTEGER could handle.  */
   else if (CONSP (check)
           && INTEGERP (XCAR (check))
           && (INTEGERP (XCDR (check))
@@ -782,8 +783,8 @@ x_handle_selection_request (struct input_event *event)
   if (NILP (local_selection_data)) goto DONE;
 
   /* Decline requests issued prior to our acquiring the selection.  */
-  local_selection_time
-    = (Time) cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
+  CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
+                  Time, local_selection_time);
   if (SELECTION_EVENT_TIME (event) != CurrentTime
       && local_selection_time > SELECTION_EVENT_TIME (event))
     goto DONE;
@@ -950,8 +951,8 @@ x_handle_selection_clear (struct input_event *event)
   /* Well, we already believe that we don't own it, so that's just fine.  */
   if (NILP (local_selection_data)) return;
 
-  local_selection_time = (Time)
-    cons_to_long (XCAR (XCDR (XCDR (local_selection_data))));
+  CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
+                  Time, local_selection_time);
 
   /* We have reasserted the selection since this SelectionClear was
      generated, so we can disregard it.  */
@@ -1212,16 +1213,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
     return Qnil;
 
   if (! NILP (time_stamp))
-    {
-      if (CONSP (time_stamp))
-        requestor_time = (Time) cons_to_long (time_stamp);
-      else if (INTEGERP (time_stamp))
-        requestor_time = (Time) XUINT (time_stamp);
-      else if (FLOATP (time_stamp))
-        requestor_time = (Time) XFLOAT_DATA (time_stamp);
-      else
-        error ("TIME_STAMP must be cons or number");
-    }
+    CONS_TO_INTEGER (time_stamp, Time, requestor_time);
 
   BLOCK_INPUT;
   TRACE2 ("Get selection %s, type %s",
@@ -1639,7 +1631,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
      convert it to a cons of integers, 16 bits in each half.
    */
   else if (format == 32 && size == sizeof (int))
-    return long_to_cons (((unsigned int *) data) [0]);
+    return INTEGER_TO_CONS (((unsigned int *) data) [0]);
   else if (format == 16 && size == sizeof (short))
     return make_number ((int) (((unsigned short *) data) [0]));
 
@@ -1665,7 +1657,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
       for (i = 0; i < size / 4; i++)
        {
          unsigned int j = ((unsigned int *) data) [i];
-         Faset (v, make_number (i), long_to_cons (j));
+         Faset (v, make_number (i), INTEGER_TO_CONS (j));
        }
       return v;
     }
@@ -1742,7 +1734,7 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
       *size_ret = 1;
       *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
       (*data_ret) [sizeof (long)] = 0;
-      (*(unsigned long **) data_ret) [0] = cons_to_long (obj);
+      (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX);
       if (NILP (type)) type = QINTEGER;
     }
   else if (VECTORP (obj))
@@ -1790,11 +1782,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
          *data_ret = (unsigned char *) xmalloc (*size_ret * data_size);
          for (i = 0; i < *size_ret; i++)
            if (*format_ret == 32)
-             (*((unsigned long **) data_ret)) [i]
-               = cons_to_long (XVECTOR (obj)->contents [i]);
+             (*((unsigned long **) data_ret)) [i] =
+               cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX);
            else
-             (*((unsigned short **) data_ret)) [i]
-               = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]);
+             (*((unsigned short **) data_ret)) [i] =
+               cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX);
        }
     }
   else
@@ -2012,8 +2004,10 @@ frame's display, or the first available X display.  */)
   selection_atom = symbol_to_x_atom (dpyinfo, selection);
 
   BLOCK_INPUT;
-  timestamp = (NILP (time_object) ? last_event_timestamp
-              : cons_to_long (time_object));
+  if (NILP (time_object))
+    timestamp = last_event_timestamp;
+  else
+    CONS_TO_INTEGER (time_object, Time, timestamp);
   XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
   UNBLOCK_INPUT;
 
@@ -2250,12 +2244,8 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
     {
       Lisp_Object o = XCAR (iter);
 
-      if (INTEGERP (o))
-        val = (long) XFASTINT (o);
-      else if (FLOATP (o))
-        val = (long) XFLOAT_DATA (o);
-      else if (CONSP (o))
-        val = (long) cons_to_long (o);
+      if (INTEGERP (o) || FLOATP (o) || CONSP (o))
+       val = cons_to_signed (o, LONG_MIN, LONG_MAX);
       else if (STRINGP (o))
         {
           BLOCK_INPUT;
@@ -2266,9 +2256,19 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
         error ("Wrong type, must be string, number or cons");
 
       if (format == 8)
-        *d08++ = (char) val;
+       {
+         if (CHAR_MIN <= val && val <= CHAR_MAX)
+           *d08++ = val;
+         else
+           error ("Out of 'char' range");
+       }
       else if (format == 16)
-        *d16++ = (short) val;
+       {
+         if (SHRT_MIN <= val && val <= SHRT_MAX)
+           *d16++ = val;
+         else
+           error ("Out of 'short' range");
+       }
       else
         *d32++ = val;
     }
@@ -2352,14 +2352,7 @@ If the value is 0 or the atom is not known, return the empty string.  */)
   Atom atom;
   int had_errors;
 
-  if (INTEGERP (value))
-    atom = (Atom) XUINT (value);
-  else if (FLOATP (value))
-    atom = (Atom) XFLOAT_DATA (value);
-  else if (CONSP (value))
-    atom = (Atom) cons_to_long (value);
-  else
-    error ("Wrong type, value must be number or cons");
+  CONS_TO_INTEGER (value, Atom, atom);
 
   BLOCK_INPUT;
   x_catch_errors (dpy);
@@ -2549,17 +2542,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, At
       else
         error ("DEST as a string must be one of PointerWindow or InputFocus");
     }
-  else if (INTEGERP (dest))
-    wdest = (Window) XFASTINT (dest);
-  else if (FLOATP (dest))
-    wdest =  (Window) XFLOAT_DATA (dest);
-  else if (CONSP (dest))
-    {
-      if (! NUMBERP (XCAR (dest)) || ! NUMBERP (XCDR (dest)))
-        error ("Both car and cdr for DEST must be numbers");
-      else
-        wdest = (Window) cons_to_long (dest);
-    }
+  else if (INTEGERP (dest) || FLOATP (dest) || CONSP (dest))
+    CONS_TO_INTEGER (dest, Window, wdest);
   else
     error ("DEST must be a frame, nil, string, number or cons");