]> code.delx.au - gnu-emacs/blobdiff - src/lisp.h
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-78
[gnu-emacs] / src / lisp.h
index 4694078195efb7f23aa11d3598481dc6bfbcaa21..3f49ac546ccad726a45026aaafa1670747af6848 100644 (file)
@@ -1,5 +1,5 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985,86,87,93,94,95,97,98,1999,2000, 2001, 2002, 2003
+   Copyright (C) 1985,86,87,93,94,95,97,98,1999,2000,01,02,03,2004
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -35,6 +35,22 @@ Boston, MA 02111-1307, USA.  */
    be compared to the sizes recorded in Lisp strings.  */
 
 #define GC_CHECK_STRING_BYTES 1
+
+/* Define this to check for short string overrun.  */
+
+#define GC_CHECK_STRING_OVERRUN 1
+
+/* Define this to check the string free list.  */
+
+#define GC_CHECK_STRING_FREE_LIST 1
+
+/* Define this to check for malloc buffer overrun.  */
+
+#define XMALLOC_OVERRUN_CHECK 1
+
+/* Define this to check for errors in cons list.  */
+/* #define GC_CHECK_CONS_LIST 1 */
+
 #endif /* 0 */
 
 
@@ -67,10 +83,6 @@ extern void die P_((const char *, const char *, int));
                           ? (void) 0                           \
                           : die ((msg), __FILE__, __LINE__)),  \
                          0)
-
-/* Let's get some compile-time checking too.  */
-#undef NO_UNION_TYPE
-
 #else
 
 /* Produce same side effects and result, but don't complain.  */
@@ -182,18 +194,13 @@ union Lisp_Object
     struct
       {
        EMACS_INT val  : VALBITS;
-       EMACS_UINT type : GCTYPEBITS;
+       enum Lisp_Type type : GCTYPEBITS;
       } s;
     struct
       {
        EMACS_UINT val : VALBITS;
-       EMACS_UINT type : GCTYPEBITS;
+       enum Lisp_Type type : GCTYPEBITS;
       } u;
-    struct
-      {
-       EMACS_UINT val          : VALBITS;
-       enum Lisp_Type type     : GCTYPEBITS;
-      } gu;
   }
 Lisp_Object;
 
@@ -208,19 +215,14 @@ union Lisp_Object
 
     struct
       {
-       EMACS_UINT type : GCTYPEBITS;
+       enum Lisp_Type type : GCTYPEBITS;
        EMACS_INT val  : VALBITS;
       } s;
     struct
       {
-       EMACS_UINT type : GCTYPEBITS;
+       enum Lisp_Type type : GCTYPEBITS;
        EMACS_UINT val : VALBITS;
       } u;
-    struct
-      {
-       enum Lisp_Type type     : GCTYPEBITS;
-       EMACS_UINT val          : VALBITS;
-      } gu;
   }
 Lisp_Object;
 
@@ -281,7 +283,8 @@ enum pvec_type
   PVEC_BOOL_VECTOR = 0x10000,
   PVEC_BUFFER = 0x20000,
   PVEC_HASH_TABLE = 0x40000,
-  PVEC_TYPE_MASK = 0x7fe00
+  PVEC_SUB_CHAR_TABLE = 0x80000,
+  PVEC_TYPE_MASK = 0x0ffe00
 
 #if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
         GDB.  It doesn't work on OS Alpha.  Moved to a variable in
@@ -292,6 +295,61 @@ enum pvec_type
 
 /* For convenience, we also store the number of elements in these bits.  */
 #define PSEUDOVECTOR_SIZE_MASK 0x1ff
+
+/* Number of bits to put in each character in the internal representation
+   of bool vectors.  This should not vary across implementations.  */
+#define BOOL_VECTOR_BITS_PER_CHAR 8
+\f
+/***** Select the tagging scheme.  *****/
+/* There are basically two options that control the tagging scheme:
+   - NO_UNION_TYPE says that Lisp_Object should be an integer instead
+     of a union.
+   - USE_LSB_TAG means that we can assume the least 3 bits of pointers are
+     always 0, and we can thus use them to hold tag bits, without
+     restricting our addressing space.
+
+   If USE_LSB_TAG is not set, then we use the top 3 bits for tagging, thus
+   restricting our possible address range.  Currently USE_LSB_TAG is not
+   allowed together with a union.  This is not due to any fundamental
+   technical (or political ;-) problem: nobody wrote the code to do it yet.
+
+   USE_LSB_TAG not only requires the least 3 bits of pointers returned by
+   malloc to be 0 but also needs to be able to impose a mult-of-8 alignment
+   on the few static Lisp_Objects used: all the defsubr as well
+   as the two special buffers buffer_defaults and buffer_local_symbols.  */
+
+/* First, try and define DECL_ALIGN(type,var) which declares a static
+   variable VAR of type TYPE with the added requirement that it be
+   TYPEBITS-aligned. */
+#ifndef NO_DECL_ALIGN
+# ifndef DECL_ALIGN
+/* What compiler directive should we use for non-gcc compilers?  -stef  */
+#  if defined (__GNUC__)
+#   define DECL_ALIGN(type, var) \
+     type __attribute__ ((__aligned__ (1 << GCTYPEBITS))) var
+#  endif
+# endif
+#endif
+
+/* Let's USE_LSB_TAG on systems where we know malloc returns mult-of-8.  */
+#if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined MAC_OSX
+/* 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.  */
+#  if defined NO_UNION_TYPE
+#   define USE_LSB_TAG
+#  endif
+# endif
+#endif
+
+/* If we cannot use 8-byte alignment, make DECL_ALIGN a no-op.  */
+#ifndef DECL_ALIGN
+# ifdef USE_LSB_TAG
+#  error "USE_LSB_TAG used without defining DECL_ALIGN"
+# endif
+# define DECL_ALIGN(type, var) type var
+#endif
+
 \f
 /* These macros extract various sorts of values from a Lisp_Object.
  For example, if tem is a Lisp_Object whose type is Lisp_Cons,
@@ -299,6 +357,27 @@ enum pvec_type
 
 #ifdef NO_UNION_TYPE
 
+#ifdef USE_LSB_TAG
+
+#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)
+#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))
+
+#else  /* not USE_LSB_TAG */
+
 #define VALMASK ((((EMACS_INT) 1) << VALBITS) - 1)
 
 /* One need to override this if there must be high bits set in data space
@@ -337,6 +416,8 @@ enum pvec_type
 #define make_number(N)         \
   ((((EMACS_INT) (N)) & VALMASK) | ((EMACS_INT) Lisp_Int) << VALBITS)
 
+#endif /* not USE_LSB_TAG */
+
 #define EQ(x, y) ((x) == (y))
 
 #else /* not NO_UNION_TYPE */
@@ -351,7 +432,7 @@ enum pvec_type
 
 #ifdef EXPLICIT_SIGN_EXTEND
 /* Make sure we sign-extend; compilers have been known to fail to do so.  */
-#define XINT(a) (((a).i << (BITS_PER_EMACS_INT - VALBITS)) \
+#define XINT(a) (((a).s.val << (BITS_PER_EMACS_INT - VALBITS)) \
                 >> (BITS_PER_EMACS_INT - VALBITS))
 #else
 #define XINT(a) ((a).s.val)
@@ -369,7 +450,7 @@ enum pvec_type
 extern Lisp_Object make_number ();
 #endif
 
-#define EQ(x, y) ((x).s.val == (y).s.val)
+#define EQ(x, y) ((x).s.val == (y).s.val && (x).s.type == (y).s.type)
 
 #endif /* NO_UNION_TYPE */
 
@@ -448,6 +529,7 @@ extern size_t pure_size;
 #define XSUBR(a) (eassert (GC_SUBRP(a)),(struct Lisp_Subr *) XPNTR(a))
 #define XBUFFER(a) (eassert (GC_BUFFERP(a)),(struct buffer *) XPNTR(a))
 #define XCHAR_TABLE(a) ((struct Lisp_Char_Table *) XPNTR(a))
+#define XSUB_CHAR_TABLE(a) ((struct Lisp_Sub_Char_Table *) XPNTR(a))
 #define XBOOL_VECTOR(a) ((struct Lisp_Bool_Vector *) XPNTR(a))
 
 /* Construct a Lisp_Object from a value or address.  */
@@ -477,6 +559,7 @@ extern size_t pure_size;
 #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
 #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
 #define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
+#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
 
 /* Convenience macros for dealing with Lisp arrays.  */
 
@@ -617,41 +700,20 @@ struct Lisp_Vector
     Lisp_Object contents[1];
   };
 
-/* A char table is a kind of vectorlike, with contents are like a
+/* A char-table is a kind of vectorlike, with contents are like a
    vector but with a few other slots.  For some purposes, it makes
-   sense to handle a chartable with type struct Lisp_Vector.  An
+   sense to handle a char-table with type struct Lisp_Vector.  An
    element of a char table can be any Lisp objects, but if it is a sub
    char-table, we treat it a table that contains information of a
-   group of characters of the same charsets or a specific character of
-   a charset.  A sub char-table has the same structure as a char table
-   except for that the former omits several slots at the tail.  A sub
-   char table appears only in an element of a char table, and there's
-   no way to access it directly from Emacs Lisp program.  */
-
-/* This is the number of slots that apply to characters or character
-   sets.  The first 128 are for ASCII, the next 128 are for 8-bit
-   European characters, and the last 128 are for multibyte characters.
-   The first 256 are indexed by the code itself, but the last 128 are
-   indexed by (charset-id + 128).  */
-#define CHAR_TABLE_ORDINARY_SLOTS 384
-
-/* This is the number of slots that apply to characters of ASCII and
-   8-bit Europeans only.  */
-#define CHAR_TABLE_SINGLE_BYTE_SLOTS 256
+   specific range of characters.  A sub char-table has the same
+   structure as a vector.  A sub char table appears only in an element
+   of a char-table, and there's no way to access it directly from
+   Emacs Lisp program.  */
 
 /* This is the number of slots that every char table must have.  This
    counts the ordinary slots and the top, defalt, parent, and purpose
    slots.  */
-#define CHAR_TABLE_STANDARD_SLOTS (CHAR_TABLE_ORDINARY_SLOTS + 4)
-
-/* This is the number of slots that apply to position-code-1 and
-   position-code-2 of a multibyte character at the 2nd and 3rd level
-   sub char tables respectively.  */
-#define SUB_CHAR_TABLE_ORDINARY_SLOTS 128
-
-/* This is the number of slots that every sub char table must have.
-   This counts the ordinary slots and the top and defalt slot.  */
-#define SUB_CHAR_TABLE_STANDARD_SLOTS (SUB_CHAR_TABLE_ORDINARY_SLOTS + 2)
+#define CHAR_TABLE_STANDARD_SLOTS (VECSIZE (struct Lisp_Char_Table) - 1)
 
 /* Return the number of "extra" slots in the char table CT.  */
 
@@ -659,70 +721,92 @@ struct Lisp_Vector
   (((CT)->size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS)
 
 /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
-   and 8-bit Europeans characters.  For these characters, do not check
-   validity of CT.  Do not follow parent.  */
-#define CHAR_TABLE_REF(CT, IDX)                                \
-  ((IDX) >= 0 && (IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS  \
-   ? (!NILP (XCHAR_TABLE (CT)->contents[IDX])          \
-      ? XCHAR_TABLE (CT)->contents[IDX]                        \
-      : XCHAR_TABLE (CT)->defalt)                      \
-   : Faref (CT, make_number (IDX)))
+   characters.  Do not check validity of CT.  */
+#define CHAR_TABLE_REF(CT, IDX)                                                 \
+  ((ASCII_CHAR_P (IDX)                                                  \
+    && SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii)                       \
+    && !NILP (XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX])) \
+   ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX]           \
+   : char_table_ref ((CT), (IDX)))
 
-/* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
-   and 8-bit Europeans characters.  However, if the result is nil,
-   return IDX.
+/* Almost equivalent to Faref (CT, IDX).  However, if the result is
+   not a character, return IDX.
 
    For these characters, do not check validity of CT
    and do not follow parent.  */
-#define CHAR_TABLE_TRANSLATE(CT, IDX)                  \
-  ((IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS                        \
-   ? (!NILP (XCHAR_TABLE (CT)->contents[IDX])          \
-      ? XINT (XCHAR_TABLE (CT)->contents[IDX])         \
-      : IDX)                                           \
-   : char_table_translate (CT, IDX))
+#define CHAR_TABLE_TRANSLATE(CT, IDX)  \
+  char_table_translate (CT, IDX)
 
 /* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
-   8-bit Europeans characters.  Do not check validity of CT.  */
-#define CHAR_TABLE_SET(CT, IDX, VAL)                   \
-  do {                                                 \
-    if (XFASTINT (IDX) < CHAR_TABLE_SINGLE_BYTE_SLOTS) \
-      XCHAR_TABLE (CT)->contents[XFASTINT (IDX)] = VAL;        \
-    else                                               \
-      Faset (CT, IDX, VAL);                            \
-  } while (0)
+   8-bit European characters.  Do not check validity of CT.  */
+#define CHAR_TABLE_SET(CT, IDX, VAL)                                   \
+  (((IDX) >= 0 && ASCII_CHAR_P (IDX)                                   \
+    && SUB_CHAR_TABLE_P (XCHAR_TABLE (CT)->ascii))                     \
+   ? XSUB_CHAR_TABLE (XCHAR_TABLE (CT)->ascii)->contents[IDX] = VAL    \
+   : char_table_set (CT, IDX, VAL))
+
+#define CHARTAB_SIZE_BITS_0 6
+#define CHARTAB_SIZE_BITS_1 4
+#define CHARTAB_SIZE_BITS_2 5
+#define CHARTAB_SIZE_BITS_3 7
+
+extern const int chartab_size[4];
+
+struct Lisp_Sub_Char_Table;
 
 struct Lisp_Char_Table
   {
     /* This is the vector's size field, which also holds the
-       pseudovector type information.  It holds the size, too.
-       The size counts the top, defalt, purpose, and parent slots.
-       The last three are not counted if this is a sub char table.  */
+       pseudovector type information.  It holds the size, too.  The size
+       counts the defalt, parent, purpose, ascii, contents, and extras
+       slots.  */
     EMACS_INT size;
     struct Lisp_Vector *next;
-    /* This holds a flag to tell if this is a top level char table (t)
-       or a sub char table (nil).  */
-    Lisp_Object top;
+
     /* This holds a default value,
        which is used whenever the value for a specific character is nil.  */
     Lisp_Object defalt;
-    /* This holds an actual value of each element.  A sub char table
-       has only SUB_CHAR_TABLE_ORDINARY_SLOTS number of elements.  */
-    Lisp_Object contents[CHAR_TABLE_ORDINARY_SLOTS];
 
-    /* A sub char table doesn't has the following slots.  */
-
-    /* This points to another char table, which we inherit from
-       when the value for a specific character is nil.
-       The `defalt' slot takes precedence over this.  */
+    /* This points to another char table, which we inherit from when the
+       value for a specific character is nil.  The `defalt' slot takes
+       precedence over this.  */
     Lisp_Object parent;
-    /* This should be a symbol which says what kind of use
-       this char-table is meant for.
-       Typically now the values can be `syntax-table' and `display-table'.  */
+
+    /* This is a symbol which says what kind of use this char-table is
+       meant for.  */
     Lisp_Object purpose;
-    /* These hold additional data.  */
+
+    /* The bottom sub char-table for characters of the range 0..127.  It
+       is nil if none of ASCII character has a specific value.  */
+    Lisp_Object ascii;
+
+    Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)];
+
+    /* These hold additional data.  It is a vector.  */
     Lisp_Object extras[1];
   };
 
+struct Lisp_Sub_Char_Table
+  {
+    /* This is the vector's size field, which also holds the
+       pseudovector type information.  It holds the size, too.  */
+    EMACS_INT size;
+    struct Lisp_Vector *next;
+
+    /* Depth of this sub char-table.  It should be 1, 2, or 3.  A sub
+       char-table of depth 1 contains 16 elments, and each element
+       covers 4096 (128*32) characters.  A sub char-table of depth 2
+       contains 32 elements, and each element covers 128 characters.  A
+       sub char-table of depth 3 contains 128 elements, and each element
+       is for one character.  */
+    Lisp_Object depth;
+
+    /* Minimum character covered by the sub char-table.  */
+    Lisp_Object min_char;
+
+    Lisp_Object contents[1];
+  };
+
 /* A boolvector is a kind of vectorlike, with contents are like a string.  */
 struct Lisp_Bool_Vector
   {
@@ -1137,7 +1221,10 @@ struct Lisp_Save_Value
   {
     int type : 16;     /* = Lisp_Misc_Save_Value */
     unsigned gcmarkbit : 1;
-    int spacer : 15;
+    int spacer : 14;
+    /* If DOGC is set, POINTER is the address of a memory
+       area containing INTEGER potential Lisp_Objects.  */
+    unsigned int dogc : 1;
     void *pointer;
     int integer;
   };
@@ -1150,6 +1237,13 @@ struct Lisp_Free
     unsigned gcmarkbit : 1;
     int spacer : 15;
     union Lisp_Misc *chain;
+#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".  */
+    char padding[((((sizeof (struct Lisp_Marker) - 1) >> GCTYPEBITS) + 1)
+                 << GCTYPEBITS) - sizeof (struct Lisp_Intfwd)];
+#endif
   };
 
 /* To get the type field of a union Lisp_Misc, use XMISCTYPE.
@@ -1216,9 +1310,9 @@ typedef unsigned char UCHAR;
   (CHAR_ALT | CHAR_SUPER | CHAR_HYPER  | CHAR_SHIFT | CHAR_CTL | CHAR_META)
 
 
-/* Actually, the current Emacs uses 19 bits for the character value
+/* Actually, the current Emacs uses 22 bits for the character value
    itself.  */
-#define CHARACTERBITS 19
+#define CHARACTERBITS 22
 
 /* The maximum byte size consumed by push_key_description.
    All callers should assure that at least this size of memory is
@@ -1274,9 +1368,9 @@ typedef unsigned char UCHAR;
 #define GLYPH int
 
 /* Mask bits for face.  */
-#define GLYPH_MASK_FACE    0x7FF80000
+#define GLYPH_MASK_FACE    0x7FC00000
  /* Mask bits for character code.  */
-#define GLYPH_MASK_CHAR    0x0007FFFF /* The lowest 19 bits */
+#define GLYPH_MASK_CHAR    0x003FFFFF /* The lowest 22 bits */
 
 /* The FAST macros assume that we already know we're in an X window.  */
 
@@ -1302,7 +1396,7 @@ typedef unsigned char UCHAR;
 \f
 /* Data type checking */
 
-#define NILP(x)  (XFASTINT (x) == XFASTINT (Qnil))
+#define NILP(x)  EQ (x, Qnil)
 #define GC_NILP(x) GC_EQ (x, Qnil)
 
 #define NUMBERP(x) (INTEGERP (x) || FLOATP (x))
@@ -1374,13 +1468,17 @@ typedef unsigned char UCHAR;
 #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER)
 #define GC_BUFFERP(x) GC_PSEUDOVECTORP (x, PVEC_BUFFER)
 #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
+#define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE)
+#define GC_SUB_CHAR_TABLE_P(x) GC_PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE)
 #define GC_CHAR_TABLE_P(x) GC_PSEUDOVECTORP (x, PVEC_CHAR_TABLE)
 #define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
 #define GC_BOOL_VECTOR_P(x) GC_PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
 #define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
 #define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME)
 
-#define SUB_CHAR_TABLE_P(x) (CHAR_TABLE_P (x) && NILP (XCHAR_TABLE (x)->top))
+/* Test for image (image . spec)  */
+#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage))
+
 \f
 #define GC_EQ(x, y) EQ (x, y)
 
@@ -1481,6 +1579,20 @@ typedef unsigned char UCHAR;
     XSETCDR ((x), tmp);                        \
   } while (0)
 
+#define CHECK_NATNUM_CAR(x) \
+  do {                                 \
+    Lisp_Object tmp = XCAR (x);                \
+    CHECK_NATNUM (tmp);                        \
+    XSETCAR ((x), tmp);                        \
+  } while (0)
+
+#define CHECK_NATNUM_CDR(x) \
+  do {                                 \
+    Lisp_Object tmp = XCDR (x);                \
+    CHECK_NATNUM (tmp);                        \
+    XSETCDR ((x), tmp);                        \
+  } while (0)
+
 /* Cast pointers to this type to compare them.  Some machines want int.  */
 #ifndef PNTR_COMPARISON_TYPE
 #define PNTR_COMPARISON_TYPE EMACS_UINT
@@ -1513,7 +1625,7 @@ typedef unsigned char UCHAR;
 
 #define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc)     \
   Lisp_Object fnname ();                                               \
-  struct Lisp_Subr sname =                                             \
+  DECL_ALIGN (struct Lisp_Subr, sname) =                               \
     { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),    \
       fnname, minargs, maxargs, lname, prompt, 0};                     \
   Lisp_Object fnname
@@ -1524,7 +1636,7 @@ typedef unsigned char UCHAR;
    arguments, so we can catch errors with maxargs at compile-time.  */
 #define DEFUN(lname, fnname, sname, minargs, maxargs, prompt, doc)     \
   Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;                          \
-  struct Lisp_Subr sname =                                             \
+  DECL_ALIGN (struct Lisp_Subr, sname) =                               \
     { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)),    \
       fnname, minargs, maxargs, lname, prompt, 0};                     \
   Lisp_Object fnname
@@ -1671,15 +1783,41 @@ extern char *stack_bottom;
    This is a good thing to do around a loop that has no side effects
    and (in particular) cannot call arbitrary Lisp code.  */
 
+#ifdef SYNC_INPUT
+extern void handle_async_input P_ ((void));
+extern int interrupt_input_pending;
+
+#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, Qnil);               \
+       Fsignal (Qquit, Qnil);                          \
+      }                                                        \
+    else if (interrupt_input_pending)                  \
+      handle_async_input ();                           \
+  } while (0)
+
+#else  /* not SYNC_INPUT */
+
 #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, Qnil);               \
        Fsignal (Qquit, Qnil);                          \
       }                                                        \
   } while (0)
 
+#endif /* not SYNC_INPUT */
+
+
 /* Nonzero if ought to quit now.  */
 
 #define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
@@ -1951,28 +2089,32 @@ extern Lisp_Object Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range;
 extern Lisp_Object Qvoid_variable, Qvoid_function;
 extern Lisp_Object Qsetting_constant, Qinvalid_read_syntax;
 extern Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch;
-extern Lisp_Object Qend_of_file, Qarith_error;
+extern Lisp_Object Qend_of_file, Qarith_error, Qmark_inactive;
 extern Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only;
-extern Lisp_Object Qmark_inactive, Qtext_read_only;
+extern Lisp_Object Qtext_read_only;
 
-extern Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
-extern Lisp_Object Qoverflow_error, Qunderflow_error;
-
-extern Lisp_Object Qintegerp, Qnumberp, Qnatnump, Qwholenump;
-extern Lisp_Object Qsymbolp, Qlistp, Qconsp;
+extern Lisp_Object Qintegerp, Qnatnump, Qwholenump, Qsymbolp, Qlistp, Qconsp;
 extern Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
-extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qvectorp;
-extern Lisp_Object Qinteger_or_marker_p, Qnumber_or_marker_p;
-extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
-extern Lisp_Object Qboundp, Qfboundp;
+extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
 extern Lisp_Object Qbuffer_or_string_p;
+extern Lisp_Object Qboundp, Qfboundp;
+extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
+
 extern Lisp_Object Qcdr;
 
-extern Lisp_Object Qfloatp, Qinteger_or_floatp, Qinteger_or_float_or_marker_p;
+extern Lisp_Object Qrange_error, Qdomain_error, Qsingularity_error;
+extern Lisp_Object Qoverflow_error, Qunderflow_error;
 
-extern Lisp_Object Qframep;
+extern Lisp_Object Qfloatp;
+extern Lisp_Object Qnumberp, Qnumber_or_marker_p;
+
+extern Lisp_Object Qinteger;
 
 extern void circular_list_error P_ ((Lisp_Object));
+EXFUN (Finteractive_form, 1);
+
+/* Defined in frame.c */
+extern Lisp_Object Qframep;
 
 EXFUN (Feq, 2);
 EXFUN (Fnull, 1);
@@ -2083,29 +2225,35 @@ EXFUN (Fread_coding_system, 2);
 EXFUN (Fread_non_nil_coding_system, 1);
 EXFUN (Ffind_operation_coding_system, MANY);
 EXFUN (Fupdate_coding_systems_internal, 0);
-EXFUN (Fencode_coding_string, 3);
-EXFUN (Fdecode_coding_string, 3);
-extern Lisp_Object detect_coding_system P_ ((const unsigned char *, int, int,
-                                            int));
+EXFUN (Fencode_coding_string, 4);
+EXFUN (Fdecode_coding_string, 4);
+extern Lisp_Object detect_coding_system P_ ((const unsigned char *, int,
+                                            int, int, int, Lisp_Object));
 extern void init_coding P_ ((void));
 extern void init_coding_once P_ ((void));
 extern void syms_of_coding P_ ((void));
-extern Lisp_Object code_convert_string_norecord P_ ((Lisp_Object, Lisp_Object,
-                                                    int));
+
+/* Defined in character.c */
+extern void init_character_once P_ ((void));
+extern void syms_of_character P_ ((void));
+EXFUN (Funibyte_char_to_multibyte, 1);
 
 /* Defined in charset.c */
-extern EMACS_INT nonascii_insert_offset;
-extern Lisp_Object Vnonascii_translation_table;
 EXFUN (Fchar_bytes, 1);
 EXFUN (Fchar_width, 1);
 EXFUN (Fstring, MANY);
 extern int chars_in_text P_ ((const unsigned char *, int));
 extern int multibyte_chars_in_text P_ ((const unsigned char *, int));
-extern int unibyte_char_to_multibyte P_ ((int));
 extern int multibyte_char_to_unibyte P_ ((int, Lisp_Object));
 extern Lisp_Object Qcharset;
+extern void init_charset P_ ((void));
 extern void init_charset_once P_ ((void));
 extern void syms_of_charset P_ ((void));
+/* Structure forward declarations.  */
+struct charset;
+
+/* Defined in composite.c */
+extern void syms_of_composite P_ ((void));
 
 /* Defined in syntax.c */
 EXFUN (Fforward_word, 1);
@@ -2123,9 +2271,8 @@ extern int next_almost_prime P_ ((int));
 extern Lisp_Object larger_vector P_ ((Lisp_Object, int, Lisp_Object));
 extern void sweep_weak_hash_tables P_ ((void));
 extern Lisp_Object Qstring_lessp;
-EXFUN (Foptimize_char_table, 1);
 extern Lisp_Object Vfeatures;
-extern Lisp_Object QCtest, QCweakness, Qequal;
+extern Lisp_Object QCtest, QCweakness, Qequal, Qeq;
 unsigned sxhash P_ ((Lisp_Object, int));
 Lisp_Object make_hash_table P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
                                 Lisp_Object, Lisp_Object, Lisp_Object,
@@ -2140,6 +2287,7 @@ void remove_hash_entry P_ ((struct Lisp_Hash_Table *, int));
 extern void init_fns P_ ((void));
 EXFUN (Fsxhash, 1);
 EXFUN (Fmake_hash_table, MANY);
+EXFUN (Fmakehash, 1);
 EXFUN (Fcopy_hash_table, 1);
 EXFUN (Fhash_table_count, 1);
 EXFUN (Fhash_table_rehash_size, 1);
@@ -2179,6 +2327,7 @@ EXFUN (Felt, 2);
 EXFUN (Fmember, 2);
 EXFUN (Frassq, 2);
 EXFUN (Fdelq, 2);
+EXFUN (Fdelete, 2);
 EXFUN (Fsort, 2);
 EXFUN (Freverse, 1);
 EXFUN (Fnreverse, 1);
@@ -2201,23 +2350,17 @@ extern void clear_string_char_byte_cache P_ ((void));
 extern int string_char_to_byte P_ ((Lisp_Object, int));
 extern int string_byte_to_char P_ ((Lisp_Object, int));
 extern Lisp_Object string_make_multibyte P_ ((Lisp_Object));
+extern Lisp_Object string_to_multibyte P_ ((Lisp_Object));
 extern Lisp_Object string_make_unibyte P_ ((Lisp_Object));
 EXFUN (Fcopy_alist, 1);
 EXFUN (Fplist_get, 2);
+EXFUN (Fsafe_plist_get, 2);
 EXFUN (Fplist_put, 3);
 EXFUN (Fplist_member, 2);
-EXFUN (Fset_char_table_parent, 2);
-EXFUN (Fchar_table_extra_slot, 2);
-EXFUN (Fset_char_table_extra_slot, 3);
 EXFUN (Frassoc, 2);
 EXFUN (Fstring_equal, 2);
 EXFUN (Fcompare_strings, 7);
 EXFUN (Fstring_lessp, 2);
-extern int char_table_translate P_ ((Lisp_Object, int));
-extern void map_char_table P_ ((void (*) (Lisp_Object, Lisp_Object, Lisp_Object),
-                               Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int,
-                               Lisp_Object *));
-extern Lisp_Object char_table_ref_and_index P_ ((Lisp_Object, int, int *));
 extern void syms_of_fns P_ ((void));
 
 /* Defined in floatfns.c */
@@ -2227,6 +2370,16 @@ EXFUN (Ftruncate, 2);
 extern void init_floatfns P_ ((void));
 extern void syms_of_floatfns P_ ((void));
 
+/* Defined in fringe.c */
+extern void syms_of_fringe P_ ((void));
+extern void init_fringe P_ ((void));
+extern void init_fringe_once P_ ((void));
+
+/* Defined in image.c */
+EXFUN (Finit_image_library, 2);
+extern void syms_of_image P_ ((void));
+extern void init_image P_ ((void));
+
 /* Defined in insdel.c */
 extern Lisp_Object Qinhibit_modification_hooks;
 extern void move_gap P_ ((int));
@@ -2240,6 +2393,7 @@ extern void insert P_ ((const unsigned char *, int));
 extern void insert_and_inherit P_ ((const unsigned char *, int));
 extern void insert_1 P_ ((const unsigned char *, int, int, int, int));
 extern void insert_1_both P_ ((const unsigned char *, int, int, int, int, int));
+extern void insert_from_gap P_ ((int, int));
 extern void insert_from_string P_ ((Lisp_Object, int, int, int, int, int));
 extern void insert_from_buffer P_ ((struct buffer *, int, int, int));
 extern void insert_char P_ ((int));
@@ -2260,6 +2414,7 @@ extern void adjust_after_replace P_ ((int, int, Lisp_Object, int, int));
 extern void adjust_after_replace_noundo P_ ((int, int, int, int, int, int));
 extern void adjust_after_insert P_ ((int, int, int, int, int));
 extern void replace_range P_ ((int, int, Lisp_Object, int, int, int));
+extern void replace_range_2 P_ ((int, int, int, int, char *, int, int, int));
 extern void syms_of_insdel P_ ((void));
 
 /* Defined in dispnew.c */
@@ -2280,6 +2435,7 @@ extern Lisp_Object Qinhibit_point_motion_hooks;
 extern Lisp_Object Qinhibit_redisplay, Qdisplay;
 extern Lisp_Object Qinhibit_eval_during_redisplay;
 extern Lisp_Object Qmessage_truncate_lines;
+extern Lisp_Object Qimage;
 extern Lisp_Object Vmessage_log_max;
 extern int message_enable_multibyte;
 extern Lisp_Object echo_area_buffer[2];
@@ -2310,14 +2466,14 @@ extern void redisplay P_ ((void));
 extern int check_point_in_composition
        P_ ((struct buffer *, int, struct buffer *, int));
 extern void redisplay_preserve_echo_area P_ ((int));
-extern void mark_window_display_accurate P_ ((Lisp_Object, int));
 extern void prepare_menu_bars P_ ((void));
 
 void set_frame_cursor_types P_ ((struct frame *, Lisp_Object));
 extern void syms_of_xdisp P_ ((void));
 extern void init_xdisp P_ ((void));
 extern Lisp_Object safe_eval P_ ((Lisp_Object));
-extern int pos_visible_p P_ ((struct window *, int, int *, int));
+extern int pos_visible_p P_ ((struct window *, int, int *,
+                             int *, int *, int));
 
 /* Defined in vm-limit.c.  */
 extern void memory_warnings P_ ((POINTER_TYPE *, void (*warnfun) ()));
@@ -2325,6 +2481,7 @@ extern void memory_warnings P_ ((POINTER_TYPE *, void (*warnfun) ()));
 /* Defined in alloc.c */
 extern void check_pure_size P_ ((void));
 extern void allocate_string_data P_ ((struct Lisp_String *, int, int));
+extern void reset_malloc_hooks P_ ((void));
 extern void uninterrupt_malloc P_ ((void));
 extern void malloc_warning P_ ((char *));
 extern void memory_full P_ ((void));
@@ -2362,8 +2519,6 @@ extern Lisp_Object make_pure_vector P_ ((EMACS_INT));
 EXFUN (Fgarbage_collect, 0);
 EXFUN (Fmake_byte_code, MANY);
 EXFUN (Fmake_bool_vector, 2);
-EXFUN (Fmake_char_table, 2);
-extern Lisp_Object make_sub_char_table P_ ((Lisp_Object));
 extern Lisp_Object Qchar_table_extra_slots;
 extern struct Lisp_Vector *allocate_vector P_ ((EMACS_INT));
 extern struct Lisp_Vector *allocate_other_vector P_ ((EMACS_INT));
@@ -2377,6 +2532,7 @@ extern Lisp_Object make_float P_ ((double));
 extern void display_malloc_warning P_ ((void));
 extern int inhibit_garbage_collection P_ ((void));
 extern Lisp_Object make_save_value P_ ((void *, int));
+extern void free_misc P_ ((Lisp_Object));
 extern void free_marker P_ ((Lisp_Object));
 extern void free_cons P_ ((struct Lisp_Cons *));
 extern void init_alloc_once P_ ((void));
@@ -2384,6 +2540,31 @@ extern void init_alloc P_ ((void));
 extern void syms_of_alloc P_ ((void));
 extern struct buffer * allocate_buffer P_ ((void));
 
+/* Defined in chartab.c */
+EXFUN (Fmake_char_table, 2);
+EXFUN (Fchar_table_parent, 1);
+EXFUN (Fset_char_table_parent, 2);
+EXFUN (Fchar_table_extra_slot, 2);
+EXFUN (Fset_char_table_extra_slot, 3);
+EXFUN (Fchar_table_range, 2);
+EXFUN (Fset_char_table_range, 3);
+EXFUN (Fset_char_table_default, 3);
+EXFUN (Foptimize_char_table, 1);
+EXFUN (Fmap_char_table, 2);
+extern Lisp_Object copy_char_table P_ ((Lisp_Object));
+extern Lisp_Object sub_char_table_ref P_ ((Lisp_Object, int));
+extern Lisp_Object char_table_ref P_ ((Lisp_Object, int));
+extern Lisp_Object char_table_ref_and_range P_ ((Lisp_Object, int,
+                                                int *, int *));
+extern Lisp_Object char_table_set P_ ((Lisp_Object, int, Lisp_Object));
+extern Lisp_Object char_table_set_range P_ ((Lisp_Object, int, int,
+                                            Lisp_Object));
+extern int char_table_translate P_ ((Lisp_Object, int));
+extern void map_char_table P_ ((void (*) (Lisp_Object, Lisp_Object,
+                                         Lisp_Object),
+                               Lisp_Object, Lisp_Object, Lisp_Object));
+extern void syms_of_chartab P_ ((void));
+
 /* Defined in print.c */
 extern Lisp_Object Vprin1_to_string_buffer;
 extern void debug_print P_ ((Lisp_Object));
@@ -2583,13 +2764,14 @@ EXFUN (Foverlay_start, 1);
 EXFUN (Foverlay_end, 1);
 extern void adjust_overlays_for_insert P_ ((EMACS_INT, EMACS_INT));
 extern void adjust_overlays_for_delete P_ ((EMACS_INT, EMACS_INT));
-extern void fix_overlays_in_range P_ ((int, int));
+extern void fix_start_end_in_overlays P_ ((int, int));
 extern void report_overlay_modification P_ ((Lisp_Object, Lisp_Object, int,
                                             Lisp_Object, Lisp_Object, Lisp_Object));
 extern int overlay_touches_p P_ ((int));
 extern Lisp_Object Vbuffer_alist, Vinhibit_read_only;
 EXFUN (Fget_buffer, 1);
 EXFUN (Fget_buffer_create, 1);
+EXFUN (Fgenerate_new_buffer_name, 2);
 EXFUN (Fset_buffer, 1);
 EXFUN (set_buffer_if_live, 1);
 EXFUN (Fbarf_if_buffer_read_only, 0);
@@ -2664,6 +2846,7 @@ extern void syms_of_fileio P_ ((void));
 EXFUN (Fmake_temp_name, 1);
 extern void init_fileio_once P_ ((void));
 extern Lisp_Object make_temp_name P_ ((Lisp_Object, int));
+EXFUN (Fmake_symbolic_link, 3);
 
 /* Defined in abbrev.c */
 
@@ -2680,6 +2863,7 @@ EXFUN (Fmatch_end, 1);
 EXFUN (Flooking_at, 1);
 extern int fast_string_match P_ ((Lisp_Object, Lisp_Object));
 extern int fast_c_string_match_ignore_case P_ ((Lisp_Object, const char *));
+extern int fast_string_match_ignore_case P_ ((Lisp_Object, Lisp_Object));
 extern int scan_buffer P_ ((int, int, int, int, int *, int));
 extern int scan_newline P_ ((int, int, int, int, int, int));
 extern int find_next_newline P_ ((int, int));
@@ -2692,7 +2876,7 @@ extern void syms_of_search P_ ((void));
 extern Lisp_Object last_minibuf_string;
 extern void choose_minibuf_frame P_ ((void));
 EXFUN (Fcompleting_read, 8);
-EXFUN (Fread_from_minibuffer, 7);
+EXFUN (Fread_from_minibuffer, 8);
 EXFUN (Fread_variable, 2);
 EXFUN (Fread_buffer, 3);
 EXFUN (Fread_minibuffer, 2);
@@ -2740,6 +2924,7 @@ extern struct kboard *echo_kboard;
 extern void cancel_echoing P_ ((void));
 extern Lisp_Object Qdisabled, QCfilter;
 extern Lisp_Object Vtty_erase_char, Vhelp_form, Vtop_level;
+extern Lisp_Object Vthrow_on_input;
 extern int input_pending;
 EXFUN (Fdiscard_input, 0);
 EXFUN (Frecursive_edit, 0);
@@ -2777,6 +2962,10 @@ extern int indented_beyond_p P_ ((int, int, double));
 extern void syms_of_indent P_ ((void));
 
 /* defined in frame.c */
+#ifdef HAVE_WINDOW_SYSTEM
+extern Lisp_Object Vx_resource_name;
+extern Lisp_Object Vx_resource_class;
+#endif /* HAVE_WINDOW_SYSTEM */
 extern Lisp_Object Qvisible;
 extern void store_frame_param P_ ((struct frame *, Lisp_Object, Lisp_Object));
 extern void store_in_alist P_ ((Lisp_Object *, Lisp_Object, Lisp_Object));
@@ -2848,7 +3037,10 @@ EXFUN (Fprocess_send_eof, 1);
 EXFUN (Fwaiting_for_user_input_p, 0);
 extern Lisp_Object Qprocessp;
 extern void kill_buffer_processes P_ ((Lisp_Object));
-extern int wait_reading_process_input P_ ((int, int, Lisp_Object, int));
+extern int wait_reading_process_output P_ ((int, int, int, int,
+                                           Lisp_Object,
+                                           struct Lisp_Process *,
+                                           int));
 extern void deactivate_process P_ ((Lisp_Object));
 extern void add_keyboard_wait_descriptor P_ ((int));
 extern void delete_keyboard_wait_descriptor P_ ((int));
@@ -2898,7 +3090,7 @@ extern void syms_of_macros P_ ((void));
 /* defined in undo.c */
 extern Lisp_Object Qinhibit_read_only;
 EXFUN (Fundo_boundary, 0);
-extern Lisp_Object truncate_undo_list P_ ((Lisp_Object, int, int));
+extern Lisp_Object truncate_undo_list P_ ((Lisp_Object, int, int, int));
 extern void record_marker_adjustment P_ ((Lisp_Object, int));
 extern void record_insert P_ ((int, int));
 extern void record_delete P_ ((int, Lisp_Object));
@@ -2914,6 +3106,7 @@ extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks;
 EXFUN (Fnext_single_property_change, 4);
 EXFUN (Fnext_single_char_property_change, 4);
 EXFUN (Fprevious_single_property_change, 4);
+EXFUN (Fget_text_property, 3);
 EXFUN (Fput_text_property, 5);
 EXFUN (Fprevious_char_property_change, 2);
 EXFUN (Fnext_char_property_change, 2);
@@ -2969,13 +3162,14 @@ extern void init_sound P_ ((void));
 
 /* Defined in category.c */
 extern void init_category_once P_ ((void));
+extern Lisp_Object char_category_set P_ ((int));
 extern void syms_of_category P_ ((void));
 
 /* Defined in ccl.c */
 extern void syms_of_ccl P_ ((void));
 
 /* Defined in dired.c */
-EXFUN (Ffile_attributes, 1);
+EXFUN (Ffile_attributes, 2);
 extern void syms_of_dired P_ ((void));
 
 /* Defined in term.c */
@@ -2985,7 +3179,8 @@ extern void fatal () NO_RETURN;
 #ifdef HAVE_X_WINDOWS
 /* Defined in fontset.c */
 extern void syms_of_fontset P_ ((void));
-EXFUN (Fset_fontset_font, 4);
+EXFUN (Fset_fontset_font, 5);
+EXFUN (Fnew_fontset, 2);
 #endif
 
 /* Defined in xfaces.c */
@@ -2997,12 +3192,12 @@ extern int getloadavg P_ ((double *, int));
 #ifdef HAVE_X_WINDOWS
 /* Defined in xfns.c */
 extern void syms_of_xfns P_ ((void));
-extern void init_xfns P_ ((void));
-extern Lisp_Object Vx_resource_name;
-extern Lisp_Object Vx_resource_class;
-EXFUN (Fxw_display_color_p, 1);
-EXFUN (Fx_file_dialog, 4);
 #endif /* HAVE_X_WINDOWS */
+#ifdef HAVE_WINDOW_SYSTEM
+/* Defined in xfns.c, w32fns.c, or macfns.c */
+EXFUN (Fxw_display_color_p, 1);
+EXFUN (Fx_file_dialog, 5);
+#endif /* HAVE_WINDOW_SYSTEM */
 
 /* Defined in xsmfns.c */
 extern void syms_of_xsmfns P_ ((void));
@@ -3015,6 +3210,11 @@ extern void syms_of_xterm P_ ((void));
 
 /* Defined in getloadavg.c */
 extern int getloadavg P_ ((double [], int));
+
+#ifdef MSDOS
+/* Defined in msdos.c */
+EXFUN (Fmsdos_downcase_filename, 1);
+#endif
 \f
 /* Nonzero means Emacs has already been initialized.
    Used during startup to detect startup of dumped Emacs.  */
@@ -3028,9 +3228,7 @@ extern void xfree P_ ((POINTER_TYPE *));
 
 extern char *xstrdup P_ ((const char *));
 
-#ifndef USE_CRT_DLL
 extern char *egetenv P_ ((char *));
-#endif
 
 /* Set up the name of the machine we're running on.  */
 extern void init_system_name P_ ((void));
@@ -3111,6 +3309,87 @@ extern Lisp_Object Vdirectory_sep_char;
     ? make_float (val) \
     : make_number ((EMACS_INT)(val)))
 
+
+/* Checks the `cycle check' variable CHECK to see if it indicates that
+   EL is part of a cycle; CHECK must be either Qnil or a value returned
+   by an earlier use of CYCLE_CHECK.  SUSPICIOUS is the number of
+   elements after which a cycle might be suspected; after that many
+   elements, this macro begins consing in order to keep more precise
+   track of elements.
+
+   Returns nil if a cycle was detected, otherwise a new value for CHECK
+   that includes EL.
+
+   CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
+   the caller should make sure that's ok.  */
+
+#define CYCLE_CHECK(check, el, suspicious)     \
+  (NILP (check)                                        \
+   ? make_number (0)                           \
+   : (INTEGERP (check)                         \
+      ? (XFASTINT (check) < (suspicious)       \
+        ? make_number (XFASTINT (check) + 1)   \
+        : Fcons (el, Qnil))                    \
+      : (!NILP (Fmemq ((el), (check)))         \
+        ? Qnil                                 \
+        : Fcons ((el), (check)))))
+
+
+/* SAFE_ALLOCA normally allocates memory on the stack, but if size is
+   larger than MAX_ALLOCA, use xmalloc to avoid overflowing the stack.  */
+
+#define MAX_ALLOCA 16*1024
+
+extern Lisp_Object safe_alloca_unwind (Lisp_Object);
+
+#define USE_SAFE_ALLOCA                        \
+  int sa_count = SPECPDL_INDEX (), sa_must_free = 0
+
+/* SAFE_ALLOCA allocates a simple buffer.  */
+
+#define SAFE_ALLOCA(buf, type, size)                     \
+  do {                                                   \
+    if ((size) < MAX_ALLOCA)                             \
+      buf = (type) alloca (size);                        \
+    else                                                 \
+      {                                                          \
+       buf = (type) xmalloc (size);                      \
+       sa_must_free++;                                   \
+       record_unwind_protect (safe_alloca_unwind,        \
+                              make_save_value (buf, 0)); \
+      }                                                          \
+  } while (0)
+
+/* SAFE_FREE frees xmalloced memory and enables GC as needed.  */
+
+#define SAFE_FREE()                    \
+  do {                                 \
+    if (sa_must_free) {                        \
+      sa_must_free = 0;                        \
+      unbind_to (sa_count, Qnil);      \
+    }                                  \
+  } while (0)
+
+
+/* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects.  */
+
+#define SAFE_ALLOCA_LISP(buf, nelt)                      \
+  do {                                                   \
+    int size_ = (nelt) * sizeof (Lisp_Object);           \
+    if (size_ < MAX_ALLOCA)                              \
+      buf = (Lisp_Object *) alloca (size_);              \
+    else                                                 \
+      {                                                          \
+       Lisp_Object arg_;                                 \
+       buf = (Lisp_Object *) xmalloc (size_);            \
+       arg_ = make_save_value (buf, nelt);               \
+       XSAVE_VALUE (arg_)->dogc = 1;                     \
+       sa_must_free++;                                   \
+       record_unwind_protect (safe_alloca_unwind, arg_); \
+      }                                                          \
+  } while (0)
+
+
 #endif /* EMACS_LISP_H */
 
 /* arch-tag: 9b2ed020-70eb-47ac-94ee-e1c2a5107d5e