Make variable forwarding explicit rather the using special values.
[bpt/emacs.git] / src / lisp.h
index 4685578..d7e88e7 100644 (file)
@@ -1,6 +1,6 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -22,11 +22,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define EMACS_LISP_H
 
 /* Declare the prototype for a general external function.  */
-#if defined (PROTOTYPES) || defined (WINDOWSNT)
 #define P_(proto) proto
-#else
-#define P_(proto) ()
-#endif
 
 /* Use the configure flag --enable-checking[=LIST] to enable various
    types of run time checks for Lisp objects.  */
@@ -139,10 +135,7 @@ extern void die P_((const char *, const char *, int)) NO_RETURN;
 #if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined DARWIN_OS
 /* We also need to be able to specify mult-of-8 alignment on static vars.  */
 # if defined DECL_ALIGN
-/* We currently do not support USE_LSB_TAG with a union Lisp_Object.  */
-#  ifndef USE_LISP_UNION_TYPE
-#   define USE_LSB_TAG
-#  endif
+#  define USE_LSB_TAG
 # endif
 #endif
 
@@ -157,37 +150,68 @@ extern void die P_((const char *, const char *, int)) NO_RETURN;
 
 /* 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
+
 enum Lisp_Type
   {
     /* Integer.  XINT (obj) is the integer value.  */
-    Lisp_Int,
+#ifdef USE_2_TAGS_FOR_INTS
+    Lisp_Int0 = 0,
+    Lisp_Int1 = LISP_INT1_TAG,
+#else
+    Lisp_Int = 0,
+#endif
 
     /* Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol.  */
-    Lisp_Symbol,
+    Lisp_Symbol = 2,
 
     /* Miscellaneous.  XMISC (object) points to a union Lisp_Misc,
        whose first member indicates the subtype.  */
-    Lisp_Misc,
+    Lisp_Misc = 3,
 
     /* String.  XSTRING (object) points to a struct Lisp_String.
        The length of the string, and its contents, are stored therein.  */
-    Lisp_String,
+    Lisp_String = LISP_STRING_TAG,
 
     /* Vector of Lisp objects, or something resembling it.
        XVECTOR (object) points to a struct Lisp_Vector, which contains
        the size and contents.  The size field also contains the type
        information, if it's not a real vector object.  */
-    Lisp_Vectorlike,
+    Lisp_Vectorlike = 5,
 
     /* Cons.  XCONS (object) points to a struct Lisp_Cons.  */
-    Lisp_Cons,
-
-    Lisp_Float,
+    Lisp_Cons = 6,
 
-    /* This is not a type code.  It is for range checking.  */
-    Lisp_Type_Limit
+    Lisp_Float = 7,
   };
 
 /* This is the set of data types that share a common structure.
@@ -199,13 +223,7 @@ enum Lisp_Misc_Type
   {
     Lisp_Misc_Free = 0x5eab,
     Lisp_Misc_Marker,
-    Lisp_Misc_Intfwd,
-    Lisp_Misc_Boolfwd,
-    Lisp_Misc_Objfwd,
-    Lisp_Misc_Buffer_Objfwd,
-    Lisp_Misc_Buffer_Local_Value,
     Lisp_Misc_Overlay,
-    Lisp_Misc_Kboard_Objfwd,
     Lisp_Misc_Save_Value,
     /* Currently floats are not a misc type,
        but let's define this in case we want to change that.  */
@@ -214,6 +232,18 @@ enum Lisp_Misc_Type
     Lisp_Misc_Limit
   };
 
+/* These are the types of forwarding objects used in the value slot
+   of symbols for special built-in variables whose value is stored in
+   C variables.  */
+enum Lisp_Fwd_Type
+  {
+    Lisp_Fwd_Int,              /* Fwd to a C `int' variable.  */
+    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.  */
+  };
+
 #ifndef GCTYPEBITS
 #define GCTYPEBITS 3
 #endif
@@ -360,18 +390,18 @@ enum pvec_type
 
 #define TYPEMASK ((((EMACS_INT) 1) << GCTYPEBITS) - 1)
 #define XTYPE(a) ((enum Lisp_Type) (((EMACS_UINT) (a)) & TYPEMASK))
-#define XINT(a) (((EMACS_INT) (a)) >> GCTYPEBITS)
-#define XUINT(a) (((EMACS_UINT) (a)) >> GCTYPEBITS)
+#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 (ptr) == 0), /* Check alignment.  */       \
      (var) = ((EMACS_INT) (type)) | ((EMACS_INT) (ptr)))
-#define make_number(N) (((EMACS_INT) (N)) << GCTYPEBITS)
-
-/* XFASTINT and XSETFASTINT are for use when the integer is known to be
-   positive, in which case the implementation can sometimes be faster
-   depending on the tagging scheme.  With USE_LSB_TAG, there's no benefit.  */
-#define XFASTINT(a) XINT (a)
-#define XSETFASTINT(a, b) ((a) = make_number (b))
 
 #define XPNTR(a) ((EMACS_INT) ((a) & ~TYPEMASK))
 
@@ -391,47 +421,43 @@ enum pvec_type
 #define XFASTINT(a) ((a) + 0)
 #define XSETFASTINT(a, b) ((a) = (b))
 
-/* Extract the value of a Lisp_Object as a signed integer.  */
+/* Extract the value of a Lisp_Object as a (un)signed integer.  */
 
-#ifndef XINT   /* Some machines need to do this differently.  */
-#define XINT(a) ((((EMACS_INT) (a)) << (BITS_PER_EMACS_INT - VALBITS)) \
+#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
 
-/* Extract the value as an unsigned integer.  This is a basis
-   for extracting it as a pointer to a structure in storage.  */
-
-#ifndef XUINT
-#define XUINT(a) ((EMACS_UINT) ((a) & VALMASK))
-#endif
-
-#ifndef XSET
 #define XSET(var, type, ptr) \
    ((var) = ((EMACS_INT)(type) << VALBITS) + ((EMACS_INT) (ptr) & VALMASK))
-#endif
-
-/* Convert a C integer into a Lisp_Object integer.  */
 
-#define make_number(N)         \
-  ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
+#define XPNTR(a) ((EMACS_UINT) ((a) & VALMASK))
 
 #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)
 
-/* 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))
-
 #ifdef EXPLICIT_SIGN_EXTEND
-/* Make sure we sign-extend; compilers have been known to fail to do so.  */
-#define XINT(a) (((a).s.val << (BITS_PER_EMACS_INT - VALBITS)) \
+/* Make sure we sign-extend; compilers have been known to fail to do so.
+   We additionally cast to EMACS_INT since it seems that some compilers
+   have been known to fail to do so, even though the bitfield is declared
+   as EMACS_INT already.  */
+#define XINT(a) ((((EMACS_INT) (a).s.val) << (BITS_PER_EMACS_INT - VALBITS)) \
                 >> (BITS_PER_EMACS_INT - VALBITS))
 #else
 #define XINT(a) ((a).s.val)
@@ -439,9 +465,31 @@ enum pvec_type
 
 #define XUINT(a) ((a).u.val)
 
-#define XSET(var, vartype, ptr) \
+#ifdef USE_LSB_TAG
+
+# define XSET(var, vartype, ptr) \
+  (eassert ((((EMACS_UINT) (ptr)) & ((1 << GCTYPEBITS) - 1)) == 0),    \
+   (var).u.val = ((EMACS_UINT) (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) ((EMACS_INT)((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 = ((EMACS_INT) (ptr))), ((var).s.type = ((char) (vartype))))
 
+#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; }))
@@ -451,6 +499,14 @@ extern Lisp_Object make_number P_ ((EMACS_INT));
 
 #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.  */
+#ifndef XFASTINT
+# define XFASTINT(a) (XINT (a))
+# define XSETFASTINT(a, b) (XSETINT (a, b))
+#endif
+
 #define EQ(x, y) (XHASH (x) == XHASH (y))
 
 #ifndef XPNTR
@@ -480,17 +536,27 @@ extern size_t pure_size;
 /* Largest and smallest representable fixnum values.  These are the C
    values.  */
 
-#define MOST_NEGATIVE_FIXNUM   - ((EMACS_INT) 1 << (VALBITS - 1))
-#define MOST_POSITIVE_FIXNUM   (((EMACS_INT) 1 << (VALBITS - 1)) - 1)
+#ifdef USE_2_TAGS_FOR_INTS
+# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << VALBITS)
+# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << VALBITS) - 1)
 /* Mask indicating the significant bits of a Lisp_Int.
    I.e. (x & INTMASK) == XUINT (make_number (x)).  */
-#define INTMASK ((((EMACS_INT) 1) << VALBITS) - 1)
+# define INTMASK ((((EMACS_INT) 1) << (VALBITS + 1)) - 1)
+#else
+# define MOST_NEGATIVE_FIXNUM  - ((EMACS_INT) 1 << (VALBITS - 1))
+# define MOST_POSITIVE_FIXNUM  (((EMACS_INT) 1 << (VALBITS - 1)) - 1)
+/* Mask indicating the significant bits of a Lisp_Int.
+   I.e. (x & INTMASK) == XUINT (make_number (x)).  */
+# define INTMASK ((((EMACS_INT) 1) << VALBITS) - 1)
+#endif
 
-/* Value is non-zero if C integer I doesn't fit into a Lisp fixnum.  */
+/* Value is non-zero if I doesn't fit into a Lisp fixnum.  It is
+   written this way so that it also works if I is of unsigned
+   type.  */
 
 #define FIXNUM_OVERFLOW_P(i) \
-  ((EMACS_INT)(i) > MOST_POSITIVE_FIXNUM \
-   || (EMACS_INT) (i) < MOST_NEGATIVE_FIXNUM)
+  ((i) > MOST_POSITIVE_FIXNUM \
+   || ((i) < 0 && (i) < MOST_NEGATIVE_FIXNUM))
 
 /* Extract a value or address from a Lisp_Object.  */
 
@@ -506,17 +572,19 @@ extern size_t pure_size;
 #define XMISCANY(a)    (eassert (MISCP (a)), &(XMISC(a)->u_any))
 #define XMISCTYPE(a)   (XMISCANY (a)->type)
 #define XMARKER(a)     (eassert (MARKERP (a)), &(XMISC(a)->u_marker))
-#define XINTFWD(a)     (eassert (INTFWDP (a)), &(XMISC(a)->u_intfwd))
-#define XBOOLFWD(a)    (eassert (BOOLFWDP (a)), &(XMISC(a)->u_boolfwd))
-#define XOBJFWD(a)     (eassert (OBJFWDP (a)), &(XMISC(a)->u_objfwd))
 #define XOVERLAY(a)    (eassert (OVERLAYP (a)), &(XMISC(a)->u_overlay))
 #define XSAVE_VALUE(a) (eassert (SAVE_VALUEP (a)), &(XMISC(a)->u_save_value))
+
+/* Forwarding object types.  */
+
+#define XFWDTYPE(a)     (a->u_intfwd.type)
+#define XINTFWD(a)     (eassert (INTFWDP (a)), &((a)->u_intfwd))
+#define XBOOLFWD(a)    (eassert (BOOLFWDP (a)), &((a)->u_boolfwd))
+#define XOBJFWD(a)     (eassert (OBJFWDP (a)), &((a)->u_objfwd))
 #define XBUFFER_OBJFWD(a) \
-  (eassert (BUFFER_OBJFWDP (a)), &(XMISC(a)->u_buffer_objfwd))
-#define XBUFFER_LOCAL_VALUE(a) \
-  (eassert (BUFFER_LOCAL_VALUEP (a)), &(XMISC(a)->u_buffer_local_value))
+  (eassert (BUFFER_OBJFWDP (a)), &((a)->u_buffer_objfwd))
 #define XKBOARD_OBJFWD(a) \
-  (eassert (KBOARD_OBJFWDP (a)), &(XMISC(a)->u_kboard_objfwd))
+  (eassert (KBOARD_OBJFWDP (a)), &((a)->u_kboard_objfwd))
 
 /* Pseudovector types.  */
 
@@ -909,7 +977,7 @@ struct Lisp_Subr
     EMACS_UINT size;
     Lisp_Object (*function) ();
     short min_args, max_args;
-    char *symbol_name;
+    const char *symbol_name;
     char *intspec;
     char *doc;
   };
@@ -928,19 +996,32 @@ enum symbol_interned
   SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2
 };
 
+enum symbol_redirect
+{
+  SYMBOL_PLAINVAL  = 4,
+  SYMBOL_VARALIAS  = 1,
+  SYMBOL_LOCALIZED = 2,
+  SYMBOL_FORWARDED   = 3
+};
+
 /* In a symbol, the markbit of the plist is used as the gc mark bit */
 
 struct Lisp_Symbol
 {
   unsigned gcmarkbit : 1;
 
-  /* Non-zero means symbol serves as a variable alias.  The symbol
-     holding the real value is found in the value slot.  */
-  unsigned indirect_variable : 1;
+  /* Indicates where the value can be found:
+     0 : it's a plain var, the value is in the `value' field.
+     1 : it's a varalias, the value is really in the `alias' symbol.
+     2 : it's a localized var, the value is in the `blv' object.
+     3 : it's a forwarding variable, the value is in `forward'.
+   */
+  enum symbol_redirect redirect : 3;
 
   /* Non-zero means symbol is constant, i.e. changing its value
-     should signal an error.  */
-  unsigned constant : 1;
+     should signal an error.  If the value is 3, then the var
+     can be changed, but only by `defconst'.  */
+  unsigned constant : 2;
 
   /* Interned state of the symbol.  This is an enumerator from
      enum symbol_interned.  */
@@ -953,10 +1034,15 @@ struct Lisp_Symbol
   Lisp_Object xname;
 
   /* Value of the symbol or Qunbound if unbound.  If this symbol is a
-     defvaralias, `value' contains the symbol for which it is an
+     defvaralias, `alias' contains the symbol for which it is an
      alias.  Use the SYMBOL_VALUE and SET_SYMBOL_VALUE macros to get
      and set a symbol's value, to take defvaralias into account.  */
-  Lisp_Object value;
+  union {
+    Lisp_Object value;
+    struct Lisp_Symbol *alias;
+    struct Lisp_Buffer_Local_Value *blv;
+    union Lisp_Fwd *fwd;
+  } val;
 
   /* Function value of the symbol or Qunbound if not fboundp.  */
   Lisp_Object function;
@@ -970,6 +1056,23 @@ struct Lisp_Symbol
 
 /* Value is name of symbol.  */
 
+#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)   \
+  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv)
+#define SYMBOL_FWD(sym)   \
+  (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd)
+#define SET_SYMBOL_VAL(sym, v)     \
+  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value = (v))
+#define SET_SYMBOL_ALIAS(sym, v)   \
+  (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias = (v))
+#define SET_SYMBOL_BLV(sym, v)     \
+  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv = (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)
 
@@ -989,24 +1092,6 @@ struct Lisp_Symbol
 
 #define SYMBOL_CONSTANT_P(sym)   XSYMBOL (sym)->constant
 
-/* Value is the value of SYM, with defvaralias taken into
-   account.  */
-
-#define SYMBOL_VALUE(sym)                      \
-   (XSYMBOL (sym)->indirect_variable           \
-    ? indirect_variable (XSYMBOL (sym))->value \
-    : XSYMBOL (sym)->value)
-
-/* Set SYM's value to VAL, taking defvaralias into account.  */
-
-#define SET_SYMBOL_VALUE(sym, val)                             \
-     do {                                                      \
-       if (XSYMBOL (sym)->indirect_variable)                   \
-        indirect_variable (XSYMBOL (sym))->value = (val);      \
-       else                                                    \
-        XSYMBOL (sym)->value = (val);                          \
-     } while (0)
-
 \f
 /***********************************************************************
                             Hash Tables
@@ -1140,9 +1225,11 @@ struct Lisp_Hash_Table
 
 struct Lisp_Misc_Any           /* Supertype of all Misc types.  */
 {
-  enum Lisp_Misc_Type type : 16;               /* = Lisp_Misc_Marker */
+  enum Lisp_Misc_Type type : 16;               /* = Lisp_Misc_??? */
   unsigned gcmarkbit : 1;
   int spacer : 15;
+  /* Make it as long as "Lisp_Free without padding". */
+  void *fill;
 };
 
 struct Lisp_Marker
@@ -1165,7 +1252,7 @@ struct Lisp_Marker
      - Fmarker_buffer
      - Fset_marker: check eq(oldbuf, newbuf) to avoid unchain+rechain.
      - unchain_marker: to find the list from which to unchain.
-     - Fkill_buffer: to unchain the markers of current indirect buffer.
+     - Fkill_buffer: to only unchain the markers of current indirect buffer.
      */
   struct buffer *buffer;
 
@@ -1179,7 +1266,10 @@ struct Lisp_Marker
   struct Lisp_Marker *next;
   /* This is the char position where the marker points.  */
   EMACS_INT charpos;
-  /* This is the byte position.  */
+  /* This is the byte position.
+     It's mostly used as a charpos<->bytepos cache (i.e. it's not directly
+     used to implement the functionality of markers, but rather to (ab)use
+     markers as a cache for char<->byte mappings).  */
   EMACS_INT bytepos;
 };
 
@@ -1189,9 +1279,7 @@ struct Lisp_Marker
    specified int variable.  */
 struct Lisp_Intfwd
   {
-    int type : 16;     /* = Lisp_Misc_Intfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Int */
     EMACS_INT *intvar;
   };
 
@@ -1201,9 +1289,7 @@ struct Lisp_Intfwd
    nil if it is zero.  */
 struct Lisp_Boolfwd
   {
-    int type : 16;     /* = Lisp_Misc_Boolfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Bool */
     int *boolvar;
   };
 
@@ -1213,9 +1299,7 @@ struct Lisp_Boolfwd
    specified variable.  */
 struct Lisp_Objfwd
   {
-    int type : 16;     /* = Lisp_Misc_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Obj */
     Lisp_Object *objvar;
   };
 
@@ -1223,11 +1307,9 @@ struct Lisp_Objfwd
    current buffer.  Value is byte index of slot within buffer.  */
 struct Lisp_Buffer_Objfwd
   {
-    int type : 16;     /* = Lisp_Misc_Buffer_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
-    Lisp_Object slottype; /* Qnil, Lisp_Int, Lisp_Symbol, or Lisp_String.  */
+    enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Buffer_Obj */
     int offset;
+    Lisp_Object slottype; /* Qnil, Lisp_Int, Lisp_Symbol, or Lisp_String.  */
   };
 
 /* struct Lisp_Buffer_Local_Value is used in a symbol value cell when
@@ -1256,48 +1338,51 @@ struct Lisp_Buffer_Objfwd
 
 struct Lisp_Buffer_Local_Value
   {
-    int type : 16;      /* = Lisp_Misc_Buffer_Local_Value  */
-    unsigned gcmarkbit : 1;
-    int spacer : 11;
-
     /* 1 means that merely setting the variable creates a local
        binding for the current buffer */
     unsigned int local_if_set : 1;
-    /* 1 means this variable is allowed to have frame-local bindings,
-       so check for them when looking for the proper binding.  */
-    unsigned int check_frame : 1;
-    /* 1 means that the binding now loaded was found
-       as a local binding for the buffer in the `buffer' slot.  */
-    unsigned int found_for_buffer : 1;
-    /* 1 means that the binding now loaded was found
-       as a local binding for the frame in the `frame' slot.  */
-    unsigned int found_for_frame : 1;
-    Lisp_Object realvalue;
-    /* The buffer and frame for which the loaded binding was found.  */
-    /* Having both is only needed if we want to allow variables that are
-       both buffer local and frame local (in which case, we currently give
-       precedence to the buffer-local binding).  I don't think such
-       a combination is desirable.  --Stef  */
-    Lisp_Object buffer, frame;
-
-    /* A cons cell, (LOADED-BINDING . DEFAULT-VALUE).
-
-       LOADED-BINDING is the binding now loaded.  It is a cons cell
-       whose cdr is the binding's value.  The cons cell may be an
-       element of a buffer's local-variable alist, or an element of a
-       frame's parameter alist, or it may be this cons cell.
-
-       DEFAULT-VALUE is the variable's default value, seen when the
-       current buffer and selected frame do not have their own
-       bindings for the variable.  When the default binding is loaded,
-       LOADED-BINDING is actually this very cons cell; thus, its car
-       points to itself.  */
-    Lisp_Object cdr;
+    /* 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) */
+    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.  */
+    /* The buffer or frame for which the loaded binding was found.  */
+    Lisp_Object where;
+    /* A cons cell that holds the default value.  It has the form
+       (SYMBOL . DEFAULT-VALUE).  */
+    Lisp_Object defcell;
+    /* The cons cell from `where's parameter alist.
+       It always has the form (SYMBOL . VALUE)
+       Note that if `forward' is non-nil, VALUE may be out of date.
+       Also if the currently loaded binding is the default binding, then
+       this is `eq'ual to defcell.  */
+    Lisp_Object valcell;
   };
 
+#define BLV_FOUND(blv) \
+  (eassert ((blv)->found == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found)
+#define SET_BLV_FOUND(blv, v) \
+  (eassert ((v) == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found = (v))
+
+#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 Lisp_Misc_Type type : 16;     /* = Lisp_Misc_Overlay */
     unsigned gcmarkbit : 1;
@@ -1310,9 +1395,7 @@ struct Lisp_Overlay
    current kboard.  */
 struct Lisp_Kboard_Objfwd
   {
-    enum Lisp_Misc_Type type : 16;     /* = Lisp_Misc_Kboard_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;   /* = Lisp_Fwd_Kboard_Obj */
     int offset;
   };
 
@@ -1341,9 +1424,9 @@ struct Lisp_Free
 #ifdef USE_LSB_TAG
     /* Try to make sure that sizeof(Lisp_Misc) preserves TYPEBITS-alignment.
        This assumes that Lisp_Marker is the largest of the alternatives and
-       that Lisp_Intfwd has the same size as "Lisp_Free w/o padding".  */
+       that Lisp_Misc_Any has the same size as "Lisp_Free w/o padding".  */
     char padding[((((sizeof (struct Lisp_Marker) - 1) >> GCTYPEBITS) + 1)
-                 << GCTYPEBITS) - sizeof (struct Lisp_Intfwd)];
+                 << GCTYPEBITS) - sizeof (struct Lisp_Misc_Any)];
 #endif
   };
 
@@ -1354,15 +1437,18 @@ union Lisp_Misc
   {
     struct Lisp_Misc_Any u_any;           /* Supertype of all Misc types.  */
     struct Lisp_Free u_free;      /* Includes padding to force alignment.  */
-    struct Lisp_Marker u_marker;
-    struct Lisp_Intfwd u_intfwd;
-    struct Lisp_Boolfwd u_boolfwd;
-    struct Lisp_Objfwd u_objfwd;
-    struct Lisp_Buffer_Objfwd u_buffer_objfwd;
-    struct Lisp_Buffer_Local_Value u_buffer_local_value;
-    struct Lisp_Overlay u_overlay;
-    struct Lisp_Kboard_Objfwd u_kboard_objfwd;
-    struct Lisp_Save_Value u_save_value;
+    struct Lisp_Marker u_marker;                        /* 5 */
+    struct Lisp_Overlay u_overlay;                      /* 5 */
+    struct Lisp_Save_Value u_save_value;                /* 3 */
+  };
+
+union Lisp_Fwd
+  {
+    struct Lisp_Intfwd u_intfwd;                        /* 2 */
+    struct Lisp_Boolfwd u_boolfwd;                      /* 2 */
+    struct Lisp_Objfwd u_objfwd;                        /* 2 */
+    struct Lisp_Buffer_Objfwd u_buffer_objfwd;          /* 2 */
+    struct Lisp_Kboard_Objfwd u_kboard_objfwd;          /* 2 */
   };
 \f
 /* Lisp floating point type */
@@ -1493,7 +1579,7 @@ typedef struct {
 #define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
 #define NATNUMP(x) (INTEGERP (x) && XINT (x) >= 0)
 
-#define INTEGERP(x) (XTYPE ((x)) == Lisp_Int)
+#define INTEGERP(x) (LISP_INT_TAG_P (XTYPE ((x))))
 #define SYMBOLP(x) (XTYPE ((x)) == Lisp_Symbol)
 #define MISCP(x) (XTYPE ((x)) == Lisp_Misc)
 #define VECTORLIKEP(x) (XTYPE ((x)) == Lisp_Vectorlike)
@@ -1504,15 +1590,13 @@ typedef struct {
 #define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
 #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
 #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
-#define INTFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
-#define BOOLFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
-#define OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
-#define BUFFER_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
-#define BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
-#define SOME_BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
-#define KBOARD_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
 #define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value)
 
+#define INTFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Int)
+#define BOOLFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Bool)
+#define OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Obj)
+#define BUFFER_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Buffer_Obj)
+#define KBOARD_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Kboard_Obj)
 
 /* True if object X is a pseudovector whose code is CODE.  */
 #define PSEUDOVECTORP(x, code)                                 \
@@ -1688,17 +1772,6 @@ typedef struct {
     A null string means call interactively with no arguments.
  `doc' is documentation for the user.  */
 
-#if (!defined (__STDC__) && !defined (PROTOTYPES))
-
-#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
-  Lisp_Object fnname ();                                               \
-  DECL_ALIGN (struct Lisp_Subr, sname) =                               \
-    { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),    \
-      fnname, minargs, maxargs, lname, intspec, 0};                    \
-  Lisp_Object fnname
-
-#else
-
 /* This version of DEFUN declares a function prototype with the right
    arguments, so we can catch errors with maxargs at compile-time.  */
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)    \
@@ -1725,8 +1798,6 @@ typedef struct {
                         Lisp_Object, Lisp_Object, Lisp_Object)
 #define DEFUN_ARGS_8   (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
                         Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
-#endif
-
 /* Non-zero if OBJ is a Lisp function.  */
 
 #define FUNCTIONP(OBJ)                                 \
@@ -1742,24 +1813,44 @@ extern void defsubr P_ ((struct Lisp_Subr *));
 #define MANY -2
 #define UNEVALLED -1
 
-extern void defvar_lisp P_ ((char *, Lisp_Object *));
-extern void defvar_lisp_nopro P_ ((char *, Lisp_Object *));
-extern void defvar_bool P_ ((char *, int *));
-extern void defvar_int P_ ((char *, EMACS_INT *));
-extern void defvar_kboard P_ ((char *, int));
+extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
+extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
+extern void defvar_bool (struct Lisp_Boolfwd *, const char *, int *);
+extern void defvar_int (struct Lisp_Intfwd *, const char *, EMACS_INT *);
+extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int);
 
 /* Macros we use to define forwarded Lisp variables.
    These are used in the syms_of_FILENAME functions.  */
 
-#define DEFVAR_LISP(lname, vname, doc) defvar_lisp (lname, vname)
-#define DEFVAR_LISP_NOPRO(lname, vname, doc) defvar_lisp_nopro (lname, vname)
-#define DEFVAR_BOOL(lname, vname, doc) defvar_bool (lname, vname)
-#define DEFVAR_INT(lname, vname, doc) defvar_int (lname, vname)
+#define DEFVAR_LISP(lname, vname, doc)         \
+  do {                                         \
+    static struct Lisp_Objfwd o_fwd;           \
+    defvar_lisp (&o_fwd, lname, vname);                \
+  } while (0)
+#define DEFVAR_LISP_NOPRO(lname, vname, doc)   \
+  do {                                         \
+    static struct Lisp_Objfwd o_fwd;           \
+    defvar_lisp_nopro (&o_fwd, lname, vname);  \
+  } while (0)
+#define DEFVAR_BOOL(lname, vname, doc)         \
+  do {                                         \
+    static struct Lisp_Boolfwd b_fwd;          \
+    defvar_bool (&b_fwd, lname, vname);                \
+  } while (0)
+#define DEFVAR_INT(lname, vname, doc)          \
+  do {                                         \
+    static struct Lisp_Intfwd i_fwd;           \
+    defvar_int (&i_fwd, lname, vname);         \
+  } while (0)
 
-#define DEFVAR_KBOARD(lname, vname, doc) \
- defvar_kboard (lname, \
-               (int)((char *)(&current_kboard->vname) \
-                     - (char *)current_kboard))
+#define DEFVAR_KBOARD(lname, vname, doc)                       \
+  do {                                                         \
+    static struct Lisp_Kboard_Objfwd ko_fwd;                   \
+    defvar_kboard (&ko_fwd,                                    \
+                  lname,                                       \
+                  (int)((char *)(&current_kboard->vname)       \
+                        - (char *)current_kboard));            \
+  } while (0)
 
 
 \f
@@ -1886,22 +1977,12 @@ extern char *stack_bottom;
 #ifdef SYNC_INPUT
 extern void process_pending_signals P_ ((void));
 extern int pending_signals;
-
-#define QUIT                                           \
-  do {                                                 \
-    if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))    \
-      {                                                        \
-        Lisp_Object flag = Vquit_flag;                 \
-       Vquit_flag = Qnil;                              \
-       if (EQ (Vthrow_on_input, flag))                 \
-         Fthrow (Vthrow_on_input, Qt);                 \
-       Fsignal (Qquit, Qnil);                          \
-      }                                                        \
-    else if (pending_signals)                          \
-      process_pending_signals ();                      \
-  } while (0)
-
+#define ELSE_PENDING_SIGNALS                           \
+  else if (pending_signals)                            \
+    process_pending_signals ();
 #else  /* not SYNC_INPUT */
+#define ELSE_PENDING_SIGNALS
+#endif /* not SYNC_INPUT */
 
 #define QUIT                                           \
   do {                                                 \
@@ -1913,10 +1994,9 @@ extern int pending_signals;
          Fthrow (Vthrow_on_input, Qt);                 \
        Fsignal (Qquit, Qnil);                          \
       }                                                        \
+    ELSE_PENDING_SIGNALS                               \
   } while (0)
 
-#endif /* not SYNC_INPUT */
-
 
 /* Nonzero if ought to quit now.  */
 
@@ -2172,15 +2252,10 @@ void staticpro P_ ((Lisp_Object *));
 \f
 /* Declare a Lisp-callable function.  The MAXARGS parameter has the same
    meaning as in the DEFUN macro, and is used to construct a prototype.  */
-#if (!defined (__STDC__) &&  !defined (PROTOTYPES))
-#define EXFUN(fnname, maxargs) \
-  extern Lisp_Object fnname ()
-#else
 /* We can use the same trick as in the DEFUN macro to generate the
    appropriate prototype.  */
 #define EXFUN(fnname, maxargs) \
   extern Lisp_Object fnname DEFUN_ARGS_ ## maxargs
-#endif
 
 /* Forward declarations for prototypes.  */
 struct window;
@@ -2218,6 +2293,7 @@ extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
 
 extern void circular_list_error P_ ((Lisp_Object)) NO_RETURN;
 EXFUN (Finteractive_form, 1);
+EXFUN (Fbyteorder, 0);
 
 /* Defined in frame.c */
 extern Lisp_Object Qframep;
@@ -2309,13 +2385,11 @@ extern void args_out_of_range P_ ((Lisp_Object, Lisp_Object)) NO_RETURN;
 extern void args_out_of_range_3 P_ ((Lisp_Object, Lisp_Object,
                                     Lisp_Object)) NO_RETURN;
 extern Lisp_Object wrong_type_argument P_ ((Lisp_Object, Lisp_Object)) NO_RETURN;
-extern void store_symval_forwarding P_ ((Lisp_Object, Lisp_Object,
-                                        Lisp_Object, struct buffer *));
-extern Lisp_Object do_symval_forwarding P_ ((Lisp_Object));
-extern Lisp_Object set_internal P_ ((Lisp_Object, Lisp_Object, struct buffer *, int));
+extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *);
+extern void set_internal (Lisp_Object, Lisp_Object, struct buffer *, int);
 extern void syms_of_data P_ ((void));
 extern void init_data P_ ((void));
-extern void swap_in_global_binding P_ ((Lisp_Object));
+extern void swap_in_global_binding P_ ((struct Lisp_Symbol *));
 
 /* Defined in cmds.c */
 EXFUN (Fend_of_line, 1);
@@ -2601,6 +2675,9 @@ extern Lisp_Object safe_eval P_ ((Lisp_Object));
 extern int pos_visible_p P_ ((struct window *, int, int *,
                              int *, int *, int *, int *, int *));
 
+/* Defined in xsettings.c */
+extern void syms_of_xsettings P_ ((void));
+
 /* Defined in vm-limit.c.  */
 extern void memory_warnings P_ ((POINTER_TYPE *, void (*warnfun) ()));
 
@@ -2640,7 +2717,8 @@ extern Lisp_Object make_uninit_multibyte_string P_ ((int, int));
 extern Lisp_Object make_string_from_bytes P_ ((const char *, int, int));
 extern Lisp_Object make_specified_string P_ ((const char *, int, int, int));
 EXFUN (Fpurecopy, 1);
-extern Lisp_Object make_pure_string P_ ((char *, int, int, int));
+extern Lisp_Object make_pure_string P_ ((const char *, int, int, int));
+extern Lisp_Object make_pure_c_string (const char *data);
 extern Lisp_Object pure_cons P_ ((Lisp_Object, Lisp_Object));
 extern Lisp_Object make_pure_vector P_ ((EMACS_INT));
 EXFUN (Fgarbage_collect, 0);
@@ -2739,6 +2817,7 @@ extern Lisp_Object read_filtered_event P_ ((int, int, int, int, Lisp_Object));
 EXFUN (Feval_region, 4);
 extern Lisp_Object check_obarray P_ ((Lisp_Object));
 extern Lisp_Object intern P_ ((const char *));
+extern Lisp_Object intern_c_string (const char *);
 extern Lisp_Object make_symbol P_ ((char *));
 extern Lisp_Object oblookup P_ ((Lisp_Object, const char *, int, int));
 #define LOADHIST_ATTACH(x) \
@@ -2747,7 +2826,7 @@ extern Lisp_Object Vcurrent_load_list;
 extern Lisp_Object Vload_history, Vload_suffixes, Vload_file_rep_suffixes;
 extern int openp P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
                      Lisp_Object *, Lisp_Object));
-extern int isfloat_string P_ ((char *));
+extern int isfloat_string P_ ((char *, int));
 extern void map_obarray P_ ((Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
                             Lisp_Object));
 extern void dir_warning P_ ((char *, Lisp_Object));
@@ -2984,7 +3063,6 @@ extern Lisp_Object close_file_unwind P_ ((Lisp_Object));
 extern void report_file_error P_ ((const char *, Lisp_Object)) NO_RETURN;
 extern int internal_delete_file P_ ((Lisp_Object));
 extern void syms_of_fileio P_ ((void));
-extern void init_fileio_once P_ ((void));
 extern Lisp_Object make_temp_name P_ ((Lisp_Object, int));
 EXFUN (Fmake_symbolic_link, 3);
 extern Lisp_Object Qdelete_file;
@@ -3352,11 +3430,13 @@ extern void syms_of_term P_ ((void));
 extern void fatal P_ ((const char *msgid, ...)) NO_RETURN;
 
 /* Defined in terminal.c */
+EXFUN (Fframe_terminal, 1);
 EXFUN (Fdelete_terminal, 2);
 extern void syms_of_terminal P_ ((void));
 
 /* Defined in font.c */
 extern void syms_of_font P_ ((void));
+extern void init_font P_ ((void));
 
 #ifdef HAVE_WINDOW_SYSTEM
 /* Defined in fontset.c */