From a60e78be5dfc2172345d140f2cd8df0a77bea0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Thu, 28 Mar 2019 22:12:37 +0100 Subject: [PATCH] Add bounds for portable fixnums, and portable-fixnum-p These are useful for macros that need to detect whether a number is a fixnum on any machine, so that the bytecode becomes portable (Bug#34781). * src/data.c (most-positive-portable-fixnum, most-negative-portable-fixnum): * lisp/subr.el (portable-fixnum-p): New. * etc/NEWS (Lisp Changes): Mention portable-fixnum-p. --- etc/NEWS | 5 +++++ lisp/subr.el | 5 +++++ src/data.c | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index 7486d6bcfe..2ab3c5b4bb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1424,6 +1424,11 @@ like 'file-attributes' that compute file sizes and other attributes, functions like 'process-id' that compute process IDs, and functions like 'user-uid' and 'group-gid' that compute user and group IDs. +Since the size of fixnums varies between platforms, the new predicate +'portable-fixnum-p' determines whether a number is a fixnum on any +machine running the current Emacs version. The corresponding bounds +are 'most-negative-portable-fixnum' and 'most-negative-portable-fixnum'. + +++ ** Although the default timestamp format is still (HI LO US PS), it is planned to change in a future Emacs version, to exploit bignums. diff --git a/lisp/subr.el b/lisp/subr.el index f1a1dddd81..efa9cd4065 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -376,6 +376,11 @@ bignump "Return t if OBJECT is a bignum." (and (integerp object) (not (fixnump object)))) +(defun portable-fixnum-p (object) + "Return t if OBJECT is a fixnum on any machine running this Emacs version." + (and (integerp object) + (<= most-negative-portable-fixnum object most-positive-portable-fixnum))) + (defun lsh (value count) "Return VALUE with its bits shifted left by COUNT. If COUNT is negative, shifting is actually to the right. diff --git a/src/data.c b/src/data.c index 15b6106cfe..6d50a14bde 100644 --- a/src/data.c +++ b/src/data.c @@ -4110,6 +4110,30 @@ This variable cannot be set; trying to do so will signal an error. */); Vmost_negative_fixnum = make_fixnum (MOST_NEGATIVE_FIXNUM); make_symbol_constant (intern_c_string ("most-negative-fixnum")); + /* The smallest portable value of EMACS_INT_MAX. */ + int least_emacs_int_max = 2147483647; /* 2**31 - 1 */ + + /* Largest and smallest values that are guaranteed to be representable + as fixnums on any machine. */ + int most_positive_portable_fixnum = least_emacs_int_max >> INTTYPEBITS; + int most_negative_portable_fixnum = -1 - most_positive_portable_fixnum; + + DEFVAR_LISP ("most-positive-portable-fixnum", + Vmost_positive_portable_fixnum, + doc: /* The largest integer representable as a fixnum on any platform. +This variable can be used to ensure portability of bytecode that works +with fixnums. It cannot be set; trying to do so will signal an error. */); + Vmost_positive_portable_fixnum = make_fixnum (most_positive_portable_fixnum); + make_symbol_constant (intern_c_string ("most-positive-portable-fixnum")); + + DEFVAR_LISP ("most-negative-portable-fixnum", + Vmost_negative_portable_fixnum, + doc: /* The least integer representable as a fixnum on any platform. +This variable can be used to ensure portability of bytecode that works +with fixnums. It cannot be set; trying to do so will signal an error. */); + Vmost_negative_portable_fixnum = make_fixnum (most_negative_portable_fixnum); + make_symbol_constant (intern_c_string ("most-negative-portable-fixnum")); + DEFSYM (Qwatchers, "watchers"); DEFSYM (Qmakunbound, "makunbound"); DEFSYM (Qunlet, "unlet"); -- 2.20.1