Move IF_LINT from lisp.h to conf_post.h
[bpt/emacs.git] / src / lisp.h
index 9e108d9..3dbea6e 100644 (file)
@@ -1,6 +1,6 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985-1987, 1993-1995, 1997-2012
-                 Free Software Foundation, Inc.
+
+Copyright (C) 1985-1987, 1993-1995, 1997-2012 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -20,6 +20,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifndef EMACS_LISP_H
 #define EMACS_LISP_H
 
+#include <stdalign.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <inttypes.h>
@@ -27,40 +28,39 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <intprops.h>
 
-/* Use the configure flag --enable-checking[=LIST] to enable various
-   types of run time checks for Lisp objects.  */
-
-#ifdef GC_CHECK_CONS_LIST
-extern void check_cons_list (void);
-#define CHECK_CONS_LIST() check_cons_list ()
-#else
-#define CHECK_CONS_LIST() ((void) 0)
+INLINE_HEADER_BEGIN
+#ifndef LISP_INLINE
+# define LISP_INLINE INLINE
 #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 */
+/* The ubiquitous max and min macros.  */
+#undef min
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
 
 /* EMACS_INT - signed integer wide enough to hold an Emacs value
    EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if
    pI - printf length modifier for EMACS_INT
    EMACS_UINT - unsigned variant of EMACS_INT */
-#ifndef EMACS_INT
+#ifndef EMACS_INT_MAX
 # if LONG_MAX < LLONG_MAX && defined WIDE_EMACS_INT
-#  define EMACS_INT long long
+typedef long long int EMACS_INT;
+typedef unsigned long long int EMACS_UINT;
 #  define EMACS_INT_MAX LLONG_MAX
 #  define pI "ll"
 # elif INT_MAX < LONG_MAX
-#  define EMACS_INT long
+typedef long int EMACS_INT;
+typedef unsigned long int EMACS_UINT;
 #  define EMACS_INT_MAX LONG_MAX
 #  define pI "l"
 # else
-#  define EMACS_INT int
+typedef int EMACS_INT;
+typedef unsigned int EMACS_UINT;
 #  define EMACS_INT_MAX INT_MAX
 #  define pI ""
 # endif
 #endif
-#define EMACS_UINT unsigned EMACS_INT
 
 /* Number of bits in some machine integer types.  */
 enum
@@ -106,158 +106,126 @@ typedef EMACS_UINT uprintmax_t;
 
 /* Extra internal type checking?  */
 
-#ifdef ENABLE_CHECKING
+/* Define an Emacs version of 'assert (COND)', since some
+   system-defined 'assert's are flaky.  COND should be free of side
+   effects; it may or may not be evaluated.  */
+#ifndef ENABLE_CHECKING
+# define eassert(X) ((void) (0 && (X))) /* Check that X compiles.  */
+#else /* ENABLE_CHECKING */
 
-extern void die (const char *, const char *, int) NO_RETURN;
+extern _Noreturn void die (const char *, const char *, int);
 
 /* The suppress_checking variable is initialized to 0 in alloc.c.  Set
    it to 1 using a debugger to temporarily disable aborting on
    detected internal inconsistencies or error conditions.
 
-   Testing suppress_checking after the supplied condition ensures that
-   the side effects produced by CHECK will be consistent, independent
-   of whether ENABLE_CHECKING is defined, or whether the checks are
-   suppressed at run time.
-
    In some cases, a good compiler may be able to optimize away the
-   CHECK macro altogether, e.g., if XSTRING (x) uses CHECK to test
+   eassert macro altogether, e.g., if XSTRING (x) uses eassert to test
    STRINGP (x), but a particular use of XSTRING is invoked only after
    testing that STRINGP (x) is true, making the test redundant.  */
-
 extern int suppress_checking EXTERNALLY_VISIBLE;
 
-#define CHECK(check,msg) (((check) || suppress_checking                \
-                          ? (void) 0                           \
-                          : die ((msg), __FILE__, __LINE__)),  \
-                         0)
-#else
-
-/* Produce same side effects and result, but don't complain.  */
-#define CHECK(check,msg) ((check),0)
-
-#endif
-
-/* Define an Emacs version of "assert", since some system ones are
-   flaky.  */
-#ifndef ENABLE_CHECKING
-#define eassert(X) ((void) (0 && (X))) /* Check that X compiles.  */
-#else /* ENABLE_CHECKING */
-#if defined (__GNUC__) && __GNUC__ >= 2 && defined (__STDC__)
-#define eassert(cond) CHECK (cond, "assertion failed: " #cond)
-#else
-#define eassert(cond) CHECK (cond, "assertion failed")
-#endif
+# define eassert(cond)                                         \
+   ((cond) || suppress_checking                                        \
+    ? (void) 0                                                 \
+    : die ("assertion failed: " # cond, __FILE__, __LINE__))
 #endif /* ENABLE_CHECKING */
 \f
-/* Use the configure flag --enable-use-lisp-union-type to make
-   Lisp_Object use a union type instead of the default int.  The flag
-   causes USE_LISP_UNION_TYPE to be defined.  */
+/* Use the configure flag --enable-check-lisp-object-type to make
+   Lisp_Object use a struct type instead of the default int.  The flag
+   causes CHECK_LISP_OBJECT_TYPE to be defined.  */
 
 /***** Select the tagging scheme.  *****/
-/* There are basically two options that control the tagging scheme:
-   - USE_LISP_UNION_TYPE says that Lisp_Object should be a union instead
-     of an integer.
+/* The following option controls the tagging scheme:
    - USE_LSB_TAG means that we can assume the least 3 bits of pointers are
      always 0, and we can thus use them to hold tag bits, without
      restricting our addressing space.
 
-   If USE_LSB_TAG is not set, then we use the top 3 bits for tagging, thus
-   restricting our possible address range.  Currently USE_LSB_TAG is not
-   allowed together with a union.  This is not due to any fundamental
-   technical (or political ;-) problem: nobody wrote the code to do it yet.
+   If ! USE_LSB_TAG, then use the top 3 bits for tagging, thus
+   restricting our possible address range.
 
    USE_LSB_TAG not only requires the least 3 bits of pointers returned by
    malloc to be 0 but also needs to be able to impose a mult-of-8 alignment
    on the few static Lisp_Objects used: all the defsubr as well
    as the two special buffers buffer_defaults and buffer_local_symbols.  */
 
-/* First, try and define DECL_ALIGN(type,var) which declares a static
-   variable VAR of type TYPE with the added requirement that it be
-   TYPEBITS-aligned.  */
-
+enum Lisp_Bits
+  {
+    /* Number of bits in a Lisp_Object tag.  This can be used in #if,
+       and for GDB's sake also as a regular symbol.  */
+    GCTYPEBITS =
 #define GCTYPEBITS 3
-#define VALBITS (BITS_PER_EMACS_INT - GCTYPEBITS)
+       GCTYPEBITS,
+
+    /* 2**GCTYPEBITS.  This must also be a macro that expands to a
+       literal integer constant, for MSVC.  */
+    GCALIGNMENT =
+#define GCALIGNMENT 8
+       GCALIGNMENT,
+
+    /* Number of bits in a Lisp_Object value, not counting the tag.  */
+    VALBITS = BITS_PER_EMACS_INT - GCTYPEBITS,
+
+    /* Number of bits in a Lisp fixnum tag.  */
+    INTTYPEBITS = GCTYPEBITS - 1,
+
+    /* Number of bits in a Lisp fixnum value, not counting the tag.  */
+    FIXNUM_BITS = VALBITS + 1
+  };
+
+#if GCALIGNMENT != 1 << GCTYPEBITS
+# error "GCALIGNMENT and GCTYPEBITS are inconsistent"
+#endif
 
 /* The maximum value that can be stored in a EMACS_INT, assuming all
    bits other than the type bits contribute to a nonnegative signed value.
    This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below.  */
 #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1))
 
-#ifndef NO_DECL_ALIGN
-# ifndef DECL_ALIGN
-#  if HAVE_ATTRIBUTE_ALIGNED
-#   define DECL_ALIGN(type, var) \
-     type __attribute__ ((__aligned__ (1 << GCTYPEBITS))) var
-#  elif defined(_MSC_VER)
-#   define ALIGN_GCTYPEBITS 8
-#   if (1 << GCTYPEBITS) != ALIGN_GCTYPEBITS
-#    error ALIGN_GCTYPEBITS is wrong!
-#   endif
-#   define DECL_ALIGN(type, var) \
-     type __declspec(align(ALIGN_GCTYPEBITS)) var
-#  else
-     /* What directives do other compilers use?  */
-#  endif
-# endif
-#endif
-
-/* Let's USE_LSB_TAG on systems where we know malloc returns mult-of-8.  */
-#if (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \
-     || defined DARWIN_OS || defined __sun)
-/* We also need to be able to specify mult-of-8 alignment on static vars.  */
-# if defined DECL_ALIGN
-/* On hosts where pointers-as-ints do not exceed VAL_MAX,
-   USE_LSB_TAG is:
+/* Unless otherwise specified, use USE_LSB_TAG on systems where:  */
+#ifndef USE_LSB_TAG
+/* 1.  We know malloc returns a multiple of 8.  */
+# if (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \
+      || defined DARWIN_OS || defined __sun)
+/* 2.  We can specify multiple-of-8 alignment on static variables.  */
+#  ifdef alignas
+/* 3.  Pointers-as-ints exceed VAL_MAX.
+   On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is:
     a. unnecessary, because the top bits of an EMACS_INT are unused, and
     b. slower, because it typically requires extra masking.
-   So, define USE_LSB_TAG only on hosts where it might be useful.  */
-#  if VAL_MAX < UINTPTR_MAX
-#   define USE_LSB_TAG
+   So, default USE_LSB_TAG to 1 only on hosts where it might be useful.  */
+#   if VAL_MAX < UINTPTR_MAX
+#    define USE_LSB_TAG 1
+#   endif
 #  endif
 # endif
 #endif
+#ifdef USE_LSB_TAG
+# undef USE_LSB_TAG
+enum enum_USE_LSB_TAG { USE_LSB_TAG = 1 };
+# define USE_LSB_TAG 1
+#else
+enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
+# define USE_LSB_TAG 0
+#endif
 
-/* If we cannot use 8-byte alignment, make DECL_ALIGN a no-op.  */
-#ifndef DECL_ALIGN
-# ifdef USE_LSB_TAG
-#  error "USE_LSB_TAG used without defining DECL_ALIGN"
+#ifndef alignas
+# define alignas(alignment) /* empty */
+# if USE_LSB_TAG
+#  error "USE_LSB_TAG requires alignas"
 # endif
-# define DECL_ALIGN(type, var) type var
 #endif
 
 
 /* Define the fundamental Lisp data structures.  */
 
-/* If USE_2_TAGBITS_FOR_INTS is defined, then Lisp integers use
-   2 tags, to give them one extra bit, thus extending their range from
-   e.g -2^28..2^28-1 to -2^29..2^29-1.  */
-#define USE_2_TAGS_FOR_INTS
-
-/* Making it work for the union case is too much trouble.  */
-#ifdef USE_LISP_UNION_TYPE
-# undef USE_2_TAGS_FOR_INTS
-#endif
-
 /* This is the set of Lisp data types.  */
 
-#if !defined USE_2_TAGS_FOR_INTS
-# define LISP_INT_TAG Lisp_Int
-# define case_Lisp_Int case Lisp_Int
-# define LISP_STRING_TAG 4
-# define LISP_INT_TAG_P(x) ((x) == Lisp_Int)
-#else
-# define LISP_INT_TAG Lisp_Int0
-# define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
-# ifdef USE_LSB_TAG
-#  define LISP_INT1_TAG 4
-#  define LISP_STRING_TAG 1
-#  define LISP_INT_TAG_P(x) (((x) & 3) == 0)
-# else
-#  define LISP_INT1_TAG 1
-#  define LISP_STRING_TAG 4
-#  define LISP_INT_TAG_P(x) (((x) & 6) == 0)
-# endif
-#endif
+/* Lisp integers use 2 tags, to give them one extra bit, thus
+   extending their range from, e.g., -2^28..2^28-1 to -2^29..2^29-1.  */
+static EMACS_INT const INTMASK = EMACS_INT_MAX >> (INTTYPEBITS - 1);
+#define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
+#define LISP_INT_TAG_P(x) (((x) & ~Lisp_Int1) == 0)
 
 /* Stolen from GDB.  The only known compiler that doesn't support
    enums in bitfields is MSVC.  */
@@ -271,12 +239,8 @@ extern int suppress_checking EXTERNALLY_VISIBLE;
 enum Lisp_Type
   {
     /* Integer.  XINT (obj) is the integer value.  */
-#ifdef USE_2_TAGS_FOR_INTS
     Lisp_Int0 = 0,
-    Lisp_Int1 = LISP_INT1_TAG,
-#else
-    Lisp_Int = 0,
-#endif
+    Lisp_Int1 = USE_LSB_TAG ? 1 << INTTYPEBITS : 1,
 
     /* Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol.  */
     Lisp_Symbol = 2,
@@ -287,7 +251,7 @@ enum Lisp_Type
 
     /* String.  XSTRING (object) points to a struct Lisp_String.
        The length of the string, and its contents, are stored therein.  */
-    Lisp_String = LISP_STRING_TAG,
+    Lisp_String = USE_LSB_TAG ? 1 : 1 << INTTYPEBITS,
 
     /* Vector of Lisp objects, or something resembling it.
        XVECTOR (object) points to a struct Lisp_Vector, which contains
@@ -331,88 +295,51 @@ enum Lisp_Fwd_Type
     Lisp_Fwd_Kboard_Obj,       /* Fwd to a Lisp_Object field of kboards.  */
   };
 
-#ifdef USE_LISP_UNION_TYPE
+#ifdef CHECK_LISP_OBJECT_TYPE
 
-#ifndef WORDS_BIGENDIAN
+typedef struct { EMACS_INT i; } Lisp_Object;
 
-/* Definition of Lisp_Object for little-endian machines.  */
-
-typedef
-union Lisp_Object
-  {
-    /* Used for comparing two Lisp_Objects;
-       also, positive integers can be accessed fast this way.  */
-    EMACS_INT i;
-
-    struct
-      {
-       /* Use explicit signed, the signedness of a bit-field of type
-          int is implementation defined.  */
-       signed EMACS_INT val  : VALBITS;
-       ENUM_BF (Lisp_Type) type : GCTYPEBITS;
-      } s;
-    struct
-      {
-       EMACS_UINT val : VALBITS;
-       ENUM_BF (Lisp_Type) type : GCTYPEBITS;
-      } u;
-  }
-Lisp_Object;
-
-#else /* If WORDS_BIGENDIAN */
-
-typedef
-union Lisp_Object
-  {
-    /* Used for comparing two Lisp_Objects;
-       also, positive integers can be accessed fast this way.  */
-    EMACS_INT i;
-
-    struct
-      {
-       ENUM_BF (Lisp_Type) type : GCTYPEBITS;
-       /* Use explicit signed, the signedness of a bit-field of type
-          int is implementation defined.  */
-       signed EMACS_INT val  : VALBITS;
-      } s;
-    struct
-      {
-       ENUM_BF (Lisp_Type) type : GCTYPEBITS;
-       EMACS_UINT val : VALBITS;
-      } u;
-  }
-Lisp_Object;
-
-#endif /* WORDS_BIGENDIAN */
+#define XLI(o) (o).i
+LISP_INLINE Lisp_Object
+XIL (EMACS_INT i)
+{
+  Lisp_Object o = { i };
+  return o;
+}
 
-#ifdef __GNUC__
-static inline Lisp_Object
+LISP_INLINE Lisp_Object
 LISP_MAKE_RVALUE (Lisp_Object o)
 {
     return o;
 }
-#else
-/* This is more portable to pre-C99 non-GCC compilers, but for
-   backwards compatibility GCC still accepts an old GNU extension
-   which caused this to only generate a warning.  */
-#define LISP_MAKE_RVALUE(o) (0 ? (o) : (o))
-#endif
 
-#else /* USE_LISP_UNION_TYPE */
+#define LISP_INITIALLY_ZERO {0}
+
+#undef CHECK_LISP_OBJECT_TYPE
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 1 };
+#else /* CHECK_LISP_OBJECT_TYPE */
 
-/* If union type is not wanted, define Lisp_Object as just a number.  */
+/* If a struct type is not wanted, define Lisp_Object as just a number.  */
 
 typedef EMACS_INT Lisp_Object;
+#define XLI(o) (o)
+#define XIL(i) (i)
 #define LISP_MAKE_RVALUE(o) (0+(o))
-#endif /* USE_LISP_UNION_TYPE */
+#define LISP_INITIALLY_ZERO 0
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 0 };
+#endif /* CHECK_LISP_OBJECT_TYPE */
 
 /* In the size word of a vector, this bit means the vector has been marked.  */
 
+static ptrdiff_t const ARRAY_MARK_FLAG
 #define ARRAY_MARK_FLAG PTRDIFF_MIN
+      = ARRAY_MARK_FLAG;
 
 /* In the size word of a struct Lisp_Vector, this bit means it's really
    some other vector-like object.  */
+static ptrdiff_t const PSEUDOVECTOR_FLAG
 #define PSEUDOVECTOR_FLAG (PTRDIFF_MAX - PTRDIFF_MAX / 2)
+      = PSEUDOVECTOR_FLAG;
 
 /* In a pseudovector, the size field actually contains a word with one
    PSEUDOVECTOR_FLAG bit set, and exactly one of the following bits to
@@ -423,167 +350,113 @@ typedef EMACS_INT Lisp_Object;
    It is not crucial, but there are plenty of bits here, so why not do it?  */
 enum pvec_type
 {
-  PVEC_NORMAL_VECTOR = 0,
-  PVEC_PROCESS = 0x200,
-  PVEC_FRAME = 0x400,
-  PVEC_COMPILED = 0x800,
-  PVEC_WINDOW = 0x1000,
-  PVEC_WINDOW_CONFIGURATION = 0x2000,
-  PVEC_SUBR = 0x4000,
-  PVEC_CHAR_TABLE = 0x8000,
-  PVEC_BOOL_VECTOR = 0x10000,
-  PVEC_BUFFER = 0x20000,
-  PVEC_HASH_TABLE = 0x40000,
-  PVEC_TERMINAL = 0x80000,
-  PVEC_SUB_CHAR_TABLE = 0x100000,
-  PVEC_FONT = 0x200000,
-  PVEC_OTHER = 0x400000,
-  PVEC_TYPE_MASK = 0x7ffe00
-
-#if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
-        GDB.  It doesn't work on OS Alpha.  Moved to a variable in
-        emacs.c.  */
-  PVEC_FLAG = PSEUDOVECTOR_FLAG
-#endif
+  PVEC_NORMAL_VECTOR = 0,      /* Unused!  */
+  PVEC_FREE,
+  PVEC_PROCESS,
+  PVEC_FRAME,
+  PVEC_WINDOW,
+  PVEC_BOOL_VECTOR,
+  PVEC_BUFFER,
+  PVEC_HASH_TABLE,
+  PVEC_TERMINAL,
+  PVEC_WINDOW_CONFIGURATION,
+  PVEC_SUBR,
+  PVEC_OTHER,
+  /* These last 4 are special because we OR them in fns.c:internal_equal,
+     so they have to use a disjoint bit pattern:
+     if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE
+                   | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */
+  PVEC_COMPILED                        = 0x10,
+  PVEC_CHAR_TABLE              = 0x20,
+  PVEC_SUB_CHAR_TABLE          = 0x30,
+  PVEC_FONT                    = 0x40
 };
 
-/* For convenience, we also store the number of elements in these bits.
-   Note that this size is not necessarily the memory-footprint size, but
-   only the number of Lisp_Object fields (that need to be traced by the GC).
-   The distinction is used e.g. by Lisp_Process which places extra
-   non-Lisp_Object fields at the end of the structure.  */
-#define PSEUDOVECTOR_SIZE_MASK 0x1ff
+/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers
+   which were stored in a Lisp_Object.  */
+#ifndef DATA_SEG_BITS
+# define DATA_SEG_BITS 0
+#endif
+enum { gdb_DATA_SEG_BITS = DATA_SEG_BITS };
+#undef DATA_SEG_BITS
 
-/* Number of bits to put in each character in the internal representation
-   of bool vectors.  This should not vary across implementations.  */
-#define BOOL_VECTOR_BITS_PER_CHAR 8
+enum More_Lisp_Bits
+  {
+    DATA_SEG_BITS = gdb_DATA_SEG_BITS,
+
+    /* For convenience, we also store the number of elements in these bits.
+       Note that this size is not necessarily the memory-footprint size, but
+       only the number of Lisp_Object fields (that need to be traced by GC).
+       The distinction is used, e.g., by Lisp_Process, which places extra
+       non-Lisp_Object fields at the end of the structure.  */
+    PSEUDOVECTOR_SIZE_BITS = 16,
+    PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1,
+    PVEC_TYPE_MASK = 0x0fff << PSEUDOVECTOR_SIZE_BITS,
+
+    /* Number of bits to put in each character in the internal representation
+       of bool vectors.  This should not vary across implementations.  */
+    BOOL_VECTOR_BITS_PER_CHAR = 8
+  };
 \f
 /* These macros extract various sorts of values from a Lisp_Object.
  For example, if tem is a Lisp_Object whose type is Lisp_Cons,
  XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons.  */
 
-#ifndef USE_LISP_UNION_TYPE
-
 /* Return a perfect hash of the Lisp_Object representation.  */
-#define XHASH(a) (a)
+#define XHASH(a) XLI (a)
 
-#ifdef USE_LSB_TAG
+#if USE_LSB_TAG
 
-#define TYPEMASK ((((EMACS_INT) 1) << GCTYPEBITS) - 1)
-#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))
-# define make_number(N) (((EMACS_INT) (N)) << (GCTYPEBITS - 1))
-#else
-# define XINT(a) (((EMACS_INT) (a)) >> GCTYPEBITS)
-# define XUINT(a) (((EMACS_UINT) (a)) >> GCTYPEBITS)
-# define make_number(N) (((EMACS_INT) (N)) << GCTYPEBITS)
-#endif
-#define XSET(var, type, ptr)                                           \
-    (eassert (XTYPE ((intptr_t) (ptr)) == 0), /* Check alignment.  */ \
-     (var) = (type) | (intptr_t) (ptr))
+enum lsb_bits
+  {
+    TYPEMASK = (1 << GCTYPEBITS) - 1,
+    VALMASK = ~ TYPEMASK
+  };
+#define XTYPE(a) ((enum Lisp_Type) (XLI (a) & TYPEMASK))
+#define XINT(a) (XLI (a) >> INTTYPEBITS)
+#define XUINT(a) ((EMACS_UINT) XLI (a) >> INTTYPEBITS)
+#define make_number(N) XIL ((EMACS_INT) (N) << INTTYPEBITS)
+#define XSET(var, type, ptr)                                              \
+  (eassert (XTYPE (XIL ((intptr_t) (ptr))) == 0), /* Check alignment.  */  \
+   (var) = XIL ((type) | (intptr_t) (ptr)))
 
-#define XPNTR(a) ((intptr_t) ((a) & ~TYPEMASK))
-#define XUNTAG(a, type) ((intptr_t) ((a) - (type)))
+#define XPNTR(a) ((intptr_t) (XLI (a) & ~TYPEMASK))
+#define XUNTAG(a, type) ((intptr_t) (XLI (a) - (type)))
 
 #else  /* not USE_LSB_TAG */
 
+static EMACS_INT const VALMASK
 #define VALMASK VAL_MAX
+      = VALMASK;
 
-/* One need to override this if there must be high bits set in data space
-   (doing the result of the below & ((1 << (GCTYPE + 1)) - 1) would work
-    on all machines, but would penalize machines which don't need it)
- */
-#define XTYPE(a) ((enum Lisp_Type) (((EMACS_UINT) (a)) >> VALBITS))
+#define XTYPE(a) ((enum Lisp_Type) ((EMACS_UINT) XLI (a) >> VALBITS))
 
 /* For integers known to be positive, XFASTINT provides fast retrieval
    and XSETFASTINT provides fast storage.  This takes advantage of the
-   fact that Lisp_Int is 0.  */
-#define XFASTINT(a) ((a) + 0)
-#define XSETFASTINT(a, b) ((a) = (b))
+   fact that Lisp integers have zero-bits in their tags.  */
+#define XFASTINT(a) (XLI (a) + 0)
+#define XSETFASTINT(a, b) ((a) = XIL (b))
 
 /* Extract the value of a Lisp_Object as a (un)signed integer.  */
 
-#ifdef USE_2_TAGS_FOR_INTS
-# define XINT(a) ((((EMACS_INT) (a)) << (GCTYPEBITS - 1)) >> (GCTYPEBITS - 1))
-# define XUINT(a) ((EMACS_UINT) ((a) & (1 + (VALMASK << 1))))
-# define make_number(N) ((((EMACS_INT) (N)) & (1 + (VALMASK << 1))))
-#else
-# define XINT(a) ((((EMACS_INT) (a)) << (BITS_PER_EMACS_INT - VALBITS))        \
-                >> (BITS_PER_EMACS_INT - VALBITS))
-# define XUINT(a) ((EMACS_UINT) ((a) & VALMASK))
-# define make_number(N)                \
-  ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
-#endif
+#define XINT(a) (XLI (a) << INTTYPEBITS >> INTTYPEBITS)
+#define XUINT(a) ((EMACS_UINT) (XLI (a) & INTMASK))
+#define make_number(N) XIL ((EMACS_INT) (N) & INTMASK)
 
-#define XSET(var, type, ptr)                             \
-   ((var) = ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \
-            + ((intptr_t) (ptr) & VALMASK)))
+#define XSET(var, type, ptr)                                 \
+  ((var) = XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS)  \
+               + ((intptr_t) (ptr) & VALMASK)))
 
-#ifdef DATA_SEG_BITS
+#if 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) ((uintptr_t) (((a) & VALMASK)) | DATA_SEG_BITS))
+#define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS))
 #else
-#define XPNTR(a) ((uintptr_t) ((a) & VALMASK))
+#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK))
 #endif
 
 #endif /* not USE_LSB_TAG */
 
-#else /* USE_LISP_UNION_TYPE */
-
-#ifdef USE_2_TAGS_FOR_INTS
-# error "USE_2_TAGS_FOR_INTS is not supported with USE_LISP_UNION_TYPE"
-#endif
-
-#define XHASH(a) ((a).i)
-#define XTYPE(a) ((enum Lisp_Type) (a).u.type)
-#define XINT(a) ((EMACS_INT) (a).s.val)
-#define XUINT(a) ((EMACS_UINT) (a).u.val)
-
-#ifdef USE_LSB_TAG
-
-# define XSET(var, vartype, ptr) \
-  (eassert ((((uintptr_t) (ptr)) & ((1 << GCTYPEBITS) - 1)) == 0),     \
-   (var).u.val = ((uintptr_t) (ptr)) >> GCTYPEBITS,                    \
-   (var).u.type = ((char) (vartype)))
-
-/* 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) ((intptr_t) (v).s.val << GCTYPEBITS)
-
-#else  /* !USE_LSB_TAG */
-
-/* For integers known to be positive, XFASTINT provides fast retrieval
-   and XSETFASTINT provides fast storage.  This takes advantage of the
-   fact that Lisp_Int is 0.  */
-# define XFASTINT(a) ((a).i + 0)
-# define XSETFASTINT(a, b) ((a).i = (b))
-
-# define XSET(var, vartype, ptr) \
-   (((var).s.val = ((intptr_t) (ptr))), ((var).s.type = ((char) (vartype))))
-
-#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) ((intptr_t) (XUINT (a) | DATA_SEG_BITS))
-#else
-#define XPNTR(a) ((intptr_t) XUINT (a))
-#endif
-
-#endif /* !USE_LSB_TAG */
-
-#if __GNUC__ >= 2 && defined (__OPTIMIZE__)
-#define make_number(N) \
-  (__extension__ ({ Lisp_Object _l; _l.s.val = (N); _l.s.type = Lisp_Int; _l; }))
-#else
-extern Lisp_Object make_number (EMACS_INT);
-#endif
-
-#endif /* USE_LISP_UNION_TYPE */
-
 /* For integers known to be positive, XFASTINT sometimes provides
    faster retrieval and XSETFASTINT provides faster storage.
    If not, fallback on the non-accelerated path.  */
@@ -601,20 +474,15 @@ extern Lisp_Object make_number (EMACS_INT);
 
 #define EQ(x, y) (XHASH (x) == XHASH (y))
 
-/* Number of bits in a fixnum, including the sign bit.  */
-#ifdef USE_2_TAGS_FOR_INTS
-# define FIXNUM_BITS (VALBITS + 1)
-#else
-# 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)
+   values.  They are macros for use in static initializers, and
+   constants for visibility to GDB.  */
+static EMACS_INT const MOST_POSITIVE_FIXNUM =
+#define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS)
+       MOST_POSITIVE_FIXNUM;
+static EMACS_INT const MOST_NEGATIVE_FIXNUM =
 #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM)
+       MOST_NEGATIVE_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
@@ -623,7 +491,7 @@ extern Lisp_Object make_number (EMACS_INT);
 #define FIXNUM_OVERFLOW_P(i) \
   (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM))
 
-static inline ptrdiff_t
+LISP_INLINE ptrdiff_t
 clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 {
   return num < lower ? lower : num <= upper ? num : upper;
@@ -701,21 +569,23 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 
 #define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code)
 #define XSETTYPED_PVECTYPE(v, size_member, code) \
-  ((v)->size_member |= PSEUDOVECTOR_FLAG | (code))
+  ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))
 #define XSETPVECTYPESIZE(v, code, sizeval) \
-  ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval))
+  ((v)->header.size = (PSEUDOVECTOR_FLAG                       \
+                      | ((code) << PSEUDOVECTOR_SIZE_BITS)     \
+                      | (sizeval)))
 
 /* The cast to struct vectorlike_header * avoids aliasing issues.  */
 #define XSETPSEUDOVECTOR(a, b, code) \
-  XSETTYPED_PSEUDOVECTOR(a, b,       \
-                        (((struct vectorlike_header *) \
-                          XUNTAG (a, Lisp_Vectorlike)) \
-                         ->size),                      \
-                        code)
+  XSETTYPED_PSEUDOVECTOR (a, b,                                        \
+                         (((struct vectorlike_header *)        \
+                           XUNTAG (a, Lisp_Vectorlike))        \
+                          ->size),                             \
+                         code)
 #define XSETTYPED_PSEUDOVECTOR(a, b, size, code)                       \
   (XSETVECTOR (a, b),                                                  \
    eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))              \
-           == (PSEUDOVECTOR_FLAG | (code))))
+           == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS))))
 
 #define XSETWINDOW_CONFIGURATION(a, b) \
   (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
@@ -739,7 +609,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 #define ASET(ARRAY, IDX, VAL)  \
   (eassert ((IDX) == (IDX)),                           \
    eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)),      \
-   AREF ((ARRAY), (IDX)) = (VAL))
+   XVECTOR (ARRAY)->contents[IDX] = (VAL))
 
 /* Convenience macros for dealing with Lisp strings.  */
 
@@ -763,8 +633,10 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 #define CHECK_TYPE(ok, Qxxxp, x) \
   do { if (!(ok)) wrong_type_argument (Qxxxp, (x)); } while (0)
 
+/* Deprecated and will be removed soon.  */
+
+#define INTERNAL_FIELD(field) field ## _
 
-\f
 /* See the macros in intervals.h.  */
 
 typedef struct interval *INTERVAL;
@@ -773,28 +645,19 @@ typedef struct interval *INTERVAL;
 #define CHECK_STRING_OR_BUFFER(x) \
   CHECK_TYPE (STRINGP (x) || BUFFERP (x), Qbuffer_or_string_p, x)
 
-\f
-/* In a cons, the markbit of the car is the gc mark bit */
-
 struct Lisp_Cons
   {
-    /* Please do not use the names of these elements in code other
-       than the core lisp implementation.  Use XCAR and XCDR below.  */
-#ifdef HIDE_LISP_IMPLEMENTATION
-    Lisp_Object car_;
-    union
-    {
-      Lisp_Object cdr_;
-      struct Lisp_Cons *chain;
-    } u;
-#else
+    /* Car of this cons cell.  */
     Lisp_Object car;
+
     union
     {
+      /* Cdr of this cons cell.  */
       Lisp_Object cdr;
+
+      /* Used to chain conses on a free list.  */
       struct Lisp_Cons *chain;
     } u;
-#endif
   };
 
 /* Take the car or cdr of something known to be a cons cell.  */
@@ -804,13 +667,8 @@ struct Lisp_Cons
    fields are not accessible as lvalues.  (What if we want to switch to
    a copying collector someday?  Cached cons cell field addresses may be
    invalidated at arbitrary points.)  */
-#ifdef HIDE_LISP_IMPLEMENTATION
-#define XCAR_AS_LVALUE(c) (XCONS ((c))->car_)
-#define XCDR_AS_LVALUE(c) (XCONS ((c))->u.cdr_)
-#else
-#define XCAR_AS_LVALUE(c) (XCONS ((c))->car)
-#define XCDR_AS_LVALUE(c) (XCONS ((c))->u.cdr)
-#endif
+#define XCAR_AS_LVALUE(c) (XCONS (c)->car)
+#define XCDR_AS_LVALUE(c) (XCONS (c)->u.cdr)
 
 /* Use these from normal code.  */
 #define XCAR(c)        LISP_MAKE_RVALUE (XCAR_AS_LVALUE (c))
@@ -871,10 +729,15 @@ extern ptrdiff_t string_bytes (struct Lisp_String *);
    Although the actual size limit (see STRING_BYTES_MAX in alloc.c)
    may be a bit smaller than STRING_BYTES_BOUND, calculating it here
    would expose alloc.c internal details that we'd rather keep
-   private.  The cast to ptrdiff_t ensures that STRING_BYTES_BOUND is
-   signed.  */
+   private.
+
+   This is a macro for use in static initializers, and a constant for
+   visibility to GDB.  The cast to ptrdiff_t ensures that
+   the macro is signed.  */
+static ptrdiff_t const STRING_BYTES_BOUND =
 #define STRING_BYTES_BOUND  \
-  min (MOST_POSITIVE_FIXNUM, (ptrdiff_t) min (SIZE_MAX, PTRDIFF_MAX) - 1)
+  ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1))
+       STRING_BYTES_BOUND;
 
 /* Mark STR as a unibyte string.  */
 #define STRING_SET_UNIBYTE(STR)  \
@@ -889,19 +752,13 @@ extern ptrdiff_t string_bytes (struct Lisp_String *);
       (STR) = empty_multibyte_string;  \
     else XSTRING (STR)->size_byte = XSTRING (STR)->size; } while (0)
 
-/* Get text properties.  */
-#define STRING_INTERVALS(STR)  (XSTRING (STR)->intervals + 0)
-
-/* Set text properties.  */
-#define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT))
-
-/* In a string or vector, the sign bit of the `size' is the gc mark bit */
+/* In a string or vector, the sign bit of the `size' is the gc mark bit.  */
 
 struct Lisp_String
   {
     ptrdiff_t size;
     ptrdiff_t size_byte;
-    INTERVAL intervals;                /* text properties in this string */
+    INTERVAL intervals;                /* Text properties in this string.  */
     unsigned char *data;
   };
 
@@ -914,41 +771,88 @@ struct Lisp_String
    <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
 struct vectorlike_header
   {
+    /* This field contains various pieces of information:
+       - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit.
+       - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain
+         vector (0) or a pseudovector (1).
+       - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number
+         of slots) of the vector.
+       - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into
+         a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest
+         PSEUDOVECTOR_SIZE_BITS.  That size normally indicates the number of
+         Lisp_Object slots at the beginning of the object that need to be
+         traced by the GC, tho some types use it slightly differently.
+       - E.g. if the pvec type is PVEC_FREE it means this is an unallocated
+         vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size
+         in bytes.  */
     ptrdiff_t size;
 
     /* When the vector is allocated from a vector block, NBYTES is used
        if the vector is not on a free list, and VECTOR is used otherwise.
        For large vector-like objects, BUFFER or VECTOR is used as a pointer
-       to the next vector-like object.  It is generally a buffer or a 
+       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 {
+      /* This is only needed for small vectors that are not free because the
+        `size' field only gives us the number of Lisp_Object slots, whereas we
+        need to know the total size, including non-Lisp_Object data.
+        FIXME: figure out a way to store this info elsewhere so we can
+        finally get rid of this extra word of overhead.  */
       ptrdiff_t nbytes;
       struct buffer *buffer;
+      /* FIXME: This can be removed: For large vectors, this field could be
+        placed *before* the vector itself.  And for small vectors on a free
+        list, this field could be stored in the vector's bytes, since the
+        empty vector is handled specially anyway.  */
       struct Lisp_Vector *vector;
     } next;
   };
 
+/* Regular vector is just a header plus array of Lisp_Objects.  */
+
 struct Lisp_Vector
   {
     struct vectorlike_header header;
     Lisp_Object contents[1];
   };
 
+/* A boolvector is a kind of vectorlike, with contents are like a string.  */
+
+struct Lisp_Bool_Vector
+  {
+    /* HEADER.SIZE is the vector's size field.  It doesn't have the real size,
+       just the subtype information.  */
+    struct vectorlike_header header;
+    /* This is the size in bits.  */
+    EMACS_INT size;
+    /* This contains the actual bits, packed into bytes.  */
+    unsigned char data[1];
+  };
+
+/* Some handy constants for calculating sizes
+   and offsets, mostly of vectorlike objects.   */
+
+enum
+  {
+    header_size = offsetof (struct Lisp_Vector, contents),
+    bool_header_size = offsetof (struct Lisp_Bool_Vector, data),
+    word_size = sizeof (Lisp_Object)
+  };
+
 /* If a struct is made to look like a vector, this macro returns the length
    of the shortest vector that would hold that struct.  */
-#define VECSIZE(type) ((sizeof (type)                                    \
-                       - offsetof (struct Lisp_Vector, contents[0])      \
-                        + sizeof (Lisp_Object) - 1) /* round up */       \
-                      / sizeof (Lisp_Object))
+
+#define VECSIZE(type)                                          \
+  ((sizeof (type) - header_size + word_size - 1) / word_size)
 
 /* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields
    at the end and we need to compute the number of Lisp_Object fields (the
    ones that the GC needs to trace).  */
-#define PSEUDOVECSIZE(type, nonlispfield) \
-  ((offsetof (type, nonlispfield) - offsetof (struct Lisp_Vector, contents[0])) \
-   / sizeof (Lisp_Object))
+
+#define PSEUDOVECSIZE(type, nonlispfield)                      \
+  ((offsetof (type, nonlispfield) - header_size) / word_size)
 
 /* A char-table is a kind of vectorlike, with contents are like a
    vector but with a few other slots.  For some purposes, it makes
@@ -960,16 +864,6 @@ struct Lisp_Vector
    of a char-table, and there's no way to access it directly from
    Emacs Lisp program.  */
 
-/* This is the number of slots that every char table must have.  This
-   counts the ordinary slots and the top, defalt, parent, and purpose
-   slots.  */
-#define CHAR_TABLE_STANDARD_SLOTS (VECSIZE (struct Lisp_Char_Table) - 1)
-
-/* Return the number of "extra" slots in the char table CT.  */
-
-#define CHAR_TABLE_EXTRA_SLOTS(CT)     \
-  (((CT)->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
-
 #ifdef __GNUC__
 
 #define CHAR_TABLE_REF_ASCII(CT, IDX)                                  \
@@ -1031,10 +925,13 @@ struct Lisp_Vector
    ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX] = VAL    \
    : char_table_set (CT, IDX, VAL))
 
-#define CHARTAB_SIZE_BITS_0 6
-#define CHARTAB_SIZE_BITS_1 4
-#define CHARTAB_SIZE_BITS_2 5
-#define CHARTAB_SIZE_BITS_3 7
+enum CHARTAB_SIZE_BITS
+  {
+    CHARTAB_SIZE_BITS_0 = 6,
+    CHARTAB_SIZE_BITS_1 = 4,
+    CHARTAB_SIZE_BITS_2 = 5,
+    CHARTAB_SIZE_BITS_3 = 7
+  };
 
 extern const int chartab_size[4];
 
@@ -1091,18 +988,6 @@ struct Lisp_Sub_Char_Table
     Lisp_Object contents[1];
   };
 
-/* A boolvector is a kind of vectorlike, with contents are like a string.  */
-struct Lisp_Bool_Vector
-  {
-    /* HEADER.SIZE is the vector's size field.  It doesn't have the real size,
-       just the subtype information.  */
-    struct vectorlike_header header;
-    /* This is the size in bits.  */
-    EMACS_INT size;
-    /* This contains the actual bits, packed into bytes.  */
-    unsigned char data[1];
-  };
-
 /* This structure describes a built-in function.
    It is generated by the DEFUN macro only.
    defsubr makes it into a Lisp object.
@@ -1133,6 +1018,19 @@ struct Lisp_Subr
     const char *doc;
   };
 
+/* This is the number of slots that every char table must have.  This
+   counts the ordinary slots and the top, defalt, parent, and purpose
+   slots.  */
+enum CHAR_TABLE_STANDARD_SLOTS
+  {
+    CHAR_TABLE_STANDARD_SLOTS = VECSIZE (struct Lisp_Char_Table) - 1
+  };
+
+/* Return the number of "extra" slots in the char table CT.  */
+
+#define CHAR_TABLE_EXTRA_SLOTS(CT)     \
+  (((CT)->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
+
 \f
 /***********************************************************************
                               Symbols
@@ -1179,10 +1077,8 @@ struct Lisp_Symbol
      special (with `defvar' etc), and shouldn't be lexically bound.  */
   unsigned declared_special : 1;
 
-  /* The symbol's name, as a Lisp string.
-     The name "xname" is used to intentionally break code referring to
-     the old field "name" of type pointer to struct Lisp_String.  */
-  Lisp_Object xname;
+  /* The symbol's name, as a Lisp string.  */
+  Lisp_Object name;
 
   /* Value of the symbol or Qunbound if unbound.  Which alternative of the
      union is used depends on the `redirect' field above.  */
@@ -1205,43 +1101,42 @@ struct Lisp_Symbol
 
 /* Value is name of symbol.  */
 
-#define SYMBOL_VAL(sym)   \
-  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value)
-#define SYMBOL_ALIAS(sym) \
+#define SYMBOL_VAL(sym)                                                        \
+  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  sym->val.value)
+#define SYMBOL_ALIAS(sym)                                              \
   (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias)
-#define SYMBOL_BLV(sym)   \
+#define SYMBOL_BLV(sym)                                                        \
   (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv)
-#define SYMBOL_FWD(sym)   \
+#define SYMBOL_FWD(sym)                                                        \
   (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd)
-#define SET_SYMBOL_VAL(sym, v)     \
+#define SET_SYMBOL_VAL(sym, v)                                         \
   (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value = (v))
-#define SET_SYMBOL_ALIAS(sym, v)   \
+#define SET_SYMBOL_ALIAS(sym, v)                                       \
   (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias = (v))
-#define SET_SYMBOL_BLV(sym, v)     \
+#define SET_SYMBOL_BLV(sym, v)                                         \
   (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv = (v))
-#define SET_SYMBOL_FWD(sym, v) \
+#define SET_SYMBOL_FWD(sym, v)                                         \
   (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd = (v))
 
-#define SYMBOL_NAME(sym)  \
-     LISP_MAKE_RVALUE (XSYMBOL (sym)->xname)
+#define SYMBOL_NAME(sym) XSYMBOL (sym)->name
 
 /* Value is non-zero if SYM is an interned symbol.  */
 
-#define SYMBOL_INTERNED_P(sym)  \
-     (XSYMBOL (sym)->interned != SYMBOL_UNINTERNED)
+#define SYMBOL_INTERNED_P(sym)                         \
+  (XSYMBOL (sym)->interned != SYMBOL_UNINTERNED)
 
 /* Value is non-zero if SYM is interned in initial_obarray.  */
 
-#define SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P(sym) \
-     (XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY)
+#define SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P(sym)                      \
+  (XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY)
 
 /* Value is non-zero if symbol is considered a constant, i.e. its
    value cannot be changed (there is an exception for keyword symbols,
    whose value can be set to the keyword symbol itself).  */
 
-#define SYMBOL_CONSTANT_P(sym)   XSYMBOL (sym)->constant
+#define SYMBOL_CONSTANT_P(sym) XSYMBOL (sym)->constant
 
-#define DEFSYM(sym, name)      \
+#define DEFSYM(sym, name)                                              \
   do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (0)
 
 \f
@@ -1360,19 +1255,18 @@ struct Lisp_Hash_Table
 
 /* Default size for hash tables if not specified.  */
 
-#define DEFAULT_HASH_SIZE 65
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE = 65 };
 
 /* Default threshold specifying when to resize a hash table.  The
    value gives the ratio of current entries in the hash table and the
    size of the hash table.  */
 
-#define DEFAULT_REHASH_THRESHOLD 0.8
+static double const DEFAULT_REHASH_THRESHOLD = 0.8;
 
 /* Default factor by which to increase the size of a hash table.  */
 
-#define DEFAULT_REHASH_SIZE 1.5
+static double const DEFAULT_REHASH_SIZE = 1.5;
 
-\f
 /* These structures are used for various misc types.  */
 
 struct Lisp_Misc_Any           /* Supertype of all Misc types.  */
@@ -1423,6 +1317,66 @@ struct Lisp_Marker
   ptrdiff_t bytepos;
 };
 
+/* START and END are markers in the overlay's buffer, and
+   PLIST is the overlay's property list.  */
+struct Lisp_Overlay
+/* An overlay's real data content is:
+   - plist
+   - buffer (really there are two buffer pointers, one per marker,
+     and both points to the same buffer)
+   - insertion type of both ends (per-marker fields)
+   - start & start byte (of start marker)
+   - end & end byte (of end marker)
+   - next (singly linked list of overlays)
+   - next fields of start and end markers (singly linked list of markers).
+   I.e. 9words plus 2 bits, 3words of which are for external linked lists.
+*/
+  {
+    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Overlay */
+    unsigned gcmarkbit : 1;
+    int spacer : 15;
+    struct Lisp_Overlay *next;
+    Lisp_Object start;
+    Lisp_Object end;
+    Lisp_Object plist;
+  };
+
+/* Hold a C pointer for later use.
+   This type of object is used in the arg to record_unwind_protect.  */
+struct Lisp_Save_Value
+  {
+    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Save_Value */
+    unsigned gcmarkbit : 1;
+    int spacer : 14;
+    /* If DOGC is set, POINTER is the address of a memory
+       area containing INTEGER potential Lisp_Objects.  */
+    unsigned int dogc : 1;
+    void *pointer;
+    ptrdiff_t integer;
+  };
+
+
+/* A miscellaneous object, when it's on the free list.  */
+struct Lisp_Free
+  {
+    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Free */
+    unsigned gcmarkbit : 1;
+    int spacer : 15;
+    union Lisp_Misc *chain;
+  };
+
+/* To get the type field of a union Lisp_Misc, use XMISCTYPE.
+   It uses one of these struct subtypes to get the type field.  */
+
+union Lisp_Misc
+  {
+    struct Lisp_Misc_Any u_any;           /* Supertype of all Misc types.  */
+    struct Lisp_Free u_free;
+    struct Lisp_Marker u_marker;
+    struct Lisp_Overlay u_overlay;
+    struct Lisp_Save_Value u_save_value;
+  };
+
 /* Forwarding pointer to an int variable.
    This is allowed only in the value cell of a symbol,
    and it means that the symbol's value really lives in the
@@ -1489,13 +1443,13 @@ struct Lisp_Buffer_Objfwd
 struct Lisp_Buffer_Local_Value
   {
     /* 1 means that merely setting the variable creates a local
-       binding for the current buffer */
+       binding for the current buffer */
     unsigned int local_if_set : 1;
     /* 1 means this variable can have frame-local bindings, otherwise, it is
        can have buffer-local bindings.  The two cannot be combined.  */
     unsigned int frame_local : 1;
     /* 1 means that the binding now loaded was found.
-       Presumably equivalent to (defcell!=valcell) */
+       Presumably equivalent to (defcell!=valcell) */
     unsigned int found : 1;
     /* If non-NULL, a forwarding to the C var where it should also be set.  */
     union Lisp_Fwd *fwd;       /* Should never be (Buffer|Kboard)_Objfwd.  */
@@ -1520,27 +1474,6 @@ struct Lisp_Buffer_Local_Value
 #define BLV_VALUE(blv) (XCDR ((blv)->valcell))
 #define SET_BLV_VALUE(blv, v) (XSETCDR ((blv)->valcell, v))
 
-/* START and END are markers in the overlay's buffer, and
-   PLIST is the overlay's property list.  */
-struct Lisp_Overlay
-/* An overlay's real data content is:
-   - plist
-   - buffer
-   - insertion type of both ends
-   - start & start_byte
-   - end & end_byte
-   - next (singly linked list of overlays).
-   - start_next and end_next (singly linked list of markers).
-   I.e. 9words plus 2 bits, 3words of which are for external linked lists.
-*/
-  {
-    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Overlay */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
-    struct Lisp_Overlay *next;
-    Lisp_Object start, end, plist;
-  };
-
 /* Like Lisp_Objfwd except that value lives in a slot in the
    current kboard.  */
 struct Lisp_Kboard_Objfwd
@@ -1549,42 +1482,6 @@ struct Lisp_Kboard_Objfwd
     int offset;
   };
 
-/* Hold a C pointer for later use.
-   This type of object is used in the arg to record_unwind_protect.  */
-struct Lisp_Save_Value
-  {
-    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Save_Value */
-    unsigned gcmarkbit : 1;
-    int spacer : 14;
-    /* If DOGC is set, POINTER is the address of a memory
-       area containing INTEGER potential Lisp_Objects.  */
-    unsigned int dogc : 1;
-    void *pointer;
-    ptrdiff_t integer;
-  };
-
-
-/* A miscellaneous object, when it's on the free list.  */
-struct Lisp_Free
-  {
-    ENUM_BF (Lisp_Misc_Type) type : 16;        /* = Lisp_Misc_Free */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
-    union Lisp_Misc *chain;
-  };
-
-/* To get the type field of a union Lisp_Misc, use XMISCTYPE.
-   It uses one of these struct subtypes to get the type field.  */
-
-union Lisp_Misc
-  {
-    struct Lisp_Misc_Any u_any;           /* Supertype of all Misc types.  */
-    struct Lisp_Free u_free;
-    struct Lisp_Marker u_marker;
-    struct Lisp_Overlay u_overlay;
-    struct Lisp_Save_Value u_save_value;
-  };
-
 union Lisp_Fwd
   {
     struct Lisp_Intfwd u_intfwd;
@@ -1594,28 +1491,18 @@ union Lisp_Fwd
     struct Lisp_Kboard_Objfwd u_kboard_objfwd;
   };
 \f
-/* Lisp floating point type */
+/* Lisp floating point type */
 struct Lisp_Float
   {
     union
     {
-#ifdef HIDE_LISP_IMPLEMENTATION
-      double data_;
-#else
       double data;
-#endif
       struct Lisp_Float *chain;
     } u;
   };
 
-#ifdef HIDE_LISP_IMPLEMENTATION
-#define XFLOAT_DATA(f) (0 ? XFLOAT (f)->u.data_ : XFLOAT (f)->u.data_)
-#else
-#define XFLOAT_DATA(f) (0 ? XFLOAT (f)->u.data :  XFLOAT (f)->u.data)
-/* This should be used only in alloc.c, which always disables
-   HIDE_LISP_IMPLEMENTATION.  */
-#define XFLOAT_INIT(f,n) (XFLOAT (f)->u.data = (n))
-#endif
+#define XFLOAT_DATA(f) (0 ? XFLOAT (f)->u.data :  XFLOAT (f)->u.data)
+#define XFLOAT_INIT(f, n) (XFLOAT (f)->u.data = (n))
 
 /* A character, declared with the following typedef, is a member
    of some character set associated with the current buffer.  */
@@ -1626,31 +1513,38 @@ typedef unsigned char UCHAR;
 
 /* Meanings of slots in a Lisp_Compiled:  */
 
-#define COMPILED_ARGLIST 0
-#define COMPILED_BYTECODE 1
-#define COMPILED_CONSTANTS 2
-#define COMPILED_STACK_DEPTH 3
-#define COMPILED_DOC_STRING 4
-#define COMPILED_INTERACTIVE 5
+enum Lisp_Compiled
+  {
+    COMPILED_ARGLIST = 0,
+    COMPILED_BYTECODE = 1,
+    COMPILED_CONSTANTS = 2,
+    COMPILED_STACK_DEPTH = 3,
+    COMPILED_DOC_STRING = 4,
+    COMPILED_INTERACTIVE = 5
+  };
 
 /* Flag bits in a character.  These also get used in termhooks.h.
    Richard Stallman <rms@gnu.ai.mit.edu> thinks that MULE
    (MUlti-Lingual Emacs) might need 22 bits for the character value
    itself, so we probably shouldn't use any bits lower than 0x0400000.  */
-#define CHAR_ALT   (0x0400000)
-#define CHAR_SUPER (0x0800000)
-#define CHAR_HYPER (0x1000000)
-#define CHAR_SHIFT (0x2000000)
-#define CHAR_CTL   (0x4000000)
-#define CHAR_META  (0x8000000)
-
-#define CHAR_MODIFIER_MASK \
-  (CHAR_ALT | CHAR_SUPER | CHAR_HYPER  | CHAR_SHIFT | CHAR_CTL | CHAR_META)
+enum char_bits
+  {
+    CHAR_ALT = 0x0400000,
+    CHAR_SUPER = 0x0800000,
+    CHAR_HYPER = 0x1000000,
+    CHAR_SHIFT = 0x2000000,
+    CHAR_CTL = 0x4000000,
+    CHAR_META = 0x8000000,
+
+    CHAR_MODIFIER_MASK =
+      CHAR_ALT | CHAR_SUPER | CHAR_HYPER | CHAR_SHIFT | CHAR_CTL | CHAR_META,
+
+    /* Actually, the current Emacs uses 22 bits for the character value
+       itself.  */
+    CHARACTERBITS = 22
+  };
 
 
-/* Actually, the current Emacs uses 22 bits for the character value
-   itself.  */
-#define CHARACTERBITS 22
 
 \f
 /* The glyph datatype, used to represent characters on the display.
@@ -1707,9 +1601,6 @@ typedef struct {
                   (XINT (gc) >> CHARACTERBITS));                       \
     }                                                                  \
   while (0)
-
-/* The ID of the mode line highlighting face.  */
-#define GLYPH_MODE_LINE_FACE 1
 \f
 /* Structure to hold mouse highlight data.  This is here because other
    header files need it for defining struct x_output etc.  */
@@ -1782,15 +1673,17 @@ typedef struct {
 /* 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)
+  TYPED_PSEUDOVECTORP (x, vectorlike_header, code)
+
+#define PSEUDOVECTOR_TYPEP(v, code)                                    \
+  (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))                  \
+   == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)))
 
 /* True if object X, with internal type struct T *, is a pseudovector whose
    code is CODE.  */
 #define TYPED_PSEUDOVECTORP(x, t, code)                                \
   (VECTORLIKEP (x)                                             \
-   && (((((struct t *) XUNTAG (x, Lisp_Vectorlike))->size      \
-        & (PSEUDOVECTOR_FLAG | (code))))                       \
-       == (PSEUDOVECTOR_FLAG | (code))))
+   && PSEUDOVECTOR_TYPEP ((struct t *) XUNTAG (x, Lisp_Vectorlike), code))
 
 /* Test for specific pseudovector types.  */
 #define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION)
@@ -1867,7 +1760,8 @@ typedef struct {
    vchild, and hchild members are all nil.  */
 
 #define CHECK_LIVE_WINDOW(x) \
-  CHECK_TYPE (WINDOWP (x) && !NILP (XWINDOW (x)->buffer), Qwindow_live_p, x)
+  CHECK_TYPE (WINDOWP (x) && !NILP (XWINDOW (x)->buffer), \
+             Qwindow_live_p, x)
 
 #define CHECK_PROCESS(x) \
   CHECK_TYPE (PROCESSP (x), Qprocessp, x)
@@ -1881,7 +1775,7 @@ typedef struct {
 #define CHECK_NATNUM(x) \
   CHECK_TYPE (NATNUMP (x), Qwholenump, x)
 
-#define CHECK_RANGED_INTEGER(lo, x, hi)                                        \
+#define CHECK_RANGED_INTEGER(x, lo, hi)                                        \
   do {                                                                 \
     CHECK_NUMBER (x);                                                  \
     if (! ((lo) <= XINT (x) && XINT (x) <= (hi)))                      \
@@ -1895,9 +1789,9 @@ typedef struct {
 #define CHECK_TYPE_RANGED_INTEGER(type, x) \
   do {                                                                 \
     if (TYPE_SIGNED (type))                                            \
-      CHECK_RANGED_INTEGER (TYPE_MINIMUM (type), x, TYPE_MAXIMUM (type)); \
+      CHECK_RANGED_INTEGER (x, TYPE_MINIMUM (type), TYPE_MAXIMUM (type)); \
     else                                                               \
-      CHECK_RANGED_INTEGER (0, x, TYPE_MAXIMUM (type));                        \
+      CHECK_RANGED_INTEGER (x, 0, TYPE_MAXIMUM (type));                        \
   } while (0)
 
 #define CHECK_MARKER(x) \
@@ -1982,16 +1876,17 @@ typedef struct {
 #ifdef _MSC_VER
 #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)),   \
+   static struct Lisp_Subr alignas (GCALIGNMENT) sname =               \
+   { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS)                             \
+     | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),               \
       { (Lisp_Object (__cdecl *)(void))fnname },                        \
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
 #else  /* not _MSC_VER */
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
    Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                         \
-   static DECL_ALIGN (struct Lisp_Subr, sname) =                       \
-     { PVEC_SUBR,                                                      \
+   static struct Lisp_Subr alignas (GCALIGNMENT) sname =               \
+     { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS,                            \
       { .a ## maxargs = fnname },                                      \
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
@@ -2026,8 +1921,11 @@ typedef struct {
    is how we define the symbol for function `name' at start-up time.  */
 extern void defsubr (struct Lisp_Subr *);
 
-#define MANY -2
-#define UNEVALLED -1
+enum maxargs
+  {
+    MANY = -2,
+    UNEVALLED = -1
+  };
 
 extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
 extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
@@ -2228,14 +2126,6 @@ extern void process_quit_flag (void);
 extern Lisp_Object Vascii_downcase_table;
 extern Lisp_Object Vascii_canon_table;
 \f
-/* Number of bytes of structure consed since last GC.  */
-
-extern EMACS_INT consing_since_gc;
-
-extern EMACS_INT gc_relative_threshold;
-
-extern EMACS_INT memory_full_cons_threshold;
-
 /* Structure for recording stack slots that need marking.  */
 
 /* This is a chain of structures, each of which points at a Lisp_Object
@@ -2442,6 +2332,104 @@ void staticpro (Lisp_Object *);
 struct window;
 struct frame;
 
+/* Simple access functions.  */
+
+LISP_INLINE Lisp_Object *
+aref_addr (Lisp_Object array, ptrdiff_t idx)
+{
+  return & XVECTOR (array)->contents[idx];
+}
+
+LISP_INLINE void
+gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val)
+{
+  /* Like ASET, but also can be used in the garbage collector:
+     sweep_weak_table calls set_hash_key etc. while the table is marked.  */
+  eassert (0 <= idx && idx < (ASIZE (array) & ~ARRAY_MARK_FLAG));
+  XVECTOR (array)->contents[idx] = val;
+}
+
+LISP_INLINE void
+set_hash_key (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+{
+  gc_aset (h->key_and_value, 2 * idx, val);
+}
+
+LISP_INLINE void
+set_hash_value (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+{
+  gc_aset (h->key_and_value, 2 * idx + 1, val);
+}
+
+LISP_INLINE void
+set_hash_next (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+{
+  gc_aset (h->next, idx, val);
+}
+
+LISP_INLINE void
+set_hash_hash (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+{
+  gc_aset (h->hash, idx, val);
+}
+
+LISP_INLINE void
+set_hash_index (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+{
+  gc_aset (h->index, idx, val);
+}
+
+/* Use these functions to set Lisp_Object
+   or pointer slots of struct Lisp_Symbol.  */
+
+LISP_INLINE void
+set_symbol_name (Lisp_Object sym, Lisp_Object name)
+{
+  XSYMBOL (sym)->name = name;
+}
+
+LISP_INLINE void
+set_symbol_function (Lisp_Object sym, Lisp_Object function)
+{
+  XSYMBOL (sym)->function = function;
+}
+
+LISP_INLINE void
+set_symbol_plist (Lisp_Object sym, Lisp_Object plist)
+{
+  XSYMBOL (sym)->plist = plist;
+}
+
+LISP_INLINE void
+set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next)
+{
+  XSYMBOL (sym)->next = next;
+}
+
+/* Set overlay's property list.  */
+
+LISP_INLINE void
+set_overlay_plist (Lisp_Object overlay, Lisp_Object plist)
+{
+  XOVERLAY (overlay)->plist = plist;
+}
+
+/* Get text properties of S.  */
+
+LISP_INLINE INTERVAL
+string_get_intervals (Lisp_Object s)
+{
+  return XSTRING (s)->intervals;
+}
+
+/* Set text properties of S to I.  */
+
+LISP_INLINE void
+string_set_intervals (Lisp_Object s, INTERVAL i)
+{
+  XSTRING (s)->intervals = i;
+}
+
 /* Defined in data.c.  */
 extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound;
 extern Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
@@ -2469,60 +2457,19 @@ extern Lisp_Object Qoverflow_error, Qunderflow_error;
 extern Lisp_Object Qfloatp;
 extern Lisp_Object Qnumberp, Qnumber_or_marker_p;
 
-extern Lisp_Object Qinteger;
+extern Lisp_Object Qinteger, Qinterval, Qsymbol, Qstring;
+extern Lisp_Object Qmisc, Qvector, Qfloat, Qcons, Qbuffer;
 
 extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
 
-EXFUN (Finteractive_form, 1);
-EXFUN (Fbyteorder, 0);
+EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST;
 
 /* Defined in frame.c */
 extern Lisp_Object Qframep;
 
 /* Defined in data.c */
-EXFUN (Fcar, 1);
-EXFUN (Fcar_safe, 1);
-EXFUN (Fcdr, 1);
-EXFUN (Fcdr_safe, 1);
-EXFUN (Fsetcar, 2);
-EXFUN (Fsetcdr, 2);
-EXFUN (Fboundp, 1);
-EXFUN (Ffboundp, 1);
-EXFUN (Fsymbol_function, 1);
-EXFUN (Fsymbol_name, 1);
 extern Lisp_Object indirect_function (Lisp_Object);
-EXFUN (Findirect_function, 2);
-EXFUN (Ffset, 2);
-EXFUN (Fsymbol_value, 1);
 extern Lisp_Object find_symbol_value (Lisp_Object);
-EXFUN (Fset, 2);
-EXFUN (Fdefault_value, 1);
-EXFUN (Fset_default, 2);
-EXFUN (Fdefault_boundp, 1);
-EXFUN (Fmake_local_variable, 1);
-EXFUN (Flocal_variable_p, 2);
-
-EXFUN (Faref, 2);
-EXFUN (Faset, 3);
-
-EXFUN (Fstring_to_number, 2);
-EXFUN (Fnumber_to_string, 1);
-EXFUN (Fgtr, 2);
-EXFUN (Flss, 2);
-EXFUN (Fgeq, 2);
-EXFUN (Fleq, 2);
-EXFUN (Fzerop, 1);
-EXFUN (Fplus, MANY);
-EXFUN (Fminus, MANY);
-EXFUN (Ftimes, MANY);
-EXFUN (Fquo, MANY);
-EXFUN (Frem, 2);
-EXFUN (Fmax, MANY);
-EXFUN (Fmin, MANY);
-
-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.
@@ -2553,10 +2500,10 @@ 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 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;
-extern Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object) NO_RETURN;
+extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object);
+extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object,
+                                          Lisp_Object);
+extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object);
 extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *);
 extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, int);
 extern void syms_of_data (void);
@@ -2564,22 +2511,11 @@ extern void init_data (void);
 extern void swap_in_global_binding (struct Lisp_Symbol *);
 
 /* Defined in cmds.c */
-EXFUN (Fend_of_line, 1);
-EXFUN (Fforward_char, 1);
-EXFUN (Fforward_line, 1);
 extern void syms_of_cmds (void);
 extern void keys_of_cmds (void);
 
 /* Defined in coding.c */
 extern Lisp_Object Qcharset;
-EXFUN (Fcoding_system_p, 1);
-EXFUN (Fcoding_system_base, 1);
-EXFUN (Fcoding_system_eol_type, 1);
-EXFUN (Fcheck_coding_system, 1);
-EXFUN (Fread_coding_system, 2);
-EXFUN (Fread_non_nil_coding_system, 1);
-EXFUN (Ffind_operation_coding_system, MANY);
-EXFUN (Fdecode_coding_string, 4);
 extern Lisp_Object detect_coding_system (const unsigned char *, ptrdiff_t,
                                          ptrdiff_t, int, int, Lisp_Object);
 extern void init_coding (void);
@@ -2587,13 +2523,11 @@ extern void init_coding_once (void);
 extern void syms_of_coding (void);
 
 /* Defined in character.c */
-EXFUN (Fchar_width, 1);
-EXFUN (Fstring, MANY);
+EXFUN (Fmax_char, 0) ATTRIBUTE_CONST;
 extern ptrdiff_t chars_in_text (const unsigned char *, ptrdiff_t);
 extern ptrdiff_t multibyte_chars_in_text (const unsigned char *, ptrdiff_t);
-extern int multibyte_char_to_unibyte (int);
-extern int multibyte_char_to_unibyte_safe (int);
-extern void init_character_once (void);
+extern int multibyte_char_to_unibyte (int) ATTRIBUTE_CONST;
+extern int multibyte_char_to_unibyte_safe (int) ATTRIBUTE_CONST;
 extern void syms_of_character (void);
 
 /* Defined in charset.c */
@@ -2607,16 +2541,14 @@ struct charset;
 extern void syms_of_composite (void);
 
 /* Defined in syntax.c */
-EXFUN (Fforward_word, 1);
-EXFUN (Fskip_chars_forward, 2);
-EXFUN (Fskip_chars_backward, 2);
 extern void init_syntax_once (void);
 extern void syms_of_syntax (void);
 
 /* Defined in fns.c */
 extern Lisp_Object QCrehash_size, QCrehash_threshold;
 enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
-extern EMACS_INT next_almost_prime (EMACS_INT);
+EXFUN (Fidentity, 1) ATTRIBUTE_CONST;
+extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST;
 extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t);
 extern void sweep_weak_hash_tables (void);
 extern Lisp_Object Qcursor_in_echo_area;
@@ -2630,48 +2562,10 @@ Lisp_Object make_hash_table (Lisp_Object, Lisp_Object, Lisp_Object,
 ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *);
 ptrdiff_t 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);
-EXFUN (Fgethash, 3);
-EXFUN (Fputhash, 3);
-EXFUN (Fremhash, 2);
-
-EXFUN (Fidentity, 1);
-EXFUN (Flength, 1);
-EXFUN (Fappend, MANY);
-EXFUN (Fconcat, MANY);
-EXFUN (Fvconcat, MANY);
-EXFUN (Fcopy_sequence, 1);
-EXFUN (Fstring_make_multibyte, 1);
-EXFUN (Fstring_make_unibyte, 1);
-EXFUN (Fstring_as_multibyte, 1);
-EXFUN (Fstring_as_unibyte, 1);
-EXFUN (Fstring_to_multibyte, 1);
-EXFUN (Fsubstring, 3);
+
 extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t);
-EXFUN (Fnth, 2);
-EXFUN (Fnthcdr, 2);
-EXFUN (Fmemq, 2);
-EXFUN (Fassq, 2);
-EXFUN (Fassoc, 2);
-EXFUN (Felt, 2);
-EXFUN (Fmember, 2);
-EXFUN (Frassq, 2);
-EXFUN (Fdelq, 2);
-EXFUN (Fdelete, 2);
-EXFUN (Fsort, 2);
-EXFUN (Freverse, 1);
-EXFUN (Fnreverse, 1);
-EXFUN (Fget, 2);
-EXFUN (Fput, 3);
-EXFUN (Fequal, 2);
-EXFUN (Fnconc, MANY);
-EXFUN (Fmapcar, 2);
-EXFUN (Fmapconcat, 3);
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
-EXFUN (Fprovide, 2);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object nconc2 (Lisp_Object, Lisp_Object);
@@ -2682,20 +2576,10 @@ extern ptrdiff_t string_char_to_byte (Lisp_Object, ptrdiff_t);
 extern ptrdiff_t string_byte_to_char (Lisp_Object, ptrdiff_t);
 extern Lisp_Object string_to_multibyte (Lisp_Object);
 extern Lisp_Object string_make_unibyte (Lisp_Object);
-EXFUN (Fcopy_alist, 1);
-EXFUN (Fplist_get, 2);
-EXFUN (Fplist_put, 3);
-EXFUN (Fplist_member, 2);
-EXFUN (Frassoc, 2);
-EXFUN (Fstring_equal, 2);
-EXFUN (Fcompare_strings, 7);
-EXFUN (Fstring_lessp, 2);
 extern void syms_of_fns (void);
 
 /* Defined in floatfns.c */
 extern double extract_float (Lisp_Object);
-EXFUN (Ffloat, 1);
-EXFUN (Ftruncate, 2);
 extern void init_floatfns (void);
 extern void syms_of_floatfns (void);
 extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y);
@@ -2713,13 +2597,12 @@ extern Lisp_Object QCascent, QCmargin, QCrelief;
 extern Lisp_Object QCconversion;
 extern int x_bitmap_mask (struct frame *, ptrdiff_t);
 extern void syms_of_image (void);
-extern void init_image (void);
 
 /* Defined in insdel.c */
 extern Lisp_Object Qinhibit_modification_hooks;
 extern void move_gap (ptrdiff_t);
 extern void move_gap_both (ptrdiff_t, ptrdiff_t);
-extern void buffer_overflow (void) NO_RETURN;
+extern _Noreturn void buffer_overflow (void);
 extern void make_gap (ptrdiff_t);
 extern ptrdiff_t copy_text (const unsigned char *, unsigned char *,
                            ptrdiff_t, int, int);
@@ -2764,15 +2647,11 @@ extern void syms_of_insdel (void);
 /* Defined in dispnew.c */
 #if (defined PROFILING \
      && (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__))
-void __executable_start (void) NO_RETURN;
+_Noreturn void __executable_start (void);
 #endif
 extern Lisp_Object selected_frame;
 extern Lisp_Object Vwindow_system;
-EXFUN (Fding, 1);
-EXFUN (Fredraw_frame, 1);
 void duration_to_sec_usec (double, int *, int *);
-EXFUN (Fsleep_for, 2);
-EXFUN (Fredisplay, 1);
 extern Lisp_Object sit_for (Lisp_Object, int, int);
 extern void init_display (void);
 extern void syms_of_display (void);
@@ -2840,34 +2719,41 @@ 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 (size_t) NO_RETURN;
-extern void buffer_memory_full (ptrdiff_t) NO_RETURN;
+extern _Noreturn void memory_full (size_t);
+extern _Noreturn void buffer_memory_full (ptrdiff_t);
 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 zero_vector;
 extern Lisp_Object *stack_base;
-EXFUN (Fcons, 2);
+extern EMACS_INT consing_since_gc;
+extern EMACS_INT gc_relative_threshold;
+extern EMACS_INT memory_full_cons_threshold;
 extern Lisp_Object list1 (Lisp_Object);
 extern Lisp_Object list2 (Lisp_Object, Lisp_Object);
 extern Lisp_Object list3 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object list4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object,
                          Lisp_Object);
-EXFUN (Flist, MANY);
-EXFUN (Fmake_list, 2);
-extern Lisp_Object allocate_misc (void);
-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 *);
+enum constype {CONSTYPE_HEAP, CONSTYPE_PURE};
+extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...);
+extern _Noreturn void string_overflow (void);
 extern Lisp_Object make_string (const char *, ptrdiff_t);
+extern Lisp_Object make_formatted_string (char *, const char *, ...)
+  ATTRIBUTE_FORMAT_PRINTF (2, 3);
 extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t);
+
+/* Make unibyte string from C string when the length isn't known.  */
+
+LISP_INLINE Lisp_Object
+build_unibyte_string (const char *str)
+{
+  return make_unibyte_string (str, strlen (str));
+}
+
 extern Lisp_Object make_multibyte_string (const char *, ptrdiff_t, ptrdiff_t);
 extern Lisp_Object make_event_array (int, Lisp_Object *);
 extern Lisp_Object make_uninit_string (EMACS_INT);
@@ -2875,14 +2761,28 @@ extern Lisp_Object make_uninit_multibyte_string (EMACS_INT, EMACS_INT);
 extern Lisp_Object make_string_from_bytes (const char *, ptrdiff_t, ptrdiff_t);
 extern Lisp_Object make_specified_string (const char *,
                                          ptrdiff_t, ptrdiff_t, int);
-EXFUN (Fpurecopy, 1);
 extern Lisp_Object make_pure_string (const char *, ptrdiff_t, ptrdiff_t, int);
-extern Lisp_Object make_pure_c_string (const char *data);
+extern Lisp_Object make_pure_c_string (const char *, ptrdiff_t);
+
+/* Make a string allocated in pure space, use STR as string data.  */
+
+LISP_INLINE Lisp_Object
+build_pure_c_string (const char *str)
+{
+  return make_pure_c_string (str, strlen (str));
+}
+
+/* Make a string from the data at STR, treating it as multibyte if the
+   data warrants.  */
+
+LISP_INLINE Lisp_Object
+build_string (const char *str)
+{
+  return make_string (str, strlen (str));
+}
+
 extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
-EXFUN (Fgarbage_collect, 0);
 extern void make_byte_code (struct Lisp_Vector *);
-EXFUN (Fmake_byte_code, MANY);
-EXFUN (Fmake_bool_vector, 2);
 extern Lisp_Object Qchar_table_extra_slots;
 extern struct Lisp_Vector *allocate_vector (EMACS_INT);
 extern struct Lisp_Vector *allocate_pseudovector (int memlen, int lisplen, int tag);
@@ -2901,6 +2801,7 @@ extern Lisp_Object make_float (double);
 extern void display_malloc_warning (void);
 extern ptrdiff_t inhibit_garbage_collection (void);
 extern Lisp_Object make_save_value (void *, ptrdiff_t);
+extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
 extern void free_marker (Lisp_Object);
 extern void free_cons (struct Lisp_Cons *);
 extern void init_alloc_once (void);
@@ -2908,6 +2809,11 @@ extern void init_alloc (void);
 extern void syms_of_alloc (void);
 extern struct buffer * allocate_buffer (void);
 extern int valid_lisp_object_p (Lisp_Object);
+#ifdef GC_CHECK_CONS_LIST
+extern void check_cons_list (void);
+#else
+#define check_cons_list() ((void) 0)
+#endif
 
 #ifdef REL_ALLOC
 /* Defined in ralloc.c */
@@ -2919,12 +2825,6 @@ extern void r_alloc_inhibit_buffer_relocation (int);
 #endif
 
 /* Defined in chartab.c */
-EXFUN (Fmake_char_table, 2);
-EXFUN (Fset_char_table_parent, 2);
-EXFUN (Fchar_table_extra_slot, 2);
-EXFUN (Fset_char_table_extra_slot, 3);
-EXFUN (Fset_char_table_range, 3);
-EXFUN (Foptimize_char_table, 2);
 extern Lisp_Object copy_char_table (Lisp_Object);
 extern Lisp_Object char_table_ref (Lisp_Object, int);
 extern Lisp_Object char_table_ref_and_range (Lisp_Object, int,
@@ -2946,11 +2846,6 @@ 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;
-EXFUN (Fprin1, 2);
-EXFUN (Fprin1_to_string, 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 temp_output_buffer_setup (const char *);
@@ -2961,8 +2856,8 @@ extern void print_error_message (Lisp_Object, Lisp_Object, const char *,
                                 Lisp_Object);
 extern Lisp_Object internal_with_output_to_temp_buffer
         (const char *, Lisp_Object (*) (Lisp_Object), Lisp_Object);
-#define FLOAT_TO_STRING_BUFSIZE 350
-extern void float_to_string (char *, double);
+enum FLOAT_TO_STRING_BUFSIZE { FLOAT_TO_STRING_BUFSIZE = 350 };
+extern int float_to_string (char *, double);
 extern void syms_of_print (void);
 
 /* Defined in doprnt.c */
@@ -2980,18 +2875,9 @@ extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t,
 /* Defined in lread.c.  */
 extern Lisp_Object Qvariable_documentation, Qstandard_input;
 extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
-EXFUN (Fread, 1);
-EXFUN (Fread_from_string, 3);
-EXFUN (Fintern, 2);
-EXFUN (Fintern_soft, 2);
-EXFUN (Funintern, 2);
-EXFUN (Fload, 5);
-EXFUN (Fget_load_suffixes, 0);
-EXFUN (Fread_char, 3);
-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 intern_1 (const char *, ptrdiff_t);
+extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t);
 extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t);
 #define LOADHIST_ATTACH(x) \
   do {                                                                 \
@@ -3008,6 +2894,18 @@ extern void init_obarray (void);
 extern void init_lread (void);
 extern void syms_of_lread (void);
 
+LISP_INLINE Lisp_Object
+intern (const char *str)
+{
+  return intern_1 (str, strlen (str));
+}
+
+LISP_INLINE Lisp_Object
+intern_c_string (const char *str)
+{
+  return intern_c_string_1 (str, strlen (str));
+}
+
 /* Defined in eval.c.  */
 extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qmacro;
 extern Lisp_Object Qinhibit_quit, Qclosure;
@@ -3028,29 +2926,18 @@ extern struct handler *handlerlist;
 
    should no longer be used.  */
 extern Lisp_Object Vrun_hooks;
-EXFUN (Frun_hooks, MANY);
-EXFUN (Frun_hook_with_args, MANY);
-EXFUN (Frun_hook_with_args_until_failure, MANY);
 extern void run_hook_with_args_2 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args,
                                       Lisp_Object (*funcall)
                                       (ptrdiff_t nargs, Lisp_Object *args));
-EXFUN (Fprogn, UNEVALLED);
-EXFUN (Finteractive_p, 0);
-EXFUN (Fthrow, 2) NO_RETURN;
-EXFUN (Fsignal, 2);
-extern void xsignal (Lisp_Object, Lisp_Object) NO_RETURN;
-extern void xsignal0 (Lisp_Object) NO_RETURN;
-extern void xsignal1 (Lisp_Object, Lisp_Object) NO_RETURN;
-extern void xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object) NO_RETURN;
-extern void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) NO_RETURN;
-extern void signal_error (const char *, Lisp_Object) NO_RETURN;
-EXFUN (Fcommandp, 2);
-EXFUN (Ffunctionp, 1);
-EXFUN (Feval, 2);
+extern _Noreturn void xsignal (Lisp_Object, Lisp_Object);
+extern _Noreturn void xsignal0 (Lisp_Object);
+extern _Noreturn void xsignal1 (Lisp_Object, Lisp_Object);
+extern _Noreturn void xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern _Noreturn void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object,
+                               Lisp_Object);
+extern _Noreturn void signal_error (const char *, Lisp_Object);
 extern Lisp_Object eval_sub (Lisp_Object form);
-EXFUN (Fapply, MANY);
-EXFUN (Ffuncall, MANY);
 extern Lisp_Object apply1 (Lisp_Object, Lisp_Object);
 extern Lisp_Object call0 (Lisp_Object);
 extern Lisp_Object call1 (Lisp_Object, Lisp_Object);
@@ -3060,23 +2947,23 @@ extern Lisp_Object call4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Li
 extern Lisp_Object call5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object call6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object call7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
-EXFUN (Fdo_auto_save, 2);
 extern Lisp_Object internal_catch (Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object);
 extern Lisp_Object internal_lisp_condition_case (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object internal_condition_case (Lisp_Object (*) (void), Lisp_Object, Lisp_Object (*) (Lisp_Object));
 extern Lisp_Object internal_condition_case_1 (Lisp_Object (*) (Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
 extern Lisp_Object internal_condition_case_2 (Lisp_Object (*) (Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
-extern Lisp_Object internal_condition_case_n (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *, Lisp_Object, Lisp_Object (*) (Lisp_Object));
+extern Lisp_Object internal_condition_case_n
+    (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *,
+     Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *));
 extern void specbind (Lisp_Object, Lisp_Object);
 extern void record_unwind_protect (Lisp_Object (*) (Lisp_Object), Lisp_Object);
 extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
-extern void error (const char *, ...) NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 2);
-extern void verror (const char *, va_list)
-  NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 0);
-extern void do_autoload (Lisp_Object, Lisp_Object);
+extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
+extern _Noreturn void verror (const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (1, 0);
 extern Lisp_Object un_autoload (Lisp_Object);
 extern void init_eval_once (void);
-extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object *);
+extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
 extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
 extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern void init_eval (void);
@@ -3085,58 +2972,26 @@ extern void mark_backtrace (void);
 #endif
 extern void syms_of_eval (void);
 
-/* Defined in editfns.c */
+/* Defined in editfns.c */
 extern Lisp_Object Qfield;
-EXFUN (Fcurrent_message, 0);
-EXFUN (Fgoto_char, 1);
-EXFUN (Fpoint_max_marker, 0);
-EXFUN (Fpoint, 0);
-EXFUN (Fpoint_marker, 0);
-EXFUN (Fline_beginning_position, 1);
-EXFUN (Fline_end_position, 1);
-EXFUN (Ffollowing_char, 0);
-EXFUN (Fprevious_char, 0);
-EXFUN (Fchar_after, 1);
-EXFUN (Finsert, MANY);
-EXFUN (Finsert_char, 3);
 extern void insert1 (Lisp_Object);
-EXFUN (Feolp, 0);
-EXFUN (Feobp, 0);
-EXFUN (Fbolp, 0);
-EXFUN (Fbobp, 0);
-EXFUN (Fformat, MANY);
-EXFUN (Fmessage, MANY);
 extern Lisp_Object format2 (const char *, Lisp_Object, Lisp_Object);
-EXFUN (Fbuffer_substring, 2);
-EXFUN (Fbuffer_string, 0);
 extern Lisp_Object save_excursion_save (void);
 extern Lisp_Object save_restriction_save (void);
 extern Lisp_Object save_excursion_restore (Lisp_Object);
 extern Lisp_Object save_restriction_restore (Lisp_Object);
-EXFUN (Fchar_to_string, 1);
-EXFUN (Fdelete_region, 2);
-EXFUN (Fnarrow_to_region, 2);
-EXFUN (Fwiden, 0);
-EXFUN (Fuser_login_name, 1);
-EXFUN (Fsystem_name, 0);
-EXFUN (Fcurrent_time, 0);
-EXFUN (Fget_internal_run_time, 0);
+extern _Noreturn void time_overflow (void);
 extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, int);
 extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
                                            ptrdiff_t, int);
 extern void init_editfns (void);
 const char *get_system_name (void);
 extern void syms_of_editfns (void);
-EXFUN (Fconstrain_to_field, 5);
-EXFUN (Ffield_end, 3);
 extern void set_time_zone_rule (const char *);
 
-/* Defined in buffer.c */
+/* Defined in buffer.c */
 extern int mouse_face_overlay_overlaps (Lisp_Object);
-extern void nsberror (Lisp_Object) NO_RETURN;
-EXFUN (Fset_buffer_multibyte, 1);
-EXFUN (Foverlay_start, 1);
-EXFUN (Foverlay_end, 1);
+extern _Noreturn void nsberror (Lisp_Object);
 extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t);
 extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);
 extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t);
@@ -3144,38 +2999,17 @@ extern void report_overlay_modification (Lisp_Object, Lisp_Object, int,
                                          Lisp_Object, Lisp_Object, Lisp_Object);
 extern int overlay_touches_p (ptrdiff_t);
 extern Lisp_Object Vbuffer_alist;
-EXFUN (Fget_buffer, 1);
-EXFUN (Fget_buffer_create, 1);
-EXFUN (Fgenerate_new_buffer_name, 2);
-EXFUN (Fset_buffer, 1);
 extern Lisp_Object set_buffer_if_live (Lisp_Object);
-EXFUN (Fbarf_if_buffer_read_only, 0);
-EXFUN (Fcurrent_buffer, 0);
-EXFUN (Fother_buffer, 3);
 extern Lisp_Object other_buffer_safely (Lisp_Object);
-EXFUN (Foverlay_get, 2);
-EXFUN (Fbuffer_modified_p, 1);
-EXFUN (Fset_buffer_modified_p, 1);
-EXFUN (Fkill_buffer, 1);
-EXFUN (Fkill_all_local_variables, 0);
-EXFUN (Fbuffer_enable_undo, 1);
-EXFUN (Ferase_buffer, 0);
 extern Lisp_Object Qpriority, Qwindow, Qbefore_string, Qafter_string;
 extern Lisp_Object get_truename_buffer (Lisp_Object);
-extern struct buffer *all_buffers;
-EXFUN (Fprevious_overlay_change, 1);
-EXFUN (Fbuffer_file_name, 1);
 extern void init_buffer_once (void);
 extern void init_buffer (void);
 extern void syms_of_buffer (void);
 extern void keys_of_buffer (void);
 
-/* Defined in marker.c */
+/* Defined in marker.c */
 
-EXFUN (Fmarker_position, 1);
-EXFUN (Fmarker_buffer, 1);
-EXFUN (Fcopy_marker, 2);
-EXFUN (Fset_marker, 3);
 extern ptrdiff_t marker_position (Lisp_Object);
 extern ptrdiff_t marker_byte_position (Lisp_Object);
 extern void clear_charpos_cache (struct buffer *);
@@ -3187,6 +3021,7 @@ extern Lisp_Object set_marker_restricted (Lisp_Object, Lisp_Object, Lisp_Object)
 extern Lisp_Object set_marker_both (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t);
 extern Lisp_Object set_marker_restricted_both (Lisp_Object, Lisp_Object,
                                                ptrdiff_t, ptrdiff_t);
+extern Lisp_Object build_marker (struct buffer *, ptrdiff_t, ptrdiff_t);
 extern void syms_of_marker (void);
 
 /* Defined in fileio.c */
@@ -3196,27 +3031,11 @@ extern Lisp_Object Qfile_exists_p;
 extern Lisp_Object Qfile_directory_p;
 extern Lisp_Object Qinsert_file_contents;
 extern Lisp_Object Qfile_name_history;
-EXFUN (Ffind_file_name_handler, 2);
-EXFUN (Ffile_name_as_directory, 1);
-EXFUN (Fexpand_file_name, 2);
-EXFUN (Ffile_name_nondirectory, 1);
-EXFUN (Fsubstitute_in_file_name, 1);
-EXFUN (Ffile_symlink_p, 1);
-EXFUN (Fverify_visited_file_modtime, 1);
-EXFUN (Ffile_exists_p, 1);
-EXFUN (Ffile_name_absolute_p, 1);
-EXFUN (Fdirectory_file_name, 1);
-EXFUN (Ffile_name_directory, 1);
 extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
-EXFUN (Ffile_accessible_directory_p, 1);
-EXFUN (Funhandled_file_name_directory, 1);
-EXFUN (Ffile_directory_p, 1);
-EXFUN (Fwrite_region, 7);
-EXFUN (Ffile_readable_p, 1);
-EXFUN (Fread_file_name, 6);
+EXFUN (Fread_file_name, 6);     /* not a normal DEFUN */
 extern Lisp_Object close_file_unwind (Lisp_Object);
 extern Lisp_Object restore_point_unwind (Lisp_Object);
-extern void report_file_error (const char *, Lisp_Object) NO_RETURN;
+extern _Noreturn void report_file_error (const char *, Lisp_Object);
 extern int internal_delete_file (Lisp_Object);
 extern void syms_of_fileio (void);
 extern Lisp_Object make_temp_name (Lisp_Object, int);
@@ -3224,19 +3043,15 @@ extern Lisp_Object Qdelete_file;
 
 /* Defined in search.c */
 extern void shrink_regexp_cache (void);
-EXFUN (Fstring_match, 3);
 extern void restore_search_regs (void);
-EXFUN (Fmatch_data, 3);
-EXFUN (Fset_match_data, 2);
-EXFUN (Fmatch_beginning, 1);
-EXFUN (Fmatch_end, 1);
 extern void record_unwind_save_match_data (void);
 struct re_registers;
 extern struct re_pattern_buffer *compile_pattern (Lisp_Object,
                                                  struct re_registers *,
                                                  Lisp_Object, int, int);
 extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object);
-extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *);
+extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
+                                                 ptrdiff_t);
 extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object);
 extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t, Lisp_Object);
@@ -3250,50 +3065,34 @@ extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t);
 extern void syms_of_search (void);
 extern void clear_regexp_cache (void);
 
-/* Defined in minibuf.c */
+/* Defined in minibuf.c */
 
 extern Lisp_Object Qcompletion_ignore_case;
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object last_minibuf_string;
-EXFUN (Fcompleting_read, 8);
-EXFUN (Fread_from_minibuffer, 7);
-EXFUN (Fread_variable, 2);
-EXFUN (Fread_buffer, 3);
-EXFUN (Fread_minibuffer, 2);
-EXFUN (Feval_minibuffer, 2);
-EXFUN (Fread_string, 5);
-EXFUN (Fassoc_string, 3);
 extern Lisp_Object get_minibuffer (EMACS_INT);
 extern void init_minibuf_once (void);
 extern void syms_of_minibuf (void);
 
-/* Defined in callint.c */
+/* Defined in callint.c */
 
 extern Lisp_Object Qminus, Qplus;
 extern Lisp_Object Qwhen;
 extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook;
-EXFUN (Fprefix_numeric_value, 1);
 extern void syms_of_callint (void);
 
-/* Defined in casefiddle.c */
+/* Defined in casefiddle.c */
 
 extern Lisp_Object Qidentity;
-EXFUN (Fdowncase, 1);
-EXFUN (Fupcase, 1);
-EXFUN (Fupcase_region, 2);
-EXFUN (Fupcase_initials, 1);
-EXFUN (Fupcase_initials_region, 2);
 extern void syms_of_casefiddle (void);
 extern void keys_of_casefiddle (void);
 
-/* Defined in casetab.c */
+/* Defined in casetab.c */
 
-EXFUN (Fset_case_table, 1);
-EXFUN (Fset_standard_case_table, 1);
 extern void init_casetab_once (void);
 extern void syms_of_casetab (void);
 
-/* Defined in keyboard.c */
+/* Defined in keyboard.c */
 
 extern Lisp_Object echo_message_buffer;
 extern struct kboard *echo_kboard;
@@ -3301,17 +3100,11 @@ extern void cancel_echoing (void);
 extern Lisp_Object Qdisabled, QCfilter;
 extern Lisp_Object Qup, Qdown, Qbottom;
 extern Lisp_Object Qtop;
+extern Lisp_Object last_undo_boundary;
 extern int input_pending;
-EXFUN (Fdiscard_input, 0);
-EXFUN (Frecursive_edit, 0);
-EXFUN (Ftop_level, 0) NO_RETURN;
 extern Lisp_Object menu_bar_items (Lisp_Object);
 extern Lisp_Object tool_bar_items (Lisp_Object, int *);
 extern void discard_mouse_events (void);
-EXFUN (Fevent_convert_list, 1);
-EXFUN (Fread_key_sequence, 5);
-EXFUN (Fset_input_interrupt_mode, 1);
-EXFUN (Fset_input_mode, 4);
 extern Lisp_Object pending_funcalls;
 extern int detect_input_pending (void);
 extern int detect_input_pending_ignore_squeezables (void);
@@ -3328,19 +3121,14 @@ extern void init_keyboard (void);
 extern void syms_of_keyboard (void);
 extern void keys_of_keyboard (void);
 
-/* Defined in indent.c */
-EXFUN (Fvertical_motion, 2);
-EXFUN (Findent_to, 2);
-EXFUN (Fmove_to_column, 2);
+/* Defined in indent.c.  */
 extern ptrdiff_t current_column (void);
 extern void invalidate_current_column (void);
 extern int indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
 extern void syms_of_indent (void);
 
-/* Defined in frame.c */
-#ifdef HAVE_WINDOW_SYSTEM
-#endif /* HAVE_WINDOW_SYSTEM */
-extern Lisp_Object Qonly;
+/* Defined in frame.c.  */
+extern Lisp_Object Qonly, Qnone;
 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);
@@ -3349,18 +3137,10 @@ extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
 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);
-EXFUN (Fmake_frame_visible, 1);
-EXFUN (Ficonify_frame, 1);
-EXFUN (Fframe_parameter, 2);
-EXFUN (Fmodify_frame_parameters, 2);
-EXFUN (Fraise_frame, 1);
-EXFUN (Fredirect_frame_focus, 2);
 extern void frames_discard_buffer (Lisp_Object);
 extern void syms_of_frame (void);
 
-/* Defined in emacs.c */
+/* Defined in emacs.c */
 extern char **initial_argv;
 extern int initial_argc;
 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
@@ -3373,7 +3153,6 @@ extern Lisp_Object Qfile_name_handler_alist;
 extern void fatal_error_signal (int);
 #endif
 extern Lisp_Object Qkill_emacs;
-EXFUN (Fkill_emacs, 1) NO_RETURN;
 #if HAVE_SETLOCALE
 void fixup_locale (void);
 void synchronize_system_messages_locale (void);
@@ -3403,16 +3182,20 @@ extern int running_asynch_code;
 
 /* 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,
+extern int wait_reading_process_output (intmax_t, int, int, int,
                                         Lisp_Object,
                                         struct Lisp_Process *,
                                         int);
+/* Max value for the first argument of wait_reading_process_output.  */
+#if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)
+/* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3.
+   The bug merely causes a bogus warning, but the warning is annoying.  */
+# define WAIT_READING_MAX min (TYPE_MAXIMUM (time_t), INTMAX_MAX)
+#else
+# define WAIT_READING_MAX INTMAX_MAX
+#endif
 extern void add_keyboard_wait_descriptor (int);
 extern void delete_keyboard_wait_descriptor (int);
 #ifdef HAVE_GPM
@@ -3420,16 +3203,14 @@ extern void add_gpm_wait_descriptor (int);
 extern void delete_gpm_wait_descriptor (int);
 #endif
 extern void close_process_descs (void);
-extern void init_process (void);
+extern void init_process_emacs (void);
 extern void syms_of_process (void);
 extern void setup_process_coding_systems (Lisp_Object);
 
-EXFUN (Fcall_process, MANY);
-extern int child_setup (int, int, int, char **, int, Lisp_Object)
 #ifndef DOS_NT
- NO_RETURN
+ _Noreturn
 #endif
- ;
+extern int child_setup (int, int, int, char **, int, Lisp_Object);
 extern void init_callproc_1 (void);
 extern void init_callproc (void);
 extern void set_initial_environment (void);
@@ -3437,7 +3218,6 @@ extern void syms_of_callproc (void);
 
 /* Defined in doc.c */
 extern Lisp_Object Qfunction_documentation;
-EXFUN (Fsubstitute_command_keys, 1);
 extern Lisp_Object read_doc_string (Lisp_Object);
 extern Lisp_Object get_doc_string (Lisp_Object, int, int);
 extern void syms_of_doc (void);
@@ -3456,15 +3236,12 @@ extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object,
 
 /* Defined in macros.c */
 extern Lisp_Object Qexecute_kbd_macro;
-EXFUN (Fexecute_kbd_macro, 3);
-EXFUN (Fcancel_kbd_macro_events, 0);
 extern void init_macros (void);
 extern void syms_of_macros (void);
 
 /* Defined in undo.c */
 extern Lisp_Object Qapply;
 extern Lisp_Object Qinhibit_read_only;
-EXFUN (Fundo_boundary, 0);
 extern void truncate_undo_list (struct buffer *);
 extern void record_marker_adjustment (Lisp_Object, ptrdiff_t);
 extern void record_insert (ptrdiff_t, ptrdiff_t);
@@ -3481,21 +3258,12 @@ extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks;
 extern Lisp_Object Qfront_sticky, Qrear_nonsticky;
 extern Lisp_Object Qminibuffer_prompt;
 
-EXFUN (Fnext_single_property_change, 4);
-EXFUN (Fnext_single_char_property_change, 4);
-EXFUN (Fprevious_single_property_change, 4);
-EXFUN (Fget_text_property, 3);
-EXFUN (Fput_text_property, 5);
-EXFUN (Fprevious_char_property_change, 2);
-EXFUN (Fnext_char_property_change, 2);
 extern void report_interval_modification (Lisp_Object, Lisp_Object);
 
 /* Defined in menu.c */
 extern void syms_of_menu (void);
 
 /* Defined in xmenu.c */
-EXFUN (Fx_popup_menu, 2);
-EXFUN (Fx_popup_dialog, 3);
 extern void syms_of_xmenu (void);
 
 /* Defined in termchar.h */
@@ -3519,7 +3287,7 @@ extern void init_all_sys_modes (void);
 extern void reset_all_sys_modes (void);
 extern void wait_for_termination (pid_t);
 extern void interruptible_wait_for_termination (pid_t);
-extern void flush_pending_output (int);
+extern void flush_pending_output (int) ATTRIBUTE_CONST;
 extern void child_setup_tty (int);
 extern void setup_pty (int);
 extern int set_window_size (int, int, int);
@@ -3532,17 +3300,14 @@ extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
 enum { READLINK_BUFSIZE = 1024 };
 extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
 
-EXFUN (Funlock_buffer, 0);
 extern void unlock_all_files (void);
 extern void lock_file (Lisp_Object);
 extern void unlock_file (Lisp_Object);
 extern void unlock_buffer (struct buffer *);
 extern void syms_of_filelock (void);
-extern void init_filelock (void);
 
 /* Defined in sound.c */
 extern void syms_of_sound (void);
-extern void init_sound (void);
 
 /* Defined in category.c */
 extern void init_category_once (void);
@@ -3562,12 +3327,10 @@ extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
 extern int *char_ins_del_vector;
 extern void mark_ttys (void);
 extern void syms_of_term (void);
-extern void fatal (const char *msgid, ...)
-  NO_RETURN ATTRIBUTE_FORMAT_PRINTF (1, 2);
+extern _Noreturn void fatal (const char *msgid, ...)
+  ATTRIBUTE_FORMAT_PRINTF (1, 2);
 
 /* Defined in terminal.c */
-EXFUN (Fframe_terminal, 1);
-EXFUN (Fdelete_terminal, 2);
 extern void syms_of_terminal (void);
 
 /* Defined in font.c */
@@ -3580,8 +3343,6 @@ extern void syms_of_fontset (void);
 
 /* Defined in xfns.c, w32fns.c, or macfns.c */
 extern Lisp_Object Qfont_param;
-EXFUN (Fxw_display_color_p, 1);
-EXFUN (Fx_focus_frame, 1);
 #endif
 
 /* Defined in xfaces.c */
@@ -3594,8 +3355,6 @@ extern Lisp_Object QCfamily, QCweight, QCslant;
 extern Lisp_Object QCheight, QCname, QCwidth, QCforeground, QCbackground;
 extern Lisp_Object Vface_alternative_font_family_alist;
 extern Lisp_Object Vface_alternative_font_registry_alist;
-EXFUN (Fclear_face_cache, 1);
-EXFUN (Fx_load_color_file, 1);
 extern void syms_of_xfaces (void);
 
 #ifdef HAVE_X_WINDOWS
@@ -3617,11 +3376,6 @@ extern void syms_of_xterm (void);
 extern char *x_get_keysym_name (int);
 #endif /* HAVE_WINDOW_SYSTEM */
 
-#ifdef MSDOS
-/* Defined in msdos.c */
-EXFUN (Fmsdos_downcase_filename, 1);
-#endif
-
 #ifdef HAVE_LIBXML2
 /* Defined in xml.c */
 extern void syms_of_xml (void);
@@ -3650,6 +3404,7 @@ extern int initialized;
 extern int immediate_quit;         /* Nonzero means ^G can quit instantly */
 
 extern void *xmalloc (size_t);
+extern void *xzalloc (size_t);
 extern void *xrealloc (void *, size_t);
 extern void xfree (void *);
 extern void *xnmalloc (ptrdiff_t, ptrdiff_t);
@@ -3663,51 +3418,6 @@ extern char *egetenv (const char *);
 /* Set up the name of the machine we're running on.  */
 extern void init_system_name (void);
 
-/* Some systems (e.g., NT) use a different path separator than Unix,
-   in addition to a device separator.  Set the path separator
-   to '/', and don't test for a device separator in IS_ANY_SEP.  */
-
-#define DIRECTORY_SEP '/'
-#ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-#endif
-#ifndef IS_DEVICE_SEP
-#ifndef DEVICE_SEP
-#define IS_DEVICE_SEP(_c_) 0
-#else
-#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
-#endif
-#endif
-#ifndef IS_ANY_SEP
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
-#endif
-
-#define SWITCH_ENUM_CAST(x) (x)
-
-/* Use this to suppress gcc's warnings.  */
-#ifdef lint
-
-/* Use CODE only if lint checking is in effect.  */
-# define IF_LINT(Code) Code
-
-/* Assume that the expression COND is true.  This differs in intent
-   from 'assert', as it is a message from the programmer to the compiler.  */
-# define lint_assume(cond) ((cond) ? (void) 0 : abort ())
-
-#else
-# define IF_LINT(Code) /* empty */
-# define lint_assume(cond) ((void) (0 && (cond)))
-#endif
-
-/* The ubiquitous min and max macros.  */
-
-#ifdef max
-#undef max
-#undef min
-#endif
-#define min(a, b)      ((a) < (b) ? (a) : (b))
-#define max(a, b)      ((a) > (b) ? (a) : (b))
-
 /* We used to use `abs', but that clashes with system headers on some
    platforms, and using a name reserved by Standard C is a bad idea
    anyway.  */
@@ -3750,27 +3460,19 @@ extern void init_system_name (void);
 /* SAFE_ALLOCA normally allocates memory on the stack, but if size is
    larger than MAX_ALLOCA, use xmalloc to avoid overflowing the stack.  */
 
-#define MAX_ALLOCA 16*1024
+enum MAX_ALLOCA { MAX_ALLOCA = 16*1024 };
 
 extern Lisp_Object safe_alloca_unwind (Lisp_Object);
+extern void *record_xmalloc (size_t);
 
 #define USE_SAFE_ALLOCA                        \
   ptrdiff_t sa_count = SPECPDL_INDEX (); int sa_must_free = 0
 
 /* SAFE_ALLOCA allocates a simple buffer.  */
 
-#define SAFE_ALLOCA(buf, type, size)                     \
-  do {                                                   \
-    if ((size) < MAX_ALLOCA)                             \
-      buf = (type) alloca (size);                        \
-    else                                                 \
-      {                                                          \
-       buf = (type) xmalloc (size);                      \
-       sa_must_free = 1;                                 \
-       record_unwind_protect (safe_alloca_unwind,        \
-                              make_save_value (buf, 0)); \
-      }                                                          \
-  } while (0)
+#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \
+                          ? alloca (size)      \
+                          : (sa_must_free = 1, record_xmalloc (size)))
 
 /* SAFE_NALLOCA sets BUF to a newly allocated array of MULTIPLIER *
    NITEMS items, each of the same type as *BUF.  MULTIPLIER must
@@ -3802,24 +3504,38 @@ extern Lisp_Object safe_alloca_unwind (Lisp_Object);
 
 /* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects.  */
 
-#define SAFE_ALLOCA_LISP(buf, nelt)                      \
-  do {                                                   \
-    if ((nelt) < MAX_ALLOCA / sizeof (Lisp_Object))      \
-      buf = (Lisp_Object *) alloca ((nelt) * sizeof (Lisp_Object));    \
-    else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Lisp_Object)) \
-      {                                                          \
-       Lisp_Object arg_;                                 \
-       buf = (Lisp_Object *) xmalloc ((nelt) * sizeof (Lisp_Object));  \
-       arg_ = make_save_value (buf, nelt);               \
-       XSAVE_VALUE (arg_)->dogc = 1;                     \
-       sa_must_free = 1;                                 \
-       record_unwind_protect (safe_alloca_unwind, arg_); \
-      }                                                          \
-    else                                                 \
-      memory_full (SIZE_MAX);                            \
+#define SAFE_ALLOCA_LISP(buf, nelt)                           \
+  do {                                                        \
+    if ((nelt) < MAX_ALLOCA / word_size)                      \
+      buf = alloca ((nelt) * word_size);                      \
+    else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
+      {                                                               \
+       Lisp_Object arg_;                                      \
+       buf = xmalloc ((nelt) * word_size);                    \
+       arg_ = make_save_value (buf, nelt);                    \
+       XSAVE_VALUE (arg_)->dogc = 1;                          \
+       sa_must_free = 1;                                      \
+       record_unwind_protect (safe_alloca_unwind, arg_);      \
+      }                                                               \
+    else                                                      \
+      memory_full (SIZE_MAX);                                 \
   } while (0)
 
 
 #include "globals.h"
 
+/* Check whether it's time for GC, and run it if so.  */
+
+LISP_INLINE void
+maybe_gc (void)
+{
+  if ((consing_since_gc > gc_cons_threshold
+       && consing_since_gc > gc_relative_threshold)
+      || (!NILP (Vmemory_full)
+         && consing_since_gc > memory_full_cons_threshold))
+    Fgarbage_collect ();
+}
+
+INLINE_HEADER_END
+
 #endif /* EMACS_LISP_H */