aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-06-03 12:02:25 -0700
committerPaul Eggert2011-06-03 12:02:25 -0700
commit201f31ae3de0b747b47863b93d6f6a747c36c960 (patch)
tree800c2c66fc648660cb957df676ea59cc911ae0fa /src
parentbe14b9ab109c8deb5745dc47cbc471e97be06486 (diff)
downloademacs-201f31ae3de0b747b47863b93d6f6a747c36c960.tar.gz
emacs-201f31ae3de0b747b47863b93d6f6a747c36c960.zip
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 (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 (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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog27
-rw-r--r--src/charset.c38
-rw-r--r--src/composite.h16
-rw-r--r--src/data.c100
-rw-r--r--src/dired.c39
-rw-r--r--src/fileio.c2
-rw-r--r--src/font.c10
-rw-r--r--src/fontset.c8
-rw-r--r--src/lisp.h28
-rw-r--r--src/undo.c15
-rw-r--r--src/xfns.c15
-rw-r--r--src/xselect.c87
12 files changed, 189 insertions, 196 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 857600fda0c..20308d40ab0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,32 @@
12011-06-03 Paul Eggert <eggert@cs.ucla.edu> 12011-06-03 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Check for overflow when converting integer to cons and back.
4 * charset.c (Fdefine_charset_internal, Fdecode_char):
5 Use cons_to_unsigned to catch overflow.
6 (Fencode_char): Use INTEGER_TO_CONS.
7 * composite.h (LGLYPH_CODE): Use cons_to_unsigned.
8 (LGLYPH_SET_CODE): Use INTEGER_TO_CONS.
9 * data.c (long_to_cons, cons_to_long): Remove.
10 (cons_to_unsigned, cons_to_signed): New functions.
11 These signal an error for invalid or out-of-range values.
12 * dired.c (Ffile_attributes): Use INTEGER_TO_CONS.
13 * fileio.c (Fset_visited_file_modtime): Use CONS_TO_INTEGER.
14 * font.c (Ffont_variation_glyphs):
15 * fontset.c (Finternal_char_font): Use INTEGER_TO_CONS.
16 * lisp.h (INTEGER_TO_CONS, CONS_TO_INTEGER): New macros.
17 (cons_to_signed, cons_to_unsigned): New decls.
18 (long_to_cons, cons_to_long): Remove decls.
19 * undo.c (record_first_change): Use INTEGER_TO_CONS.
20 (Fprimitive_undo): Use CONS_TO_INTEGER.
21 * xfns.c (Fx_window_property): Likewise.
22 * xselect.c (x_own_selection, selection_data_to_lisp_data):
23 Use INTEGER_TO_CONS.
24 (x_handle_selection_request, x_handle_selection_clear)
25 (x_get_foreign_selection, Fx_disown_selection_internal)
26 (Fx_get_atom_name, x_send_client_event): Use CONS_TO_INTEGER.
27 (lisp_data_to_selection_data): Use cons_to_unsigned.
28 (x_fill_property_data): Use cons_to_signed. Report values out of range.
29
3 Fix doc for machines with wider system times such as time_t. 30 Fix doc for machines with wider system times such as time_t.
4 On such machines, it's now safe to assume that EMACS_INT is as 31 On such machines, it's now safe to assume that EMACS_INT is as
5 wide as the system times, so that shifting right by 16 will 32 wide as the system times, so that shifting right by 16 will
diff --git a/src/charset.c b/src/charset.c
index bfebe02f52e..770e98c99e1 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -932,17 +932,8 @@ usage: (define-charset-internal ...) */)
932 val = args[charset_arg_min_code]; 932 val = args[charset_arg_min_code];
933 if (! NILP (val)) 933 if (! NILP (val))
934 { 934 {
935 unsigned code; 935 unsigned code = cons_to_unsigned (val, UINT_MAX);
936 936
937 if (INTEGERP (val))
938 code = XINT (val);
939 else
940 {
941 CHECK_CONS (val);
942 CHECK_NUMBER_CAR (val);
943 CHECK_NUMBER_CDR (val);
944 code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
945 }
946 if (code < charset.min_code 937 if (code < charset.min_code
947 || code > charset.max_code) 938 || code > charset.max_code)
948 args_out_of_range_3 (make_number (charset.min_code), 939 args_out_of_range_3 (make_number (charset.min_code),
@@ -954,17 +945,8 @@ usage: (define-charset-internal ...) */)
954 val = args[charset_arg_max_code]; 945 val = args[charset_arg_max_code];
955 if (! NILP (val)) 946 if (! NILP (val))
956 { 947 {
957 unsigned code; 948 unsigned code = cons_to_unsigned (val, UINT_MAX);
958 949
959 if (INTEGERP (val))
960 code = XINT (val);
961 else
962 {
963 CHECK_CONS (val);
964 CHECK_NUMBER_CAR (val);
965 CHECK_NUMBER_CDR (val);
966 code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val)));
967 }
968 if (code < charset.min_code 950 if (code < charset.min_code
969 || code > charset.max_code) 951 || code > charset.max_code)
970 args_out_of_range_3 (make_number (charset.min_code), 952 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. */)
1865 struct charset *charsetp; 1847 struct charset *charsetp;
1866 1848
1867 CHECK_CHARSET_GET_ID (charset, id); 1849 CHECK_CHARSET_GET_ID (charset, id);
1868 if (CONSP (code_point)) 1850 code = cons_to_unsigned (code_point, UINT_MAX);
1869 {
1870 CHECK_NATNUM_CAR (code_point);
1871 CHECK_NATNUM_CDR (code_point);
1872 code = (XINT (XCAR (code_point)) << 16) | (XINT (XCDR (code_point)));
1873 }
1874 else
1875 {
1876 CHECK_NATNUM (code_point);
1877 code = XINT (code_point);
1878 }
1879 charsetp = CHARSET_FROM_ID (id); 1851 charsetp = CHARSET_FROM_ID (id);
1880 c = DECODE_CHAR (charsetp, code); 1852 c = DECODE_CHAR (charsetp, code);
1881 return (c >= 0 ? make_number (c) : Qnil); 1853 return (c >= 0 ? make_number (c) : Qnil);
@@ -1900,9 +1872,7 @@ code-point in CCS. Currently not supported and just ignored. */)
1900 code = ENCODE_CHAR (charsetp, XINT (ch)); 1872 code = ENCODE_CHAR (charsetp, XINT (ch));
1901 if (code == CHARSET_INVALID_CODE (charsetp)) 1873 if (code == CHARSET_INVALID_CODE (charsetp))
1902 return Qnil; 1874 return Qnil;
1903 if (code > 0x7FFFFFF) 1875 return INTEGER_TO_CONS (code);
1904 return Fcons (make_number (code >> 16), make_number (code & 0xFFFF));
1905 return make_number (code);
1906} 1876}
1907 1877
1908 1878
diff --git a/src/composite.h b/src/composite.h
index cc8ca10a139..0f81911f0b0 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -265,10 +265,7 @@ enum lglyph_indices
265#define LGLYPH_CODE(g) \ 265#define LGLYPH_CODE(g) \
266 (NILP (AREF ((g), LGLYPH_IX_CODE)) \ 266 (NILP (AREF ((g), LGLYPH_IX_CODE)) \
267 ? FONT_INVALID_CODE \ 267 ? FONT_INVALID_CODE \
268 : CONSP (AREF ((g), LGLYPH_IX_CODE)) \ 268 : cons_to_unsigned (AREF (g, LGLYPH_IX_CODE), TYPE_MAXIMUM (unsigned)))
269 ? ((XFASTINT (XCAR (AREF ((g), LGLYPH_IX_CODE))) << 16) \
270 | (XFASTINT (XCDR (AREF ((g), LGLYPH_IX_CODE))))) \
271 : XFASTINT (AREF ((g), LGLYPH_IX_CODE)))
272#define LGLYPH_WIDTH(g) XINT (AREF ((g), LGLYPH_IX_WIDTH)) 269#define LGLYPH_WIDTH(g) XINT (AREF ((g), LGLYPH_IX_WIDTH))
273#define LGLYPH_LBEARING(g) XINT (AREF ((g), LGLYPH_IX_LBEARING)) 270#define LGLYPH_LBEARING(g) XINT (AREF ((g), LGLYPH_IX_LBEARING))
274#define LGLYPH_RBEARING(g) XINT (AREF ((g), LGLYPH_IX_RBEARING)) 271#define LGLYPH_RBEARING(g) XINT (AREF ((g), LGLYPH_IX_RBEARING))
@@ -280,15 +277,8 @@ enum lglyph_indices
280#define LGLYPH_SET_CHAR(g, val) ASET ((g), LGLYPH_IX_CHAR, make_number (val)) 277#define LGLYPH_SET_CHAR(g, val) ASET ((g), LGLYPH_IX_CHAR, make_number (val))
281/* Callers must assure that VAL is not negative! */ 278/* Callers must assure that VAL is not negative! */
282#define LGLYPH_SET_CODE(g, val) \ 279#define LGLYPH_SET_CODE(g, val) \
283 do { \ 280 ASET (g, LGLYPH_IX_CODE, \
284 if (val == FONT_INVALID_CODE) \ 281 val == FONT_INVALID_CODE ? Qnil : INTEGER_TO_CONS (val))
285 ASET ((g), LGLYPH_IX_CODE, Qnil); \
286 else if ((EMACS_INT)val > MOST_POSITIVE_FIXNUM) \
287 ASET ((g), LGLYPH_IX_CODE, Fcons (make_number ((val) >> 16), \
288 make_number ((val) & 0xFFFF))); \
289 else \
290 ASET ((g), LGLYPH_IX_CODE, make_number (val)); \
291 } while (0)
292 282
293#define LGLYPH_SET_WIDTH(g, val) ASET ((g), LGLYPH_IX_WIDTH, make_number (val)) 283#define LGLYPH_SET_WIDTH(g, val) ASET ((g), LGLYPH_IX_WIDTH, make_number (val))
294#define LGLYPH_SET_LBEARING(g, val) ASET ((g), LGLYPH_IX_LBEARING, make_number (val)) 284#define LGLYPH_SET_LBEARING(g, val) ASET ((g), LGLYPH_IX_LBEARING, make_number (val))
diff --git a/src/data.c b/src/data.c
index 522f0156ebd..408234f25cb 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2324,33 +2324,89 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0,
2324 return Qnil; 2324 return Qnil;
2325} 2325}
2326 2326
2327/* Convert between long values and pairs of Lisp integers. 2327/* Convert the cons-of-integers, integer, or float value C to an
2328 Note that long_to_cons returns a single Lisp integer 2328 unsigned value with maximum value MAX. Signal an error if C does not
2329 when the value fits in one. */ 2329 have a valid format or is out of range. */
2330uintmax_t
2331cons_to_unsigned (Lisp_Object c, uintmax_t max)
2332{
2333 int valid = 0;
2334 uintmax_t val IF_LINT (= 0);
2335 if (INTEGERP (c))
2336 {
2337 valid = 0 <= XINT (c);
2338 val = XINT (c);
2339 }
2340 else if (FLOATP (c))
2341 {
2342 double d = XFLOAT_DATA (c);
2343 if (0 <= d
2344 && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1))
2345 {
2346 val = d;
2347 valid = 1;
2348 }
2349 }
2350 else if (CONSP (c))
2351 {
2352 Lisp_Object top = XCAR (c);
2353 Lisp_Object bot = XCDR (c);
2354 if (CONSP (bot))
2355 bot = XCAR (bot);
2356 if (NATNUMP (top) && XFASTINT (top) <= UINTMAX_MAX >> 16 && NATNUMP (bot))
2357 {
2358 uintmax_t utop = XFASTINT (top);
2359 val = (utop << 16) | XFASTINT (bot);
2360 valid = 1;
2361 }
2362 }
2330 2363
2331Lisp_Object 2364 if (! (valid && val <= max))
2332long_to_cons (long unsigned int i) 2365 error ("Not an in-range integer, float, or cons of integers");
2333{ 2366 return val;
2334 unsigned long top = i >> 16;
2335 unsigned int bot = i & 0xFFFF;
2336 if (top == 0)
2337 return make_number (bot);
2338 if (top == (unsigned long)-1 >> 16)
2339 return Fcons (make_number (-1), make_number (bot));
2340 return Fcons (make_number (top), make_number (bot));
2341} 2367}
2342 2368
2343unsigned long 2369/* Convert the cons-of-integers, integer, or float value C to a signed
2344cons_to_long (Lisp_Object c) 2370 value with extrema MIN and MAX. Signal an error if C does not have
2371 a valid format or is out of range. */
2372intmax_t
2373cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max)
2345{ 2374{
2346 Lisp_Object top, bot; 2375 int valid = 0;
2376 intmax_t val IF_LINT (= 0);
2347 if (INTEGERP (c)) 2377 if (INTEGERP (c))
2348 return XINT (c); 2378 {
2349 top = XCAR (c); 2379 val = XINT (c);
2350 bot = XCDR (c); 2380 valid = 1;
2351 if (CONSP (bot)) 2381 }
2352 bot = XCAR (bot); 2382 else if (FLOATP (c))
2353 return ((XINT (top) << 16) | XINT (bot)); 2383 {
2384 double d = XFLOAT_DATA (c);
2385 if (min <= d
2386 && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1))
2387 {
2388 val = d;
2389 valid = 1;
2390 }
2391 }
2392 else if (CONSP (c))
2393 {
2394 Lisp_Object top = XCAR (c);
2395 Lisp_Object bot = XCDR (c);
2396 if (CONSP (bot))
2397 bot = XCAR (bot);
2398 if (INTEGERP (top) && INTMAX_MIN >> 16 <= XINT (top)
2399 && XINT (top) <= INTMAX_MAX >> 16 && INTEGERP (bot))
2400 {
2401 intmax_t itop = XINT (top);
2402 val = (itop << 16) | XINT (bot);
2403 valid = 1;
2404 }
2405 }
2406
2407 if (! (valid && min <= val && val <= max))
2408 error ("Not an in-range integer, float, or cons of integers");
2409 return val;
2354} 2410}
2355 2411
2356DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, 2412DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,
diff --git a/src/dired.c b/src/dired.c
index 0fe2ead56ef..3bf4fd9a023 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -900,12 +900,9 @@ Elements of the attribute list are:
900 This is a floating point number if the size is too large for an integer. 900 This is a floating point number if the size is too large for an integer.
901 8. File modes, as a string of ten letters or dashes as in ls -l. 901 8. File modes, as a string of ten letters or dashes as in ls -l.
902 9. t if file's gid would change if file were deleted and recreated. 902 9. t if file's gid would change if file were deleted and recreated.
90310. inode number. If inode number is larger than what Emacs integer 90310. inode number. If it is larger than what the Emacs integer
904 can hold, but all but the bottom 16 bits still fits, this is a cons cell 904 can hold, this is a cons cell containing two integers: first the
905 containing two integers: first the high part, then the low 16 bits. 905 high part, then the low 16 bits.
906 If the inode number is still wider, this is of the form
907 (HIGH MIDDLE . LOW): first the high bits, then the middle 24 bits,
908 and finally the low 16 bits.
90911. Filesystem device number. If it is larger than what the Emacs 90611. Filesystem device number. If it is larger than what the Emacs
910 integer can hold, this is a cons cell, similar to the inode number. 907 integer can hold, this is a cons cell, similar to the inode number.
911 908
@@ -998,34 +995,8 @@ so last access time will always be midnight of that day. */)
998#else /* file gid will be egid */ 995#else /* file gid will be egid */
999 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil; 996 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
1000#endif /* not BSD4_2 */ 997#endif /* not BSD4_2 */
1001 if (!FIXNUM_OVERFLOW_P (s.st_ino)) 998 values[10] = INTEGER_TO_CONS (s.st_ino);
1002 /* Keep the most common cases as integers. */ 999 values[11] = INTEGER_TO_CONS (s.st_dev);
1003 values[10] = make_number (s.st_ino);
1004 else if (!FIXNUM_OVERFLOW_P (s.st_ino >> 16))
1005 /* To allow inode numbers larger than VALBITS, separate the bottom
1006 16 bits. */
1007 values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
1008 make_number ((EMACS_INT)(s.st_ino & 0xffff)));
1009 else
1010 {
1011 /* To allow inode numbers beyond what INTEGER_TO_CONS can handle,
1012 separate into 2 24-bit high parts and a 16-bit bottom part.
1013 The code on the next line avoids a compiler warning on
1014 systems where st_ino is 32 bit wide. (bug#766). */
1015 EMACS_INT high_ino = s.st_ino >> 31 >> 1;
1016
1017 values[10] = Fcons (make_number (high_ino >> 8),
1018 Fcons (make_number (((high_ino & 0xff) << 16)
1019 + (s.st_ino >> 16 & 0xffff)),
1020 make_number (s.st_ino & 0xffff)));
1021 }
1022
1023 /* Likewise for device. */
1024 if (FIXNUM_OVERFLOW_P (s.st_dev))
1025 values[11] = Fcons (make_number (s.st_dev >> 16),
1026 make_number (s.st_dev & 0xffff));
1027 else
1028 values[11] = make_number (s.st_dev);
1029 1000
1030 return Flist (sizeof(values) / sizeof(values[0]), values); 1001 return Flist (sizeof(values) / sizeof(values[0]), values);
1031} 1002}
diff --git a/src/fileio.c b/src/fileio.c
index 48dac80a39f..2f7716d5b54 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5005,7 +5005,7 @@ An argument specifies the modification time value to use
5005{ 5005{
5006 if (!NILP (time_list)) 5006 if (!NILP (time_list))
5007 { 5007 {
5008 current_buffer->modtime = cons_to_long (time_list); 5008 CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
5009 current_buffer->modtime_size = -1; 5009 current_buffer->modtime_size = -1;
5010 } 5010 }
5011 else 5011 else
diff --git a/src/font.c b/src/font.c
index 398198324a4..326c9d80e44 100644
--- a/src/font.c
+++ b/src/font.c
@@ -4388,16 +4388,8 @@ where
4388 for (i = 0; i < 255; i++) 4388 for (i = 0; i < 255; i++)
4389 if (variations[i]) 4389 if (variations[i])
4390 { 4390 {
4391 Lisp_Object code;
4392 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16)); 4391 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4393 /* Stops GCC whining about limited range of data type. */ 4392 Lisp_Object code = INTEGER_TO_CONS (variations[i]);
4394 EMACS_INT var = variations[i];
4395
4396 if (var > MOST_POSITIVE_FIXNUM)
4397 code = Fcons (make_number ((variations[i]) >> 16),
4398 make_number ((variations[i]) & 0xFFFF));
4399 else
4400 code = make_number (variations[i]);
4401 val = Fcons (Fcons (make_number (vs), code), val); 4393 val = Fcons (Fcons (make_number (vs), code), val);
4402 } 4394 }
4403 return val; 4395 return val;
diff --git a/src/fontset.c b/src/fontset.c
index 46637b53b3e..fec3c56b036 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1859,17 +1859,11 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
1859 { 1859 {
1860 unsigned code = face->font->driver->encode_char (face->font, c); 1860 unsigned code = face->font->driver->encode_char (face->font, c);
1861 Lisp_Object font_object; 1861 Lisp_Object font_object;
1862 /* Assignment to EMACS_INT stops GCC whining about limited range
1863 of data type. */
1864 EMACS_INT cod = code;
1865 1862
1866 if (code == FONT_INVALID_CODE) 1863 if (code == FONT_INVALID_CODE)
1867 return Qnil; 1864 return Qnil;
1868 XSETFONT (font_object, face->font); 1865 XSETFONT (font_object, face->font);
1869 if (cod <= MOST_POSITIVE_FIXNUM) 1866 return Fcons (font_object, INTEGER_TO_CONS (code));
1870 return Fcons (font_object, make_number (code));
1871 return Fcons (font_object, Fcons (make_number (code >> 16),
1872 make_number (code & 0xFFFF)));
1873 } 1867 }
1874 return Qnil; 1868 return Qnil;
1875} 1869}
diff --git a/src/lisp.h b/src/lisp.h
index e694bbcc58e..1defda151ae 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2405,9 +2405,33 @@ EXFUN (Fadd1, 1);
2405EXFUN (Fsub1, 1); 2405EXFUN (Fsub1, 1);
2406EXFUN (Fmake_variable_buffer_local, 1); 2406EXFUN (Fmake_variable_buffer_local, 1);
2407 2407
2408/* Convert the integer I to an Emacs representation, either the integer
2409 itself, or a cons of two integers, or if all else fails a float.
2410 The float might lose information; this happens only in extreme cases
2411 such as 32-bit EMACS_INT and 64-bit time_t with outlandish time values,
2412 and these aren't worth complicating the interface.
2413
2414 I should not have side effects. */
2415#define INTEGER_TO_CONS(i) \
2416 (! FIXNUM_OVERFLOW_P (i) \
2417 ? make_number (i) \
2418 : ! ((FIXNUM_OVERFLOW_P (INTMAX_MIN >> 16) \
2419 || FIXNUM_OVERFLOW_P (UINTMAX_MAX >> 16)) \
2420 && FIXNUM_OVERFLOW_P ((i) >> 16)) \
2421 ? Fcons (make_number ((i) >> 16), make_number ((i) & 0xffff)) \
2422 : make_float (i))
2423
2424/* Convert the Emacs representation CONS back to an integer of type
2425 TYPE, storing the result the variable VAR. Signal an error if CONS
2426 is not a valid representation or is out of range for TYPE. */
2427#define CONS_TO_INTEGER(cons, type, var) \
2428 (TYPE_SIGNED (type) \
2429 ? ((var) = cons_to_signed (cons, TYPE_MINIMUM (type), TYPE_MAXIMUM (type))) \
2430 : ((var) = cons_to_unsigned (cons, TYPE_MAXIMUM (type))))
2431extern intmax_t cons_to_signed (Lisp_Object, intmax_t, intmax_t);
2432extern uintmax_t cons_to_unsigned (Lisp_Object, uintmax_t);
2433
2408extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *); 2434extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
2409extern Lisp_Object long_to_cons (unsigned long);
2410extern unsigned long cons_to_long (Lisp_Object);
2411extern void args_out_of_range (Lisp_Object, Lisp_Object) NO_RETURN; 2435extern void args_out_of_range (Lisp_Object, Lisp_Object) NO_RETURN;
2412extern void args_out_of_range_3 (Lisp_Object, Lisp_Object, 2436extern void args_out_of_range_3 (Lisp_Object, Lisp_Object,
2413 Lisp_Object) NO_RETURN; 2437 Lisp_Object) NO_RETURN;
diff --git a/src/undo.c b/src/undo.c
index 142960545a7..e7e9ae5632e 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -212,7 +212,6 @@ record_change (EMACS_INT beg, EMACS_INT length)
212void 212void
213record_first_change (void) 213record_first_change (void)
214{ 214{
215 Lisp_Object high, low;
216 struct buffer *base_buffer = current_buffer; 215 struct buffer *base_buffer = current_buffer;
217 216
218 if (EQ (BVAR (current_buffer, undo_list), Qt)) 217 if (EQ (BVAR (current_buffer, undo_list), Qt))
@@ -225,9 +224,9 @@ record_first_change (void)
225 if (base_buffer->base_buffer) 224 if (base_buffer->base_buffer)
226 base_buffer = base_buffer->base_buffer; 225 base_buffer = base_buffer->base_buffer;
227 226
228 XSETFASTINT (high, (base_buffer->modtime >> 16) & 0xffff); 227 BVAR (current_buffer, undo_list) =
229 XSETFASTINT (low, base_buffer->modtime & 0xffff); 228 Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)),
230 BVAR (current_buffer, undo_list) = Fcons (Fcons (Qt, Fcons (high, low)), BVAR (current_buffer, undo_list)); 229 BVAR (current_buffer, undo_list));
231} 230}
232 231
233/* Record a change in property PROP (whose old value was VAL) 232/* Record a change in property PROP (whose old value was VAL)
@@ -499,13 +498,9 @@ Return what remains of the list. */)
499 if (EQ (car, Qt)) 498 if (EQ (car, Qt))
500 { 499 {
501 /* Element (t high . low) records previous modtime. */ 500 /* Element (t high . low) records previous modtime. */
502 Lisp_Object high, low;
503 time_t mod_time;
504 struct buffer *base_buffer = current_buffer; 501 struct buffer *base_buffer = current_buffer;
505 502 time_t mod_time;
506 high = Fcar (cdr); 503 CONS_TO_INTEGER (cdr, time_t, mod_time);
507 low = Fcdr (cdr);
508 mod_time = (XFASTINT (high) << 16) + XFASTINT (low);
509 504
510 if (current_buffer->base_buffer) 505 if (current_buffer->base_buffer)
511 base_buffer = current_buffer->base_buffer; 506 base_buffer = current_buffer->base_buffer;
diff --git a/src/xfns.c b/src/xfns.c
index f3dc493ff85..1b425f602d9 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4295,18 +4295,9 @@ no value of TYPE (always string in the MS Windows case). */)
4295 4295
4296 if (! NILP (source)) 4296 if (! NILP (source))
4297 { 4297 {
4298 if (NUMBERP (source)) 4298 CONS_TO_INTEGER (source, Window, target_window);
4299 { 4299 if (! target_window)
4300 if (FLOATP (source)) 4300 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4301 target_window = (Window) XFLOAT (source);
4302 else
4303 target_window = XFASTINT (source);
4304
4305 if (target_window == 0)
4306 target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
4307 }
4308 else if (CONSP (source))
4309 target_window = cons_to_long (source);
4310 } 4301 }
4311 4302
4312 BLOCK_INPUT; 4303 BLOCK_INPUT;
diff --git a/src/xselect.c b/src/xselect.c
index ca2b1812a61..7545a44b1bc 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -335,7 +335,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
335 Lisp_Object prev_value; 335 Lisp_Object prev_value;
336 336
337 selection_data = list4 (selection_name, selection_value, 337 selection_data = list4 (selection_name, selection_value,
338 long_to_cons (timestamp), frame); 338 INTEGER_TO_CONS (timestamp), frame);
339 prev_value = LOCAL_SELECTION (selection_name, dpyinfo); 339 prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
340 340
341 dpyinfo->terminal->Vselection_alist 341 dpyinfo->terminal->Vselection_alist
@@ -419,7 +419,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
419 || INTEGERP (check) 419 || INTEGERP (check)
420 || NILP (value)) 420 || NILP (value))
421 return value; 421 return value;
422 /* Check for a value that cons_to_long could handle. */ 422 /* Check for a value that CONS_TO_INTEGER could handle. */
423 else if (CONSP (check) 423 else if (CONSP (check)
424 && INTEGERP (XCAR (check)) 424 && INTEGERP (XCAR (check))
425 && (INTEGERP (XCDR (check)) 425 && (INTEGERP (XCDR (check))
@@ -782,8 +782,8 @@ x_handle_selection_request (struct input_event *event)
782 if (NILP (local_selection_data)) goto DONE; 782 if (NILP (local_selection_data)) goto DONE;
783 783
784 /* Decline requests issued prior to our acquiring the selection. */ 784 /* Decline requests issued prior to our acquiring the selection. */
785 local_selection_time 785 CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
786 = (Time) cons_to_long (XCAR (XCDR (XCDR (local_selection_data)))); 786 Time, local_selection_time);
787 if (SELECTION_EVENT_TIME (event) != CurrentTime 787 if (SELECTION_EVENT_TIME (event) != CurrentTime
788 && local_selection_time > SELECTION_EVENT_TIME (event)) 788 && local_selection_time > SELECTION_EVENT_TIME (event))
789 goto DONE; 789 goto DONE;
@@ -950,8 +950,8 @@ x_handle_selection_clear (struct input_event *event)
950 /* Well, we already believe that we don't own it, so that's just fine. */ 950 /* Well, we already believe that we don't own it, so that's just fine. */
951 if (NILP (local_selection_data)) return; 951 if (NILP (local_selection_data)) return;
952 952
953 local_selection_time = (Time) 953 CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))),
954 cons_to_long (XCAR (XCDR (XCDR (local_selection_data)))); 954 Time, local_selection_time);
955 955
956 /* We have reasserted the selection since this SelectionClear was 956 /* We have reasserted the selection since this SelectionClear was
957 generated, so we can disregard it. */ 957 generated, so we can disregard it. */
@@ -1213,16 +1213,7 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
1213 return Qnil; 1213 return Qnil;
1214 1214
1215 if (! NILP (time_stamp)) 1215 if (! NILP (time_stamp))
1216 { 1216 CONS_TO_INTEGER (time_stamp, Time, requestor_time);
1217 if (CONSP (time_stamp))
1218 requestor_time = (Time) cons_to_long (time_stamp);
1219 else if (INTEGERP (time_stamp))
1220 requestor_time = (Time) XUINT (time_stamp);
1221 else if (FLOATP (time_stamp))
1222 requestor_time = (Time) XFLOAT_DATA (time_stamp);
1223 else
1224 error ("TIME_STAMP must be cons or number");
1225 }
1226 1217
1227 BLOCK_INPUT; 1218 BLOCK_INPUT;
1228 1219
@@ -1652,7 +1643,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1652 convert it to a cons of integers, 16 bits in each half. 1643 convert it to a cons of integers, 16 bits in each half.
1653 */ 1644 */
1654 else if (format == 32 && size == sizeof (unsigned int)) 1645 else if (format == 32 && size == sizeof (unsigned int))
1655 return long_to_cons (((unsigned int *) data) [0]); 1646 return INTEGER_TO_CONS (((unsigned int *) data) [0]);
1656 else if (format == 16 && size == sizeof (unsigned short)) 1647 else if (format == 16 && size == sizeof (unsigned short))
1657 return make_number ((int) (((unsigned short *) data) [0])); 1648 return make_number ((int) (((unsigned short *) data) [0]));
1658 1649
@@ -1678,7 +1669,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1678 for (i = 0; i < size / 4; i++) 1669 for (i = 0; i < size / 4; i++)
1679 { 1670 {
1680 unsigned int j = ((unsigned int *) data) [i]; 1671 unsigned int j = ((unsigned int *) data) [i];
1681 Faset (v, make_number (i), long_to_cons (j)); 1672 Faset (v, make_number (i), INTEGER_TO_CONS (j));
1682 } 1673 }
1683 return v; 1674 return v;
1684 } 1675 }
@@ -1755,7 +1746,7 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1755 *size_ret = 1; 1746 *size_ret = 1;
1756 *data_ret = (unsigned char *) xmalloc (sizeof (unsigned long) + 1); 1747 *data_ret = (unsigned char *) xmalloc (sizeof (unsigned long) + 1);
1757 (*data_ret) [sizeof (unsigned long)] = 0; 1748 (*data_ret) [sizeof (unsigned long)] = 0;
1758 (*(unsigned long **) data_ret) [0] = cons_to_long (obj); 1749 (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX);
1759 if (NILP (type)) type = QINTEGER; 1750 if (NILP (type)) type = QINTEGER;
1760 } 1751 }
1761 else if (VECTORP (obj)) 1752 else if (VECTORP (obj))
@@ -1803,11 +1794,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1803 *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); 1794 *data_ret = (unsigned char *) xmalloc (*size_ret * data_size);
1804 for (i = 0; i < *size_ret; i++) 1795 for (i = 0; i < *size_ret; i++)
1805 if (*format_ret == 32) 1796 if (*format_ret == 32)
1806 (*((unsigned long **) data_ret)) [i] 1797 (*((unsigned long **) data_ret)) [i] =
1807 = cons_to_long (XVECTOR (obj)->contents [i]); 1798 cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX);
1808 else 1799 else
1809 (*((unsigned short **) data_ret)) [i] 1800 (*((unsigned short **) data_ret)) [i] =
1810 = (unsigned short) cons_to_long (XVECTOR (obj)->contents [i]); 1801 cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX);
1811 } 1802 }
1812 } 1803 }
1813 else 1804 else
@@ -2025,8 +2016,10 @@ frame's display, or the first available X display. */)
2025 selection_atom = symbol_to_x_atom (dpyinfo, selection); 2016 selection_atom = symbol_to_x_atom (dpyinfo, selection);
2026 2017
2027 BLOCK_INPUT; 2018 BLOCK_INPUT;
2028 timestamp = (NILP (time_object) ? last_event_timestamp 2019 if (NILP (time_object))
2029 : cons_to_long (time_object)); 2020 timestamp = last_event_timestamp;
2021 else
2022 CONS_TO_INTEGER (time_object, Time, timestamp);
2030 XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp); 2023 XSetSelectionOwner (dpyinfo->display, selection_atom, None, timestamp);
2031 UNBLOCK_INPUT; 2024 UNBLOCK_INPUT;
2032 2025
@@ -2232,12 +2225,8 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
2232 { 2225 {
2233 Lisp_Object o = XCAR (iter); 2226 Lisp_Object o = XCAR (iter);
2234 2227
2235 if (INTEGERP (o)) 2228 if (INTEGERP (o) || FLOATP (o) || CONSP (o))
2236 val = (long) XFASTINT (o); 2229 val = cons_to_signed (o, LONG_MIN, LONG_MAX);
2237 else if (FLOATP (o))
2238 val = (long) XFLOAT_DATA (o);
2239 else if (CONSP (o))
2240 val = (long) cons_to_long (o);
2241 else if (STRINGP (o)) 2230 else if (STRINGP (o))
2242 { 2231 {
2243 BLOCK_INPUT; 2232 BLOCK_INPUT;
@@ -2248,9 +2237,19 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format)
2248 error ("Wrong type, must be string, number or cons"); 2237 error ("Wrong type, must be string, number or cons");
2249 2238
2250 if (format == 8) 2239 if (format == 8)
2251 *d08++ = (char) val; 2240 {
2241 if (CHAR_MIN <= val && val <= CHAR_MAX)
2242 *d08++ = val;
2243 else
2244 error ("Out of 'char' range");
2245 }
2252 else if (format == 16) 2246 else if (format == 16)
2253 *d16++ = (short) val; 2247 {
2248 if (SHRT_MIN <= val && val <= SHRT_MAX)
2249 *d16++ = val;
2250 else
2251 error ("Out of 'short' range");
2252 }
2254 else 2253 else
2255 *d32++ = val; 2254 *d32++ = val;
2256 } 2255 }
@@ -2334,14 +2333,7 @@ If the value is 0 or the atom is not known, return the empty string. */)
2334 Atom atom; 2333 Atom atom;
2335 int had_errors; 2334 int had_errors;
2336 2335
2337 if (INTEGERP (value)) 2336 CONS_TO_INTEGER (value, Atom, atom);
2338 atom = (Atom) XUINT (value);
2339 else if (FLOATP (value))
2340 atom = (Atom) XFLOAT_DATA (value);
2341 else if (CONSP (value))
2342 atom = (Atom) cons_to_long (value);
2343 else
2344 error ("Wrong type, value must be number or cons");
2345 2337
2346 BLOCK_INPUT; 2338 BLOCK_INPUT;
2347 x_catch_errors (dpy); 2339 x_catch_errors (dpy);
@@ -2531,17 +2523,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, At
2531 else 2523 else
2532 error ("DEST as a string must be one of PointerWindow or InputFocus"); 2524 error ("DEST as a string must be one of PointerWindow or InputFocus");
2533 } 2525 }
2534 else if (INTEGERP (dest)) 2526 else if (INTEGERP (dest) || FLOATP (dest) || CONSP (dest))
2535 wdest = (Window) XFASTINT (dest); 2527 CONS_TO_INTEGER (dest, Window, wdest);
2536 else if (FLOATP (dest))
2537 wdest = (Window) XFLOAT_DATA (dest);
2538 else if (CONSP (dest))
2539 {
2540 if (! NUMBERP (XCAR (dest)) || ! NUMBERP (XCDR (dest)))
2541 error ("Both car and cdr for DEST must be numbers");
2542 else
2543 wdest = (Window) cons_to_long (dest);
2544 }
2545 else 2528 else
2546 error ("DEST must be a frame, nil, string, number or cons"); 2529 error ("DEST must be a frame, nil, string, number or cons");
2547 2530