]> code.delx.au - gnu-emacs/blobdiff - src/lisp.h
Pacify gcc -Wparentheses
[gnu-emacs] / src / lisp.h
index 82a99fcca343bea60a9b0a8b4c5b9cdc2875ed8f..8d44b972717f2b22946d04478319fc24ce5440ab 100644 (file)
@@ -1,6 +1,6 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
 
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1987, 1993-1995, 1997-2014 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1997-2015 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
 Inc.
 
 This file is part of GNU Emacs.
@@ -44,12 +44,13 @@ INLINE_HEADER_BEGIN
    definitions or enums visible to the debugger.  It's used for symbols
    that .gdbinit needs.  */
 
    definitions or enums visible to the debugger.  It's used for symbols
    that .gdbinit needs.  */
 
+#define DECLARE_GDB_SYM(type, id) type const id EXTERNALLY_VISIBLE
 #ifdef MAIN_PROGRAM
 #ifdef MAIN_PROGRAM
-# define DEFINE_GDB_SYMBOL_BEGIN(type, id) type const id EXTERNALLY_VISIBLE
+# define DEFINE_GDB_SYMBOL_BEGIN(type, id) DECLARE_GDB_SYM (type, id)
 # define DEFINE_GDB_SYMBOL_END(id) = id;
 #else
 # define DEFINE_GDB_SYMBOL_END(id) = id;
 #else
-# define DEFINE_GDB_SYMBOL_BEGIN(type, id)
-# define DEFINE_GDB_SYMBOL_END(val)
+# define DEFINE_GDB_SYMBOL_BEGIN(type, id) extern DECLARE_GDB_SYM (type, id)
+# define DEFINE_GDB_SYMBOL_END(val) ;
 #endif
 
 /* The ubiquitous max and min macros.  */
 #endif
 
 /* The ubiquitous max and min macros.  */
@@ -257,16 +258,17 @@ enum Lisp_Bits
 
 /* The maximum value that can be stored in a EMACS_INT, assuming all
    bits other than the type bits contribute to a nonnegative signed value.
 
 /* The maximum value that can be stored in a EMACS_INT, assuming all
    bits other than the type bits contribute to a nonnegative signed value.
-   This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below.  */
+   This can be used in #if, e.g., '#if USB_TAG' below expands to an
+   expression involving VAL_MAX.  */
 #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1))
 
 /* Whether the least-significant bits of an EMACS_INT contain the tag.
 #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1))
 
 /* Whether the least-significant bits of an EMACS_INT contain the tag.
-   On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is:
+   On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is:
     a. unnecessary, because the top bits of an EMACS_INT are unused, and
     b. slower, because it typically requires extra masking.
    So, USE_LSB_TAG is true only on hosts where it might be useful.  */
 DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG)
     a. unnecessary, because the top bits of an EMACS_INT are unused, and
     b. slower, because it typically requires extra masking.
    So, USE_LSB_TAG is true only on hosts where it might be useful.  */
 DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG)
-#define USE_LSB_TAG (EMACS_INT_MAX >> GCTYPEBITS < INTPTR_MAX)
+#define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX)
 DEFINE_GDB_SYMBOL_END (USE_LSB_TAG)
 
 #if !USE_LSB_TAG && !defined WIDE_EMACS_INT
 DEFINE_GDB_SYMBOL_END (USE_LSB_TAG)
 
 #if !USE_LSB_TAG && !defined WIDE_EMACS_INT
@@ -282,17 +284,7 @@ error !;
 # endif
 #endif
 
 # endif
 #endif
 
-/* This should work with GCC.  Clang has known problems; see
-   http://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00506.html.  */
-#ifndef USE_STACK_LISP_OBJECTS
-# if defined __GNUC__ && !defined __clang__
-#  define USE_STACK_LISP_OBJECTS true
-# else
-#  define USE_STACK_LISP_OBJECTS false
-# endif
-#endif
-
-#if defined HAVE_STRUCT_ATTRIBUTE_ALIGNED && USE_STACK_LISP_OBJECTS
+#ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED
 # define GCALIGNED __attribute__ ((aligned (GCALIGNMENT)))
 #else
 # define GCALIGNED /* empty */
 # define GCALIGNED __attribute__ ((aligned (GCALIGNMENT)))
 #else
 # define GCALIGNED /* empty */
@@ -346,7 +338,7 @@ error !;
 #define lisp_h_CONSP(x) (XTYPE (x) == Lisp_Cons)
 #define lisp_h_EQ(x, y) (XLI (x) == XLI (y))
 #define lisp_h_FLOATP(x) (XTYPE (x) == Lisp_Float)
 #define lisp_h_CONSP(x) (XTYPE (x) == Lisp_Cons)
 #define lisp_h_EQ(x, y) (XLI (x) == XLI (y))
 #define lisp_h_FLOATP(x) (XTYPE (x) == Lisp_Float)
-#define lisp_h_INTEGERP(x) ((XTYPE (x) & ~Lisp_Int1) == 0)
+#define lisp_h_INTEGERP(x) ((XTYPE (x) & (Lisp_Int0 | ~Lisp_Int1)) == Lisp_Int0)
 #define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 #define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc)
 #define lisp_h_NILP(x) EQ (x, Qnil)
 #define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 #define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc)
 #define lisp_h_NILP(x) EQ (x, Qnil)
@@ -370,7 +362,7 @@ error !;
 #endif
 #if USE_LSB_TAG
 # define lisp_h_make_number(n) \
 #endif
 #if USE_LSB_TAG
 # define lisp_h_make_number(n) \
-    XIL ((EMACS_INT) ((EMACS_UINT) (n) << INTTYPEBITS))
+    XIL ((EMACS_INT) (((EMACS_UINT) (n) << INTTYPEBITS) + Lisp_Int0))
 # define lisp_h_XFASTINT(a) XINT (a)
 # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS)
 # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
 # define lisp_h_XFASTINT(a) XINT (a)
 # define lisp_h_XINT(a) (XLI (a) >> INTTYPEBITS)
 # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
@@ -582,7 +574,73 @@ typedef EMACS_INT Lisp_Object;
 #define LISP_INITIALLY_ZERO 0
 enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
 #endif /* CHECK_LISP_OBJECT_TYPE */
 #define LISP_INITIALLY_ZERO 0
 enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
 #endif /* CHECK_LISP_OBJECT_TYPE */
+\f
+/* Forward declarations.  */
+
+/* Defined in this file.  */
+union Lisp_Fwd;
+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);
+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);
+extern void char_table_set (Lisp_Object, int, Lisp_Object);
+
+/* Defined in data.c.  */
+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, Qt, Qvectorp;
+extern Lisp_Object Qbool_vector_p;
+extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
+extern Lisp_Object Qwindow;
+extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object);
+extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object);
+
+/* Defined in emacs.c.  */
+extern bool might_dump;
+/* True means Emacs has already been initialized.
+   Used during startup to detect startup of dumped Emacs.  */
+extern bool initialized;
+
+/* Defined in eval.c.  */
+extern Lisp_Object Qautoload;
+
+/* Defined in floatfns.c.  */
+extern double extract_float (Lisp_Object);
+
+/* Defined in process.c.  */
+extern Lisp_Object Qprocessp;
+
+/* Defined in window.c.  */
+extern Lisp_Object Qwindowp;
 
 
+/* Defined in xdisp.c.  */
+extern Lisp_Object Qimage;
+extern Lisp_Object Qfontification_functions;
+\f
 /* Convert a Lisp_Object to the corresponding EMACS_INT and vice versa.
    At the machine level, these operations are no-ops.  */
 LISP_MACRO_DEFUN (XLI, EMACS_INT, (Lisp_Object o), (o))
 /* Convert a Lisp_Object to the corresponding EMACS_INT and vice versa.
    At the machine level, these operations are no-ops.  */
 LISP_MACRO_DEFUN (XLI, EMACS_INT, (Lisp_Object o), (o))
@@ -682,13 +740,18 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type))
 INLINE Lisp_Object
 make_number (EMACS_INT n)
 {
 INLINE Lisp_Object
 make_number (EMACS_INT n)
 {
+  EMACS_INT int0 = Lisp_Int0;
   if (USE_LSB_TAG)
     {
       EMACS_UINT u = n;
       n = u << INTTYPEBITS;
   if (USE_LSB_TAG)
     {
       EMACS_UINT u = n;
       n = u << INTTYPEBITS;
+      n += int0;
     }
   else
     }
   else
-    n &= INTMASK;
+    {
+      n &= INTMASK;
+      n += (int0 << VALBITS);
+    }
   return XIL (n);
 }
 
   return XIL (n);
 }
 
@@ -711,7 +774,8 @@ XINT (Lisp_Object a)
 INLINE EMACS_INT
 XFASTINT (Lisp_Object a)
 {
 INLINE EMACS_INT
 XFASTINT (Lisp_Object a)
 {
-  EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a);
+  EMACS_INT int0 = Lisp_Int0;
+  EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a) - (int0 << VALBITS);
   eassert (0 <= n);
   return n;
 }
   eassert (0 <= n);
   return n;
 }
@@ -756,7 +820,8 @@ INLINE Lisp_Object
 make_natnum (EMACS_INT n)
 {
   eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM);
 make_natnum (EMACS_INT n)
 {
   eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM);
-  return USE_LSB_TAG ? make_number (n) : XIL (n);
+  EMACS_INT int0 = Lisp_Int0;
+  return USE_LSB_TAG ? make_number (n) : XIL (n + (int0 << VALBITS));
 }
 
 /* Return true if X and Y are the same object.  */
 }
 
 /* Return true if X and Y are the same object.  */
@@ -775,71 +840,6 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
   return num < lower ? lower : num <= upper ? num : upper;
 }
 \f
   return num < lower ? lower : num <= upper ? num : upper;
 }
 \f
-/* Forward declarations.  */
-
-/* Defined in this file.  */
-union Lisp_Fwd;
-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);
-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);
-extern void char_table_set (Lisp_Object, int, Lisp_Object);
-
-/* Defined in data.c.  */
-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, Qt, Qvectorp;
-extern Lisp_Object Qbool_vector_p;
-extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
-extern Lisp_Object Qwindow;
-extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object);
-extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object);
-
-/* Defined in emacs.c.  */
-extern bool might_dump;
-/* True means Emacs has already been initialized.
-   Used during startup to detect startup of dumped Emacs.  */
-extern bool initialized;
-
-/* Defined in eval.c.  */
-extern Lisp_Object Qautoload;
-
-/* Defined in floatfns.c.  */
-extern double extract_float (Lisp_Object);
-
-/* Defined in process.c.  */
-extern Lisp_Object Qprocessp;
-
-/* Defined in window.c.  */
-extern Lisp_Object Qwindowp;
-
-/* Defined in xdisp.c.  */
-extern Lisp_Object Qimage;
-\f
 
 /* Extract a value or address from a Lisp_Object.  */
 
 
 /* Extract a value or address from a Lisp_Object.  */
 
@@ -1082,7 +1082,7 @@ CDR_SAFE (Lisp_Object c)
 
 /* In a string or vector, the sign bit of the `size' is the gc mark bit.  */
 
 
 /* In a string or vector, the sign bit of the `size' is the gc mark bit.  */
 
-struct Lisp_String
+struct GCALIGNED Lisp_String
   {
     ptrdiff_t size;
     ptrdiff_t size_byte;
   {
     ptrdiff_t size;
     ptrdiff_t size_byte;
@@ -3699,8 +3699,6 @@ extern Lisp_Object make_uninit_bool_vector (EMACS_INT);
 extern Lisp_Object bool_vector_fill (Lisp_Object, Lisp_Object);
 extern _Noreturn void string_overflow (void);
 extern Lisp_Object make_string (const char *, ptrdiff_t);
 extern Lisp_Object bool_vector_fill (Lisp_Object, Lisp_Object);
 extern _Noreturn void string_overflow (void);
 extern Lisp_Object make_string (const char *, ptrdiff_t);
-extern Lisp_Object local_string_init (struct Lisp_String *, char const *,
-                                     ptrdiff_t);
 extern Lisp_Object make_formatted_string (char *, const char *, ...)
   ATTRIBUTE_FORMAT_PRINTF (2, 3);
 extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t);
 extern Lisp_Object make_formatted_string (char *, const char *, ...)
   ATTRIBUTE_FORMAT_PRINTF (2, 3);
 extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t);
@@ -3789,8 +3787,6 @@ extern struct Lisp_Hash_Table *allocate_hash_table (void);
 extern struct window *allocate_window (void);
 extern struct frame *allocate_frame (void);
 extern struct Lisp_Process *allocate_process (void);
 extern struct window *allocate_window (void);
 extern struct frame *allocate_frame (void);
 extern struct Lisp_Process *allocate_process (void);
-extern Lisp_Object local_vector_init (struct Lisp_Vector *, ptrdiff_t,
-                                     Lisp_Object);
 extern struct terminal *allocate_terminal (void);
 extern bool gc_in_progress;
 extern bool abort_on_gc;
 extern struct terminal *allocate_terminal (void);
 extern bool gc_in_progress;
 extern bool abort_on_gc;
@@ -3877,7 +3873,7 @@ extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t,
   ATTRIBUTE_FORMAT_PRINTF (5, 0);
 
 /* Defined in lread.c.  */
   ATTRIBUTE_FORMAT_PRINTF (5, 0);
 
 /* Defined in lread.c.  */
-extern Lisp_Object Qvariable_documentation, Qstandard_input;
+extern Lisp_Object Qsize, Qvariable_documentation, Qstandard_input;
 extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
 extern Lisp_Object Qlexical_binding;
 extern Lisp_Object check_obarray (Lisp_Object);
 extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
 extern Lisp_Object Qlexical_binding;
 extern Lisp_Object check_obarray (Lisp_Object);
@@ -4004,7 +4000,6 @@ extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
                                            ptrdiff_t, bool);
 extern void init_editfns (void);
 extern void syms_of_editfns (void);
                                            ptrdiff_t, bool);
 extern void init_editfns (void);
 extern void syms_of_editfns (void);
-extern void set_time_zone_rule (const char *);
 
 /* Defined in buffer.c.  */
 extern bool mouse_face_overlay_overlaps (Lisp_Object);
 
 /* Defined in buffer.c.  */
 extern bool mouse_face_overlay_overlaps (Lisp_Object);
@@ -4081,6 +4076,7 @@ extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
 extern ptrdiff_t scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, bool);
                               ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
 extern ptrdiff_t scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, bool);
+extern ptrdiff_t scan_newline_from_point (ptrdiff_t, ptrdiff_t *, ptrdiff_t *);
 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,
 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,
@@ -4412,6 +4408,7 @@ extern void syms_of_xsmfns (void);
 extern void syms_of_xselect (void);
 
 /* Defined in xterm.c.  */
 extern void syms_of_xselect (void);
 
 /* Defined in xterm.c.  */
+extern void init_xterm (void);
 extern void syms_of_xterm (void);
 #endif /* HAVE_X_WINDOWS */
 
 extern void syms_of_xterm (void);
 #endif /* HAVE_X_WINDOWS */
 
@@ -4433,6 +4430,7 @@ extern void syms_of_decompress (void);
 
 #ifdef HAVE_DBUS
 /* Defined in dbusbind.c.  */
 
 #ifdef HAVE_DBUS
 /* Defined in dbusbind.c.  */
+void init_dbusbind (void);
 void syms_of_dbusbind (void);
 #endif
 
 void syms_of_dbusbind (void);
 #endif
 
@@ -4596,172 +4594,111 @@ lisp_word_count (ptrdiff_t nbytes)
 
 
 /* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate
 
 
 /* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate
-   block-scoped conses and function-scoped vectors and strings.  These objects
-   are not managed by the garbage collector, so they are dangerous: passing
-   them out of their scope (e.g., to user code) results in undefined behavior.
+   block-scoped conses and strings.  These objects are not
+   managed by the garbage collector, so they are dangerous: passing them
+   out of their scope (e.g., to user code) results in undefined behavior.
    Conversely, they have better performance because GC is not involved.
 
    Conversely, they have better performance because GC is not involved.
 
-   This feature is experimental and requires careful debugging.  It's enabled
-   by default if GCC or a compiler that mimics GCC well (like Intel C/C++) is
-   used, except clang (see notice above).  For other compilers, brave users can
-   compile with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS' to get into the game.
-   Note that this feature requires GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS.  */
+   This feature is experimental and requires careful debugging.
+   Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it.  */
 
 
-/* A struct Lisp_Cons inside a union that is no larger and may be
-   better-aligned.  */
+#ifndef USE_STACK_LISP_OBJECTS
+# define USE_STACK_LISP_OBJECTS true
+#endif
+
+/* USE_STACK_LISP_OBJECTS requires GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS.  */
+
+#if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS
+# undef USE_STACK_LISP_OBJECTS
+# define USE_STACK_LISP_OBJECTS false
+#endif
+
+#ifdef GC_CHECK_STRING_BYTES
+enum { defined_GC_CHECK_STRING_BYTES = true };
+#else
+enum { defined_GC_CHECK_STRING_BYTES = false };
+#endif
+
+/* Struct inside unions that are typically no larger and aligned enough.  */
 
 union Aligned_Cons
 {
   struct Lisp_Cons s;
   double d; intmax_t i; void *p;
 };
 
 union Aligned_Cons
 {
   struct Lisp_Cons s;
   double d; intmax_t i; void *p;
 };
-verify (sizeof (struct Lisp_Cons) == sizeof (union Aligned_Cons));
-
-/* Allocate a block-scoped cons.  */
-
-#define scoped_cons(car, cdr)                                          \
-   ((USE_STACK_LISP_OBJECTS                                            \
-     && alignof (union Aligned_Cons) % GCALIGNMENT == 0)               \
-    ? make_lisp_ptr (&((union Aligned_Cons) {{car, {cdr}}}).s, Lisp_Cons) \
-    : Fcons (car, cdr))
-
-/* Convenient utility macros similar to listX functions.  */
-
-#if USE_STACK_LISP_OBJECTS
-# define scoped_list1(a) scoped_cons (a, Qnil)
-# define scoped_list2(a, b) scoped_cons (a, scoped_list1 (b))
-# define scoped_list3(a, b, c) scoped_cons (a, scoped_list2 (b, c))
-# define scoped_list4(a, b, c, d) scoped_cons (a, scoped_list3 (b, c, d))
-#else
-# define scoped_list1(a) list1 (a)
-# define scoped_list2(a, b) list2 (a, b)
-# define scoped_list3(a, b, c) list3 (a, b, c)
-# define scoped_list4(a, b, c, d) list4 (a, b, c, d)
-#endif
 
 
-/* Local allocators require both statement expressions and a
-   GCALIGNMENT-aligned alloca.  clang's alloca isn't properly aligned
-   in some cases.  In the absence of solid information, play it safe
-   for other non-GCC compilers.  */
-#if (USE_STACK_LISP_OBJECTS && HAVE_STATEMENT_EXPRESSIONS \
-     && __GNUC__ && !__clang__)
-# define USE_LOCAL_ALLOCATORS
-#endif
+union Aligned_String
+{
+  struct Lisp_String s;
+  double d; intmax_t i; void *p;
+};
 
 
-/* Any function that uses a local allocator should start with either
-   'USE_SAFE_ALLOCA; or 'USE_LOCAL_ALLOCA;' (but not both).  */
-#ifdef USE_LOCAL_ALLOCATORS
-# define USE_LOCAL_ALLOCA ptrdiff_t sa_avail = MAX_ALLOCA
-#else
-# define USE_LOCAL_ALLOCA
-#endif
+/* True for stack-based cons and string implementations, respectively.
+   Use stack-based strings only if stack-based cons also works.
+   Otherwise, STACK_CONS would create heap-based cons cells that
+   could point to stack-based strings, which is a no-no.  */
 
 
-#ifdef USE_LOCAL_ALLOCATORS
-
-/* Return a function-scoped cons whose car is X and cdr is Y.  */
-
-# define local_cons(x, y)                                              \
-    (sizeof (struct Lisp_Cons) <= sa_avail                             \
-     ? ({                                                              \
-         struct Lisp_Cons *c_ = AVAIL_ALLOCA (sizeof (struct Lisp_Cons)); \
-         c_->car = (x);                                                \
-         c_->u.cdr = (y);                                              \
-         make_lisp_ptr (c_, Lisp_Cons);                                \
-       })                                                              \
-     : Fcons (x, y))
-
-# define local_list1(a) local_cons (a, Qnil)
-# define local_list2(a, b) local_cons (a, local_list1 (b))
-# define local_list3(a, b, c) local_cons (a, local_list2 (b, c))
-# define local_list4(a, b, c, d) local_cons (a, local_list3 (b, c, d))
-
-/* Return a function-scoped vector of length SIZE, with each element
-   being INIT.  */
-
-# define make_local_vector(size, init)                                 \
-    ({                                                                 \
-       ptrdiff_t size_ = size;                                         \
-       Lisp_Object vec_;                                               \
-       if (size_ <= lisp_word_count (sa_avail - header_size))          \
-        {                                                              \
-          void *ptr_ = AVAIL_ALLOCA (size_ * word_size + header_size); \
-          vec_ = local_vector_init (ptr_, size_, init);                \
-        }                                                              \
-       else                                                            \
-        vec_ = Fmake_vector (make_number (size_), init);               \
-       vec_;                                                           \
-    })
-
-enum { LISP_STRING_OVERHEAD = sizeof (struct Lisp_String) + 1 };
-
-/* Return a function-scoped string with contents DATA and length NBYTES.  */
-
-# define make_local_string(data, nbytes)                               \
-    ({                                                                 \
-       ptrdiff_t nbytes_ = nbytes;                                     \
-       Lisp_Object string_;                                            \
-       if (nbytes_ <= sa_avail - LISP_STRING_OVERHEAD)                 \
-        {                                                              \
-          struct Lisp_String *ptr_ = AVAIL_ALLOCA (LISP_STRING_OVERHEAD \
-                                                   + nbytes_);         \
-          string_ = local_string_init (ptr_, data, nbytes_);           \
-        }                                                              \
-       else                                                            \
-        string_ = make_string (data, nbytes_);                         \
-       string_;                                                                \
-    })
-
-/* Return a function-scoped string with contents DATA.  */
-
-# define build_local_string(data)                      \
-    ({ char const *data1_ = (data);                    \
-       make_local_string (data1_, strlen (data1_)); })
+enum
+  {
+    USE_STACK_CONS = (USE_STACK_LISP_OBJECTS
+                     && alignof (union Aligned_Cons) % GCALIGNMENT == 0),
+    USE_STACK_STRING = (USE_STACK_CONS
+                       && !defined_GC_CHECK_STRING_BYTES
+                       && alignof (union Aligned_String) % GCALIGNMENT == 0)
+  };
 
 
+/* Auxiliary macros used for auto allocation of Lisp objects.  Please
+   use these only in macros like AUTO_CONS that declare a local
+   variable whose lifetime will be clear to the programmer.  */
+#define STACK_CONS(a, b) \
+  make_lisp_ptr (&(union Aligned_Cons) { { a, { b } } }.s, Lisp_Cons)
+#define AUTO_CONS_EXPR(a, b) \
+  (USE_STACK_CONS ? STACK_CONS (a, b) : Fcons (a, b))
+
+/* Declare NAME as an auto Lisp cons or short list if possible, a
+   GC-based one otherwise.  This is in the sense of the C keyword
+   'auto'; i.e., the object has the lifetime of the containing block.
+   The resulting object should not be made visible to user Lisp code.  */
+
+#define AUTO_CONS(name, a, b) Lisp_Object name = AUTO_CONS_EXPR (a, b)
+#define AUTO_LIST1(name, a)                                            \
+  Lisp_Object name = (USE_STACK_CONS ? STACK_CONS (a, Qnil) : list1 (a))
+#define AUTO_LIST2(name, a, b)                                         \
+  Lisp_Object name = (USE_STACK_CONS                                   \
+                     ? STACK_CONS (a, STACK_CONS (b, Qnil))            \
+                     : list2 (a, b))
+#define AUTO_LIST3(name, a, b, c)                                      \
+  Lisp_Object name = (USE_STACK_CONS                                   \
+                     ? STACK_CONS (a, STACK_CONS (b, STACK_CONS (c, Qnil))) \
+                     : list3 (a, b, c))
+#define AUTO_LIST4(name, a, b, c, d)                                   \
+    Lisp_Object name                                                   \
+      = (USE_STACK_CONS                                                        \
+        ? STACK_CONS (a, STACK_CONS (b, STACK_CONS (c,                 \
+                                                    STACK_CONS (d, Qnil)))) \
+        : list4 (a, b, c, d))
+
+/* Check whether stack-allocated strings are ASCII-only.  */
+
+#if defined (ENABLE_CHECKING) && USE_STACK_LISP_OBJECTS
+extern const char *verify_ascii (const char *);
 #else
 #else
-
-/* Safer but slower implementations.  */
-INLINE Lisp_Object
-local_cons (Lisp_Object car, Lisp_Object cdr)
-{
-  return Fcons (car, cdr);
-}
-INLINE Lisp_Object
-local_list1 (Lisp_Object a)
-{
-  return list1 (a);
-}
-INLINE Lisp_Object
-local_list2 (Lisp_Object a, Lisp_Object b)
-{
-  return list2 (a, b);
-}
-INLINE Lisp_Object
-local_list3 (Lisp_Object a, Lisp_Object b, Lisp_Object c)
-{
-  return list3 (a, b, c);
-}
-INLINE Lisp_Object
-local_list4 (Lisp_Object a, Lisp_Object b, Lisp_Object c, Lisp_Object d)
-{
-  return list4 (a, b, c, d);
-}
-INLINE Lisp_Object
-make_local_vector (ptrdiff_t size, Lisp_Object init)
-{
-  return Fmake_vector (make_number (size), init);
-}
-INLINE Lisp_Object
-make_local_string (char const *str, ptrdiff_t nbytes)
-{
-  return make_string (str, nbytes);
-}
-INLINE Lisp_Object
-build_local_string (const char *str)
-{
-  return build_string (str);
-}
+# define verify_ascii(str) (str)
 #endif
 
 #endif
 
+/* Declare NAME as an auto Lisp string if possible, a GC-based one if not.
+   Take its value from STR.  STR is not necessarily copied and should
+   contain only ASCII characters.  The resulting Lisp string should
+   not be modified or made visible to user code.  */
+
+#define AUTO_STRING(name, str)                                         \
+  Lisp_Object name =                                                   \
+    (USE_STACK_STRING                                                  \
+     ? (make_lisp_ptr                                                  \
+       ((&(union Aligned_String)                                       \
+         {{strlen (str), -1, 0, (unsigned char *) verify_ascii (str)}}.s), \
+         Lisp_String))                                                 \
+     : build_string (verify_ascii (str)))
 
 /* Loop over all tails of a list, checking for cycles.
    FIXME: Make tortoise and n internal declarations.
 
 /* Loop over all tails of a list, checking for cycles.
    FIXME: Make tortoise and n internal declarations.