* lisp.h (eassert): Assume that COND is true when optimizing.
[bpt/emacs.git] / src / lisp.h
index f76bbfb..f949978 100644 (file)
@@ -31,11 +31,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <limits.h>
 
 #include <intprops.h>
+#include <verify.h>
 
 INLINE_HEADER_BEGIN
-#ifndef LISP_INLINE
-# define LISP_INLINE INLINE
-#endif
 
 /* The ubiquitous max and min macros.  */
 #undef min
@@ -73,7 +71,6 @@ enum
     BITS_PER_SHORT     = CHAR_BIT * sizeof (short),
     BITS_PER_INT       = CHAR_BIT * sizeof (int),
     BITS_PER_LONG      = CHAR_BIT * sizeof (long int),
-    BITS_PER_PTRDIFF_T = CHAR_BIT * sizeof (ptrdiff_t),
     BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT)
   };
 
@@ -111,11 +108,12 @@ typedef EMACS_UINT uprintmax_t;
 
 /* Extra internal type 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.  */
+/* Define an Emacs version of 'assert (COND)'.  COND should be free of
+   side effects; it may be evaluated zero or more times.  If COND is false,
+   Emacs reliably crashes if ENABLE_CHECKING is defined and behavior
+   is undefined if not.  The compiler may assume COND while optimizing.  */
 #ifndef ENABLE_CHECKING
-# define eassert(X) ((void) (0 && (X))) /* Check that X compiles.  */
+# define eassert(cond) assume (cond)
 #else /* ENABLE_CHECKING */
 
 extern _Noreturn void die (const char *, const char *, int);
@@ -131,10 +129,11 @@ extern _Noreturn void die (const char *, const char *, int);
 extern bool suppress_checking EXTERNALLY_VISIBLE;
 
 # define eassert(cond)                                         \
-   ((cond) || suppress_checking                                        \
-    ? (void) 0                                                 \
-    : die ("assertion failed: " # cond, __FILE__, __LINE__))
+   (suppress_checking || (cond)                                \
+    ? assume (cond)                                            \
+    : die (# cond, __FILE__, __LINE__))
 #endif /* ENABLE_CHECKING */
+
 \f
 /* Use the configure flag --enable-check-lisp-object-type to make
    Lisp_Object use a struct type instead of the default int.  The flag
@@ -227,7 +226,7 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
    would otherwise cause a serious performance problem.
 
    For each such operation OP, define a macro lisp_h_OP that contains
-   the operation's implementation.  That way, OP can be implementated
+   the operation's implementation.  That way, OP can be implemented
    via a macro definition like this:
 
      #define OP(x) lisp_h_OP (x)
@@ -346,11 +345,11 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
    ARGS should be parenthesized.  Implement the function by calling
    lisp_h_NAME ARGS.  */
 #define LISP_MACRO_DEFUN(name, type, argdecls, args) \
-  LISP_INLINE type (name) argdecls { return lisp_h_##name args; }
+  INLINE type (name) argdecls { return lisp_h_##name args; }
 
 /* like LISP_MACRO_DEFUN, except NAME returns void.  */
 #define LISP_MACRO_DEFUN_VOID(name, argdecls, args) \
-  LISP_INLINE void (name) argdecls { lisp_h_##name args; }
+  INLINE void (name) argdecls { lisp_h_##name args; }
 
 
 /* Define the fundamental Lisp data structures.  */
@@ -364,9 +363,9 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
 #define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1))
 #define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
 
-/* Idea stolen from GDB.  MSVC doesn't support enums in bitfields,
-   and xlc complains vociferously about them.  */
-#if defined _MSC_VER || defined __IBMC__
+/* Idea stolen from GDB.  Pedantic GCC complains about enum bitfields,
+   MSVC doesn't support them, and xlc complains vociferously about them.  */
+#if defined __STRICT_ANSI__ || defined _MSC_VER || defined __IBMC__
 #define ENUM_BF(TYPE) unsigned int
 #else
 #define ENUM_BF(TYPE) enum TYPE
@@ -399,7 +398,7 @@ enum Lisp_Type
     /* Cons.  XCONS (object) points to a struct Lisp_Cons.  */
     Lisp_Cons = 6,
 
-    Lisp_Float = 7,
+    Lisp_Float = 7
   };
 
 /* This is the set of data types that share a common structure.
@@ -429,7 +428,7 @@ enum Lisp_Fwd_Type
     Lisp_Fwd_Bool,             /* Fwd to a C boolean var.  */
     Lisp_Fwd_Obj,              /* Fwd to a C Lisp_Object variable.  */
     Lisp_Fwd_Buffer_Obj,       /* Fwd to a Lisp_Object field of buffers.  */
-    Lisp_Fwd_Kboard_Obj,       /* Fwd to a Lisp_Object field of kboards.  */
+    Lisp_Fwd_Kboard_Obj                /* Fwd to a Lisp_Object field of kboards.  */
   };
 
 /* If you want to define a new Lisp data type, here are some
@@ -442,8 +441,7 @@ enum Lisp_Fwd_Type
    displayed to users.  These are Lisp_Save_Value, a Lisp_Misc
    subtype; and PVEC_OTHER, a kind of vectorlike object.  The former
    is suitable for temporarily stashing away pointers and integers in
-   a Lisp object (see the existing uses of make_save_value and
-   XSAVE_VALUE).  The latter is useful for vector-like Lisp objects
+   a Lisp object.  The latter is useful for vector-like Lisp objects
    that need to be used as part of other objects, but which are never
    shown to users or Lisp code (search for PVEC_OTHER in xterm.c for
    an example).
@@ -612,14 +610,14 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type))
 
 /* Make a Lisp integer representing the value of the low order
    bits of N.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 make_number (EMACS_INT n)
 {
   return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK);
 }
 
 /* Extract A's value as a signed integer.  */
-LISP_INLINE EMACS_INT
+INLINE EMACS_INT
 XINT (Lisp_Object a)
 {
   EMACS_INT i = XLI (a);
@@ -629,7 +627,7 @@ XINT (Lisp_Object a)
 /* Like XINT (A), but may be faster.  A must be nonnegative.
    If ! USE_LSB_TAG, this takes advantage of the fact that Lisp
    integers have zero-bits in their tags.  */
-LISP_INLINE EMACS_INT
+INLINE EMACS_INT
 XFASTINT (Lisp_Object a)
 {
   EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a);
@@ -638,7 +636,7 @@ XFASTINT (Lisp_Object a)
 }
 
 /* Extract A's type.  */
-LISP_INLINE enum Lisp_Type
+INLINE enum Lisp_Type
 XTYPE (Lisp_Object a)
 {
   EMACS_UINT i = XLI (a);
@@ -646,7 +644,7 @@ XTYPE (Lisp_Object a)
 }
 
 /* Extract A's pointer value, assuming A's type is TYPE.  */
-LISP_INLINE void *
+INLINE void *
 XUNTAG (Lisp_Object a, int type)
 {
   if (USE_LSB_TAG)
@@ -660,7 +658,7 @@ XUNTAG (Lisp_Object a, int type)
 #endif /* ! USE_LSB_TAG */
 
 /* Extract A's value as an unsigned integer.  */
-LISP_INLINE EMACS_UINT
+INLINE EMACS_UINT
 XUINT (Lisp_Object a)
 {
   EMACS_UINT i = XLI (a);
@@ -673,7 +671,7 @@ XUINT (Lisp_Object a)
 LISP_MACRO_DEFUN (XHASH, EMACS_INT, (Lisp_Object a), (a))
 
 /* Like make_number (N), but may be faster.  N must be in nonnegative range.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 make_natnum (EMACS_INT n)
 {
   eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM);
@@ -690,7 +688,7 @@ LISP_MACRO_DEFUN (EQ, bool, (Lisp_Object x, Lisp_Object y), (x, y))
 #define FIXNUM_OVERFLOW_P(i) \
   (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM))
 
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 {
   return num < lower ? lower : num <= upper ? num : upper;
@@ -700,31 +698,31 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
 
 /* Defined in this file.  */
 union Lisp_Fwd;
-LISP_INLINE bool BOOL_VECTOR_P (Lisp_Object);
-LISP_INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *);
-LISP_INLINE bool BUFFERP (Lisp_Object);
-LISP_INLINE bool CHAR_TABLE_P (Lisp_Object);
-LISP_INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t);
-LISP_INLINE bool (CONSP) (Lisp_Object);
-LISP_INLINE bool (FLOATP) (Lisp_Object);
-LISP_INLINE bool functionp (Lisp_Object);
-LISP_INLINE bool (INTEGERP) (Lisp_Object);
-LISP_INLINE bool (MARKERP) (Lisp_Object);
-LISP_INLINE bool (MISCP) (Lisp_Object);
-LISP_INLINE bool (NILP) (Lisp_Object);
-LISP_INLINE bool OVERLAYP (Lisp_Object);
-LISP_INLINE bool PROCESSP (Lisp_Object);
-LISP_INLINE bool PSEUDOVECTORP (Lisp_Object, int);
-LISP_INLINE bool SAVE_VALUEP (Lisp_Object);
-LISP_INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
+INLINE bool BOOL_VECTOR_P (Lisp_Object);
+INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *);
+INLINE bool BUFFERP (Lisp_Object);
+INLINE bool CHAR_TABLE_P (Lisp_Object);
+INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t);
+INLINE bool (CONSP) (Lisp_Object);
+INLINE bool (FLOATP) (Lisp_Object);
+INLINE bool functionp (Lisp_Object);
+INLINE bool (INTEGERP) (Lisp_Object);
+INLINE bool (MARKERP) (Lisp_Object);
+INLINE bool (MISCP) (Lisp_Object);
+INLINE bool (NILP) (Lisp_Object);
+INLINE bool OVERLAYP (Lisp_Object);
+INLINE bool PROCESSP (Lisp_Object);
+INLINE bool PSEUDOVECTORP (Lisp_Object, int);
+INLINE bool SAVE_VALUEP (Lisp_Object);
+INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t,
                                              Lisp_Object);
-LISP_INLINE bool STRINGP (Lisp_Object);
-LISP_INLINE bool SUB_CHAR_TABLE_P (Lisp_Object);
-LISP_INLINE bool SUBRP (Lisp_Object);
-LISP_INLINE bool (SYMBOLP) (Lisp_Object);
-LISP_INLINE bool (VECTORLIKEP) (Lisp_Object);
-LISP_INLINE bool WINDOWP (Lisp_Object);
-LISP_INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object);
+INLINE bool STRINGP (Lisp_Object);
+INLINE bool SUB_CHAR_TABLE_P (Lisp_Object);
+INLINE bool SUBRP (Lisp_Object);
+INLINE bool (SYMBOLP) (Lisp_Object);
+INLINE bool (VECTORLIKEP) (Lisp_Object);
+INLINE bool WINDOWP (Lisp_Object);
+INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object);
 
 /* Defined in chartab.c.  */
 extern Lisp_Object char_table_ref (Lisp_Object, int);
@@ -735,7 +733,9 @@ extern int char_table_translate (Lisp_Object, int);
 extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p;
 extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
 extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp;
+extern Lisp_Object Qbool_vector_p;
 extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
+extern Lisp_Object Qwindow;
 extern Lisp_Object Ffboundp (Lisp_Object);
 extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object);
 
@@ -762,14 +762,14 @@ extern Lisp_Object Qimage;
 
 LISP_MACRO_DEFUN (XCONS, struct Lisp_Cons *, (Lisp_Object a), (a))
 
-LISP_INLINE struct Lisp_Vector *
+INLINE struct Lisp_Vector *
 XVECTOR (Lisp_Object a)
 {
   eassert (VECTORLIKEP (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct Lisp_String *
+INLINE struct Lisp_String *
 XSTRING (Lisp_Object a)
 {
   eassert (STRINGP (a));
@@ -778,7 +778,7 @@ XSTRING (Lisp_Object a)
 
 LISP_MACRO_DEFUN (XSYMBOL, struct Lisp_Symbol *, (Lisp_Object a), (a))
 
-LISP_INLINE struct Lisp_Float *
+INLINE struct Lisp_Float *
 XFLOAT (Lisp_Object a)
 {
   eassert (FLOATP (a));
@@ -787,55 +787,55 @@ XFLOAT (Lisp_Object a)
 
 /* Pseudovector types.  */
 
-LISP_INLINE struct Lisp_Process *
+INLINE struct Lisp_Process *
 XPROCESS (Lisp_Object a)
 {
   eassert (PROCESSP (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct window *
+INLINE struct window *
 XWINDOW (Lisp_Object a)
 {
   eassert (WINDOWP (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct terminal *
+INLINE struct terminal *
 XTERMINAL (Lisp_Object a)
 {
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct Lisp_Subr *
+INLINE struct Lisp_Subr *
 XSUBR (Lisp_Object a)
 {
   eassert (SUBRP (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct buffer *
+INLINE struct buffer *
 XBUFFER (Lisp_Object a)
 {
   eassert (BUFFERP (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct Lisp_Char_Table *
+INLINE struct Lisp_Char_Table *
 XCHAR_TABLE (Lisp_Object a)
 {
   eassert (CHAR_TABLE_P (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct Lisp_Sub_Char_Table *
+INLINE struct Lisp_Sub_Char_Table *
 XSUB_CHAR_TABLE (Lisp_Object a)
 {
   eassert (SUB_CHAR_TABLE_P (a));
   return XUNTAG (a, Lisp_Vectorlike);
 }
 
-LISP_INLINE struct Lisp_Bool_Vector *
+INLINE struct Lisp_Bool_Vector *
 XBOOL_VECTOR (Lisp_Object a)
 {
   eassert (BOOL_VECTOR_P (a));
@@ -844,7 +844,7 @@ XBOOL_VECTOR (Lisp_Object a)
 
 /* Construct a Lisp_Object from a value or address.  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 make_lisp_ptr (void *ptr, enum Lisp_Type type)
 {
   EMACS_UINT utype = type;
@@ -854,7 +854,7 @@ make_lisp_ptr (void *ptr, enum Lisp_Type type)
   return a;
 }
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 make_lisp_proc (struct Lisp_Process *p)
 {
   return make_lisp_ptr (p, Lisp_Vectorlike);
@@ -867,11 +867,7 @@ make_lisp_proc (struct Lisp_Process *p)
 #define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String))
 #define XSETSYMBOL(a, b) ((a) = make_lisp_ptr (b, Lisp_Symbol))
 #define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float))
-
-/* Misc types.  */
-
 #define XSETMISC(a, b) ((a) = make_lisp_ptr (b, Lisp_Misc))
-#define XSETMARKER(a, b) (XSETMISC (a, b), XMISCTYPE (a) = Lisp_Misc_Marker)
 
 /* Pseudovector types.  */
 
@@ -942,12 +938,12 @@ struct Lisp_Cons
    fields are not accessible.  (What if we want to switch to
    a copying collector someday?  Cached cons cell field addresses may be
    invalidated at arbitrary points.)  */
-LISP_INLINE Lisp_Object *
+INLINE Lisp_Object *
 xcar_addr (Lisp_Object c)
 {
   return &XCONS (c)->car;
 }
-LISP_INLINE Lisp_Object *
+INLINE Lisp_Object *
 xcdr_addr (Lisp_Object c)
 {
   return &XCONS (c)->u.cdr;
@@ -961,26 +957,26 @@ LISP_MACRO_DEFUN (XCDR, Lisp_Object, (Lisp_Object c), (c))
 
    Note that both arguments may refer to the same object, so 'n'
    should not be read after 'c' is first modified.  */
-LISP_INLINE void
+INLINE void
 XSETCAR (Lisp_Object c, Lisp_Object n)
 {
   *xcar_addr (c) = n;
 }
-LISP_INLINE void
+INLINE void
 XSETCDR (Lisp_Object c, Lisp_Object n)
 {
   *xcdr_addr (c) = n;
 }
 
 /* Take the car or cdr of something whose type is not known.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CAR (Lisp_Object c)
 {
   return (CONSP (c) ? XCAR (c)
          : NILP (c) ? Qnil
          : wrong_type_argument (Qlistp, c));
 }
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CDR (Lisp_Object c)
 {
   return (CONSP (c) ? XCDR (c)
@@ -989,12 +985,12 @@ CDR (Lisp_Object c)
 }
 
 /* Take the car or cdr of something whose type is not known.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CAR_SAFE (Lisp_Object c)
 {
   return CONSP (c) ? XCAR (c) : Qnil;
 }
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CDR_SAFE (Lisp_Object c)
 {
   return CONSP (c) ? XCDR (c) : Qnil;
@@ -1011,7 +1007,7 @@ struct Lisp_String
   };
 
 /* True if STR is a multibyte string.  */
-LISP_INLINE bool
+INLINE bool
 STRING_MULTIBYTE (Lisp_Object str)
 {
   return 0 <= XSTRING (str)->size_byte;
@@ -1048,53 +1044,57 @@ STRING_MULTIBYTE (Lisp_Object str)
 
 /* Convenience functions for dealing with Lisp strings.  */
 
-LISP_INLINE unsigned char *
+INLINE unsigned char *
 SDATA (Lisp_Object string)
 {
   return XSTRING (string)->data;
 }
-LISP_INLINE char *
+INLINE char *
 SSDATA (Lisp_Object string)
 {
   /* Avoid "differ in sign" warnings.  */
   return (char *) SDATA (string);
 }
-LISP_INLINE unsigned char
+INLINE unsigned char
 SREF (Lisp_Object string, ptrdiff_t index)
 {
   return SDATA (string)[index];
 }
-LISP_INLINE void
+INLINE void
 SSET (Lisp_Object string, ptrdiff_t index, unsigned char new)
 {
   SDATA (string)[index] = new;
 }
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 SCHARS (Lisp_Object string)
 {
   return XSTRING (string)->size;
 }
-LISP_INLINE ptrdiff_t
+
+#ifdef GC_CHECK_STRING_BYTES
+extern ptrdiff_t string_bytes (struct Lisp_String *);
+#endif
+INLINE ptrdiff_t
 STRING_BYTES (struct Lisp_String *s)
 {
 #ifdef GC_CHECK_STRING_BYTES
-  extern ptrdiff_t string_bytes (struct Lisp_String *);
   return string_bytes (s);
 #else
   return s->size_byte < 0 ? s->size : s->size_byte;
 #endif
 }
-LISP_INLINE ptrdiff_t
+
+INLINE ptrdiff_t
 SBYTES (Lisp_Object string)
 {
   return STRING_BYTES (XSTRING (string));
 }
-LISP_INLINE void
+INLINE void
 STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize)
 {
   XSTRING (string)->size = newsize;
 }
-LISP_INLINE void
+INLINE void
 STRING_COPYIN (Lisp_Object string, ptrdiff_t index, char const *new,
               ptrdiff_t count)
 {
@@ -1132,12 +1132,19 @@ struct vectorlike_header
     ptrdiff_t size;
   };
 
-/* Regular vector is just a header plus array of Lisp_Objects.  */
+/* Regular vector is just a header plus array of Lisp_Objects...  */
 
 struct Lisp_Vector
   {
     struct vectorlike_header header;
-    Lisp_Object contents[1];
+    union {
+      /* ...but sometimes there is also a pointer internally used in
+        vector allocation code.  Usually you don't want to touch this.  */
+      struct Lisp_Vector *next;
+
+      /* We can't use FLEXIBLE_ARRAY_MEMBER here.  */
+      Lisp_Object contents[1];
+    } u;
   };
 
 /* A boolvector is a kind of vectorlike, with contents are like a string.  */
@@ -1150,7 +1157,7 @@ struct Lisp_Bool_Vector
     /* This is the size in bits.  */
     EMACS_INT size;
     /* This contains the actual bits, packed into bytes.  */
-    unsigned char data[1];
+    unsigned char data[FLEXIBLE_ARRAY_MEMBER];
   };
 
 /* Some handy constants for calculating sizes
@@ -1158,45 +1165,45 @@ struct Lisp_Bool_Vector
 
 enum
   {
-    header_size = offsetof (struct Lisp_Vector, contents),
+    header_size = offsetof (struct Lisp_Vector, u.contents),
     bool_header_size = offsetof (struct Lisp_Bool_Vector, data),
     word_size = sizeof (Lisp_Object)
   };
 
 /* Conveniences for dealing with Lisp arrays.  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 AREF (Lisp_Object array, ptrdiff_t idx)
 {
-  return XVECTOR (array)->contents[idx];
+  return XVECTOR (array)->u.contents[idx];
 }
 
-LISP_INLINE Lisp_Object *
+INLINE Lisp_Object *
 aref_addr (Lisp_Object array, ptrdiff_t idx)
 {
-  return & XVECTOR (array)->contents[idx];
+  return & XVECTOR (array)->u.contents[idx];
 }
 
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 ASIZE (Lisp_Object array)
 {
   return XVECTOR (array)->header.size;
 }
 
-LISP_INLINE void
+INLINE void
 ASET (Lisp_Object array, ptrdiff_t idx, Lisp_Object val)
 {
   eassert (0 <= idx && idx < ASIZE (array));
-  XVECTOR (array)->contents[idx] = val;
+  XVECTOR (array)->u.contents[idx] = val;
 }
 
-LISP_INLINE void
+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;
+  XVECTOR (array)->u.contents[idx] = val;
 }
 
 /* If a struct is made to look like a vector, this macro returns the length
@@ -1273,7 +1280,7 @@ struct Lisp_Char_Table
     Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)];
 
     /* These hold additional data.  It is a vector.  */
-    Lisp_Object extras[1];
+    Lisp_Object extras[FLEXIBLE_ARRAY_MEMBER];
   };
 
 struct Lisp_Sub_Char_Table
@@ -1294,10 +1301,10 @@ struct Lisp_Sub_Char_Table
     Lisp_Object min_char;
 
     /* Use set_sub_char_table_contents to set this.  */
-    Lisp_Object contents[1];
+    Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER];
   };
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
 {
   struct Lisp_Char_Table *tbl = NULL;
@@ -1317,7 +1324,7 @@ CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
 
 /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
    characters.  Do not check validity of CT.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 CHAR_TABLE_REF (Lisp_Object ct, int idx)
 {
   return (ASCII_CHAR_P (idx)
@@ -1327,7 +1334,7 @@ CHAR_TABLE_REF (Lisp_Object ct, int idx)
 
 /* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
    8-bit European characters.  Do not check validity of CT.  */
-LISP_INLINE void
+INLINE void
 CHAR_TABLE_SET (Lisp_Object ct, int idx, Lisp_Object val)
 {
   if (ASCII_CHAR_P (idx) && SUB_CHAR_TABLE_P (XCHAR_TABLE (ct)->ascii))
@@ -1367,12 +1374,12 @@ struct Lisp_Subr
    slots.  */
 enum CHAR_TABLE_STANDARD_SLOTS
   {
-    CHAR_TABLE_STANDARD_SLOTS = VECSIZE (struct Lisp_Char_Table) - 1
+    CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras)
   };
 
 /* Return the number of "extra" slots in the char table CT.  */
 
-LISP_INLINE int
+INLINE int
 CHAR_TABLE_EXTRA_SLOTS (struct Lisp_Char_Table *ct)
 {
   return ((ct->header.size & PSEUDOVECTOR_SIZE_MASK)
@@ -1451,19 +1458,19 @@ struct Lisp_Symbol
 
 LISP_MACRO_DEFUN (SYMBOL_VAL, Lisp_Object, (struct Lisp_Symbol *sym), (sym))
 
-LISP_INLINE struct Lisp_Symbol *
+INLINE struct Lisp_Symbol *
 SYMBOL_ALIAS (struct Lisp_Symbol *sym)
 {
   eassert (sym->redirect == SYMBOL_VARALIAS);
   return sym->val.alias;
 }
-LISP_INLINE struct Lisp_Buffer_Local_Value *
+INLINE struct Lisp_Buffer_Local_Value *
 SYMBOL_BLV (struct Lisp_Symbol *sym)
 {
   eassert (sym->redirect == SYMBOL_LOCALIZED);
   return sym->val.blv;
 }
-LISP_INLINE union Lisp_Fwd *
+INLINE union Lisp_Fwd *
 SYMBOL_FWD (struct Lisp_Symbol *sym)
 {
   eassert (sym->redirect == SYMBOL_FORWARDED);
@@ -1473,26 +1480,26 @@ SYMBOL_FWD (struct Lisp_Symbol *sym)
 LISP_MACRO_DEFUN_VOID (SET_SYMBOL_VAL,
                       (struct Lisp_Symbol *sym, Lisp_Object v), (sym, v))
 
-LISP_INLINE void
+INLINE void
 SET_SYMBOL_ALIAS (struct Lisp_Symbol *sym, struct Lisp_Symbol *v)
 {
   eassert (sym->redirect == SYMBOL_VARALIAS);
   sym->val.alias = v;
 }
-LISP_INLINE void
+INLINE void
 SET_SYMBOL_BLV (struct Lisp_Symbol *sym, struct Lisp_Buffer_Local_Value *v)
 {
   eassert (sym->redirect == SYMBOL_LOCALIZED);
   sym->val.blv = v;
 }
-LISP_INLINE void
+INLINE void
 SET_SYMBOL_FWD (struct Lisp_Symbol *sym, union Lisp_Fwd *v)
 {
   eassert (sym->redirect == SYMBOL_FORWARDED);
   sym->val.fwd = v;
 }
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 SYMBOL_NAME (Lisp_Object sym)
 {
   return XSYMBOL (sym)->name;
@@ -1500,7 +1507,7 @@ SYMBOL_NAME (Lisp_Object sym)
 
 /* Value is true if SYM is an interned symbol.  */
 
-LISP_INLINE bool
+INLINE bool
 SYMBOL_INTERNED_P (Lisp_Object sym)
 {
   return XSYMBOL (sym)->interned != SYMBOL_UNINTERNED;
@@ -1508,7 +1515,7 @@ SYMBOL_INTERNED_P (Lisp_Object sym)
 
 /* Value is true if SYM is interned in initial_obarray.  */
 
-LISP_INLINE bool
+INLINE bool
 SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (Lisp_Object sym)
 {
   return XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY;
@@ -1604,7 +1611,7 @@ struct Lisp_Hash_Table
 };
 
 
-LISP_INLINE struct Lisp_Hash_Table *
+INLINE struct Lisp_Hash_Table *
 XHASH_TABLE (Lisp_Object a)
 {
   return XUNTAG (a, Lisp_Vectorlike);
@@ -1613,21 +1620,21 @@ XHASH_TABLE (Lisp_Object a)
 #define XSET_HASH_TABLE(VAR, PTR) \
      (XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE))
 
-LISP_INLINE bool
+INLINE bool
 HASH_TABLE_P (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_HASH_TABLE);
 }
 
 /* Value is the key part of entry IDX in hash table H.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 HASH_KEY (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
   return AREF (h->key_and_value, 2 * idx);
 }
 
 /* Value is the value part of entry IDX in hash table H.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
   return AREF (h->key_and_value, 2 * idx + 1);
@@ -1635,14 +1642,14 @@ HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 
 /* Value is the index of the next entry following the one at IDX
    in hash table H.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
   return AREF (h->next, idx);
 }
 
 /* Value is the hash code computed for entry IDX in hash table H.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
   return AREF (h->hash, idx);
@@ -1650,14 +1657,14 @@ HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 
 /* Value is the index of the element in hash table H that is the
    start of the collision list at index IDX in the index vector of H.  */
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
   return AREF (h->index, idx);
 }
 
 /* Value is the size of hash table H.  */
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 HASH_TABLE_SIZE (struct Lisp_Hash_Table *h)
 {
   return ASIZE (h->next);
@@ -1680,7 +1687,7 @@ static double const DEFAULT_REHASH_SIZE = 1.5;
 /* Combine two integers X and Y for hashing.  The result might not fit
    into a Lisp integer.  */
 
-LISP_INLINE EMACS_UINT
+INLINE EMACS_UINT
 sxhash_combine (EMACS_UINT x, EMACS_UINT y)
 {
   return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y;
@@ -1688,7 +1695,7 @@ sxhash_combine (EMACS_UINT x, EMACS_UINT y)
 
 /* Hash X, returning a value that fits into a fixnum.  */
 
-LISP_INLINE EMACS_UINT
+INLINE EMACS_UINT
 SXHASH_REDUCE (EMACS_UINT x)
 {
   return (x ^ x >> (BITS_PER_EMACS_INT - FIXNUM_BITS)) & INTMASK;
@@ -1774,12 +1781,13 @@ enum
   {
     SAVE_UNUSED,
     SAVE_INTEGER,
+    SAVE_FUNCPOINTER,
     SAVE_POINTER,
     SAVE_OBJECT
   };
 
 /* Number of bits needed to store one of the above values.  */
-enum { SAVE_SLOT_BITS = 2 };
+enum { SAVE_SLOT_BITS = 3 };
 
 /* Number of slots in a save value where save_type is nonzero.  */
 enum { SAVE_VALUE_SLOTS = 4 };
@@ -1800,8 +1808,8 @@ enum Lisp_Save_Type
     SAVE_TYPE_PTR_INT = SAVE_POINTER + (SAVE_INTEGER << SAVE_SLOT_BITS),
     SAVE_TYPE_PTR_OBJ = SAVE_POINTER + (SAVE_OBJECT << SAVE_SLOT_BITS),
     SAVE_TYPE_PTR_PTR = SAVE_POINTER + (SAVE_POINTER << SAVE_SLOT_BITS),
-    SAVE_TYPE_PTR_PTR_OBJ
-      = SAVE_POINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS),
+    SAVE_TYPE_FUNCPTR_PTR_OBJ
+      = SAVE_FUNCPOINTER + (SAVE_TYPE_PTR_OBJ << SAVE_SLOT_BITS),
 
     /* This has an extra bit indicating it's raw memory.  */
     SAVE_TYPE_MEMORY = SAVE_TYPE_PTR_INT + (1 << (SAVE_TYPE_BITS - 1))
@@ -1810,46 +1818,29 @@ enum Lisp_Save_Type
 /* Special object used to hold a different values for later use.
 
    This is mostly used to package C integers and pointers to call
-   record_unwind_protect.  Typical task is to pass just one C pointer
-   to unwind function.  You should pack pointer with make_save_pointer
-   and then get it back with XSAVE_POINTER, e.g.:
-
-   ...
-     struct my_data *md = get_my_data ();
-     record_unwind_protect (my_unwind, make_save_pointer (md));
-   ...
-
-   Lisp_Object my_unwind (Lisp_Object arg)
-   {
-     struct my_data *md = XSAVE_POINTER (arg, 0);
-     ...
-   }
-
-   If yon need to pass more than just one C pointer, you should
-   use make_save_value.  This function allows you to pack up to
-   SAVE_VALUE_SLOTS integers, pointers or Lisp_Objects and
-   conveniently get them back with XSAVE_POINTER, XSAVE_INTEGER and
-   XSAVE_OBJECT macros:
+   record_unwind_protect when two or more values need to be saved.
+   For example:
 
    ...
      struct my_data *md = get_my_data ();
-     Lisp_Object my_object = get_my_object ();
-     record_unwind_protect
-       (my_unwind, make_save_value (SAVE_TYPE_PTR_OBJ, md, my_object));
+     ptrdiff_t mi = get_my_integer ();
+     record_unwind_protect (my_unwind, make_save_ptr_int (md, mi));
    ...
 
    Lisp_Object my_unwind (Lisp_Object arg)
    {
      struct my_data *md = XSAVE_POINTER (arg, 0);
-     Lisp_Object my_object = XSAVE_OBJECT (arg, 1);
+     ptrdiff_t mi = XSAVE_INTEGER (arg, 1);
      ...
    }
 
    If ENABLE_CHECKING is in effect, XSAVE_xxx macros do type checking of the
    saved objects and raise eassert if type of the saved object doesn't match
    the type which is extracted.  In the example above, XSAVE_INTEGER (arg, 2)
-   or XSAVE_OBJECT (arg, 0) are wrong because nothing was saved in slot 2 and
-   Lisp_Object was saved in slot 1 of ARG.  */
+   and XSAVE_OBJECT (arg, 0) are wrong because nothing was saved in slot 2 and
+   slot 0 is a pointer.  */
+
+typedef void (*voidfuncptr) (void);
 
 struct Lisp_Save_Value
   {
@@ -1857,22 +1848,24 @@ struct Lisp_Save_Value
     unsigned gcmarkbit : 1;
     int spacer : 32 - (16 + 1 + SAVE_TYPE_BITS);
 
-    /* DATA[N] may hold up to SAVE_VALUE_SLOTS entries.  The type of
-       V's Ith entry is given by save_type (V, I).  E.g., if save_type
-       (V, 3) == SAVE_INTEGER, V->data[3].integer is in use.
+    /* V->data may hold up to SAVE_VALUE_SLOTS entries.  The type of
+       V's data entries are determined by V->save_type.  E.g., if
+       V->save_type == SAVE_TYPE_PTR_OBJ, V->data[0] is a pointer,
+       V->data[1] is an integer, and V's other data entries are unused.
 
-       If SAVE_TYPE == SAVE_TYPE_MEMORY, DATA[0].pointer is the address of
-       a memory area containing DATA[1].integer potential Lisp_Objects.  */
+       If V->save_type == SAVE_TYPE_MEMORY, V->data[0].pointer is the address of
+       a memory area containing V->data[1].integer potential Lisp_Objects.  */
     ENUM_BF (Lisp_Save_Type) save_type : SAVE_TYPE_BITS;
     union {
       void *pointer;
+      voidfuncptr funcpointer;
       ptrdiff_t integer;
       Lisp_Object object;
     } data[SAVE_VALUE_SLOTS];
   };
 
 /* Return the type of V's Nth saved value.  */
-LISP_INLINE int
+INLINE int
 save_type (struct Lisp_Save_Value *v, int n)
 {
   eassert (0 <= n && n < SAVE_VALUE_SLOTS);
@@ -1881,28 +1874,34 @@ save_type (struct Lisp_Save_Value *v, int n)
 
 /* Get and set the Nth saved pointer.  */
 
-LISP_INLINE void *
+INLINE void *
 XSAVE_POINTER (Lisp_Object obj, int n)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
-  return XSAVE_VALUE (obj)->data[n].pointer;;
+  return XSAVE_VALUE (obj)->data[n].pointer;
 }
-LISP_INLINE void
+INLINE void
 set_save_pointer (Lisp_Object obj, int n, void *val)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER);
   XSAVE_VALUE (obj)->data[n].pointer = val;
 }
+INLINE voidfuncptr
+XSAVE_FUNCPOINTER (Lisp_Object obj, int n)
+{
+  eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_FUNCPOINTER);
+  return XSAVE_VALUE (obj)->data[n].funcpointer;
+}
 
 /* Likewise for the saved integer.  */
 
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 XSAVE_INTEGER (Lisp_Object obj, int n)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER);
   return XSAVE_VALUE (obj)->data[n].integer;
 }
-LISP_INLINE void
+INLINE void
 set_save_integer (Lisp_Object obj, int n, ptrdiff_t val)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER);
@@ -1911,7 +1910,7 @@ set_save_integer (Lisp_Object obj, int n, ptrdiff_t val)
 
 /* Extract Nth saved object.  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 XSAVE_OBJECT (Lisp_Object obj, int n)
 {
   eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_OBJECT);
@@ -1939,40 +1938,40 @@ union Lisp_Misc
     struct Lisp_Save_Value u_save_value;
   };
 
-LISP_INLINE union Lisp_Misc *
+INLINE union Lisp_Misc *
 XMISC (Lisp_Object a)
 {
   return XUNTAG (a, Lisp_Misc);
 }
 
-LISP_INLINE struct Lisp_Misc_Any *
+INLINE struct Lisp_Misc_Any *
 XMISCANY (Lisp_Object a)
 {
   eassert (MISCP (a));
   return & XMISC (a)->u_any;
 }
 
-LISP_INLINE enum Lisp_Misc_Type
+INLINE enum Lisp_Misc_Type
 XMISCTYPE (Lisp_Object a)
 {
   return XMISCANY (a)->type;
 }
 
-LISP_INLINE struct Lisp_Marker *
+INLINE struct Lisp_Marker *
 XMARKER (Lisp_Object a)
 {
   eassert (MARKERP (a));
   return & XMISC (a)->u_marker;
 }
 
-LISP_INLINE struct Lisp_Overlay *
+INLINE struct Lisp_Overlay *
 XOVERLAY (Lisp_Object a)
 {
   eassert (OVERLAYP (a));
   return & XMISC (a)->u_overlay;
 }
 
-LISP_INLINE struct Lisp_Save_Value *
+INLINE struct Lisp_Save_Value *
 XSAVE_VALUE (Lisp_Object a)
 {
   eassert (SAVE_VALUEP (a));
@@ -2086,13 +2085,13 @@ union Lisp_Fwd
     struct Lisp_Kboard_Objfwd u_kboard_objfwd;
   };
 
-LISP_INLINE enum Lisp_Fwd_Type
+INLINE enum Lisp_Fwd_Type
 XFWDTYPE (union Lisp_Fwd *a)
 {
   return a->u_intfwd.type;
 }
 
-LISP_INLINE struct Lisp_Buffer_Objfwd *
+INLINE struct Lisp_Buffer_Objfwd *
 XBUFFER_OBJFWD (union Lisp_Fwd *a)
 {
   eassert (BUFFER_OBJFWDP (a));
@@ -2109,7 +2108,7 @@ struct Lisp_Float
     } u;
   };
 
-LISP_INLINE double
+INLINE double
 XFLOAT_DATA (Lisp_Object f)
 {
   return XFLOAT (f)->u.data;
@@ -2169,54 +2168,22 @@ enum char_bits
     CHARACTERBITS = 22
   };
 \f
-/* Structure to hold mouse highlight data.  This is here because other
-   header files need it for defining struct x_output etc.  */
-typedef struct {
-  /* These variables describe the range of text currently shown in its
-     mouse-face, together with the window they apply to.  As long as
-     the mouse stays within this range, we need not redraw anything on
-     its account.  Rows and columns are glyph matrix positions in
-     MOUSE_FACE_WINDOW.  */
-  int mouse_face_beg_row, mouse_face_beg_col;
-  int mouse_face_beg_x, mouse_face_beg_y;
-  int mouse_face_end_row, mouse_face_end_col;
-  int mouse_face_end_x, mouse_face_end_y;
-  Lisp_Object mouse_face_window;
-  int mouse_face_face_id;
-  Lisp_Object mouse_face_overlay;
-
-  /* FRAME and X, Y position of mouse when last checked for
-     highlighting.  X and Y can be negative or out of range for the frame.  */
-  struct frame *mouse_face_mouse_frame;
-  int mouse_face_mouse_x, mouse_face_mouse_y;
-
-  /* Nonzero if part of the text currently shown in
-     its mouse-face is beyond the window end.  */
-  unsigned mouse_face_past_end : 1;
-
-  /* Nonzero means defer mouse-motion highlighting.  */
-  unsigned mouse_face_defer : 1;
-
-  /* Nonzero means that the mouse highlight should not be shown.  */
-  unsigned mouse_face_hidden : 1;
-} Mouse_HLInfo;
-\f
 /* Data type checking.  */
 
 LISP_MACRO_DEFUN (NILP, bool, (Lisp_Object x), (x))
 
-LISP_INLINE bool
+INLINE bool
 NUMBERP (Lisp_Object x)
 {
   return INTEGERP (x) || FLOATP (x);
 }
-LISP_INLINE bool
+INLINE bool
 NATNUMP (Lisp_Object x)
 {
   return INTEGERP (x) && 0 <= XINT (x);
 }
 
-LISP_INLINE bool
+INLINE bool
 RANGED_INTEGERP (intmax_t lo, Lisp_Object x, intmax_t hi)
 {
   return INTEGERP (x) && lo <= XINT (x) && XINT (x) <= hi;
@@ -2235,40 +2202,40 @@ LISP_MACRO_DEFUN (INTEGERP, bool, (Lisp_Object x), (x))
 LISP_MACRO_DEFUN (VECTORLIKEP, bool, (Lisp_Object x), (x))
 LISP_MACRO_DEFUN (MARKERP, bool, (Lisp_Object x), (x))
 
-LISP_INLINE bool
+INLINE bool
 STRINGP (Lisp_Object x)
 {
   return XTYPE (x) == Lisp_String;
 }
-LISP_INLINE bool
+INLINE bool
 VECTORP (Lisp_Object x)
 {
   return VECTORLIKEP (x) && ! (ASIZE (x) & PSEUDOVECTOR_FLAG);
 }
-LISP_INLINE bool
+INLINE bool
 OVERLAYP (Lisp_Object x)
 {
   return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay;
 }
-LISP_INLINE bool
+INLINE bool
 SAVE_VALUEP (Lisp_Object x)
 {
   return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value;
 }
 
-LISP_INLINE bool
+INLINE bool
 AUTOLOADP (Lisp_Object x)
 {
   return CONSP (x) && EQ (Qautoload, XCAR (x));
 }
 
-LISP_INLINE bool
+INLINE bool
 BUFFER_OBJFWDP (union Lisp_Fwd *a)
 {
   return XFWDTYPE (a) == Lisp_Fwd_Buffer_Obj;
 }
 
-LISP_INLINE bool
+INLINE bool
 PSEUDOVECTOR_TYPEP (struct vectorlike_header *a, int code)
 {
   return ((a->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))
@@ -2276,7 +2243,7 @@ PSEUDOVECTOR_TYPEP (struct vectorlike_header *a, int code)
 }
 
 /* True if A is a pseudovector whose code is CODE.  */
-LISP_INLINE bool
+INLINE bool
 PSEUDOVECTORP (Lisp_Object a, int code)
 {
   if (! VECTORLIKEP (a))
@@ -2292,87 +2259,87 @@ PSEUDOVECTORP (Lisp_Object a, int code)
 
 /* Test for specific pseudovector types.  */
 
-LISP_INLINE bool
+INLINE bool
 WINDOW_CONFIGURATIONP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_WINDOW_CONFIGURATION);
 }
 
-LISP_INLINE bool
+INLINE bool
 PROCESSP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_PROCESS);
 }
 
-LISP_INLINE bool
+INLINE bool
 WINDOWP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_WINDOW);
 }
 
-LISP_INLINE bool
+INLINE bool
 TERMINALP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_TERMINAL);
 }
 
-LISP_INLINE bool
+INLINE bool
 SUBRP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_SUBR);
 }
 
-LISP_INLINE bool
+INLINE bool
 COMPILEDP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_COMPILED);
 }
 
-LISP_INLINE bool
+INLINE bool
 BUFFERP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_BUFFER);
 }
 
-LISP_INLINE bool
+INLINE bool
 CHAR_TABLE_P (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_CHAR_TABLE);
 }
 
-LISP_INLINE bool
+INLINE bool
 SUB_CHAR_TABLE_P (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_SUB_CHAR_TABLE);
 }
 
-LISP_INLINE bool
+INLINE bool
 BOOL_VECTOR_P (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_BOOL_VECTOR);
 }
 
-LISP_INLINE bool
+INLINE bool
 FRAMEP (Lisp_Object a)
 {
   return PSEUDOVECTORP (a, PVEC_FRAME);
 }
 
 /* Test for image (image . spec)  */
-LISP_INLINE bool
+INLINE bool
 IMAGEP (Lisp_Object x)
 {
   return CONSP (x) && EQ (XCAR (x), Qimage);
 }
 
 /* Array types.  */
-LISP_INLINE bool
+INLINE bool
 ARRAYP (Lisp_Object x)
 {
   return VECTORP (x) || STRINGP (x) || CHAR_TABLE_P (x) || BOOL_VECTOR_P (x);
 }
 \f
-LISP_INLINE void
+INLINE void
 CHECK_LIST (Lisp_Object x)
 {
   CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x);
@@ -2382,52 +2349,57 @@ LISP_MACRO_DEFUN_VOID (CHECK_LIST_CONS, (Lisp_Object x, Lisp_Object y), (x, y))
 LISP_MACRO_DEFUN_VOID (CHECK_SYMBOL, (Lisp_Object x), (x))
 LISP_MACRO_DEFUN_VOID (CHECK_NUMBER, (Lisp_Object x), (x))
 
-LISP_INLINE void
+INLINE void
 CHECK_STRING (Lisp_Object x)
 {
   CHECK_TYPE (STRINGP (x), Qstringp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_STRING_CAR (Lisp_Object x)
 {
   CHECK_TYPE (STRINGP (XCAR (x)), Qstringp, XCAR (x));
 }
-LISP_INLINE void
+INLINE void
 CHECK_CONS (Lisp_Object x)
 {
   CHECK_TYPE (CONSP (x), Qconsp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_VECTOR (Lisp_Object x)
 {
   CHECK_TYPE (VECTORP (x), Qvectorp, x);
 }
-LISP_INLINE void
+INLINE void
+CHECK_BOOL_VECTOR (Lisp_Object x)
+{
+  CHECK_TYPE (BOOL_VECTOR_P (x), Qbool_vector_p, x);
+}
+INLINE void
 CHECK_VECTOR_OR_STRING (Lisp_Object x)
 {
   CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_ARRAY (Lisp_Object x, Lisp_Object Qxxxp)
 {
   CHECK_TYPE (ARRAYP (x), Qxxxp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_BUFFER (Lisp_Object x)
 {
   CHECK_TYPE (BUFFERP (x), Qbufferp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_WINDOW (Lisp_Object x)
 {
   CHECK_TYPE (WINDOWP (x), Qwindowp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_PROCESS (Lisp_Object x)
 {
   CHECK_TYPE (PROCESSP (x), Qprocessp, x);
 }
-LISP_INLINE void
+INLINE void
 CHECK_NATNUM (Lisp_Object x)
 {
   CHECK_TYPE (NATNUMP (x), Qwholenump, x);
@@ -2456,13 +2428,13 @@ CHECK_NATNUM (Lisp_Object x)
   do { if (MARKERP ((x))) XSETFASTINT (x, marker_position (x)); \
     else CHECK_TYPE (INTEGERP (x), Qinteger_or_marker_p, x); } while (0)
 
-LISP_INLINE double
+INLINE double
 XFLOATINT (Lisp_Object n)
 {
   return extract_float (n);
 }
 
-LISP_INLINE void
+INLINE void
 CHECK_NUMBER_OR_FLOAT (Lisp_Object x)
 {
   CHECK_TYPE (FLOATP (x) || INTEGERP (x), Qnumberp, x);
@@ -2474,7 +2446,7 @@ CHECK_NUMBER_OR_FLOAT (Lisp_Object x)
 
 /* Since we can't assign directly to the CAR or CDR fields of a cons
    cell, use these when checking that those fields contain numbers.  */
-LISP_INLINE void
+INLINE void
 CHECK_NUMBER_CAR (Lisp_Object x)
 {
   Lisp_Object tmp = XCAR (x);
@@ -2482,7 +2454,7 @@ CHECK_NUMBER_CAR (Lisp_Object x)
   XSETCAR (x, tmp);
 }
 
-LISP_INLINE void
+INLINE void
 CHECK_NUMBER_CDR (Lisp_Object x)
 {
   Lisp_Object tmp = XCDR (x);
@@ -2527,11 +2499,16 @@ CHECK_NUMBER_CDR (Lisp_Object x)
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
 #else  /* not _MSC_VER */
+# if __STDC_VERSION__ < 199901
+#  define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname
+# else
+#  define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname
+# endif
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
    Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                         \
    static struct Lisp_Subr alignas (GCALIGNMENT) sname =               \
      { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS },                                \
-       { .a ## maxargs = fnname },                                     \
+       { DEFUN_FUNCTION_INIT (fnname, maxargs) },                      \
        minargs, maxargs, lname, intspec, 0};                           \
    Lisp_Object fnname
 #endif
@@ -2555,7 +2532,7 @@ CHECK_NUMBER_CDR (Lisp_Object x)
                         Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
 
 /* True if OBJ is a Lisp function.  */
-LISP_INLINE bool
+INLINE bool
 FUNCTIONP (Lisp_Object obj)
 {
   return functionp (obj);
@@ -2654,11 +2631,9 @@ typedef jmp_buf sys_jmp_buf;
    - The specpdl stack: keeps track of active unwind-protect and
      dynamic-let-bindings.  Allocated from the `specpdl' array, a manually
      managed stack.
-   - The catch stack: keeps track of active catch tags.
-     Allocated on the C stack.  This is where the setmp data is kept.
-   - The handler stack: keeps track of active condition-case handlers.
-     Allocated on the C stack.  Every entry there also uses an entry in
-     the catch stack.  */
+   - The handler stack: keeps track of active catch tags and condition-case
+     handlers.  Allocated in a manually managed stack implemented by a
+     doubly-linked list allocated via xmalloc and never freed.  */
 
 /* Structure for recording Lisp call stack for backtrace purposes.  */
 
@@ -2666,27 +2641,15 @@ typedef jmp_buf sys_jmp_buf;
    they are bound by a function application or a let form, stores the
    code to be executed for unwind-protect forms.
 
-   If func is non-zero, undoing this binding applies func to old_value;
-      This implements record_unwind_protect.
-
-   Otherwise, the element is a variable binding.
-
-   If the symbol field is a symbol, it is an ordinary variable binding.
-
-   Otherwise, it should be a structure (SYMBOL WHERE . CURRENT-BUFFER),
-   which means having bound a local value while CURRENT-BUFFER was active.
-   If WHERE is nil this means we saw the default value when binding SYMBOL.
-   WHERE being a buffer or frame means we saw a buffer-local or frame-local
-   value.  Other values of WHERE mean an internal error.
-
-   NOTE: The specbinding struct is defined here, because SPECPDL_INDEX is
+   NOTE: The specbinding union is defined here, because SPECPDL_INDEX is
    used all over the place, needs to be fast, and needs to know the size of
-   struct specbinding.  But only eval.c should access it.  */
-
-typedef Lisp_Object (*specbinding_func) (Lisp_Object);
+   union specbinding.  But only eval.c should access it.  */
 
 enum specbind_tag {
-  SPECPDL_UNWIND,              /* An unwind_protect function.  */
+  SPECPDL_UNWIND,              /* An unwind_protect function on Lisp_Object.  */
+  SPECPDL_UNWIND_PTR,          /* Likewise, on void *.  */
+  SPECPDL_UNWIND_INT,          /* Likewise, on int.  */
+  SPECPDL_UNWIND_VOID,         /* Likewise, with no arg.  */
   SPECPDL_BACKTRACE,           /* An element of the backtrace.  */
   SPECPDL_LET,                 /* A plain and simple dynamic let-binding.  */
   /* Tags greater than SPECPDL_LET must be "subkinds" of LET.  */
@@ -2694,77 +2657,62 @@ enum specbind_tag {
   SPECPDL_LET_DEFAULT          /* A global binding for a localized var.  */
 };
 
-struct specbinding
+union specbinding
   {
-    enum specbind_tag kind;
-    union {
-      struct {
-       Lisp_Object arg;
-       specbinding_func func;
-      } unwind;
-      struct {
-       /* `where' is not used in the case of SPECPDL_LET.  */
-       Lisp_Object symbol, old_value, where;
-      } let;
-      struct {
-       Lisp_Object function;
-       Lisp_Object *args;
-       ptrdiff_t nargs : BITS_PER_PTRDIFF_T - 1;
-       bool debug_on_exit : 1;
-      } bt;
-    } v;
+    ENUM_BF (specbind_tag) kind : CHAR_BIT;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      void (*func) (Lisp_Object);
+      Lisp_Object arg;
+    } unwind;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      void (*func) (void *);
+      void *arg;
+    } unwind_ptr;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      void (*func) (int);
+      int arg;
+    } unwind_int;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      void (*func) (void);
+    } unwind_void;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      /* `where' is not used in the case of SPECPDL_LET.  */
+      Lisp_Object symbol, old_value, where;
+    } let;
+    struct {
+      ENUM_BF (specbind_tag) kind : CHAR_BIT;
+      bool debug_on_exit : 1;
+      Lisp_Object function;
+      Lisp_Object *args;
+      ptrdiff_t nargs;
+    } bt;
   };
 
-extern struct specbinding *specpdl;
-extern struct specbinding *specpdl_ptr;
+extern union specbinding *specpdl;
+extern union specbinding *specpdl_ptr;
 extern ptrdiff_t specpdl_size;
 
-LISP_INLINE ptrdiff_t
+INLINE ptrdiff_t
 SPECPDL_INDEX (void)
 {
   return specpdl_ptr - specpdl;
 }
 
-/* Everything needed to describe an active condition case.
+/* This structure helps implement the `catch/throw' and `condition-case/signal'
+   control structures.  A struct handler contains all the information needed to
+   restore the state of the interpreter after a non-local jump.
 
-   Members are volatile if their values need to survive _longjmp when
-   a 'struct handler' is a local variable.  */
-struct handler
-  {
-    /* The handler clauses and variable from the condition-case form.  */
-    /* For a handler set up in Lisp code, this is always a list.
-       For an internal handler set up by internal_condition_case*,
-       this can instead be the symbol t or `error'.
-       t: handle all conditions.
-       error: handle all conditions, and errors can run the debugger
-              or display a backtrace.  */
-    Lisp_Object handler;
-
-    Lisp_Object volatile var;
-
-    /* Fsignal stores here the condition-case clause that applies,
-       and Fcondition_case thus knows which clause to run.  */
-    Lisp_Object volatile chosen_clause;
-
-    /* Used to effect the longjump out to the handler.  */
-    struct catchtag *tag;
-
-    /* The next enclosing handler.  */
-    struct handler *next;
-  };
-
-/* This structure helps implement the `catch' and `throw' control
-   structure.  A struct catchtag contains all the information needed
-   to restore the state of the interpreter after a non-local jump.
-
-   Handlers for error conditions (represented by `struct handler'
-   structures) just point to a catch tag to do the cleanup required
-   for their jumps.
+   handler structures are chained together in a doubly linked list; the `next'
+   member points to the next outer catchtag and the `nextfree' member points in
+   the other direction to the next inner element (which is typically the next
+   free element since we mostly use it on the deepest handler).
 
-   catchtag structures are chained together in the C calling stack;
-   the `next' member points to the next outer catchtag.
-
-   A call like (throw TAG VAL) searches for a catchtag whose `tag'
+   A call like (throw TAG VAL) searches for a catchtag whose `tag_or_ch'
    member is TAG, and then unbinds to it.  The `val' member is used to
    hold VAL while the stack is unwound; `val' is returned as the value
    of the catch form.
@@ -2773,24 +2721,63 @@ struct handler
    state.
 
    Members are volatile if their values need to survive _longjmp when
-   a 'struct catchtag' is a local variable.  */
-struct catchtag
+   a 'struct handler' is a local variable.  */
+
+enum handlertype { CATCHER, CONDITION_CASE };
+
+struct handler
 {
-  Lisp_Object tag;
-  Lisp_Object volatile val;
-  struct catchtag *volatile next;
+  enum handlertype type;
+  Lisp_Object tag_or_ch;
+  Lisp_Object val;
+  struct handler *next;
+  struct handler *nextfree;
+
+  /* The bytecode interpreter can have several handlers active at the same
+     time, so when we longjmp to one of them, it needs to know which handler
+     this was and what was the corresponding internal state.  This is stored
+     here, and when we longjmp we make sure that handlerlist points to the
+     proper handler.  */
+  Lisp_Object *bytecode_top;
+  int bytecode_dest;
+
+  /* Most global vars are reset to their value via the specpdl mechanism,
+     but a few others are handled by storing their value here.  */
 #if 1 /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but they're defined later.  */
   struct gcpro *gcpro;
 #endif
   sys_jmp_buf jmp;
-  struct handler *handlerlist;
   EMACS_INT lisp_eval_depth;
-  ptrdiff_t volatile pdlcount;
+  ptrdiff_t pdlcount;
   int poll_suppress_count;
   int interrupt_input_blocked;
   struct byte_stack *byte_stack;
 };
 
+/* Fill in the components of c, and put it on the list.  */
+#define PUSH_HANDLER(c, tag_ch_val, handlertype)       \
+  if (handlerlist && handlerlist->nextfree)            \
+    (c) = handlerlist->nextfree;                       \
+  else                                                 \
+    {                                                  \
+      (c) = xmalloc (sizeof (struct handler));         \
+      (c)->nextfree = NULL;                            \
+      if (handlerlist)                                 \
+       handlerlist->nextfree = (c);                    \
+    }                                                  \
+  (c)->type = (handlertype);                           \
+  (c)->tag_or_ch = (tag_ch_val);                       \
+  (c)->val = Qnil;                                     \
+  (c)->next = handlerlist;                             \
+  (c)->lisp_eval_depth = lisp_eval_depth;              \
+  (c)->pdlcount = SPECPDL_INDEX ();                    \
+  (c)->poll_suppress_count = poll_suppress_count;      \
+  (c)->interrupt_input_blocked = interrupt_input_blocked;\
+  (c)->gcpro = gcprolist;                              \
+  (c)->byte_stack = byte_stack_list;                   \
+  handlerlist = (c);
+
+
 extern Lisp_Object memory_signal_data;
 
 /* An address near the bottom of the stack.
@@ -3047,22 +3034,22 @@ struct frame;
 
 /* Copy COUNT Lisp_Objects from ARGS to contents of V starting from OFFSET.  */
 
-LISP_INLINE void
+INLINE void
 vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Object *args, ptrdiff_t count)
 {
   eassert (0 <= offset && 0 <= count && offset + count <= ASIZE (v));
-  memcpy (XVECTOR (v)->contents + offset, args, count * sizeof *args);
+  memcpy (XVECTOR (v)->u.contents + offset, args, count * sizeof *args);
 }
 
 /* Functions to modify hash tables.  */
 
-LISP_INLINE void
+INLINE void
 set_hash_key_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
 {
   gc_aset (h->key_and_value, 2 * idx, val);
 }
 
-LISP_INLINE void
+INLINE void
 set_hash_value_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
 {
   gc_aset (h->key_and_value, 2 * idx + 1, val);
@@ -3071,19 +3058,19 @@ set_hash_value_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
 /* Use these functions to set Lisp_Object
    or pointer slots of struct Lisp_Symbol.  */
 
-LISP_INLINE void
+INLINE void
 set_symbol_function (Lisp_Object sym, Lisp_Object function)
 {
   XSYMBOL (sym)->function = function;
 }
 
-LISP_INLINE void
+INLINE void
 set_symbol_plist (Lisp_Object sym, Lisp_Object plist)
 {
   XSYMBOL (sym)->plist = plist;
 }
 
-LISP_INLINE void
+INLINE void
 set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next)
 {
   XSYMBOL (sym)->next = next;
@@ -3091,7 +3078,7 @@ set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next)
 
 /* Buffer-local (also frame-local) variable access functions.  */
 
-LISP_INLINE int
+INLINE int
 blv_found (struct Lisp_Buffer_Local_Value *blv)
 {
   eassert (blv->found == !EQ (blv->defcell, blv->valcell));
@@ -3100,7 +3087,7 @@ blv_found (struct Lisp_Buffer_Local_Value *blv)
 
 /* Set overlay's property list.  */
 
-LISP_INLINE void
+INLINE void
 set_overlay_plist (Lisp_Object overlay, Lisp_Object plist)
 {
   XOVERLAY (overlay)->plist = plist;
@@ -3108,7 +3095,7 @@ set_overlay_plist (Lisp_Object overlay, Lisp_Object plist)
 
 /* Get text properties of S.  */
 
-LISP_INLINE INTERVAL
+INLINE INTERVAL
 string_intervals (Lisp_Object s)
 {
   return XSTRING (s)->intervals;
@@ -3116,7 +3103,7 @@ string_intervals (Lisp_Object s)
 
 /* Set text properties of S to I.  */
 
-LISP_INLINE void
+INLINE void
 set_string_intervals (Lisp_Object s, INTERVAL i)
 {
   XSTRING (s)->intervals = i;
@@ -3125,12 +3112,12 @@ set_string_intervals (Lisp_Object s, INTERVAL i)
 /* Set a Lisp slot in TABLE to VAL.  Most code should use this instead
    of setting slots directly.  */
 
-LISP_INLINE void
+INLINE void
 set_char_table_defalt (Lisp_Object table, Lisp_Object val)
 {
   XCHAR_TABLE (table)->defalt = val;
 }
-LISP_INLINE void
+INLINE void
 set_char_table_purpose (Lisp_Object table, Lisp_Object val)
 {
   XCHAR_TABLE (table)->purpose = val;
@@ -3138,21 +3125,21 @@ set_char_table_purpose (Lisp_Object table, Lisp_Object val)
 
 /* Set different slots in (sub)character tables.  */
 
-LISP_INLINE void
+INLINE void
 set_char_table_extras (Lisp_Object table, ptrdiff_t idx, Lisp_Object val)
 {
   eassert (0 <= idx && idx < CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (table)));
   XCHAR_TABLE (table)->extras[idx] = val;
 }
 
-LISP_INLINE void
+INLINE void
 set_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val)
 {
   eassert (0 <= idx && idx < (1 << CHARTAB_SIZE_BITS_0));
   XCHAR_TABLE (table)->contents[idx] = val;
 }
 
-LISP_INLINE void
+INLINE void
 set_sub_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val)
 {
   XSUB_CHAR_TABLE (table)->contents[idx] = val;
@@ -3193,6 +3180,16 @@ EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST;
 /* Defined in data.c.  */
 extern Lisp_Object indirect_function (Lisp_Object);
 extern Lisp_Object find_symbol_value (Lisp_Object);
+enum Arith_Comparison {
+  ARITH_EQUAL,
+  ARITH_NOTEQUAL,
+  ARITH_LESS,
+  ARITH_GRTR,
+  ARITH_LESS_OR_EQUAL,
+  ARITH_GRTR_OR_EQUAL
+};
+extern Lisp_Object arithcompare (Lisp_Object num1, Lisp_Object num2,
+                                 enum Arith_Comparison comparison);
 
 /* 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.
@@ -3287,6 +3284,7 @@ extern struct hash_table_test hashtest_eql, hashtest_equal;
 
 extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t);
+extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);
@@ -3353,8 +3351,9 @@ extern void del_range_byte (ptrdiff_t, ptrdiff_t, bool);
 extern void del_range_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool);
 extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t,
                                ptrdiff_t, ptrdiff_t, bool);
-extern void modify_region_1 (ptrdiff_t, ptrdiff_t, bool);
+extern void modify_text (ptrdiff_t, ptrdiff_t);
 extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
+extern void prepare_to_modify_buffer_1 (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
 extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t);
 extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t,
                                 ptrdiff_t, ptrdiff_t);
@@ -3370,7 +3369,6 @@ extern void syms_of_insdel (void);
      && (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__))
 _Noreturn void __executable_start (void);
 #endif
-extern Lisp_Object selected_frame;
 extern Lisp_Object Vwindow_system;
 extern Lisp_Object sit_for (Lisp_Object, bool, int);
 extern void init_display (void);
@@ -3386,20 +3384,16 @@ extern Lisp_Object Qimage, Qtext, Qboth, Qboth_horiz, Qtext_image_horiz;
 extern Lisp_Object Qspace, Qcenter, QCalign_to;
 extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
 extern Lisp_Object Qleft_margin, Qright_margin;
-extern Lisp_Object Qglyphless_char;
 extern Lisp_Object QCdata, QCfile;
 extern Lisp_Object QCmap;
 extern Lisp_Object Qrisky_local_variable;
-extern struct frame *last_glyphless_glyph_frame;
-extern int last_glyphless_glyph_face_id;
-extern int last_glyphless_glyph_merged_face_id;
-extern int noninteractive_need_newline;
+extern bool noninteractive_need_newline;
 extern Lisp_Object echo_area_buffer[2];
 extern void add_to_log (const char *, Lisp_Object, Lisp_Object);
 extern void check_message_stack (void);
 extern void setup_echo_area_for_printing (int);
 extern bool push_message (void);
-extern Lisp_Object pop_message_unwind (Lisp_Object);
+extern void pop_message_unwind (void);
 extern Lisp_Object restore_message_unwind (Lisp_Object);
 extern void restore_message (void);
 extern Lisp_Object current_message (void);
@@ -3460,19 +3454,19 @@ extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...);
 
 /* Build a frequently used 2/3/4-integer lists.  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 list2i (EMACS_INT x, EMACS_INT y)
 {
   return list2 (make_number (x), make_number (y));
 }
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 list3i (EMACS_INT x, EMACS_INT y, EMACS_INT w)
 {
   return list3 (make_number (x), make_number (y), make_number (w));
 }
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h)
 {
   return list4 (make_number (x), make_number (y),
@@ -3487,14 +3481,14 @@ 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
+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_event_array (ptrdiff_t, Lisp_Object *);
 extern Lisp_Object make_uninit_string (EMACS_INT);
 extern Lisp_Object make_uninit_multibyte_string (EMACS_INT, EMACS_INT);
 extern Lisp_Object make_string_from_bytes (const char *, ptrdiff_t, ptrdiff_t);
@@ -3505,7 +3499,7 @@ 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
+INLINE Lisp_Object
 build_pure_c_string (const char *str)
 {
   return make_pure_c_string (str, strlen (str));
@@ -3514,7 +3508,7 @@ build_pure_c_string (const char *str)
 /* Make a string from the data at STR, treating it as multibyte if the
    data warrants.  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 build_string (const char *str)
 {
   return make_string (str, strlen (str));
@@ -3535,7 +3529,7 @@ extern struct Lisp_Vector *allocate_vector (EMACS_INT);
    ASET (v, 1, Ffunction_can_gc ());
    ASET (v, 2, obj1);  */
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 make_uninit_vector (ptrdiff_t size)
 {
   Lisp_Object v;
@@ -3561,8 +3555,16 @@ extern bool abort_on_gc;
 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 (enum Lisp_Save_Type, ...);
-extern Lisp_Object make_save_pointer (void *);
+extern Lisp_Object make_save_int_int_int (ptrdiff_t, ptrdiff_t, ptrdiff_t);
+extern Lisp_Object make_save_obj_obj_obj_obj (Lisp_Object, Lisp_Object,
+                                             Lisp_Object, Lisp_Object);
+extern Lisp_Object make_save_ptr (void *);
+extern Lisp_Object make_save_ptr_int (void *, ptrdiff_t);
+extern Lisp_Object make_save_ptr_ptr (void *, void *);
+extern Lisp_Object make_save_funcptr_ptr_obj (void (*) (void), void *,
+                                             Lisp_Object);
+extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t);
+extern void free_save_value (Lisp_Object);
 extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object);
 extern void free_marker (Lisp_Object);
 extern void free_cons (struct Lisp_Cons *);
@@ -3574,7 +3576,7 @@ extern int valid_lisp_object_p (Lisp_Object);
 #ifdef GC_CHECK_CONS_LIST
 extern void check_cons_list (void);
 #else
-LISP_INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); }
+INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); }
 #endif
 
 #ifdef REL_ALLOC
@@ -3642,7 +3644,7 @@ extern Lisp_Object check_obarray (Lisp_Object);
 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);
-LISP_INLINE void
+INLINE void
 LOADHIST_ATTACH (Lisp_Object x)
 {
   if (initialized)
@@ -3654,18 +3656,17 @@ extern Lisp_Object string_to_number (char const *, int, bool);
 extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
                          Lisp_Object);
 extern void dir_warning (const char *, Lisp_Object);
-extern void close_load_descs (void);
 extern void init_obarray (void);
 extern void init_lread (void);
 extern void syms_of_lread (void);
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 intern (const char *str)
 {
   return intern_1 (str, strlen (str));
 }
 
-LISP_INLINE Lisp_Object
+INLINE Lisp_Object
 intern_c_string (const char *str)
 {
   return intern_c_string_1 (str, strlen (str));
@@ -3678,10 +3679,8 @@ extern Lisp_Object Qand_rest;
 extern Lisp_Object Vautoload_queue;
 extern Lisp_Object Vsignaling_function;
 extern Lisp_Object inhibit_lisp_code;
-#if BYTE_MARK_STACK
-extern struct catchtag *catchlist;
 extern struct handler *handlerlist;
-#endif
+
 /* To run a normal hook, use the appropriate function from the list below.
    The calling convention:
 
@@ -3720,12 +3719,19 @@ 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 void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
+extern void record_unwind_protect_ptr (void (*) (void *), void *);
+extern void record_unwind_protect_int (void (*) (int), int);
+extern void record_unwind_protect_void (void (*) (void));
+extern void record_unwind_protect_nothing (void);
+extern void clear_unwind_protect (ptrdiff_t);
+extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object);
+extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
 extern Lisp_Object unbind_to (ptrdiff_t, 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 un_autoload (Lisp_Object);
 extern Lisp_Object call_debugger (Lisp_Object arg);
 extern void init_eval_once (void);
 extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
@@ -3733,6 +3739,7 @@ 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);
 extern void syms_of_eval (void);
+extern void unwind_body (Lisp_Object);
 extern void record_in_backtrace (Lisp_Object function,
                                 Lisp_Object *args, ptrdiff_t nargs);
 extern void mark_specpdl (void);
@@ -3748,8 +3755,8 @@ extern void insert1 (Lisp_Object);
 extern Lisp_Object format2 (const char *, Lisp_Object, Lisp_Object);
 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);
+extern void save_excursion_restore (Lisp_Object);
+extern void save_restriction_restore (Lisp_Object);
 extern _Noreturn void time_overflow (void);
 extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
 extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
@@ -3767,10 +3774,7 @@ extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t);
 extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool,
                                          Lisp_Object, Lisp_Object, Lisp_Object);
 extern bool overlay_touches_p (ptrdiff_t);
-extern Lisp_Object Vbuffer_alist;
-extern Lisp_Object set_buffer_if_live (Lisp_Object);
 extern Lisp_Object other_buffer_safely (Lisp_Object);
-extern Lisp_Object Qpriority, Qwindow, Qbefore_string, Qafter_string;
 extern Lisp_Object get_truename_buffer (Lisp_Object);
 extern void init_buffer_once (void);
 extern void init_buffer (void);
@@ -3795,14 +3799,20 @@ extern void syms_of_marker (void);
 /* Defined in fileio.c.  */
 
 extern Lisp_Object Qfile_error;
+extern Lisp_Object Qfile_notify_error;
 extern Lisp_Object Qfile_exists_p;
 extern Lisp_Object Qfile_directory_p;
 extern Lisp_Object Qinsert_file_contents;
 extern Lisp_Object Qfile_name_history;
 extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
+extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object,
+                                Lisp_Object, Lisp_Object, Lisp_Object,
+                                Lisp_Object, int);
 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 close_file_unwind (int);
+extern void fclose_unwind (void *);
+extern void restore_point_unwind (Lisp_Object);
+extern _Noreturn void report_file_errno (const char *, Lisp_Object, int);
 extern _Noreturn void report_file_error (const char *, Lisp_Object);
 extern bool internal_delete_file (Lisp_Object);
 extern Lisp_Object emacs_readlinkat (int, const char *);
@@ -3830,8 +3840,8 @@ extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t, Lisp_Object);
 extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
-extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
-                              EMACS_INT, bool);
+extern ptrdiff_t scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
+                              ptrdiff_t, bool);
 extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t,
                                       ptrdiff_t, ptrdiff_t *);
 extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t,
@@ -3908,7 +3918,7 @@ extern Lisp_Object Qvisible;
 extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
 extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
 extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
-#if HAVE_NS || defined(WINDOWSNT)
+#if HAVE_NS || defined WINDOWSNT
 extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
 #endif
 extern void frames_discard_buffer (Lisp_Object);
@@ -3933,9 +3943,9 @@ void fixup_locale (void);
 void synchronize_system_messages_locale (void);
 void synchronize_system_time_locale (void);
 #else
-LISP_INLINE void fixup_locale (void) {}
-LISP_INLINE void synchronize_system_messages_locale (void) {}
-LISP_INLINE void synchronize_system_time_locale (void) {}
+INLINE void fixup_locale (void) {}
+INLINE void synchronize_system_messages_locale (void) {}
+INLINE void synchronize_system_time_locale (void) {}
 #endif
 extern void shut_down_emacs (int, Lisp_Object);
 
@@ -3980,11 +3990,11 @@ extern void delete_keyboard_wait_descriptor (int);
 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_emacs (void);
 extern void syms_of_process (void);
 extern void setup_process_coding_systems (Lisp_Object);
 
+/* Defined in callproc.c.  */
 #ifndef DOS_NT
  _Noreturn
 #endif
@@ -4064,7 +4074,6 @@ extern void init_sys_modes (struct tty_display_info *);
 extern void reset_sys_modes (struct tty_display_info *);
 extern void init_all_sys_modes (void);
 extern void reset_all_sys_modes (void);
-extern void 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);
@@ -4074,9 +4083,12 @@ extern void init_random (void);
 extern void emacs_backtrace (int);
 extern _Noreturn void emacs_abort (void) NO_INLINE;
 extern int emacs_open (const char *, int, int);
+extern int emacs_pipe (int[2]);
 extern int emacs_close (int);
 extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
 extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
+extern ptrdiff_t emacs_write_sig (int, char const *, ptrdiff_t);
+extern void emacs_perror (char const *);
 
 extern void unlock_all_files (void);
 extern void lock_file (Lisp_Object);
@@ -4178,6 +4190,11 @@ extern void syms_of_xml (void);
 extern void xml_cleanup_parser (void);
 #endif
 
+#ifdef HAVE_ZLIB
+/* Defined in decompress.c.  */
+extern void syms_of_decompress (void);
+#endif
+
 #ifdef HAVE_DBUS
 /* Defined in dbusbind.c.  */
 void syms_of_dbusbind (void);
@@ -4211,10 +4228,17 @@ extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t);
 extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t);
 
 extern char *xstrdup (const char *);
+extern char *xlispstrdup (Lisp_Object);
 extern void xputenv (const char *);
 
 extern char *egetenv (const char *);
 
+/* Copy Lisp string to temporary (allocated on stack) C string.  */
+
+#define xlispstrdupa(string)                   \
+  memcpy (alloca (SBYTES (string) + 1),                \
+         SSDATA (string), SBYTES (string) + 1)
+
 /* Set up the name of the machine we're running on.  */
 extern void init_system_name (void);
 
@@ -4235,7 +4259,6 @@ extern void init_system_name (void);
 
 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                        \
@@ -4259,8 +4282,7 @@ extern void *record_xmalloc (size_t);
       {                                                                 \
        (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \
        sa_must_free = 1;                                        \
-       record_unwind_protect (safe_alloca_unwind,               \
-                              make_save_pointer (buf));         \
+       record_unwind_protect_ptr (xfree, buf);                  \
       }                                                                 \
   } while (0)
 
@@ -4285,18 +4307,24 @@ extern void *record_xmalloc (size_t);
       {                                                               \
        Lisp_Object arg_;                                      \
        buf = xmalloc ((nelt) * word_size);                    \
-       arg_ = make_save_value (SAVE_TYPE_MEMORY, buf, nelt);  \
+       arg_ = make_save_memory (buf, nelt);                   \
        sa_must_free = 1;                                      \
-       record_unwind_protect (safe_alloca_unwind, arg_);      \
+       record_unwind_protect (free_save_value, arg_);         \
       }                                                               \
     else                                                      \
       memory_full (SIZE_MAX);                                 \
   } while (0)
 
+/* Do a `for' loop over alist values.  */
+
+#define FOR_EACH_ALIST_VALUE(head_var, list_var, value_var)            \
+  for (list_var = head_var;                                            \
+       (CONSP (list_var) && (value_var = XCDR (XCAR (list_var)), 1));  \
+       list_var = XCDR (list_var))
 
 /* Check whether it's time for GC, and run it if so.  */
 
-LISP_INLINE void
+INLINE void
 maybe_gc (void)
 {
   if ((consing_since_gc > gc_cons_threshold
@@ -4306,7 +4334,7 @@ maybe_gc (void)
     Fgarbage_collect ();
 }
 
-LISP_INLINE bool
+INLINE bool
 functionp (Lisp_Object object)
 {
   if (SYMBOLP (object) && !NILP (Ffboundp (object)))
@@ -4338,6 +4366,40 @@ functionp (Lisp_Object object)
     return 0;
 }
 
+INLINE uint16_t
+swap16 (uint16_t val)
+{
+    return (val << 8) | (val & 0xFF);
+}
+
+INLINE uint32_t
+swap32 (uint32_t val)
+{
+  uint32_t low = swap16 (val & 0xFFFF);
+  uint32_t high = swap16 (val >> 16);
+  return (low << 16) | high;
+}
+
+#ifdef UINT64_MAX
+INLINE uint64_t
+swap64 (uint64_t val)
+{
+  uint64_t low = swap32 (val & 0xFFFFFFFF);
+  uint64_t high = swap32 (val >> 32);
+  return (low << 32) | high;
+}
+#endif
+
+#if ((SIZE_MAX >> 31) >> 1) & 1
+# define BITS_PER_SIZE_T 64
+#else
+# define BITS_PER_SIZE_T 32
+#endif
+
+/* Round x to the next multiple of y.  Does not overflow.  Evaluates
+   arguments repeatedly.  */
+#define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0)))
+
 INLINE_HEADER_END
 
 #endif /* EMACS_LISP_H */