Check for overflow when converting integer to cons and back.
[bpt/emacs.git] / src / lisp.h
index 420d602..1c1e3ec 100644 (file)
@@ -22,6 +22,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <stdarg.h>
 #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.  */
@@ -33,25 +36,28 @@ extern void check_cons_list (void);
 #define CHECK_CONS_LIST() ((void) 0)
 #endif
 
+/* Temporarily disable wider-than-pointer integers until they're tested more.
+   Build with CFLAGS='-DWIDE_EMACS_INT' to try them out.  */
+/* #undef WIDE_EMACS_INT */
+
 /* These are default choices for the types to use.  */
-#ifdef _LP64
 #ifndef EMACS_INT
-#define EMACS_INT long
-#define BITS_PER_EMACS_INT BITS_PER_LONG
-#define pEd "ld"
-#endif
-#ifndef EMACS_UINT
-#define EMACS_UINT unsigned long
-#endif
-#else /* not _LP64 */
-#ifndef EMACS_INT
-#define EMACS_INT int
-#define BITS_PER_EMACS_INT BITS_PER_INT
-#define pEd "d"
+# if BITS_PER_LONG < BITS_PER_LONG_LONG && defined WIDE_EMACS_INT
+#  define EMACS_INT long long
+#  define BITS_PER_EMACS_INT BITS_PER_LONG_LONG
+#  define pI "ll"
+# elif BITS_PER_INT < BITS_PER_LONG
+#  define EMACS_INT long
+#  define BITS_PER_EMACS_INT BITS_PER_LONG
+#  define pI "l"
+# else
+#  define EMACS_INT int
+#  define BITS_PER_EMACS_INT BITS_PER_INT
+#  define pI ""
+# endif
 #endif
 #ifndef EMACS_UINT
-#define EMACS_UINT unsigned int
-#endif
+# define EMACS_UINT unsigned EMACS_INT
 #endif
 
 /* Extra internal type checking?  */
@@ -313,7 +319,7 @@ Lisp_Object;
 #endif /* WORDS_BIGENDIAN */
 
 #ifdef __GNUC__
-static __inline__ Lisp_Object
+static inline Lisp_Object
 LISP_MAKE_RVALUE (Lisp_Object o)
 {
     return o;
@@ -398,7 +404,7 @@ enum pvec_type
 #ifdef USE_LSB_TAG
 
 #define TYPEMASK ((((EMACS_INT) 1) << GCTYPEBITS) - 1)
-#define XTYPE(a) ((enum Lisp_Type) (((EMACS_UINT) (a)) & TYPEMASK))
+#define XTYPE(a) ((enum Lisp_Type) ((a) & TYPEMASK))
 #ifdef USE_2_TAGS_FOR_INTS
 # define XINT(a) (((EMACS_INT) (a)) >> (GCTYPEBITS - 1))
 # define XUINT(a) (((EMACS_UINT) (a)) >> (GCTYPEBITS - 1))
@@ -408,11 +414,11 @@ enum pvec_type
 # define XUINT(a) (((EMACS_UINT) (a)) >> GCTYPEBITS)
 # define make_number(N) (((EMACS_INT) (N)) << GCTYPEBITS)
 #endif
-#define XSET(var, type, ptr)                                   \
-    (eassert (XTYPE (ptr) == 0), /* Check alignment.  */       \
-     (var) = ((EMACS_INT) (type)) | ((EMACS_INT) (ptr)))
+#define XSET(var, type, ptr)                                           \
+    (eassert (XTYPE ((intptr_t) (ptr)) == 0), /* Check alignment.  */ \
+     (var) = (type) | (intptr_t) (ptr))
 
-#define XPNTR(a) ((EMACS_INT) ((a) & ~TYPEMASK))
+#define XPNTR(a) ((intptr_t) ((a) & ~TYPEMASK))
 
 #else  /* not USE_LSB_TAG */
 
@@ -446,14 +452,14 @@ enum pvec_type
 
 #define XSET(var, type, ptr)                             \
    ((var) = ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \
-            + ((EMACS_INT) (ptr) & VALMASK)))
+            + ((intptr_t) (ptr) & VALMASK)))
 
 #ifdef DATA_SEG_BITS
 /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
    which were stored in a Lisp_Object */
-#define XPNTR(a) ((EMACS_UINT) (((a) & VALMASK) | DATA_SEG_BITS))
+#define XPNTR(a) ((uintptr_t) (((a) & VALMASK)) | DATA_SEG_BITS))
 #else
-#define XPNTR(a) ((EMACS_UINT) ((a) & VALMASK))
+#define XPNTR(a) ((uintptr_t) ((a) & VALMASK))
 #endif
 
 #endif /* not USE_LSB_TAG */
@@ -466,8 +472,8 @@ enum pvec_type
 
 #define XHASH(a) ((a).i)
 #define XTYPE(a) ((enum Lisp_Type) (a).u.type)
-#define XINT(a) ((a).s.val)
-#define XUINT(a) ((a).u.val)
+#define XINT(a) ((EMACS_INT) (a).s.val)
+#define XUINT(a) ((EMACS_UINT) (a).u.val)
 
 #ifdef USE_LSB_TAG
 
@@ -479,7 +485,7 @@ enum pvec_type
 /* Some versions of gcc seem to consider the bitfield width when issuing
    the "cast to pointer from integer of different size" warning, so the
    cast is here to widen the value back to its natural size.  */
-# define XPNTR(v) ((EMACS_INT)((v).s.val) << GCTYPEBITS)
+# define XPNTR(v) ((intptr_t) (v).s.val << GCTYPEBITS)
 
 #else  /* !USE_LSB_TAG */
 
@@ -495,9 +501,9 @@ enum pvec_type
 #ifdef DATA_SEG_BITS
 /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
    which were stored in a Lisp_Object */
-#define XPNTR(a) (XUINT (a) | DATA_SEG_BITS)
+#define XPNTR(a) ((intptr_t) (XUINT (a) | DATA_SEG_BITS))
 #else
-#define XPNTR(a) ((EMACS_INT) XUINT (a))
+#define XPNTR(a) ((intptr_t) XUINT (a))
 #endif
 
 #endif /* !USE_LSB_TAG */
@@ -521,30 +527,27 @@ extern Lisp_Object make_number (EMACS_INT);
 
 #define EQ(x, y) (XHASH (x) == XHASH (y))
 
-/* Largest and smallest representable fixnum values.  These are the C
-   values.  */
-
+/* Number of bits in a fixnum, including the sign bit.  */
 #ifdef USE_2_TAGS_FOR_INTS
-# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << VALBITS)
-# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << VALBITS) - 1)
-/* Mask indicating the significant bits of a Lisp_Int.
-   I.e. (x & INTMASK) == XUINT (make_number (x)).  */
-# define INTMASK ((((EMACS_INT) 1) << (VALBITS + 1)) - 1)
+# define FIXNUM_BITS (VALBITS + 1)
 #else
-# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << (VALBITS - 1))
-# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << (VALBITS - 1)) - 1)
-/* Mask indicating the significant bits of a Lisp_Int.
-   I.e. (x & INTMASK) == XUINT (make_number (x)).  */
-# define INTMASK ((((EMACS_INT) 1) << VALBITS) - 1)
+# define FIXNUM_BITS VALBITS
 #endif
 
+/* Mask indicating the significant bits of a fixnum.  */
+#define INTMASK (((EMACS_INT) 1 << FIXNUM_BITS) - 1)
+
+/* Largest and smallest representable fixnum values.  These are the C
+   values.  */
+#define MOST_POSITIVE_FIXNUM (INTMASK / 2)
+#define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
+
 /* Value is non-zero if I doesn't fit into a Lisp fixnum.  It is
    written this way so that it also works if I is of unsigned
-   type.  */
+   type or if I is a NaN.  */
 
 #define FIXNUM_OVERFLOW_P(i) \
-  ((i) > MOST_POSITIVE_FIXNUM \
-   || ((i) < 0 && (i) < MOST_NEGATIVE_FIXNUM))
+  (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM))
 
 /* Extract a value or address from a Lisp_Object.  */
 
@@ -601,17 +604,30 @@ extern Lisp_Object make_number (EMACS_INT);
 
 /* Pseudovector types.  */
 
-#define XSETPVECTYPE(v,code) ((v)->size |= PSEUDOVECTOR_FLAG | (code))
+#define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE(v, header.size, code)
+#define XSETTYPED_PVECTYPE(v, size_member, code) \
+  ((v)->size_member |= PSEUDOVECTOR_FLAG | (code))
+#define XSETPVECTYPESIZE(v, code, sizeval) \
+  ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval))
+
+/* The cast to struct vectorlike_header * avoids aliasing issues.  */
 #define XSETPSEUDOVECTOR(a, b, code) \
+  XSETTYPED_PSEUDOVECTOR(a, b,       \
+                        ((struct vectorlike_header *) XPNTR (a))->size, \
+                        code)
+#define XSETTYPED_PSEUDOVECTOR(a, b, size, code)                       \
   (XSETVECTOR (a, b),                                                  \
-   eassert ((XVECTOR (a)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
+   eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))              \
            == (PSEUDOVECTOR_FLAG | (code))))
+
 #define XSETWINDOW_CONFIGURATION(a, b) \
   (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
 #define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
 #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
 #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
+/* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header.  */
+#define XSETSUBR(a, b) \
+  XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR)
 #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED))
 #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
 #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
@@ -621,7 +637,7 @@ extern Lisp_Object make_number (EMACS_INT);
 /* Convenience macros for dealing with Lisp arrays.  */
 
 #define AREF(ARRAY, IDX)       XVECTOR ((ARRAY))->contents[IDX]
-#define ASIZE(ARRAY)           XVECTOR ((ARRAY))->size
+#define ASIZE(ARRAY)           XVECTOR ((ARRAY))->header.size
 /* The IDX==IDX tries to detect when the macro argument is side-effecting.  */
 #define ASET(ARRAY, IDX, VAL)  \
   (eassert ((IDX) == (IDX)),                           \
@@ -749,6 +765,12 @@ extern EMACS_INT string_bytes (struct Lisp_String *);
 
 #endif /* not GC_CHECK_STRING_BYTES */
 
+/* A string cannot contain more bytes than a fixnum can represent,
+   nor can it be so long that C pointer arithmetic stops working on
+   the string plus a terminating null.  */
+#define STRING_BYTES_MAX  \
+  min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)
+
 /* Mark STR as a unibyte string.  */
 #define STRING_SET_UNIBYTE(STR)  \
   do { if (EQ (STR, empty_multibyte_string))  \
@@ -778,10 +800,30 @@ struct Lisp_String
     unsigned char *data;
   };
 
-struct Lisp_Vector
+/* Header of vector-like objects.  This documents the layout constraints on
+   vectors and pseudovectors other than struct Lisp_Subr.  It also prevents
+   compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR
+   and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *,
+   because when two such pointers potentially alias, a compiler won't
+   incorrectly reorder loads and stores to their size fields.  See
+   <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
+struct vectorlike_header
   {
     EMACS_UINT size;
-    struct Lisp_Vector *next;
+
+    /* Pointer to the next vector-like object.  It is generally a buffer or a
+       Lisp_Vector alias, so for convenience it is a union instead of a
+       pointer: this way, one can write P->next.vector instead of ((struct
+       Lisp_Vector *) P->next).  */
+    union {
+      struct buffer *buffer;
+      struct Lisp_Vector *vector;
+    } next;
+  };
+
+struct Lisp_Vector
+  {
+    struct vectorlike_header header;
     Lisp_Object contents[1];
   };
 
@@ -817,7 +859,7 @@ struct Lisp_Vector
 /* Return the number of "extra" slots in the char table CT.  */
 
 #define CHAR_TABLE_EXTRA_SLOTS(CT)     \
-  (((CT)->size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
+  (((CT)->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
 
 #ifdef __GNUC__
 
@@ -882,12 +924,11 @@ struct Lisp_Sub_Char_Table;
 
 struct Lisp_Char_Table
   {
-    /* This is the vector's size field, which also holds the
+    /* HEADER.SIZE is the vector's size field, which also holds the
        pseudovector type information.  It holds the size, too.
        The size counts the defalt, parent, purpose, ascii,
        contents, and extras slots.  */
-    EMACS_UINT size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
 
     /* This holds a default value,
        which is used whenever the value for a specific character is nil.  */
@@ -914,10 +955,9 @@ struct Lisp_Char_Table
 
 struct Lisp_Sub_Char_Table
   {
-    /* This is the vector's size field, which also holds the
+    /* HEADER.SIZE is the vector's size field, which also holds the
        pseudovector type information.  It holds the size, too.  */
-    EMACS_INT size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
 
     /* Depth of this sub char-table.  It should be 1, 2, or 3.  A sub
        char-table of depth 1 contains 16 elements, and each element
@@ -936,10 +976,9 @@ struct Lisp_Sub_Char_Table
 /* A boolvector is a kind of vectorlike, with contents are like a string.  */
 struct Lisp_Bool_Vector
   {
-    /* This is the vector's size field.  It doesn't have the real size,
+    /* HEADER.SIZE is the vector's size field.  It doesn't have the real size,
        just the subtype information.  */
-    EMACS_UINT vector_size;
-    struct Lisp_Vector *next;
+    struct vectorlike_header header;
     /* This is the size in bits.  */
     EMACS_UINT size;
     /* This contains the actual bits, packed into bytes.  */
@@ -952,7 +991,7 @@ struct Lisp_Bool_Vector
 
    This type is treated in most respects as a pseudovector,
    but since we never dynamically allocate or free them,
-   we don't need a next-vector field.  */
+   we don't need a struct vectorlike_header and its 'next' field.  */
 
 struct Lisp_Subr
   {
@@ -1099,9 +1138,8 @@ struct Lisp_Symbol
 
 struct Lisp_Hash_Table
 {
-  /* Vector fields.  The hash table code doesn't refer to these.  */
-  EMACS_UINT size;
-  struct Lisp_Vector *vec_next;
+  /* This is for Lisp; the hash table code does not refer to it.  */
+  struct vectorlike_header header;
 
   /* Function used to compare keys.  */
   Lisp_Object test;
@@ -1147,7 +1185,7 @@ struct Lisp_Hash_Table
      a special way (e.g. because of weakness).  */
 
   /* Number of key/value entries in the table.  */
-  unsigned int count;
+  EMACS_INT count;
 
   /* Vector of keys and values.  The key of item I is found at index
      2 * I, the value is found at index 2 * I + 1.
@@ -1159,11 +1197,12 @@ struct Lisp_Hash_Table
   struct Lisp_Hash_Table *next_weak;
 
   /* C function to compare two keys.  */
-  int (* cmpfn) (struct Lisp_Hash_Table *, Lisp_Object,
-                 unsigned, Lisp_Object, unsigned);
+  int (*cmpfn) (struct Lisp_Hash_Table *,
+               Lisp_Object, EMACS_UINT,
+               Lisp_Object, EMACS_UINT);
 
   /* C function to compute hash code.  */
-  unsigned (* hashfn) (struct Lisp_Hash_Table *, Lisp_Object);
+  EMACS_UINT (*hashfn) (struct Lisp_Hash_Table *, Lisp_Object);
 };
 
 
@@ -1202,7 +1241,7 @@ struct Lisp_Hash_Table
 
 /* Value is the size of hash table H.  */
 
-#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
+#define HASH_TABLE_SIZE(H) ASIZE ((H)->next)
 
 /* Default size for hash tables if not specified.  */
 
@@ -1620,7 +1659,7 @@ typedef struct {
 #define CONSP(x) (XTYPE ((x)) == Lisp_Cons)
 
 #define FLOATP(x) (XTYPE ((x)) == Lisp_Float)
-#define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
+#define VECTORP(x) (VECTORLIKEP (x) && !(ASIZE (x) & PSEUDOVECTOR_FLAG))
 #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
 #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 #define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value)
@@ -1631,10 +1670,17 @@ typedef struct {
 #define BUFFER_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Buffer_Obj)
 #define KBOARD_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Kboard_Obj)
 
-/* True if object X is a pseudovector whose code is CODE.  */
+/* True if object X is a pseudovector whose code is CODE.  The cast to struct
+   vectorlike_header * avoids aliasing issues.  */
 #define PSEUDOVECTORP(x, code)                                 \
+  TYPED_PSEUDOVECTORP(x, vectorlike_header, code)
+
+/* True if object X, with internal type struct T *, is a pseudovector whose
+   code is CODE.  */
+#define TYPED_PSEUDOVECTORP(x, t, code)                                \
   (VECTORLIKEP (x)                                             \
-   && (((XVECTOR (x)->size & (PSEUDOVECTOR_FLAG | (code))))    \
+   && (((((struct t *) XPNTR (x))->size                                \
+        & (PSEUDOVECTOR_FLAG | (code))))                       \
        == (PSEUDOVECTOR_FLAG | (code))))
 
 /* Test for specific pseudovector types.  */
@@ -1642,7 +1688,8 @@ typedef struct {
 #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS)
 #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW)
 #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL)
-#define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR)
+/* SUBRP is special since Lisp_Subr lacks struct vectorlike_header.  */
+#define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR)
 #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED)
 #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
 #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
@@ -1777,8 +1824,8 @@ typedef struct {
     XSETCDR ((x), tmp);                        \
   } while (0)
 
-/* Cast pointers to this type to compare them.  Some machines want int.  */
-#define PNTR_COMPARISON_TYPE EMACS_UINT
+/* Cast pointers to this type to compare them.  */
+#define PNTR_COMPARISON_TYPE uintptr_t
 \f
 /* Define a built-in function for calling from Lisp.
  `lname' should be the name to give the function in Lisp,
@@ -1806,12 +1853,8 @@ typedef struct {
  `doc' is documentation for the user.  */
 
 /* This version of DEFUN declares a function prototype with the right
-   arguments, so we can catch errors with maxargs at compile-time.
-   DEFUN defines an internal function, and DEFUE is similar but defines a
-   external function, which can be used in other C-language modules.  */
-#define DEFUN static DEFINE_FUNC
-#define DEFUE extern DEFINE_FUNC
-#define DEFINE_FUNC(lname, fnname, sname, minargs, maxargs, intspec, doc) \
+   arguments, so we can catch errors with maxargs at compile-time.  */
+#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
   Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                          \
   static DECL_ALIGN (struct Lisp_Subr, sname) =                                \
     { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),    \
@@ -2057,7 +2100,7 @@ extern Lisp_Object Vascii_canon_table;
 \f
 /* Number of bytes of structure consed since last GC.  */
 
-extern int consing_since_gc;
+extern EMACS_INT consing_since_gc;
 
 extern EMACS_INT gc_relative_threshold;
 
@@ -2280,8 +2323,6 @@ void staticpro (Lisp_Object *);
    appropriate prototype.  */
 #define EXFUN(fnname, maxargs) \
   extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
-#define INFUN(fnname, maxargs) \
-  static Lisp_Object fnname DEFUN_ARGS_ ## maxargs
 
 /* Forward declarations for prototypes.  */
 struct window;
@@ -2369,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;
@@ -2434,19 +2501,19 @@ extern void syms_of_syntax (void);
 
 /* Defined in fns.c */
 extern Lisp_Object QCrehash_size, QCrehash_threshold;
-extern int next_almost_prime (int);
-extern Lisp_Object larger_vector (Lisp_Object, int, Lisp_Object);
+extern EMACS_INT next_almost_prime (EMACS_INT);
+extern Lisp_Object larger_vector (Lisp_Object, EMACS_INT, Lisp_Object);
 extern void sweep_weak_hash_tables (void);
 extern Lisp_Object Qcursor_in_echo_area;
 extern Lisp_Object Qstring_lessp;
 extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq, Qeql;
-unsigned sxhash (Lisp_Object, int);
+EMACS_UINT sxhash (Lisp_Object, int);
 Lisp_Object make_hash_table (Lisp_Object, Lisp_Object, Lisp_Object,
                              Lisp_Object, Lisp_Object, Lisp_Object,
                              Lisp_Object);
-int hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, unsigned *);
-int hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
-              unsigned);
+EMACS_INT hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *);
+EMACS_INT hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
+                   EMACS_UINT);
 void init_weak_hash_tables (void);
 extern void init_fns (void);
 EXFUN (Fmake_hash_table, MANY);
@@ -2539,7 +2606,6 @@ extern void move_gap_both (EMACS_INT, EMACS_INT);
 extern void make_gap (EMACS_INT);
 extern EMACS_INT copy_text (const unsigned char *, unsigned char *,
                            EMACS_INT, int, int);
-extern EMACS_INT count_size_as_multibyte (const unsigned char *, EMACS_INT);
 extern int count_combining_before (const unsigned char *,
                                   EMACS_INT, EMACS_INT, EMACS_INT);
 extern int count_combining_after (const unsigned char *,
@@ -2568,12 +2634,7 @@ extern Lisp_Object del_range_2 (EMACS_INT, EMACS_INT,
                                EMACS_INT, EMACS_INT, int);
 extern void modify_region (struct buffer *, EMACS_INT, EMACS_INT, int);
 extern void prepare_to_modify_buffer (EMACS_INT, EMACS_INT, EMACS_INT *);
-extern void signal_before_change (EMACS_INT, EMACS_INT, EMACS_INT *);
 extern void signal_after_change (EMACS_INT, EMACS_INT, EMACS_INT);
-extern void adjust_after_replace (EMACS_INT, EMACS_INT, Lisp_Object,
-                                 EMACS_INT, EMACS_INT);
-extern void adjust_after_replace_noundo (EMACS_INT, EMACS_INT, EMACS_INT,
-                                        EMACS_INT, EMACS_INT, EMACS_INT);
 extern void adjust_after_insert (EMACS_INT, EMACS_INT, EMACS_INT,
                                 EMACS_INT, EMACS_INT);
 extern void adjust_markers_for_delete (EMACS_INT, EMACS_INT,
@@ -2657,11 +2718,13 @@ extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
 extern void reset_malloc_hooks (void);
 extern void uninterrupt_malloc (void);
 extern void malloc_warning (const char *);
-extern void memory_full (void) NO_RETURN;
-extern void buffer_memory_full (void) NO_RETURN;
+extern void memory_full (size_t) NO_RETURN;
+extern void buffer_memory_full (EMACS_INT) NO_RETURN;
 extern int survives_gc_p (Lisp_Object);
 extern void mark_object (Lisp_Object);
+#if defined REL_ALLOC && !defined SYSTEM_MALLOC
 extern void refill_memory_reserve (void);
+#endif
 extern const char *pending_malloc_warning;
 extern Lisp_Object *stack_base;
 EXFUN (Fcons, 2);
@@ -2678,6 +2741,7 @@ EXFUN (Fmake_vector, 2);
 EXFUN (Fvector, MANY);
 EXFUN (Fmake_symbol, 1);
 EXFUN (Fmake_marker, 0);
+extern void string_overflow (void) NO_RETURN;
 EXFUN (Fmake_string, 2);
 extern Lisp_Object build_string (const char *);
 extern Lisp_Object make_string (const char *, EMACS_INT);
@@ -2750,16 +2814,13 @@ extern void syms_of_chartab (void);
 /* Defined in print.c */
 extern Lisp_Object Vprin1_to_string_buffer;
 extern void debug_print (Lisp_Object) EXTERNALLY_VISIBLE;
-extern void safe_debug_print (Lisp_Object) EXTERNALLY_VISIBLE;
 EXFUN (Fprin1, 2);
 EXFUN (Fprin1_to_string, 2);
-EXFUN (Fprinc, 2);
 EXFUN (Fterpri, 1);
 EXFUN (Fprint, 2);
 EXFUN (Ferror_message_string, 1);
 extern Lisp_Object Qstandard_output;
 extern Lisp_Object Qexternal_debugging_output;
-extern void debug_output_compilation_hack (int);
 extern void temp_output_buffer_setup (const char *);
 extern int print_level;
 extern Lisp_Object Qprint_escape_newlines;
@@ -2772,10 +2833,12 @@ extern Lisp_Object internal_with_output_to_temp_buffer
 extern void float_to_string (char *, double);
 extern void syms_of_print (void);
 
+/* Defined in doprnt.c */
+extern size_t doprnt (char *, size_t, const char *, const char *, va_list);
+
 /* Defined in lread.c.  */
 extern Lisp_Object Qvariable_documentation, Qstandard_input;
 extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-extern Lisp_Object initial_obarray;
 EXFUN (Fread, 1);
 EXFUN (Fread_from_string, 3);
 EXFUN (Fintern, 2);
@@ -2788,7 +2851,6 @@ EXFUN (Fread_event, 3);
 extern Lisp_Object check_obarray (Lisp_Object);
 extern Lisp_Object intern (const char *);
 extern Lisp_Object intern_c_string (const char *);
-extern Lisp_Object make_symbol (const char *);
 extern Lisp_Object oblookup (Lisp_Object, const char *, EMACS_INT, EMACS_INT);
 #define LOADHIST_ATTACH(x) \
   do {                                                                 \
@@ -2796,7 +2858,7 @@ extern Lisp_Object oblookup (Lisp_Object, const char *, EMACS_INT, EMACS_INT);
   } while (0)
 extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
                   Lisp_Object *, Lisp_Object);
-extern int isfloat_string (const char *, int);
+Lisp_Object string_to_number (char const *, int, int);
 extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
                          Lisp_Object);
 extern void dir_warning (const char *, Lisp_Object);
@@ -2977,14 +3039,12 @@ extern EMACS_INT marker_byte_position (Lisp_Object);
 extern void clear_charpos_cache (struct buffer *);
 extern EMACS_INT charpos_to_bytepos (EMACS_INT);
 extern EMACS_INT buf_charpos_to_bytepos (struct buffer *, EMACS_INT);
-extern EMACS_INT verify_bytepos (EMACS_INT charpos);
 extern EMACS_INT buf_bytepos_to_charpos (struct buffer *, EMACS_INT);
 extern void unchain_marker (struct Lisp_Marker *marker);
 extern Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object set_marker_both (Lisp_Object, Lisp_Object, EMACS_INT, EMACS_INT);
 extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object,
                                                EMACS_INT, EMACS_INT);
-extern int count_markers (struct buffer *);
 extern void syms_of_marker (void);
 
 /* Defined in fileio.c */
@@ -3057,7 +3117,6 @@ extern void clear_regexp_cache (void);
 extern Lisp_Object Qcompletion_ignore_case;
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object last_minibuf_string;
-extern void choose_minibuf_frame (void);
 EXFUN (Fcompleting_read, 8);
 EXFUN (Fread_from_minibuffer, 7);
 EXFUN (Fread_variable, 2);
@@ -3098,7 +3157,6 @@ extern void syms_of_casetab (void);
 
 /* Defined in keyboard.c */
 
-extern int echoing;
 extern Lisp_Object echo_message_buffer;
 extern struct kboard *echo_kboard;
 extern void cancel_echoing (void);
@@ -3125,7 +3183,9 @@ extern void cmd_error_internal (Lisp_Object, const char *);
 extern Lisp_Object command_loop_1 (void);
 extern Lisp_Object recursive_edit_1 (void);
 extern void record_auto_save (void);
+#ifdef SIGDANGER
 extern void force_auto_save_soon (void);
+#endif
 extern void init_keyboard (void);
 extern void syms_of_keyboard (void);
 extern void keys_of_keyboard (void);
@@ -3149,7 +3209,9 @@ extern Lisp_Object Qvisible;
 extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
 extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
 extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
+#if HAVE_NS
 extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
+#endif
 extern Lisp_Object frame_buffer_predicate (Lisp_Object);
 EXFUN (Fselect_frame, 2);
 EXFUN (Fselected_frame, 0);
@@ -3208,12 +3270,13 @@ extern int inhibit_window_system;
 /* Nonzero means that a filter or a sentinel is running.  */
 extern int running_asynch_code;
 
-/* Defined in process.c */
+/* Defined in process.c */
 extern Lisp_Object QCtype, Qlocal;
 EXFUN (Fget_buffer_process, 1);
 EXFUN (Fprocess_status, 1);
 EXFUN (Fkill_process, 2);
 EXFUN (Fwaiting_for_user_input_p, 0);
+extern Lisp_Object Qprocessp;
 extern void kill_buffer_processes (Lisp_Object);
 extern int wait_reading_process_output (int, int, int, int,
                                         Lisp_Object,
@@ -3322,17 +3385,17 @@ extern void reset_sys_modes (struct tty_display_info *);
 extern void init_all_sys_modes (void);
 extern void reset_all_sys_modes (void);
 extern void wait_for_termination (int);
+extern void interruptible_wait_for_termination (int);
 extern void flush_pending_output (int);
 extern void child_setup_tty (int);
 extern void setup_pty (int);
 extern int set_window_size (int, int, int);
-extern void create_process (Lisp_Object, char **, Lisp_Object);
-extern long get_random (void);
+extern EMACS_INT get_random (void);
 extern void seed_random (long);
 extern int emacs_open (const char *, int, int);
 extern int emacs_close (int);
-extern int emacs_read (int, char *, unsigned int);
-extern int emacs_write (int, const char *, unsigned int);
+extern EMACS_INT emacs_read (int, char *, EMACS_INT);
+extern EMACS_INT emacs_write (int, const char *, EMACS_INT);
 enum { READLINK_BUFSIZE = 1024 };
 extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
 #ifndef HAVE_MEMSET