diff options
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 2498 |
1 files changed, 1376 insertions, 1122 deletions
diff --git a/src/lisp.h b/src/lisp.h index f57b21ffbdc..8f61f486924 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1,6 +1,6 @@ -/* Fundamental definitions for GNU Emacs Lisp interpreter. +/* Fundamental definitions for GNU Emacs Lisp interpreter. -*- coding: utf-8 -*- -Copyright (C) 1985-1987, 1993-1995, 1997-2013 Free Software Foundation, +Copyright (C) 1985-1987, 1993-1995, 1997-2015 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -24,19 +24,35 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <setjmp.h> #include <stdalign.h> #include <stdarg.h> -#include <stdbool.h> #include <stddef.h> #include <float.h> #include <inttypes.h> #include <limits.h> #include <intprops.h> +#include <verify.h> #include "systhread.h" INLINE_HEADER_BEGIN -#ifndef LISP_INLINE -# define LISP_INLINE INLINE + +/* Define a TYPE constant ID as an externally visible name. Use like this: + + DEFINE_GDB_SYMBOL_BEGIN (TYPE, ID) + # define ID (some integer preprocessor expression of type TYPE) + DEFINE_GDB_SYMBOL_END (ID) + + This hack is for the benefit of compilers that do not make macro + 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 +# define DEFINE_GDB_SYMBOL_BEGIN(type, id) DECLARE_GDB_SYM (type, id) +# define DEFINE_GDB_SYMBOL_END(id) = id; +#else +# 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. */ @@ -45,35 +61,82 @@ INLINE_HEADER_BEGIN #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) +/* Number of elements in an array. */ +#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) + +/* Number of bits in a Lisp_Object tag. */ +DEFINE_GDB_SYMBOL_BEGIN (int, GCTYPEBITS) +#define GCTYPEBITS 3 +DEFINE_GDB_SYMBOL_END (GCTYPEBITS) + +/* The number of bits needed in an EMACS_INT over and above the number + of bits in a pointer. This is 0 on systems where: + 1. We can specify multiple-of-8 alignment on static variables. + 2. We know malloc returns a multiple of 8. */ +#if (defined alignas \ + && (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ + || defined DARWIN_OS || defined __sun || defined __MINGW32__ \ + || defined CYGWIN)) +# define NONPOINTER_BITS 0 +#else +# define NONPOINTER_BITS GCTYPEBITS +#endif + /* EMACS_INT - signed integer wide enough to hold an Emacs value EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if pI - printf length modifier for EMACS_INT EMACS_UINT - unsigned variant of EMACS_INT */ #ifndef EMACS_INT_MAX -# if LONG_MAX < LLONG_MAX && defined WIDE_EMACS_INT +# if INTPTR_MAX <= 0 +# error "INTPTR_MAX misconfigured" +# elif INTPTR_MAX <= INT_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT +typedef int EMACS_INT; +typedef unsigned int EMACS_UINT; +# define EMACS_INT_MAX INT_MAX +# define pI "" +# elif INTPTR_MAX <= LONG_MAX >> NONPOINTER_BITS && !defined WIDE_EMACS_INT +typedef long int EMACS_INT; +typedef unsigned long EMACS_UINT; +# define EMACS_INT_MAX LONG_MAX +# define pI "l" +/* Check versus LLONG_MAX, not LLONG_MAX >> NONPOINTER_BITS. + In theory this is not safe, but in practice it seems to be OK. */ +# elif INTPTR_MAX <= LLONG_MAX typedef long long int EMACS_INT; typedef unsigned long long int EMACS_UINT; # define EMACS_INT_MAX LLONG_MAX # define pI "ll" -# elif INT_MAX < LONG_MAX -typedef long int EMACS_INT; -typedef unsigned long int EMACS_UINT; -# define EMACS_INT_MAX LONG_MAX -# define pI "l" # else -typedef int EMACS_INT; -typedef unsigned int EMACS_UINT; -# define EMACS_INT_MAX INT_MAX -# define pI "" +# error "INTPTR_MAX too large" # endif #endif +/* Number of bits to put in each character in the internal representation + of bool vectors. This should not vary across implementations. */ +enum { BOOL_VECTOR_BITS_PER_CHAR = +#define BOOL_VECTOR_BITS_PER_CHAR 8 + BOOL_VECTOR_BITS_PER_CHAR +}; + +/* An unsigned integer type representing a fixed-length bit sequence, + suitable for bool vector words, GC mark bits, etc. Normally it is size_t + for speed, but it is unsigned char on weird platforms. */ +#if BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT +typedef size_t bits_word; +# define BITS_WORD_MAX SIZE_MAX +enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) }; +#else +typedef unsigned char bits_word; +# define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1) +enum { BITS_PER_BITS_WORD = BOOL_VECTOR_BITS_PER_CHAR }; +#endif +verify (BITS_WORD_MAX >> (BITS_PER_BITS_WORD - 1) == 1); + /* Number of bits in some machine integer types. */ enum { BITS_PER_CHAR = CHAR_BIT, BITS_PER_SHORT = CHAR_BIT * sizeof (short), - BITS_PER_INT = CHAR_BIT * sizeof (int), BITS_PER_LONG = CHAR_BIT * sizeof (long int), BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) }; @@ -112,30 +175,50 @@ typedef EMACS_UINT uprintmax_t; /* Extra internal type checking? */ -/* Define an Emacs version of 'assert (COND)', since some - system-defined 'assert's are flaky. COND should be free of side - effects; it may or may not be evaluated. */ +/* Define Emacs versions of <assert.h>'s 'assert (COND)' and <verify.h>'s + 'assume (COND)'. COND should be free of side effects, as it may or + may not be evaluated. + + 'eassert (COND)' checks COND at runtime if ENABLE_CHECKING is + defined and suppress_checking is false, and does nothing otherwise. + Emacs dies if COND is checked and is false. The suppress_checking + variable is initialized to 0 in alloc.c. Set it to 1 using a + debugger to temporarily disable aborting on detected internal + inconsistencies or error conditions. + + In some cases, a good compiler may be able to optimize away the + eassert macro even if ENABLE_CHECKING is true, e.g., if XSTRING (x) + uses eassert to test STRINGP (x), but a particular use of XSTRING + is invoked only after testing that STRINGP (x) is true, making the + test redundant. + + eassume is like eassert except that it also causes the compiler to + assume that COND is true afterwards, regardless of whether runtime + checking is enabled. This can improve performance in some cases, + though it can degrade performance in others. It's often suboptimal + for COND to call external functions or access volatile storage. */ + #ifndef ENABLE_CHECKING -# define eassert(X) ((void) (0 && (X))) /* Check that X compiles. */ +# define eassert(cond) ((void) (false && (cond))) /* Check COND compiles. */ +# define eassume(cond) assume (cond) #else /* ENABLE_CHECKING */ extern _Noreturn void die (const char *, const char *, int); -/* The suppress_checking variable is initialized to 0 in alloc.c. Set - it to 1 using a debugger to temporarily disable aborting on - detected internal inconsistencies or error conditions. - - In some cases, a good compiler may be able to optimize away the - eassert macro altogether, e.g., if XSTRING (x) uses eassert to test - STRINGP (x), but a particular use of XSTRING is invoked only after - testing that STRINGP (x) is true, making the test redundant. */ extern bool suppress_checking EXTERNALLY_VISIBLE; # define eassert(cond) \ (suppress_checking || (cond) \ ? (void) 0 \ : die (# cond, __FILE__, __LINE__)) +# define eassume(cond) \ + (suppress_checking \ + ? assume (cond) \ + : (cond) \ + ? (void) 0 \ + : die (# cond, __FILE__, __LINE__)) #endif /* ENABLE_CHECKING */ + /* Use the configure flag --enable-check-lisp-object-type to make Lisp_Object use a struct type instead of the default int. The flag @@ -152,17 +235,11 @@ extern bool suppress_checking EXTERNALLY_VISIBLE; 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. */ + on the few static Lisp_Objects used: lispsym, all the defsubr, and + the two special buffers buffer_defaults and buffer_local_symbols. */ enum Lisp_Bits { - /* Number of bits in a Lisp_Object tag. This can be used in #if, - and for GDB's sake also as a regular symbol. */ - GCTYPEBITS = -#define GCTYPEBITS 3 - GCTYPEBITS, - /* 2**GCTYPEBITS. This must be a macro that expands to a literal integer constant, for MSVC. */ #define GCALIGNMENT 8 @@ -183,43 +260,34 @@ 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. - This can be used in #if, e.g., '#if VAL_MAX < UINTPTR_MAX' below. */ + This can be used in #if, e.g., '#if USE_LSB_TAG' below expands to an + expression involving VAL_MAX. */ #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) -/* Unless otherwise specified, use USE_LSB_TAG on systems where: */ -#ifndef USE_LSB_TAG -/* 1. We know malloc returns a multiple of 8. */ -# if (defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ \ - || defined DARWIN_OS || defined __sun) -/* 2. We can specify multiple-of-8 alignment on static variables. */ -# ifdef alignas -/* 3. Pointers-as-ints exceed VAL_MAX. - On hosts where pointers-as-ints do not exceed VAL_MAX, USE_LSB_TAG is: +/* Whether the least-significant bits of an EMACS_INT contain the tag. + 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, default USE_LSB_TAG to 1 only on hosts where it might be useful. */ -# if VAL_MAX < UINTPTR_MAX -# define USE_LSB_TAG 1 -# endif -# endif -# endif -#endif -#ifdef USE_LSB_TAG -# undef USE_LSB_TAG -enum enum_USE_LSB_TAG { USE_LSB_TAG = 1 }; -# define USE_LSB_TAG 1 -#else -enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; -# define USE_LSB_TAG 0 + 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 (VAL_MAX / 2 < INTPTR_MAX) +DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) + +#if !USE_LSB_TAG && !defined WIDE_EMACS_INT +# error "USE_LSB_TAG not supported on this platform; please report this." \ + "Try 'configure --with-wide-int' to work around the problem." +error !; #endif #ifndef alignas -# define alignas(alignment) /* empty */ -# if USE_LSB_TAG -# error "USE_LSB_TAG requires alignas" -# endif +# error "alignas not defined" #endif +#ifdef HAVE_STRUCT_ATTRIBUTE_ALIGNED +# define GCALIGNED __attribute__ ((aligned (GCALIGNMENT))) +#else +# define GCALIGNED /* empty */ +#endif /* Some operations are so commonly executed that they are implemented as macros, not functions, because otherwise runtime performance would @@ -235,10 +303,6 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; and/or via a function definition like this: - LISP_MACRO_DEFUN (OP, Lisp_Object, (Lisp_Object x), (x)) - - which macro-expands to this: - Lisp_Object (OP) (Lisp_Object x) { return lisp_h_OP (x); } without worrying about the implementations diverging, since @@ -264,12 +328,12 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; #define lisp_h_CHECK_LIST_CONS(x, y) CHECK_TYPE (CONSP (x), Qlistp, y) #define lisp_h_CHECK_NUMBER(x) CHECK_TYPE (INTEGERP (x), Qintegerp, x) #define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x) -#define lisp_h_CHECK_TYPE(ok, Qxxxp, x) \ - ((ok) ? (void) 0 : (void) wrong_type_argument (Qxxxp, x)) +#define lisp_h_CHECK_TYPE(ok, predicate, x) \ + ((ok) ? (void) 0 : (void) wrong_type_argument (predicate, x)) #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) @@ -285,24 +349,25 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; #define lisp_h_XCONS(a) \ (eassert (CONSP (a)), (struct Lisp_Cons *) XUNTAG (a, Lisp_Cons)) #define lisp_h_XHASH(a) XUINT (a) -#define lisp_h_XPNTR(a) \ - ((void *) (intptr_t) ((XLI (a) & VALMASK) | DATA_SEG_BITS)) -#define lisp_h_XSYMBOL(a) \ - (eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol)) #ifndef GC_CHECK_CONS_LIST # define lisp_h_check_cons_list() ((void) 0) #endif #if USE_LSB_TAG -# define lisp_h_make_number(n) XIL ((EMACS_INT) (n) << INTTYPEBITS) +# define lisp_h_make_number(n) \ + 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_XSYMBOL(a) \ + (eassert (SYMBOLP (a)), \ + (struct Lisp_Symbol *) ((uintptr_t) XLI (a) - Lisp_Symbol \ + + (char *) lispsym)) # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) -# define lisp_h_XUNTAG(a, type) ((void *) (XLI (a) - (type))) +# define lisp_h_XUNTAG(a, type) ((void *) (intptr_t) (XLI (a) - (type))) #endif /* When compiling via gcc -O0, define the key operations as macros, as Emacs is too slow otherwise. To disable this optimization, compile - with -DINLINING=0. */ + with -DINLINING=false. */ #if (defined __NO_INLINE__ \ && ! defined __OPTIMIZE__ && ! defined __OPTIMIZE_SIZE__ \ && ! (defined INLINING && ! INLINING)) @@ -311,7 +376,7 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; # define CHECK_LIST_CONS(x, y) lisp_h_CHECK_LIST_CONS (x, y) # define CHECK_NUMBER(x) lisp_h_CHECK_NUMBER (x) # define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x) -# define CHECK_TYPE(ok, Qxxxp, x) lisp_h_CHECK_TYPE (ok, Qxxxp, x) +# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) # define CONSP(x) lisp_h_CONSP (x) # define EQ(x, y) lisp_h_EQ (x, y) # define FLOATP(x) lisp_h_FLOATP (x) @@ -328,8 +393,6 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; # define XCDR(c) lisp_h_XCDR (c) # define XCONS(a) lisp_h_XCONS (a) # define XHASH(a) lisp_h_XHASH (a) -# define XPNTR(a) lisp_h_XPNTR (a) -# define XSYMBOL(a) lisp_h_XSYMBOL (a) # ifndef GC_CHECK_CONS_LIST # define check_cons_list() lisp_h_check_cons_list () # endif @@ -337,22 +400,12 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; # define make_number(n) lisp_h_make_number (n) # define XFASTINT(a) lisp_h_XFASTINT (a) # define XINT(a) lisp_h_XINT (a) +# define XSYMBOL(a) lisp_h_XSYMBOL (a) # define XTYPE(a) lisp_h_XTYPE (a) # define XUNTAG(a, type) lisp_h_XUNTAG (a, type) # endif #endif -/* Define NAME as a lisp.h inline function that returns TYPE and has - arguments declared as ARGDECLS and passed as ARGS. ARGDECLS and - ARGS should be parenthesized. Implement the function by calling - lisp_h_NAME ARGS. */ -#define LISP_MACRO_DEFUN(name, type, argdecls, args) \ - LISP_INLINE type (name) argdecls { return lisp_h_##name args; } - -/* like LISP_MACRO_DEFUN, except NAME returns void. */ -#define LISP_MACRO_DEFUN_VOID(name, argdecls, args) \ - LISP_INLINE void (name) argdecls { lisp_h_##name args; } - /* Define the fundamental Lisp data structures. */ @@ -366,8 +419,10 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; #define case_Lisp_Int case Lisp_Int0: case Lisp_Int1 /* Idea stolen from GDB. Pedantic GCC complains about enum bitfields, - MSVC doesn't support them, and xlc complains vociferously about them. */ -#if defined __STRICT_ANSI__ || defined _MSC_VER || defined __IBMC__ + MSVC doesn't support them, and xlc and Oracle Studio c99 complain + vociferously about them. */ +#if (defined __STRICT_ANSI__ || defined _MSC_VER || defined __IBMC__ \ + || (defined __SUNPRO_C && __STDC__)) #define ENUM_BF(TYPE) unsigned int #else #define ENUM_BF(TYPE) enum TYPE @@ -376,20 +431,20 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; enum Lisp_Type { - /* Integer. XINT (obj) is the integer value. */ - Lisp_Int0 = 0, - Lisp_Int1 = USE_LSB_TAG ? 1 << INTTYPEBITS : 1, - /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */ - Lisp_Symbol = 2, + Lisp_Symbol = 0, /* Miscellaneous. XMISC (object) points to a union Lisp_Misc, whose first member indicates the subtype. */ - Lisp_Misc = 3, + Lisp_Misc = 1, + + /* Integer. XINT (obj) is the integer value. */ + Lisp_Int0 = 2, + Lisp_Int1 = USE_LSB_TAG ? 6 : 3, /* String. XSTRING (object) points to a struct Lisp_String. The length of the string, and its contents, are stored therein. */ - Lisp_String = USE_LSB_TAG ? 1 : 1 << INTTYPEBITS, + Lisp_String = 4, /* Vector of Lisp objects, or something resembling it. XVECTOR (object) points to a struct Lisp_Vector, which contains @@ -398,7 +453,7 @@ enum Lisp_Type Lisp_Vectorlike = 5, /* Cons. XCONS (object) points to a struct Lisp_Cons. */ - Lisp_Cons = 6, + Lisp_Cons = USE_LSB_TAG ? 3 : 6, Lisp_Float = 7 }; @@ -414,6 +469,7 @@ enum Lisp_Misc_Type Lisp_Misc_Marker, Lisp_Misc_Overlay, Lisp_Misc_Save_Value, + Lisp_Misc_Finalizer, /* Currently floats are not a misc type, but let's define this in case we want to change that. */ Lisp_Misc_Float, @@ -491,26 +547,205 @@ enum Lisp_Fwd_Type typedef struct { EMACS_INT i; } Lisp_Object; -#define LISP_INITIALLY_ZERO {0} +#define LISP_INITIALLY(i) {i} #undef CHECK_LISP_OBJECT_TYPE -enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 1 }; +enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = true }; #else /* CHECK_LISP_OBJECT_TYPE */ /* If a struct type is not wanted, define Lisp_Object as just a number. */ typedef EMACS_INT Lisp_Object; -#define LISP_INITIALLY_ZERO 0 -enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = 0 }; +#define LISP_INITIALLY(i) (i) +enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false }; #endif /* CHECK_LISP_OBJECT_TYPE */ +#define LISP_INITIALLY_ZERO LISP_INITIALLY (0) + +/* 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 bool FINALIZERP (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 bool TERMINALP (Lisp_Object); +INLINE bool THREADP (Lisp_Object); +INLINE bool MUTEXP (Lisp_Object); +INLINE bool CONDVARP (Lisp_Object); +INLINE struct Lisp_Save_Value *XSAVE_VALUE (Lisp_Object); +INLINE struct Lisp_Finalizer *XFINALIZER (Lisp_Object); +INLINE struct Lisp_Symbol *(XSYMBOL) (Lisp_Object); +INLINE void *(XUNTAG) (Lisp_Object, int); + +/* 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 _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 floatfns.c. */ +extern double extract_float (Lisp_Object); + + +/* Interned state of a symbol. */ + +enum symbol_interned +{ + SYMBOL_UNINTERNED = 0, + SYMBOL_INTERNED = 1, + SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2 +}; + +enum symbol_redirect +{ + SYMBOL_PLAINVAL = 4, + SYMBOL_VARALIAS = 1, + SYMBOL_LOCALIZED = 2, + SYMBOL_FORWARDED = 3 +}; + +struct Lisp_Symbol +{ + bool_bf gcmarkbit : 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_BF (symbol_redirect) redirect : 3; + + /* Non-zero means symbol is constant, i.e. changing its value + 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. */ + unsigned interned : 2; + + /* True means that this variable has been explicitly declared + special (with `defvar' etc), and shouldn't be lexically bound. */ + bool_bf declared_special : 1; + + /* True if pointed to from purespace and hence can't be GC'd. */ + bool_bf pinned : 1; + + /* The symbol's name, as a Lisp string. */ + Lisp_Object name; + + /* Value of the symbol or Qunbound if unbound. Which alternative of the + union is used depends on the `redirect' field above. */ + 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 Qnil if not fboundp. */ + Lisp_Object function; + + /* The symbol's property list. */ + Lisp_Object plist; + + /* Next symbol in obarray bucket, if the symbol is interned. */ + struct Lisp_Symbol *next; +}; + +/* Declare a Lisp-callable function. The MAXARGS parameter has the same + meaning as in the DEFUN macro, and is used to construct a prototype. */ +/* 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 + +/* Note that the weird token-substitution semantics of ANSI C makes + this work for MANY and UNEVALLED. */ +#define DEFUN_ARGS_MANY (ptrdiff_t, Lisp_Object *) +#define DEFUN_ARGS_UNEVALLED (Lisp_Object) +#define DEFUN_ARGS_0 (void) +#define DEFUN_ARGS_1 (Lisp_Object) +#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object) +#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + 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) + +/* Yield an integer that contains TAG along with PTR. */ +#define TAG_PTR(tag, ptr) \ + ((USE_LSB_TAG ? (tag) : (EMACS_UINT) (tag) << VALBITS) + (uintptr_t) (ptr)) + +/* Yield an integer that contains a symbol tag along with OFFSET. + OFFSET should be the offset in bytes from 'lispsym' to the symbol. */ +#define TAG_SYMOFFSET(offset) TAG_PTR (Lisp_Symbol, offset) + +/* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to + XLI (builtin_lisp_symbol (Qwhatever)), + except the former expands to an integer constant expression. */ +#define XLI_BUILTIN_LISPSYM(iname) TAG_SYMOFFSET ((iname) * sizeof *lispsym) + +/* Declare extern constants for Lisp symbols. These can be helpful + when using a debugger like GDB, on older platforms where the debug + format does not represent C macros. */ +#define DEFINE_LISP_SYMBOL(name) \ + DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name) \ + DEFINE_GDB_SYMBOL_END (LISP_INITIALLY (XLI_BUILTIN_LISPSYM (i##name))) + +/* By default, define macros for Qt, etc., as this leads to a bit + better performance in the core Emacs interpreter. A plugin can + define DEFINE_NON_NIL_Q_SYMBOL_MACROS to be false, to be portable to + other Emacs instances that assign different values to Qt, etc. */ +#ifndef DEFINE_NON_NIL_Q_SYMBOL_MACROS +# define DEFINE_NON_NIL_Q_SYMBOL_MACROS true +#endif + +#include "globals.h" + /* Header of vector-like objects. This documents the layout constraints on vectors and pseudovectors (objects of PVEC_xxx subtype). It also prevents compilers from being fooled by Emacs's type punning: XSETPSEUDOVECTOR and PSEUDOVECTORP cast their pointers to struct vectorlike_header *, because when two such pointers potentially alias, a compiler won't incorrectly reorder loads and stores to their size fields. See - <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ + Bug#8546. */ struct vectorlike_header { /* The only field contains various pieces of information: @@ -539,20 +774,30 @@ struct vectorlike_header /* 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)) -LISP_MACRO_DEFUN (XIL, Lisp_Object, (EMACS_INT i), (i)) + +INLINE EMACS_INT +(XLI) (Lisp_Object o) +{ + return lisp_h_XLI (o); +} + +INLINE Lisp_Object +(XIL) (EMACS_INT i) +{ + return lisp_h_XIL (i); +} /* In the size word of a vector, this bit means the vector has been marked. */ -static ptrdiff_t const ARRAY_MARK_FLAG -#define ARRAY_MARK_FLAG PTRDIFF_MIN - = ARRAY_MARK_FLAG; +DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, ARRAY_MARK_FLAG) +# define ARRAY_MARK_FLAG PTRDIFF_MIN +DEFINE_GDB_SYMBOL_END (ARRAY_MARK_FLAG) /* In the size word of a struct Lisp_Vector, this bit means it's really some other vector-like object. */ -static ptrdiff_t const PSEUDOVECTOR_FLAG -#define PSEUDOVECTOR_FLAG (PTRDIFF_MAX - PTRDIFF_MAX / 2) - = PSEUDOVECTOR_FLAG; +DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, PSEUDOVECTOR_FLAG) +# define PSEUDOVECTOR_FLAG (PTRDIFF_MAX - PTRDIFF_MAX / 2) +DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG) /* In a pseudovector, the size field actually contains a word with one PSEUDOVECTOR_FLAG bit set, and one of the following values extracted @@ -581,18 +826,8 @@ enum pvec_type PVEC_FONT /* Should be last because it's used for range checking. */ }; -/* DATA_SEG_BITS forces extra bits to be or'd in with any pointers - which were stored in a Lisp_Object. */ -#ifndef DATA_SEG_BITS -# define DATA_SEG_BITS 0 -#endif -enum { gdb_DATA_SEG_BITS = DATA_SEG_BITS }; -#undef DATA_SEG_BITS - enum More_Lisp_Bits { - DATA_SEG_BITS = gdb_DATA_SEG_BITS, - /* For convenience, we also store the number of elements in these bits. Note that this size is not necessarily the memory-footprint size, but only the number of Lisp_Object fields (that need to be traced by GC). @@ -609,36 +844,61 @@ enum More_Lisp_Bits /* Used to extract pseudovector subtype information. */ PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS, - PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS, - - /* Number of bits to put in each character in the internal representation - of bool vectors. This should not vary across implementations. */ - BOOL_VECTOR_BITS_PER_CHAR = 8 + PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS }; /* These functions extract various sorts of values from a Lisp_Object. - For example, if tem is a Lisp_Object whose type is Lisp_Cons, - XCONS (tem) is the struct Lisp_Cons * pointing to the memory for that cons. */ + For example, if tem is a Lisp_Object whose type is Lisp_Cons, + XCONS (tem) is the struct Lisp_Cons * pointing to the memory for + that cons. */ -static EMACS_INT const VALMASK -#define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX) - = VALMASK; +/* Mask for the value (as opposed to the type bits) of a Lisp object. */ +DEFINE_GDB_SYMBOL_BEGIN (EMACS_INT, VALMASK) +# define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX) +DEFINE_GDB_SYMBOL_END (VALMASK) /* Largest and smallest representable fixnum values. These are the C values. They are macros for use in static initializers. */ #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) -/* Extract the pointer hidden within A. */ -LISP_MACRO_DEFUN (XPNTR, void *, (Lisp_Object a), (a)) - #if USE_LSB_TAG -LISP_MACRO_DEFUN (make_number, Lisp_Object, (EMACS_INT n), (n)) -LISP_MACRO_DEFUN (XINT, EMACS_INT, (Lisp_Object a), (a)) -LISP_MACRO_DEFUN (XFASTINT, EMACS_INT, (Lisp_Object a), (a)) -LISP_MACRO_DEFUN (XTYPE, enum Lisp_Type, (Lisp_Object a), (a)) -LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type)) +INLINE Lisp_Object +(make_number) (EMACS_INT n) +{ + return lisp_h_make_number (n); +} + +INLINE EMACS_INT +(XINT) (Lisp_Object a) +{ + return lisp_h_XINT (a); +} + +INLINE EMACS_INT +(XFASTINT) (Lisp_Object a) +{ + return lisp_h_XFASTINT (a); +} + +INLINE struct Lisp_Symbol * +(XSYMBOL) (Lisp_Object a) +{ + return lisp_h_XSYMBOL (a); +} + +INLINE enum Lisp_Type +(XTYPE) (Lisp_Object a) +{ + return lisp_h_XTYPE (a); +} + +INLINE void * +(XUNTAG) (Lisp_Object a, int type) +{ + return lisp_h_XUNTAG (a, type); +} #else /* ! USE_LSB_TAG */ @@ -648,33 +908,60 @@ LISP_MACRO_DEFUN (XUNTAG, void *, (Lisp_Object a, int type), (a, type)) /* Make a Lisp integer representing the value of the low order bits of N. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object make_number (EMACS_INT n) { - return XIL (USE_LSB_TAG ? n << INTTYPEBITS : n & INTMASK); + EMACS_INT int0 = Lisp_Int0; + if (USE_LSB_TAG) + { + EMACS_UINT u = n; + n = u << INTTYPEBITS; + n += int0; + } + else + { + n &= INTMASK; + n += (int0 << VALBITS); + } + return XIL (n); } /* Extract A's value as a signed integer. */ -LISP_INLINE EMACS_INT +INLINE EMACS_INT XINT (Lisp_Object a) { EMACS_INT i = XLI (a); - return (USE_LSB_TAG ? i : i << INTTYPEBITS) >> INTTYPEBITS; + if (! USE_LSB_TAG) + { + EMACS_UINT u = i; + i = u << INTTYPEBITS; + } + return i >> INTTYPEBITS; } /* Like XINT (A), but may be faster. A must be nonnegative. If ! USE_LSB_TAG, this takes advantage of the fact that Lisp integers have zero-bits in their tags. */ -LISP_INLINE EMACS_INT +INLINE EMACS_INT XFASTINT (Lisp_Object a) { - EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a); + EMACS_INT int0 = Lisp_Int0; + EMACS_INT n = USE_LSB_TAG ? XINT (a) : XLI (a) - (int0 << VALBITS); eassert (0 <= n); return n; } +/* Extract A's value as a symbol. */ +INLINE struct Lisp_Symbol * +XSYMBOL (Lisp_Object a) +{ + uintptr_t i = (uintptr_t) XUNTAG (a, Lisp_Symbol); + void *p = (char *) lispsym + i; + return p; +} + /* Extract A's type. */ -LISP_INLINE enum Lisp_Type +INLINE enum Lisp_Type XTYPE (Lisp_Object a) { EMACS_UINT i = XLI (a); @@ -682,21 +969,17 @@ XTYPE (Lisp_Object a) } /* Extract A's pointer value, assuming A's type is TYPE. */ -LISP_INLINE void * +INLINE void * XUNTAG (Lisp_Object a, int type) { - if (USE_LSB_TAG) - { - intptr_t i = XLI (a) - type; - return (void *) i; - } - return XPNTR (a); + intptr_t i = USE_LSB_TAG ? XLI (a) - type : XLI (a) & VALMASK; + return (void *) i; } #endif /* ! USE_LSB_TAG */ /* Extract A's value as an unsigned integer. */ -LISP_INLINE EMACS_UINT +INLINE EMACS_UINT XUINT (Lisp_Object a) { EMACS_UINT i = XLI (a); @@ -706,122 +989,71 @@ XUINT (Lisp_Object a) /* Return A's (Lisp-integer sized) hash. Happens to be like XUINT right now, but XUINT should only be applied to objects we know are integers. */ -LISP_MACRO_DEFUN (XHASH, EMACS_INT, (Lisp_Object a), (a)) + +INLINE EMACS_INT +(XHASH) (Lisp_Object a) +{ + return lisp_h_XHASH (a); +} /* Like make_number (N), but may be faster. N must be in nonnegative range. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object make_natnum (EMACS_INT n) { eassert (0 <= n && n <= MOST_POSITIVE_FIXNUM); - 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. */ -LISP_MACRO_DEFUN (EQ, bool, (Lisp_Object x, Lisp_Object y), (x, y)) -/* Value is non-zero if I doesn't fit into a Lisp fixnum. It is +INLINE bool +(EQ) (Lisp_Object x, Lisp_Object y) +{ + return lisp_h_EQ (x, y); +} + +/* Value is true 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 or if I is a NaN. */ #define FIXNUM_OVERFLOW_P(i) \ (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM)) -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) { return num < lower ? lower : num <= upper ? num : upper; } -/* Forward declarations. */ - -/* Defined in this file. */ -union Lisp_Fwd; -LISP_INLINE bool BOOL_VECTOR_P (Lisp_Object); -LISP_INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *); -LISP_INLINE bool BUFFERP (Lisp_Object); -LISP_INLINE bool CHAR_TABLE_P (Lisp_Object); -LISP_INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object, ptrdiff_t); -LISP_INLINE bool (CONSP) (Lisp_Object); -LISP_INLINE bool (FLOATP) (Lisp_Object); -LISP_INLINE bool functionp (Lisp_Object); -LISP_INLINE bool (INTEGERP) (Lisp_Object); -LISP_INLINE bool (MARKERP) (Lisp_Object); -LISP_INLINE bool (MISCP) (Lisp_Object); -LISP_INLINE bool (NILP) (Lisp_Object); -LISP_INLINE bool OVERLAYP (Lisp_Object); -LISP_INLINE bool PROCESSP (Lisp_Object); -LISP_INLINE bool PSEUDOVECTORP (Lisp_Object, int); -LISP_INLINE bool SAVE_VALUEP (Lisp_Object); -LISP_INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t, - Lisp_Object); -LISP_INLINE bool STRINGP (Lisp_Object); -LISP_INLINE bool SUB_CHAR_TABLE_P (Lisp_Object); -LISP_INLINE bool SUBRP (Lisp_Object); -LISP_INLINE bool (SYMBOLP) (Lisp_Object); -LISP_INLINE bool (VECTORLIKEP) (Lisp_Object); -LISP_INLINE bool WINDOWP (Lisp_Object); -LISP_INLINE bool THREADP (Lisp_Object); -LISP_INLINE bool MUTEXP (Lisp_Object); -LISP_INLINE bool CONDVARP (Lisp_Object); -LISP_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); -extern int char_table_translate (Lisp_Object, int); - -/* 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, Qvectorp; -extern Lisp_Object Qvector_or_char_table_p, Qwholenump; -extern Lisp_Object Qwindow; -extern Lisp_Object Ffboundp (Lisp_Object); -extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); - -/* Defined in emacs.c. */ -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 thread.c. */ -extern Lisp_Object Qthreadp, Qmutexp, Qcondition_variable_p; - -/* Defined in window.c. */ -extern Lisp_Object Qwindowp; - -/* Defined in xdisp.c. */ -extern Lisp_Object Qimage; - /* Extract a value or address from a Lisp_Object. */ -LISP_MACRO_DEFUN (XCONS, struct Lisp_Cons *, (Lisp_Object a), (a)) +INLINE struct Lisp_Cons * +(XCONS) (Lisp_Object a) +{ + return lisp_h_XCONS (a); +} -LISP_INLINE struct Lisp_Vector * +INLINE struct Lisp_Vector * XVECTOR (Lisp_Object a) { eassert (VECTORLIKEP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_String * +INLINE struct Lisp_String * XSTRING (Lisp_Object a) { eassert (STRINGP (a)); return XUNTAG (a, Lisp_String); } -LISP_MACRO_DEFUN (XSYMBOL, struct Lisp_Symbol *, (Lisp_Object a), (a)) +/* The index of the C-defined Lisp symbol SYM. + This can be used in a static initializer. */ +#define SYMBOL_INDEX(sym) i##sym -LISP_INLINE struct Lisp_Float * +INLINE struct Lisp_Float * XFLOAT (Lisp_Object a) { eassert (FLOATP (a)); @@ -830,76 +1062,77 @@ XFLOAT (Lisp_Object a) /* Pseudovector types. */ -LISP_INLINE struct Lisp_Process * +INLINE struct Lisp_Process * XPROCESS (Lisp_Object a) { eassert (PROCESSP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct window * +INLINE struct window * XWINDOW (Lisp_Object a) { eassert (WINDOWP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct terminal * +INLINE struct terminal * XTERMINAL (Lisp_Object a) { + eassert (TERMINALP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_Subr * +INLINE struct Lisp_Subr * XSUBR (Lisp_Object a) { eassert (SUBRP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct buffer * +INLINE struct buffer * XBUFFER (Lisp_Object a) { eassert (BUFFERP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_Char_Table * +INLINE struct Lisp_Char_Table * XCHAR_TABLE (Lisp_Object a) { eassert (CHAR_TABLE_P (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_Sub_Char_Table * +INLINE struct Lisp_Sub_Char_Table * XSUB_CHAR_TABLE (Lisp_Object a) { eassert (SUB_CHAR_TABLE_P (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_Bool_Vector * +INLINE struct Lisp_Bool_Vector * XBOOL_VECTOR (Lisp_Object a) { eassert (BOOL_VECTOR_P (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct thread_state * +INLINE struct thread_state * XTHREAD (Lisp_Object a) { eassert (THREADP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_Mutex * +INLINE struct Lisp_Mutex * XMUTEX (Lisp_Object a) { eassert (MUTEXP (a)); return XUNTAG (a, Lisp_Vectorlike); } -LISP_INLINE struct Lisp_CondVar * +INLINE struct Lisp_CondVar * XCONDVAR (Lisp_Object a) { eassert (CONDVARP (a)); @@ -908,20 +1141,26 @@ XCONDVAR (Lisp_Object a) /* Construct a Lisp_Object from a value or address. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object make_lisp_ptr (void *ptr, enum Lisp_Type type) { - EMACS_UINT utype = type; - EMACS_UINT typebits = USE_LSB_TAG ? type : utype << VALBITS; - Lisp_Object a = XIL (typebits | (uintptr_t) ptr); + Lisp_Object a = XIL (TAG_PTR (type, ptr)); eassert (XTYPE (a) == type && XUNTAG (a, type) == ptr); return a; } -LISP_INLINE Lisp_Object -make_lisp_proc (struct Lisp_Process *p) +INLINE Lisp_Object +make_lisp_symbol (struct Lisp_Symbol *sym) +{ + Lisp_Object a = XIL (TAG_SYMOFFSET ((char *) sym - (char *) lispsym)); + eassert (XSYMBOL (a) == sym); + return a; +} + +INLINE Lisp_Object +builtin_lisp_symbol (int index) { - return make_lisp_ptr (p, Lisp_Vectorlike); + return make_lisp_symbol (lispsym + index); } #define XSETINT(a, b) ((a) = make_number (b)) @@ -929,13 +1168,9 @@ make_lisp_proc (struct Lisp_Process *p) #define XSETCONS(a, b) ((a) = make_lisp_ptr (b, Lisp_Cons)) #define XSETVECTOR(a, b) ((a) = make_lisp_ptr (b, Lisp_Vectorlike)) #define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String)) -#define XSETSYMBOL(a, b) ((a) = make_lisp_ptr (b, Lisp_Symbol)) +#define XSETSYMBOL(a, b) ((a) = make_lisp_symbol (b)) #define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float)) - -/* Misc types. */ - #define XSETMISC(a, b) ((a) = make_lisp_ptr (b, Lisp_Misc)) -#define XSETMARKER(a, b) (XSETMISC (a, b), XMISCTYPE (a) = Lisp_Misc_Marker) /* Pseudovector types. */ @@ -974,20 +1209,38 @@ make_lisp_proc (struct Lisp_Process *p) #define XSETMUTEX(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_MUTEX)) #define XSETCONDVAR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CONDVAR)) -/* Type checking. */ +/* Efficiently convert a pointer to a Lisp object and back. The + pointer is represented as a Lisp integer, so the garbage collector + does not know about it. The pointer should not have both Lisp_Int1 + bits set, which makes this conversion inherently unportable. */ -LISP_MACRO_DEFUN_VOID (CHECK_TYPE, (int ok, Lisp_Object Qxxxp, Lisp_Object x), - (ok, Qxxxp, x)) +INLINE void * +XINTPTR (Lisp_Object a) +{ + return XUNTAG (a, Lisp_Int0); +} + +INLINE Lisp_Object +make_pointer_integer (void *p) +{ + Lisp_Object a = XIL (TAG_PTR (Lisp_Int0, p)); + eassert (INTEGERP (a) && XINTPTR (a) == p); + return a; +} -/* Deprecated and will be removed soon. */ +/* Type checking. */ -#define INTERNAL_FIELD(field) field ## _ +INLINE void +(CHECK_TYPE) (int ok, Lisp_Object predicate, Lisp_Object x) +{ + lisp_h_CHECK_TYPE (ok, predicate, x); +} /* See the macros in intervals.h. */ typedef struct interval *INTERVAL; -struct Lisp_Cons +struct GCALIGNED Lisp_Cons { /* Car of this cons cell. */ Lisp_Object car; @@ -1009,45 +1262,55 @@ struct Lisp_Cons fields are not accessible. (What if we want to switch to a copying collector someday? Cached cons cell field addresses may be invalidated at arbitrary points.) */ -LISP_INLINE Lisp_Object * +INLINE Lisp_Object * xcar_addr (Lisp_Object c) { return &XCONS (c)->car; } -LISP_INLINE Lisp_Object * +INLINE Lisp_Object * xcdr_addr (Lisp_Object c) { return &XCONS (c)->u.cdr; } /* Use these from normal code. */ -LISP_MACRO_DEFUN (XCAR, Lisp_Object, (Lisp_Object c), (c)) -LISP_MACRO_DEFUN (XCDR, Lisp_Object, (Lisp_Object c), (c)) + +INLINE Lisp_Object +(XCAR) (Lisp_Object c) +{ + return lisp_h_XCAR (c); +} + +INLINE Lisp_Object +(XCDR) (Lisp_Object c) +{ + return lisp_h_XCDR (c); +} /* Use these to set the fields of a cons cell. Note that both arguments may refer to the same object, so 'n' should not be read after 'c' is first modified. */ -LISP_INLINE void +INLINE void XSETCAR (Lisp_Object c, Lisp_Object n) { *xcar_addr (c) = n; } -LISP_INLINE void +INLINE void XSETCDR (Lisp_Object c, Lisp_Object n) { *xcdr_addr (c) = n; } /* Take the car or cdr of something whose type is not known. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object CAR (Lisp_Object c) { return (CONSP (c) ? XCAR (c) : NILP (c) ? Qnil : wrong_type_argument (Qlistp, c)); } -LISP_INLINE Lisp_Object +INLINE Lisp_Object CDR (Lisp_Object c) { return (CONSP (c) ? XCDR (c) @@ -1056,12 +1319,12 @@ CDR (Lisp_Object c) } /* Take the car or cdr of something whose type is not known. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object CAR_SAFE (Lisp_Object c) { return CONSP (c) ? XCAR (c) : Qnil; } -LISP_INLINE Lisp_Object +INLINE Lisp_Object CDR_SAFE (Lisp_Object c) { return CONSP (c) ? XCDR (c) : Qnil; @@ -1069,7 +1332,7 @@ CDR_SAFE (Lisp_Object c) /* 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; @@ -1078,7 +1341,7 @@ struct Lisp_String }; /* True if STR is a multibyte string. */ -LISP_INLINE bool +INLINE bool STRING_MULTIBYTE (Lisp_Object str) { return 0 <= XSTRING (str)->size_byte; @@ -1101,42 +1364,48 @@ STRING_MULTIBYTE (Lisp_Object str) ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, min (SIZE_MAX, PTRDIFF_MAX) - 1)) /* Mark STR as a unibyte string. */ -#define STRING_SET_UNIBYTE(STR) \ - do { if (EQ (STR, empty_multibyte_string)) \ - (STR) = empty_unibyte_string; \ - else XSTRING (STR)->size_byte = -1; } while (0) +#define STRING_SET_UNIBYTE(STR) \ + do { \ + if (EQ (STR, empty_multibyte_string)) \ + (STR) = empty_unibyte_string; \ + else \ + XSTRING (STR)->size_byte = -1; \ + } while (false) /* Mark STR as a multibyte string. Assure that STR contains only ASCII characters in advance. */ -#define STRING_SET_MULTIBYTE(STR) \ - do { if (EQ (STR, empty_unibyte_string)) \ - (STR) = empty_multibyte_string; \ - else XSTRING (STR)->size_byte = XSTRING (STR)->size; } while (0) +#define STRING_SET_MULTIBYTE(STR) \ + do { \ + if (EQ (STR, empty_unibyte_string)) \ + (STR) = empty_multibyte_string; \ + else \ + XSTRING (STR)->size_byte = XSTRING (STR)->size; \ + } while (false) /* Convenience functions for dealing with Lisp strings. */ -LISP_INLINE unsigned char * +INLINE unsigned char * SDATA (Lisp_Object string) { return XSTRING (string)->data; } -LISP_INLINE char * +INLINE char * SSDATA (Lisp_Object string) { /* Avoid "differ in sign" warnings. */ return (char *) SDATA (string); } -LISP_INLINE unsigned char +INLINE unsigned char SREF (Lisp_Object string, ptrdiff_t index) { return SDATA (string)[index]; } -LISP_INLINE void +INLINE void SSET (Lisp_Object string, ptrdiff_t index, unsigned char new) { SDATA (string)[index] = new; } -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t SCHARS (Lisp_Object string) { return XSTRING (string)->size; @@ -1145,7 +1414,7 @@ SCHARS (Lisp_Object string) #ifdef GC_CHECK_STRING_BYTES extern ptrdiff_t string_bytes (struct Lisp_String *); #endif -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t STRING_BYTES (struct Lisp_String *s) { #ifdef GC_CHECK_STRING_BYTES @@ -1155,24 +1424,18 @@ STRING_BYTES (struct Lisp_String *s) #endif } -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t SBYTES (Lisp_Object string) { return STRING_BYTES (XSTRING (string)); } -LISP_INLINE void +INLINE void STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize) { XSTRING (string)->size = newsize; } -LISP_INLINE void -STRING_COPYIN (Lisp_Object string, ptrdiff_t index, char const *new, - ptrdiff_t count) -{ - memcpy (SDATA (string) + index, new, count); -} -/* Regular vector is just a header plus array of Lisp_Objects. */ +/* A regular vector is just a header plus an array of Lisp_Objects. */ struct Lisp_Vector { @@ -1180,7 +1443,14 @@ struct Lisp_Vector Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; }; -/* A boolvector is a kind of vectorlike, with contents are like a string. */ +/* C11 prohibits alignof (struct Lisp_Vector), so compute it manually. */ +enum + { + ALIGNOF_STRUCT_LISP_VECTOR + = alignof (union { struct vectorlike_header a; Lisp_Object b; }) + }; + +/* A boolvector is a kind of vectorlike, with contents like a string. */ struct Lisp_Bool_Vector { @@ -1189,10 +1459,81 @@ struct Lisp_Bool_Vector struct vectorlike_header header; /* This is the size in bits. */ EMACS_INT size; - /* This contains the actual bits, packed into bytes. */ - unsigned char data[FLEXIBLE_ARRAY_MEMBER]; + /* The actual bits, packed into bytes. + Zeros fill out the last word if needed. + The bits are in little-endian order in the bytes, and + the bytes are in little-endian order in the words. */ + bits_word data[FLEXIBLE_ARRAY_MEMBER]; }; +INLINE EMACS_INT +bool_vector_size (Lisp_Object a) +{ + EMACS_INT size = XBOOL_VECTOR (a)->size; + eassume (0 <= size); + return size; +} + +INLINE bits_word * +bool_vector_data (Lisp_Object a) +{ + return XBOOL_VECTOR (a)->data; +} + +INLINE unsigned char * +bool_vector_uchar_data (Lisp_Object a) +{ + return (unsigned char *) bool_vector_data (a); +} + +/* The number of data words and bytes in a bool vector with SIZE bits. */ + +INLINE EMACS_INT +bool_vector_words (EMACS_INT size) +{ + eassume (0 <= size && size <= EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1)); + return (size + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; +} + +INLINE EMACS_INT +bool_vector_bytes (EMACS_INT size) +{ + eassume (0 <= size && size <= EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1)); + return (size + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR; +} + +/* True if A's Ith bit is set. */ + +INLINE bool +bool_vector_bitref (Lisp_Object a, EMACS_INT i) +{ + eassume (0 <= i && i < bool_vector_size (a)); + return !! (bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR] + & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR))); +} + +INLINE Lisp_Object +bool_vector_ref (Lisp_Object a, EMACS_INT i) +{ + return bool_vector_bitref (a, i) ? Qt : Qnil; +} + +/* Set A's Ith bit to B. */ + +INLINE void +bool_vector_set (Lisp_Object a, EMACS_INT i, bool b) +{ + unsigned char *addr; + + eassume (0 <= i && i < bool_vector_size (a)); + addr = &bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR]; + + if (b) + *addr |= 1 << (i % BOOL_VECTOR_BITS_PER_CHAR); + else + *addr &= ~ (1 << (i % BOOL_VECTOR_BITS_PER_CHAR)); +} + /* Some handy constants for calculating sizes and offsets, mostly of vectorlike objects. */ @@ -1205,32 +1546,32 @@ enum /* Conveniences for dealing with Lisp arrays. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object AREF (Lisp_Object array, ptrdiff_t idx) { return XVECTOR (array)->contents[idx]; } -LISP_INLINE Lisp_Object * +INLINE Lisp_Object * aref_addr (Lisp_Object array, ptrdiff_t idx) { return & XVECTOR (array)->contents[idx]; } -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t ASIZE (Lisp_Object array) { return XVECTOR (array)->header.size; } -LISP_INLINE void +INLINE void ASET (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) { eassert (0 <= idx && idx < ASIZE (array)); XVECTOR (array)->contents[idx] = val; } -LISP_INLINE void +INLINE void gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) { /* Like ASET, but also can be used in the garbage collector: @@ -1239,6 +1580,22 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) XVECTOR (array)->contents[idx] = val; } +/* True, since Qnil's representation is zero. Every place in the code + that assumes Qnil is zero should verify (NIL_IS_ZERO), to make it easy + to find such assumptions later if we change Qnil to be nonzero. */ +enum { NIL_IS_ZERO = XLI_BUILTIN_LISPSYM (iQnil) == 0 }; + +/* Clear the object addressed by P, with size NBYTES, so that all its + bytes are zero and all its Lisp values are nil. */ +INLINE void +memclear (void *p, ptrdiff_t nbytes) +{ + eassert (0 <= nbytes); + verify (NIL_IS_ZERO); + /* Since Qnil is zero, memset suffices. */ + memset (p, 0, nbytes); +} + /* If a struct is made to look like a vector, this macro returns the length of the shortest vector that would hold that struct. */ @@ -1255,14 +1612,14 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) /* Compute A OP B, using the unsigned comparison operator OP. A and B should be integer expressions. This is not the same as mathematical comparison; for example, UNSIGNED_CMP (0, <, -1) - returns 1. For efficiency, prefer plain unsigned comparison if A + returns true. For efficiency, prefer plain unsigned comparison if A and B's sizes both fit (after integer promotion). */ #define UNSIGNED_CMP(a, op, b) \ (max (sizeof ((a) + 0), sizeof ((b) + 0)) <= sizeof (unsigned) \ ? ((a) + (unsigned) 0) op ((b) + (unsigned) 0) \ : ((a) + (uintmax_t) 0) op ((b) + (uintmax_t) 0)) -/* Nonzero iff C is an ASCII character. */ +/* True iff C is an ASCII character. */ #define ASCII_CHAR_P(c) UNSIGNED_CMP (c, <, 0x80) /* A char-table is a kind of vectorlike, with contents are like a @@ -1270,10 +1627,11 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) 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 - 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. */ + specific range of characters. A sub char-table is like a vector but + with two integer fields between the header and Lisp data, which means + that it has to be marked with some precautions (see mark_char_table + in alloc.c). 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. */ enum CHARTAB_SIZE_BITS { @@ -1328,16 +1686,16 @@ struct Lisp_Sub_Char_Table 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; + int depth; /* Minimum character covered by the sub char-table. */ - Lisp_Object min_char; + int min_char; /* Use set_sub_char_table_contents to set this. */ Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; }; -LISP_INLINE Lisp_Object +INLINE Lisp_Object CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx) { struct Lisp_Char_Table *tbl = NULL; @@ -1357,7 +1715,7 @@ CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx) /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII characters. Do not check validity of CT. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object CHAR_TABLE_REF (Lisp_Object ct, int idx) { return (ASCII_CHAR_P (idx) @@ -1367,7 +1725,7 @@ CHAR_TABLE_REF (Lisp_Object ct, int idx) /* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and 8-bit European characters. Do not check validity of CT. */ -LISP_INLINE void +INLINE void CHAR_TABLE_SET (Lisp_Object ct, int idx, Lisp_Object val) { if (ASCII_CHAR_P (idx) && SUB_CHAR_TABLE_P (XCHAR_TABLE (ct)->ascii)) @@ -1402,137 +1760,88 @@ struct Lisp_Subr const char *doc; }; -/* This is the number of slots that every char table must have. This - counts the ordinary slots and the top, defalt, parent, and purpose - slots. */ -enum CHAR_TABLE_STANDARD_SLOTS +enum char_table_specials { - CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras) + /* 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. */ + CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras), + + /* This is an index of first Lisp_Object field in Lisp_Sub_Char_Table + when the latter is treated as an ordinary Lisp_Vector. */ + SUB_CHAR_TABLE_OFFSET = PSEUDOVECSIZE (struct Lisp_Sub_Char_Table, contents) }; /* Return the number of "extra" slots in the char table CT. */ -LISP_INLINE int +INLINE int CHAR_TABLE_EXTRA_SLOTS (struct Lisp_Char_Table *ct) { return ((ct->header.size & PSEUDOVECTOR_SIZE_MASK) - CHAR_TABLE_STANDARD_SLOTS); } - +/* Make sure that sub char-table contents slot is where we think it is. */ +verify (offsetof (struct Lisp_Sub_Char_Table, contents) + == offsetof (struct Lisp_Vector, contents[SUB_CHAR_TABLE_OFFSET])); + /*********************************************************************** Symbols ***********************************************************************/ -/* Interned state of a symbol. */ - -enum symbol_interned -{ - SYMBOL_UNINTERNED = 0, - SYMBOL_INTERNED = 1, - SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2 -}; - -enum symbol_redirect -{ - SYMBOL_PLAINVAL = 4, - SYMBOL_VARALIAS = 1, - SYMBOL_LOCALIZED = 2, - SYMBOL_FORWARDED = 3 -}; - -struct Lisp_Symbol -{ - unsigned gcmarkbit : 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_BF (symbol_redirect) redirect : 3; - - /* Non-zero means symbol is constant, i.e. changing its value - 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. */ - unsigned interned : 2; - - /* Non-zero means that this variable has been explicitly declared - special (with `defvar' etc), and shouldn't be lexically bound. */ - unsigned declared_special : 1; - - /* The symbol's name, as a Lisp string. */ - Lisp_Object name; - - /* Value of the symbol or Qunbound if unbound. Which alternative of the - union is used depends on the `redirect' field above. */ - 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 Qnil if not fboundp. */ - Lisp_Object function; - - /* The symbol's property list. */ - Lisp_Object plist; - - /* Next symbol in obarray bucket, if the symbol is interned. */ - struct Lisp_Symbol *next; -}; - /* Value is name of symbol. */ -LISP_MACRO_DEFUN (SYMBOL_VAL, Lisp_Object, (struct Lisp_Symbol *sym), (sym)) +INLINE Lisp_Object +(SYMBOL_VAL) (struct Lisp_Symbol *sym) +{ + return lisp_h_SYMBOL_VAL (sym); +} -LISP_INLINE struct Lisp_Symbol * +INLINE struct Lisp_Symbol * SYMBOL_ALIAS (struct Lisp_Symbol *sym) { eassert (sym->redirect == SYMBOL_VARALIAS); return sym->val.alias; } -LISP_INLINE struct Lisp_Buffer_Local_Value * +INLINE struct Lisp_Buffer_Local_Value * SYMBOL_BLV (struct Lisp_Symbol *sym) { eassert (sym->redirect == SYMBOL_LOCALIZED); return sym->val.blv; } -LISP_INLINE union Lisp_Fwd * +INLINE union Lisp_Fwd * SYMBOL_FWD (struct Lisp_Symbol *sym) { eassert (sym->redirect == SYMBOL_FORWARDED); return sym->val.fwd; } -LISP_MACRO_DEFUN_VOID (SET_SYMBOL_VAL, - (struct Lisp_Symbol *sym, Lisp_Object v), (sym, v)) +INLINE void +(SET_SYMBOL_VAL) (struct Lisp_Symbol *sym, Lisp_Object v) +{ + lisp_h_SET_SYMBOL_VAL (sym, v); +} -LISP_INLINE void +INLINE void SET_SYMBOL_ALIAS (struct Lisp_Symbol *sym, struct Lisp_Symbol *v) { eassert (sym->redirect == SYMBOL_VARALIAS); sym->val.alias = v; } -LISP_INLINE void +INLINE void SET_SYMBOL_BLV (struct Lisp_Symbol *sym, struct Lisp_Buffer_Local_Value *v) { eassert (sym->redirect == SYMBOL_LOCALIZED); sym->val.blv = v; } -LISP_INLINE void +INLINE void SET_SYMBOL_FWD (struct Lisp_Symbol *sym, union Lisp_Fwd *v) { eassert (sym->redirect == SYMBOL_FORWARDED); sym->val.fwd = v; } -LISP_INLINE Lisp_Object +INLINE Lisp_Object SYMBOL_NAME (Lisp_Object sym) { return XSYMBOL (sym)->name; @@ -1540,7 +1849,7 @@ SYMBOL_NAME (Lisp_Object sym) /* Value is true if SYM is an interned symbol. */ -LISP_INLINE bool +INLINE bool SYMBOL_INTERNED_P (Lisp_Object sym) { return XSYMBOL (sym)->interned != SYMBOL_UNINTERNED; @@ -1548,7 +1857,7 @@ SYMBOL_INTERNED_P (Lisp_Object sym) /* Value is true if SYM is interned in initial_obarray. */ -LISP_INLINE bool +INLINE bool SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (Lisp_Object sym) { return XSYMBOL (sym)->interned == SYMBOL_INTERNED_IN_INITIAL_OBARRAY; @@ -1558,10 +1867,15 @@ SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (Lisp_Object sym) value cannot be changed (there is an exception for keyword symbols, whose value can be set to the keyword symbol itself). */ -LISP_MACRO_DEFUN (SYMBOL_CONSTANT_P, int, (Lisp_Object sym), (sym)) +INLINE int +(SYMBOL_CONSTANT_P) (Lisp_Object sym) +{ + return lisp_h_SYMBOL_CONSTANT_P (sym); +} -#define DEFSYM(sym, name) \ - do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (0) +/* Placeholder for make-docfile to process. The actual symbol + definition is done by lread.c's defsym. */ +#define DEFSYM(sym, name) /* empty */ /*********************************************************************** @@ -1606,8 +1920,8 @@ struct Lisp_Hash_Table ratio, a float. */ Lisp_Object rehash_threshold; - /* Vector of hash codes.. If hash[I] is nil, this means that that - entry I is unused. */ + /* Vector of hash codes. If hash[I] is nil, this means that the + I-th entry is unused. */ Lisp_Object hash; /* Vector used to chain entries. If entry I is free, next[I] is the @@ -1644,7 +1958,7 @@ struct Lisp_Hash_Table }; -LISP_INLINE struct Lisp_Hash_Table * +INLINE struct Lisp_Hash_Table * XHASH_TABLE (Lisp_Object a) { return XUNTAG (a, Lisp_Vectorlike); @@ -1653,21 +1967,21 @@ XHASH_TABLE (Lisp_Object a) #define XSET_HASH_TABLE(VAR, PTR) \ (XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE)) -LISP_INLINE bool +INLINE bool HASH_TABLE_P (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_HASH_TABLE); } /* Value is the key part of entry IDX in hash table H. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object HASH_KEY (struct Lisp_Hash_Table *h, ptrdiff_t idx) { return AREF (h->key_and_value, 2 * idx); } /* Value is the value part of entry IDX in hash table H. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx) { return AREF (h->key_and_value, 2 * idx + 1); @@ -1675,14 +1989,14 @@ HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx) /* Value is the index of the next entry following the one at IDX in hash table H. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx) { return AREF (h->next, idx); } /* Value is the hash code computed for entry IDX in hash table H. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) { return AREF (h->hash, idx); @@ -1690,14 +2004,14 @@ HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx) /* Value is the index of the element in hash table H that is the start of the collision list at index IDX in the index vector of H. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) { return AREF (h->index, idx); } /* Value is the size of hash table H. */ -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t HASH_TABLE_SIZE (struct Lisp_Hash_Table *h) { return ASIZE (h->next); @@ -1720,7 +2034,7 @@ static double const DEFAULT_REHASH_SIZE = 1.5; /* Combine two integers X and Y for hashing. The result might not fit into a Lisp integer. */ -LISP_INLINE EMACS_UINT +INLINE EMACS_UINT sxhash_combine (EMACS_UINT x, EMACS_UINT y) { return (x << 4) + (x >> (BITS_PER_EMACS_INT - 4)) + y; @@ -1728,7 +2042,7 @@ sxhash_combine (EMACS_UINT x, EMACS_UINT y) /* Hash X, returning a value that fits into a fixnum. */ -LISP_INLINE EMACS_UINT +INLINE EMACS_UINT SXHASH_REDUCE (EMACS_UINT x) { return (x ^ x >> (BITS_PER_EMACS_INT - FIXNUM_BITS)) & INTMASK; @@ -1739,22 +2053,22 @@ SXHASH_REDUCE (EMACS_UINT x) struct Lisp_Misc_Any /* Supertype of all Misc types. */ { ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_??? */ - unsigned gcmarkbit : 1; - int spacer : 15; + bool_bf gcmarkbit : 1; + unsigned spacer : 15; }; struct Lisp_Marker { ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Marker */ - unsigned gcmarkbit : 1; - int spacer : 13; + bool_bf gcmarkbit : 1; + unsigned spacer : 13; /* This flag is temporarily used in the functions decode/encode_coding_object to record that the marker position must be adjusted after the conversion. */ - unsigned int need_adjustment : 1; - /* 1 means normal insertion at the marker's position + bool_bf need_adjustment : 1; + /* True means normal insertion at the marker's position leaves the marker after the inserted text. */ - unsigned int insertion_type : 1; + bool_bf insertion_type : 1; /* This is the buffer that the marker points into, or 0 if it points nowhere. Note: a chain of markers can contain markers pointing into different buffers (the chain is per buffer_text rather than per buffer, so it's @@ -1800,8 +2114,8 @@ struct Lisp_Overlay */ { ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Overlay */ - unsigned gcmarkbit : 1; - int spacer : 15; + bool_bf gcmarkbit : 1; + unsigned spacer : 15; struct Lisp_Overlay *next; Lisp_Object start; Lisp_Object end; @@ -1878,8 +2192,8 @@ typedef void (*voidfuncptr) (void); struct Lisp_Save_Value { ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */ - unsigned gcmarkbit : 1; - int spacer : 32 - (16 + 1 + SAVE_TYPE_BITS); + bool_bf gcmarkbit : 1; + unsigned spacer : 32 - (16 + 1 + SAVE_TYPE_BITS); /* V->data may hold up to SAVE_VALUE_SLOTS entries. The type of V's data entries are determined by V->save_type. E.g., if @@ -1898,7 +2212,7 @@ struct Lisp_Save_Value }; /* Return the type of V's Nth saved value. */ -LISP_INLINE int +INLINE int save_type (struct Lisp_Save_Value *v, int n) { eassert (0 <= n && n < SAVE_VALUE_SLOTS); @@ -1907,19 +2221,19 @@ save_type (struct Lisp_Save_Value *v, int n) /* Get and set the Nth saved pointer. */ -LISP_INLINE void * +INLINE void * XSAVE_POINTER (Lisp_Object obj, int n) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER); return XSAVE_VALUE (obj)->data[n].pointer; } -LISP_INLINE void +INLINE void set_save_pointer (Lisp_Object obj, int n, void *val) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_POINTER); XSAVE_VALUE (obj)->data[n].pointer = val; } -LISP_INLINE voidfuncptr +INLINE voidfuncptr XSAVE_FUNCPOINTER (Lisp_Object obj, int n) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_FUNCPOINTER); @@ -1928,13 +2242,13 @@ XSAVE_FUNCPOINTER (Lisp_Object obj, int n) /* Likewise for the saved integer. */ -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t XSAVE_INTEGER (Lisp_Object obj, int n) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER); return XSAVE_VALUE (obj)->data[n].integer; } -LISP_INLINE void +INLINE void set_save_integer (Lisp_Object obj, int n, ptrdiff_t val) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_INTEGER); @@ -1943,19 +2257,34 @@ set_save_integer (Lisp_Object obj, int n, ptrdiff_t val) /* Extract Nth saved object. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object XSAVE_OBJECT (Lisp_Object obj, int n) { eassert (save_type (XSAVE_VALUE (obj), n) == SAVE_OBJECT); return XSAVE_VALUE (obj)->data[n].object; } +/* A finalizer sentinel. */ +struct Lisp_Finalizer + { + struct Lisp_Misc_Any base; + + /* Circular list of all active weak references. */ + struct Lisp_Finalizer *prev; + struct Lisp_Finalizer *next; + + /* Call FUNCTION when the finalizer becomes unreachable, even if + FUNCTION contains a reference to the finalizer; i.e., call + FUNCTION when it is reachable _only_ through finalizers. */ + Lisp_Object function; + }; + /* A miscellaneous object, when it's on the free list. */ struct Lisp_Free { ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Free */ - unsigned gcmarkbit : 1; - int spacer : 15; + bool_bf gcmarkbit : 1; + unsigned spacer : 15; union Lisp_Misc *chain; }; @@ -1969,47 +2298,56 @@ union Lisp_Misc struct Lisp_Marker u_marker; struct Lisp_Overlay u_overlay; struct Lisp_Save_Value u_save_value; + struct Lisp_Finalizer u_finalizer; }; -LISP_INLINE union Lisp_Misc * +INLINE union Lisp_Misc * XMISC (Lisp_Object a) { return XUNTAG (a, Lisp_Misc); } -LISP_INLINE struct Lisp_Misc_Any * +INLINE struct Lisp_Misc_Any * XMISCANY (Lisp_Object a) { eassert (MISCP (a)); return & XMISC (a)->u_any; } -LISP_INLINE enum Lisp_Misc_Type +INLINE enum Lisp_Misc_Type XMISCTYPE (Lisp_Object a) { return XMISCANY (a)->type; } -LISP_INLINE struct Lisp_Marker * +INLINE struct Lisp_Marker * XMARKER (Lisp_Object a) { eassert (MARKERP (a)); return & XMISC (a)->u_marker; } -LISP_INLINE struct Lisp_Overlay * +INLINE struct Lisp_Overlay * XOVERLAY (Lisp_Object a) { eassert (OVERLAYP (a)); return & XMISC (a)->u_overlay; } -LISP_INLINE struct Lisp_Save_Value * +INLINE struct Lisp_Save_Value * XSAVE_VALUE (Lisp_Object a) { eassert (SAVE_VALUEP (a)); return & XMISC (a)->u_save_value; } + +INLINE struct Lisp_Finalizer * +XFINALIZER (Lisp_Object a) +{ + eassert (FINALIZERP (a)); + return & XMISC (a)->u_finalizer; +} + /* Forwarding pointer to an int variable. This is allowed only in the value cell of a symbol, @@ -2023,8 +2361,8 @@ struct Lisp_Intfwd /* Boolean forwarding pointer to an int variable. This is like Lisp_Intfwd except that the ostensible - "value" of the symbol is t if the int variable is nonzero, - nil if it is zero. */ + "value" of the symbol is t if the bool variable is true, + nil if it is false. */ struct Lisp_Boolfwd { enum Lisp_Fwd_Type type; /* = Lisp_Fwd_Bool */ @@ -2077,15 +2415,15 @@ struct Lisp_Buffer_Objfwd struct Lisp_Buffer_Local_Value { - /* 1 means that merely setting the variable creates a local + /* True means that merely setting the variable creates a local binding for the current buffer. */ - unsigned int local_if_set : 1; - /* 1 means this variable can have frame-local bindings, otherwise, it is + bool_bf local_if_set : 1; + /* True 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. + bool_bf frame_local : 1; + /* True means that the binding now loaded was found. Presumably equivalent to (defcell!=valcell). */ - unsigned int found : 1; + bool_bf 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. */ @@ -2118,13 +2456,13 @@ union Lisp_Fwd struct Lisp_Kboard_Objfwd u_kboard_objfwd; }; -LISP_INLINE enum Lisp_Fwd_Type +INLINE enum Lisp_Fwd_Type XFWDTYPE (union Lisp_Fwd *a) { return a->u_intfwd.type; } -LISP_INLINE struct Lisp_Buffer_Objfwd * +INLINE struct Lisp_Buffer_Objfwd * XBUFFER_OBJFWD (union Lisp_Fwd *a) { eassert (BUFFER_OBJFWDP (a)); @@ -2141,7 +2479,7 @@ struct Lisp_Float } u; }; -LISP_INLINE double +INLINE double XFLOAT_DATA (Lisp_Object f) { return XFLOAT (f)->u.data; @@ -2201,54 +2539,26 @@ enum char_bits CHARACTERBITS = 22 }; -/* Structure to hold mouse highlight data. This is here because other - header files need it for defining struct x_output etc. */ -typedef struct { - /* These variables describe the range of text currently shown in its - mouse-face, together with the window they apply to. As long as - the mouse stays within this range, we need not redraw anything on - its account. Rows and columns are glyph matrix positions in - MOUSE_FACE_WINDOW. */ - int mouse_face_beg_row, mouse_face_beg_col; - int mouse_face_beg_x, mouse_face_beg_y; - int mouse_face_end_row, mouse_face_end_col; - int mouse_face_end_x, mouse_face_end_y; - Lisp_Object mouse_face_window; - int mouse_face_face_id; - Lisp_Object mouse_face_overlay; - - /* FRAME and X, Y position of mouse when last checked for - highlighting. X and Y can be negative or out of range for the frame. */ - struct frame *mouse_face_mouse_frame; - int mouse_face_mouse_x, mouse_face_mouse_y; - - /* Nonzero if part of the text currently shown in - its mouse-face is beyond the window end. */ - unsigned mouse_face_past_end : 1; - - /* Nonzero means defer mouse-motion highlighting. */ - unsigned mouse_face_defer : 1; - - /* Nonzero means that the mouse highlight should not be shown. */ - unsigned mouse_face_hidden : 1; -} Mouse_HLInfo; - /* Data type checking. */ -LISP_MACRO_DEFUN (NILP, bool, (Lisp_Object x), (x)) +INLINE bool +(NILP) (Lisp_Object x) +{ + return lisp_h_NILP (x); +} -LISP_INLINE bool +INLINE bool NUMBERP (Lisp_Object x) { return INTEGERP (x) || FLOATP (x); } -LISP_INLINE bool +INLINE bool NATNUMP (Lisp_Object x) { return INTEGERP (x) && 0 <= XINT (x); } -LISP_INLINE bool +INLINE bool RANGED_INTEGERP (intmax_t lo, Lisp_Object x, intmax_t hi) { return INTEGERP (x) && lo <= XINT (x) && XINT (x) <= hi; @@ -2259,48 +2569,82 @@ RANGED_INTEGERP (intmax_t lo, Lisp_Object x, intmax_t hi) && (TYPE_SIGNED (type) ? TYPE_MINIMUM (type) <= XINT (x) : 0 <= XINT (x)) \ && XINT (x) <= TYPE_MAXIMUM (type)) -LISP_MACRO_DEFUN (CONSP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (FLOATP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (MISCP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (SYMBOLP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (INTEGERP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (VECTORLIKEP, bool, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN (MARKERP, bool, (Lisp_Object x), (x)) +INLINE bool +(CONSP) (Lisp_Object x) +{ + return lisp_h_CONSP (x); +} +INLINE bool +(FLOATP) (Lisp_Object x) +{ + return lisp_h_FLOATP (x); +} +INLINE bool +(MISCP) (Lisp_Object x) +{ + return lisp_h_MISCP (x); +} +INLINE bool +(SYMBOLP) (Lisp_Object x) +{ + return lisp_h_SYMBOLP (x); +} +INLINE bool +(INTEGERP) (Lisp_Object x) +{ + return lisp_h_INTEGERP (x); +} +INLINE bool +(VECTORLIKEP) (Lisp_Object x) +{ + return lisp_h_VECTORLIKEP (x); +} +INLINE bool +(MARKERP) (Lisp_Object x) +{ + return lisp_h_MARKERP (x); +} -LISP_INLINE bool +INLINE bool STRINGP (Lisp_Object x) { return XTYPE (x) == Lisp_String; } -LISP_INLINE bool +INLINE bool VECTORP (Lisp_Object x) { return VECTORLIKEP (x) && ! (ASIZE (x) & PSEUDOVECTOR_FLAG); } -LISP_INLINE bool +INLINE bool OVERLAYP (Lisp_Object x) { return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay; } -LISP_INLINE bool +INLINE bool SAVE_VALUEP (Lisp_Object x) { return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value; } -LISP_INLINE bool +INLINE bool +FINALIZERP (Lisp_Object x) +{ + return MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Finalizer; +} + +INLINE bool AUTOLOADP (Lisp_Object x) { return CONSP (x) && EQ (Qautoload, XCAR (x)); } -LISP_INLINE bool +INLINE bool BUFFER_OBJFWDP (union Lisp_Fwd *a) { return XFWDTYPE (a) == Lisp_Fwd_Buffer_Obj; } -LISP_INLINE bool +INLINE bool PSEUDOVECTOR_TYPEP (struct vectorlike_header *a, int code) { return ((a->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) @@ -2308,11 +2652,11 @@ PSEUDOVECTOR_TYPEP (struct vectorlike_header *a, int code) } /* True if A is a pseudovector whose code is CODE. */ -LISP_INLINE bool +INLINE bool PSEUDOVECTORP (Lisp_Object a, int code) { if (! VECTORLIKEP (a)) - return 0; + return false; else { /* Converting to struct vectorlike_header * avoids aliasing issues. */ @@ -2324,160 +2668,186 @@ PSEUDOVECTORP (Lisp_Object a, int code) /* Test for specific pseudovector types. */ -LISP_INLINE bool +INLINE bool WINDOW_CONFIGURATIONP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_WINDOW_CONFIGURATION); } -LISP_INLINE bool +INLINE bool PROCESSP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_PROCESS); } -LISP_INLINE bool +INLINE bool WINDOWP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_WINDOW); } -LISP_INLINE bool +INLINE bool TERMINALP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_TERMINAL); } -LISP_INLINE bool +INLINE bool SUBRP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_SUBR); } -LISP_INLINE bool +INLINE bool COMPILEDP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_COMPILED); } -LISP_INLINE bool +INLINE bool BUFFERP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_BUFFER); } -LISP_INLINE bool +INLINE bool CHAR_TABLE_P (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_CHAR_TABLE); } -LISP_INLINE bool +INLINE bool SUB_CHAR_TABLE_P (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_SUB_CHAR_TABLE); } -LISP_INLINE bool +INLINE bool BOOL_VECTOR_P (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_BOOL_VECTOR); } -LISP_INLINE bool +INLINE bool FRAMEP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_FRAME); } -LISP_INLINE bool +INLINE bool THREADP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_THREAD); } -LISP_INLINE bool +INLINE bool MUTEXP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_MUTEX); } -LISP_INLINE bool +INLINE bool CONDVARP (Lisp_Object a) { return PSEUDOVECTORP (a, PVEC_CONDVAR); } /* Test for image (image . spec) */ -LISP_INLINE bool +INLINE bool IMAGEP (Lisp_Object x) { return CONSP (x) && EQ (XCAR (x), Qimage); } /* Array types. */ -LISP_INLINE bool +INLINE bool ARRAYP (Lisp_Object x) { return VECTORP (x) || STRINGP (x) || CHAR_TABLE_P (x) || BOOL_VECTOR_P (x); } -LISP_INLINE void +INLINE void CHECK_LIST (Lisp_Object x) { CHECK_TYPE (CONSP (x) || NILP (x), Qlistp, x); } -LISP_MACRO_DEFUN_VOID (CHECK_LIST_CONS, (Lisp_Object x, Lisp_Object y), (x, y)) -LISP_MACRO_DEFUN_VOID (CHECK_SYMBOL, (Lisp_Object x), (x)) -LISP_MACRO_DEFUN_VOID (CHECK_NUMBER, (Lisp_Object x), (x)) +INLINE void +(CHECK_LIST_CONS) (Lisp_Object x, Lisp_Object y) +{ + lisp_h_CHECK_LIST_CONS (x, y); +} + +INLINE void +(CHECK_SYMBOL) (Lisp_Object x) +{ + lisp_h_CHECK_SYMBOL (x); +} + +INLINE void +(CHECK_NUMBER) (Lisp_Object x) +{ + lisp_h_CHECK_NUMBER (x); +} -LISP_INLINE void +INLINE void CHECK_STRING (Lisp_Object x) { CHECK_TYPE (STRINGP (x), Qstringp, x); } -LISP_INLINE void +INLINE void CHECK_STRING_CAR (Lisp_Object x) { CHECK_TYPE (STRINGP (XCAR (x)), Qstringp, XCAR (x)); } -LISP_INLINE void +INLINE void CHECK_CONS (Lisp_Object x) { CHECK_TYPE (CONSP (x), Qconsp, x); } -LISP_INLINE void +INLINE void CHECK_VECTOR (Lisp_Object x) { CHECK_TYPE (VECTORP (x), Qvectorp, x); } -LISP_INLINE void +INLINE void +CHECK_BOOL_VECTOR (Lisp_Object x) +{ + CHECK_TYPE (BOOL_VECTOR_P (x), Qbool_vector_p, x); +} +/* This is a bit special because we always need size afterwards. */ +INLINE ptrdiff_t CHECK_VECTOR_OR_STRING (Lisp_Object x) { - CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x); + if (VECTORP (x)) + return ASIZE (x); + if (STRINGP (x)) + return SCHARS (x); + wrong_type_argument (Qarrayp, x); } -LISP_INLINE void -CHECK_ARRAY (Lisp_Object x, Lisp_Object Qxxxp) +INLINE void +CHECK_ARRAY (Lisp_Object x, Lisp_Object predicate) { - CHECK_TYPE (ARRAYP (x), Qxxxp, x); + CHECK_TYPE (ARRAYP (x), predicate, x); } -LISP_INLINE void +INLINE void CHECK_BUFFER (Lisp_Object x) { CHECK_TYPE (BUFFERP (x), Qbufferp, x); } -LISP_INLINE void +INLINE void CHECK_WINDOW (Lisp_Object x) { CHECK_TYPE (WINDOWP (x), Qwindowp, x); } -LISP_INLINE void +#ifdef subprocesses +INLINE void CHECK_PROCESS (Lisp_Object x) { CHECK_TYPE (PROCESSP (x), Qprocessp, x); } -LISP_INLINE void +#endif +INLINE void CHECK_NATNUM (Lisp_Object x) { CHECK_TYPE (NATNUMP (x), Qwholenump, x); @@ -2493,49 +2863,57 @@ CHECK_NATNUM (Lisp_Object x) ? MOST_NEGATIVE_FIXNUM \ : (lo)), \ make_number (min (hi, MOST_POSITIVE_FIXNUM))); \ - } while (0) + } while (false) #define CHECK_TYPE_RANGED_INTEGER(type, x) \ do { \ if (TYPE_SIGNED (type)) \ CHECK_RANGED_INTEGER (x, TYPE_MINIMUM (type), TYPE_MAXIMUM (type)); \ else \ CHECK_RANGED_INTEGER (x, 0, TYPE_MAXIMUM (type)); \ - } while (0) + } while (false) -#define CHECK_NUMBER_COERCE_MARKER(x) \ - do { if (MARKERP ((x))) XSETFASTINT (x, marker_position (x)); \ - else CHECK_TYPE (INTEGERP (x), Qinteger_or_marker_p, x); } while (0) +#define CHECK_NUMBER_COERCE_MARKER(x) \ + do { \ + if (MARKERP ((x))) \ + XSETFASTINT (x, marker_position (x)); \ + else \ + CHECK_TYPE (INTEGERP (x), Qinteger_or_marker_p, x); \ + } while (false) -LISP_INLINE double +INLINE double XFLOATINT (Lisp_Object n) { return extract_float (n); } -LISP_INLINE void +INLINE void CHECK_NUMBER_OR_FLOAT (Lisp_Object x) { - CHECK_TYPE (FLOATP (x) || INTEGERP (x), Qnumberp, x); + CHECK_TYPE (NUMBERP (x), Qnumberp, x); } -#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(x) \ - do { if (MARKERP (x)) XSETFASTINT (x, marker_position (x)); \ - else CHECK_TYPE (INTEGERP (x) || FLOATP (x), Qnumber_or_marker_p, x); } while (0) +#define CHECK_NUMBER_OR_FLOAT_COERCE_MARKER(x) \ + do { \ + if (MARKERP (x)) \ + XSETFASTINT (x, marker_position (x)); \ + else \ + CHECK_TYPE (NUMBERP (x), Qnumber_or_marker_p, x); \ + } while (false) -LISP_INLINE void +INLINE void CHECK_THREAD (Lisp_Object x) { CHECK_TYPE (THREADP (x), Qthreadp, x); } -LISP_INLINE void +INLINE void CHECK_MUTEX (Lisp_Object x) { CHECK_TYPE (MUTEXP (x), Qmutexp, x); } -LISP_INLINE void +INLINE void CHECK_CONDVAR (Lisp_Object x) { CHECK_TYPE (CONDVARP (x), Qcondition_variable_p, x); @@ -2543,7 +2921,7 @@ CHECK_CONDVAR (Lisp_Object x) /* Since we can't assign directly to the CAR or CDR fields of a cons cell, use these when checking that those fields contain numbers. */ -LISP_INLINE void +INLINE void CHECK_NUMBER_CAR (Lisp_Object x) { Lisp_Object tmp = XCAR (x); @@ -2551,7 +2929,7 @@ CHECK_NUMBER_CAR (Lisp_Object x) XSETCAR (x, tmp); } -LISP_INLINE void +INLINE void CHECK_NUMBER_CDR (Lisp_Object x) { Lisp_Object tmp = XCDR (x); @@ -2596,40 +2974,16 @@ CHECK_NUMBER_CDR (Lisp_Object x) minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #else /* not _MSC_VER */ -# if __STDC_VERSION__ < 199901 -# define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname -# else -# define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname -# endif #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ - Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ - { DEFUN_FUNCTION_INIT (fnname, maxargs) }, \ + { .a ## maxargs = fnname }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #endif -/* Note that the weird token-substitution semantics of ANSI C makes - this work for MANY and UNEVALLED. */ -#define DEFUN_ARGS_MANY (ptrdiff_t, Lisp_Object *) -#define DEFUN_ARGS_UNEVALLED (Lisp_Object) -#define DEFUN_ARGS_0 (void) -#define DEFUN_ARGS_1 (Lisp_Object) -#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object) -#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object) -#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) -#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ - Lisp_Object) -#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ - Lisp_Object, Lisp_Object) -#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ - 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) - /* True if OBJ is a Lisp function. */ -LISP_INLINE bool +INLINE bool FUNCTIONP (Lisp_Object obj) { return functionp (obj); @@ -2645,6 +2999,15 @@ enum maxargs UNEVALLED = -1 }; +/* Call a function F that accepts many args, passing it ARRAY's elements. */ +#define CALLMANY(f, array) (f) (ARRAYELTS (array), array) + +/* Call a function F that accepts many args, passing it the remaining args, + E.g., 'return CALLN (Fformat, fmt, text);' is less error-prone than + '{ Lisp_Object a[2]; a[0] = fmt; a[1] = text; return Fformat (2, a); }'. + CALLN is overkill for simple usages like 'Finsert (1, &text);'. */ +#define CALLN(f, ...) CALLMANY (f, ((Lisp_Object []) {__VA_ARGS__})) + 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 *, bool *); @@ -2672,34 +3035,34 @@ extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int); do { \ static struct Lisp_Objfwd o_fwd; \ defvar_lisp (&o_fwd, lname, &globals.f_ ## vname); \ - } while (0) + } while (false) #define DEFVAR_LISP_NOPRO(lname, vname, doc) \ do { \ static struct Lisp_Objfwd o_fwd; \ defvar_lisp_nopro (&o_fwd, lname, &globals.f_ ## vname); \ - } while (0) + } while (false) #define DEFVAR_BOOL(lname, vname, doc) \ do { \ static struct Lisp_Boolfwd b_fwd; \ defvar_bool (&b_fwd, lname, &globals.f_ ## vname); \ - } while (0) + } while (false) #define DEFVAR_INT(lname, vname, doc) \ do { \ static struct Lisp_Intfwd i_fwd; \ defvar_int (&i_fwd, lname, &globals.f_ ## vname); \ - } while (0) + } while (false) #define DEFVAR_BUFFER_DEFAULTS(lname, vname, doc) \ do { \ static struct Lisp_Objfwd o_fwd; \ defvar_lisp_nopro (&o_fwd, lname, &BVAR (&buffer_defaults, vname)); \ - } while (0) + } while (false) #define DEFVAR_KBOARD(lname, vname, doc) \ do { \ static struct Lisp_Kboard_Objfwd ko_fwd; \ defvar_kboard (&ko_fwd, lname, offsetof (KBOARD, vname ## _)); \ - } while (0) + } while (false) /* Save and restore the instruction and environment pointers, without affecting the signal mask. */ @@ -2728,11 +3091,9 @@ typedef jmp_buf sys_jmp_buf; - The specpdl stack: keeps track of active unwind-protect and dynamic-let-bindings. Allocated from the `specpdl' array, a manually managed stack. - - The catch stack: keeps track of active catch tags. - Allocated on the C stack. This is where the setmp data is kept. - - The handler stack: keeps track of active condition-case handlers. - Allocated on the C stack. Every entry there also uses an entry in - the catch stack. */ + - The handler stack: keeps track of active catch tags and condition-case + handlers. Allocated in a manually managed stack implemented by a + doubly-linked list allocated via xmalloc and never freed. */ /* Structure for recording Lisp call stack for backtrace purposes. */ @@ -2740,19 +3101,6 @@ typedef jmp_buf sys_jmp_buf; they are bound by a function application or a let form, stores the code to be executed for unwind-protect forms. - If func is non-zero, undoing this binding applies func to old_value; - This implements record_unwind_protect. - - Otherwise, the element is a variable binding. - - If the symbol field is a symbol, it is an ordinary variable binding. - - Otherwise, it should be a structure (SYMBOL WHERE . CURRENT-BUFFER), - which means having bound a local value while CURRENT-BUFFER was active. - If WHERE is nil this means we saw the default value when binding SYMBOL. - WHERE being a buffer or frame means we saw a buffer-local or frame-local - value. Other values of WHERE mean an internal error. - NOTE: The specbinding union is defined here, because SPECPDL_INDEX is used all over the place, needs to be fast, and needs to know the size of union specbinding. But only eval.c should access it. */ @@ -2801,7 +3149,7 @@ union specbinding } let; struct { ENUM_BF (specbind_tag) kind : CHAR_BIT; - bool debug_on_exit : 1; + bool_bf debug_on_exit : 1; Lisp_Object function; Lisp_Object *args; ptrdiff_t nargs; @@ -2812,52 +3160,22 @@ union specbinding /* extern union specbinding *specpdl_ptr; */ /* extern ptrdiff_t specpdl_size; */ -LISP_INLINE ptrdiff_t +INLINE ptrdiff_t SPECPDL_INDEX (void) { return specpdl_ptr - specpdl; } -/* Everything needed to describe an active condition case. - - Members are volatile if their values need to survive _longjmp when - a 'struct handler' is a local variable. */ -struct handler - { - /* The handler clauses and variable from the condition-case form. */ - /* For a handler set up in Lisp code, this is always a list. - For an internal handler set up by internal_condition_case*, - this can instead be the symbol t or `error'. - t: handle all conditions. - error: handle all conditions, and errors can run the debugger - or display a backtrace. */ - Lisp_Object handler; - - Lisp_Object volatile var; - - /* Fsignal stores here the condition-case clause that applies, - and Fcondition_case thus knows which clause to run. */ - Lisp_Object volatile chosen_clause; - - /* Used to effect the longjump out to the handler. */ - struct catchtag *tag; - - /* The next enclosing handler. */ - struct handler *next; - }; +/* This structure helps implement the `catch/throw' and `condition-case/signal' + control structures. A struct handler contains all the information needed to + restore the state of the interpreter after a non-local jump. -/* This structure helps implement the `catch' and `throw' control - structure. A struct catchtag contains all the information needed - to restore the state of the interpreter after a non-local jump. + handler structures are chained together in a doubly linked list; the `next' + member points to the next outer catchtag and the `nextfree' member points in + the other direction to the next inner element (which is typically the next + free element since we mostly use it on the deepest handler). - Handlers for error conditions (represented by `struct handler' - structures) just point to a catch tag to do the cleanup required - for their jumps. - - catchtag structures are chained together in the C calling stack; - the `next' member points to the next outer catchtag. - - A call like (throw TAG VAL) searches for a catchtag whose `tag' + A call like (throw TAG VAL) searches for a catchtag whose `tag_or_ch' member is TAG, and then unbinds to it. The `val' member is used to hold VAL while the stack is unwound; `val' is returned as the value of the catch form. @@ -2866,24 +3184,58 @@ struct handler state. Members are volatile if their values need to survive _longjmp when - a 'struct catchtag' is a local variable. */ -struct catchtag -{ - Lisp_Object tag; - Lisp_Object volatile val; - struct catchtag *volatile next; -#if 1 /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but they're defined later. */ - struct gcpro *gcpro; -#endif + a 'struct handler' is a local variable. */ + +enum handlertype { CATCHER, CONDITION_CASE }; + +struct handler +{ + enum handlertype type; + Lisp_Object tag_or_ch; + Lisp_Object val; + struct handler *next; + struct handler *nextfree; + + /* The bytecode interpreter can have several handlers active at the same + time, so when we longjmp to one of them, it needs to know which handler + this was and what was the corresponding internal state. This is stored + here, and when we longjmp we make sure that handlerlist points to the + proper handler. */ + Lisp_Object *bytecode_top; + int bytecode_dest; + + /* Most global vars are reset to their value via the specpdl mechanism, + but a few others are handled by storing their value here. */ sys_jmp_buf jmp; - struct handler *f_handlerlist; EMACS_INT f_lisp_eval_depth; - ptrdiff_t volatile pdlcount; + ptrdiff_t pdlcount; int poll_suppress_count; int interrupt_input_blocked; struct byte_stack *byte_stack; }; +/* Fill in the components of c, and put it on the list. */ +#define PUSH_HANDLER(c, tag_ch_val, handlertype) \ + if (handlerlist->nextfree) \ + (c) = handlerlist->nextfree; \ + else \ + { \ + (c) = xmalloc (sizeof (struct handler)); \ + (c)->nextfree = NULL; \ + handlerlist->nextfree = (c); \ + } \ + (c)->type = (handlertype); \ + (c)->tag_or_ch = (tag_ch_val); \ + (c)->val = Qnil; \ + (c)->next = handlerlist; \ + (c)->f_lisp_eval_depth = lisp_eval_depth; \ + (c)->pdlcount = SPECPDL_INDEX (); \ + (c)->poll_suppress_count = poll_suppress_count; \ + (c)->interrupt_input_blocked = interrupt_input_blocked;\ + (c)->byte_stack = byte_stack_list; \ + handlerlist = (c); + + extern Lisp_Object memory_signal_data; /* Check quit-flag and quit if it is non-nil. @@ -2894,7 +3246,7 @@ extern Lisp_Object memory_signal_data; Unless that is impossible, of course. But it is very desirable to avoid creating loops where QUIT is impossible. - Exception: if you set immediate_quit to nonzero, + Exception: if you set immediate_quit to true, then the handler that responds to the C-g does the quit itself. This is a good thing to do around a loop that has no side effects and (in particular) cannot call arbitrary Lisp code. @@ -2912,227 +3264,27 @@ extern void process_quit_flag (void); process_quit_flag (); \ else if (pending_signals) \ process_pending_signals (); \ - } while (0) + } while (false) -/* Nonzero if ought to quit now. */ +/* True if ought to quit now. */ #define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) extern Lisp_Object Vascii_downcase_table; extern Lisp_Object Vascii_canon_table; -/* Structure for recording stack slots that need marking. */ - -/* This is a chain of structures, each of which points at a Lisp_Object - variable whose value should be marked in garbage collection. - Normally every link of the chain is an automatic variable of a function, - and its `val' points to some argument or local variable of the function. - On exit to the function, the chain is set back to the value it had on entry. - This way, no link remains in the chain when the stack frame containing the - link disappears. - - Every function that can call Feval must protect in this fashion all - Lisp_Object variables whose contents will be used again. */ - -struct gcpro -{ - struct gcpro *next; - - /* Address of first protected variable. */ - volatile Lisp_Object *var; - - /* Number of consecutive protected variables. */ - ptrdiff_t nvars; - -#ifdef DEBUG_GCPRO - int level; -#endif -}; - -/* Values of GC_MARK_STACK during compilation: - - 0 Use GCPRO as before - 1 Do the real thing, make GCPROs and UNGCPRO no-ops. - 2 Mark the stack, and check that everything GCPRO'd is - marked. - 3 Mark using GCPRO's, mark stack last, and count how many - dead objects are kept alive. - - Formerly, method 0 was used. Currently, method 1 is used unless - otherwise specified by hand when building, e.g., - "make CPPFLAGS='-DGC_MARK_STACK=GC_USE_GCPROS_AS_BEFORE'". - Methods 2 and 3 are present mainly to debug the transition from 0 to 1. */ - -#define GC_USE_GCPROS_AS_BEFORE 0 -#define GC_MAKE_GCPROS_NOOPS 1 -#define GC_MARK_STACK_CHECK_GCPROS 2 -#define GC_USE_GCPROS_CHECK_ZOMBIES 3 - -#ifndef GC_MARK_STACK -#define GC_MARK_STACK GC_MAKE_GCPROS_NOOPS -#endif - -/* Whether we do the stack marking manually. */ -#define BYTE_MARK_STACK !(GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ - || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS) - - -#if GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS - -/* Do something silly with gcproN vars just so gcc shuts up. */ -/* You get warnings from MIPSPro... */ - -#define GCPRO1(varname) ((void) gcpro1) -#define GCPRO2(varname1, varname2) ((void) gcpro2, (void) gcpro1) -#define GCPRO3(varname1, varname2, varname3) \ - ((void) gcpro3, (void) gcpro2, (void) gcpro1) -#define GCPRO4(varname1, varname2, varname3, varname4) \ - ((void) gcpro4, (void) gcpro3, (void) gcpro2, (void) gcpro1) -#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ - ((void) gcpro5, (void) gcpro4, (void) gcpro3, (void) gcpro2, (void) gcpro1) -#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \ - ((void) gcpro6, (void) gcpro5, (void) gcpro4, (void) gcpro3, (void) gcpro2, \ - (void) gcpro1) -#define UNGCPRO ((void) 0) - -#else /* GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS */ - -#ifndef DEBUG_GCPRO - -#define GCPRO1(varname) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \ - gcprolist = &gcpro1; } - -#define GCPRO2(varname1, varname2) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcprolist = &gcpro2; } - -#define GCPRO3(varname1, varname2, varname3) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcprolist = &gcpro3; } - -#define GCPRO4(varname1, varname2, varname3, varname4) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcprolist = &gcpro4; } - -#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcprolist = &gcpro5; } - -#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &varname6; gcpro6.nvars = 1; \ - gcprolist = &gcpro6; } - -#define UNGCPRO (gcprolist = gcpro1.next) - -#else - -#define GCPRO1(varname) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level++; \ - gcprolist = &gcpro1; } - -#define GCPRO2(varname1, varname2) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro2.level = gcpro_level++; \ - gcprolist = &gcpro2; } - -#define GCPRO3(varname1, varname2, varname3) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro3.level = gcpro_level++; \ - gcprolist = &gcpro3; } - -#define GCPRO4(varname1, varname2, varname3, varname4) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro4.level = gcpro_level++; \ - gcprolist = &gcpro4; } - -#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro5.level = gcpro_level++; \ - gcprolist = &gcpro5; } - -#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \ - {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ - gcpro1.level = gcpro_level; \ - gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ - gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ - gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ - gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ - gcpro6.next = &gcpro5; gcpro6.var = &varname6; gcpro6.nvars = 1; \ - gcpro6.level = gcpro_level++; \ - gcprolist = &gcpro6; } - -#define UNGCPRO \ - ((--gcpro_level != gcpro1.level) \ - ? (emacs_abort (), 0) \ - : ((gcprolist = gcpro1.next), 0)) - -#endif /* DEBUG_GCPRO */ -#endif /* GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS */ - - -/* Evaluate expr, UNGCPRO, and then return the value of expr. */ -#define RETURN_UNGCPRO(expr) \ -do \ - { \ - Lisp_Object ret_ungc_val; \ - ret_ungc_val = (expr); \ - UNGCPRO; \ - return ret_ungc_val; \ - } \ -while (0) - /* Call staticpro (&var) to protect static variable `var'. */ void staticpro (Lisp_Object *); -/* Declare a Lisp-callable function. The MAXARGS parameter has the same - meaning as in the DEFUN macro, and is used to construct a prototype. */ -/* 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 - -#include "globals.h" - /* Forward declarations for prototypes. */ struct window; struct frame; /* Copy COUNT Lisp_Objects from ARGS to contents of V starting from OFFSET. */ -LISP_INLINE void +INLINE void vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Object *args, ptrdiff_t count) { eassert (0 <= offset && 0 <= count && offset + count <= ASIZE (v)); @@ -3141,13 +3293,13 @@ vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Object *args, ptrdiff_t count) /* Functions to modify hash tables. */ -LISP_INLINE void +INLINE void set_hash_key_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) { gc_aset (h->key_and_value, 2 * idx, val); } -LISP_INLINE void +INLINE void set_hash_value_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) { gc_aset (h->key_and_value, 2 * idx + 1, val); @@ -3156,19 +3308,19 @@ set_hash_value_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val) /* Use these functions to set Lisp_Object or pointer slots of struct Lisp_Symbol. */ -LISP_INLINE void +INLINE void set_symbol_function (Lisp_Object sym, Lisp_Object function) { XSYMBOL (sym)->function = function; } -LISP_INLINE void +INLINE void set_symbol_plist (Lisp_Object sym, Lisp_Object plist) { XSYMBOL (sym)->plist = plist; } -LISP_INLINE void +INLINE void set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next) { XSYMBOL (sym)->next = next; @@ -3176,7 +3328,7 @@ set_symbol_next (Lisp_Object sym, struct Lisp_Symbol *next) /* Buffer-local (also frame-local) variable access functions. */ -LISP_INLINE int +INLINE int blv_found (struct Lisp_Buffer_Local_Value *blv) { eassert (blv->found == !EQ (blv->defcell, blv->valcell)); @@ -3185,7 +3337,7 @@ blv_found (struct Lisp_Buffer_Local_Value *blv) /* Set overlay's property list. */ -LISP_INLINE void +INLINE void set_overlay_plist (Lisp_Object overlay, Lisp_Object plist) { XOVERLAY (overlay)->plist = plist; @@ -3193,7 +3345,7 @@ set_overlay_plist (Lisp_Object overlay, Lisp_Object plist) /* Get text properties of S. */ -LISP_INLINE INTERVAL +INLINE INTERVAL string_intervals (Lisp_Object s) { return XSTRING (s)->intervals; @@ -3201,7 +3353,7 @@ string_intervals (Lisp_Object s) /* Set text properties of S to I. */ -LISP_INLINE void +INLINE void set_string_intervals (Lisp_Object s, INTERVAL i) { XSTRING (s)->intervals = i; @@ -3210,12 +3362,12 @@ set_string_intervals (Lisp_Object s, INTERVAL i) /* Set a Lisp slot in TABLE to VAL. Most code should use this instead of setting slots directly. */ -LISP_INLINE void +INLINE void set_char_table_defalt (Lisp_Object table, Lisp_Object val) { XCHAR_TABLE (table)->defalt = val; } -LISP_INLINE void +INLINE void set_char_table_purpose (Lisp_Object table, Lisp_Object val) { XCHAR_TABLE (table)->purpose = val; @@ -3223,61 +3375,39 @@ set_char_table_purpose (Lisp_Object table, Lisp_Object val) /* Set different slots in (sub)character tables. */ -LISP_INLINE void +INLINE void set_char_table_extras (Lisp_Object table, ptrdiff_t idx, Lisp_Object val) { eassert (0 <= idx && idx < CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (table))); XCHAR_TABLE (table)->extras[idx] = val; } -LISP_INLINE void +INLINE void set_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val) { eassert (0 <= idx && idx < (1 << CHARTAB_SIZE_BITS_0)); XCHAR_TABLE (table)->contents[idx] = val; } -LISP_INLINE void +INLINE void set_sub_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val) { XSUB_CHAR_TABLE (table)->contents[idx] = val; } /* Defined in data.c. */ -extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound; -extern Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; -extern Lisp_Object Qerror, Qquit, Qargs_out_of_range; -extern Lisp_Object Qvoid_variable, Qvoid_function; -extern Lisp_Object Qinvalid_read_syntax; -extern Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch; -extern Lisp_Object Quser_error, Qend_of_file, Qarith_error, Qmark_inactive; -extern Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only; -extern Lisp_Object Qtext_read_only; -extern Lisp_Object Qinteractive_form; -extern Lisp_Object Qcircular_list; -extern Lisp_Object Qintegerp, Qwholenump, Qsymbolp, Qlistp, Qconsp; -extern Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; -extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; -extern Lisp_Object Qbuffer_or_string_p; -extern Lisp_Object Qfboundp; -extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p; - -extern Lisp_Object Qcdr; - -extern Lisp_Object Qrange_error, Qoverflow_error; - -extern Lisp_Object Qfloatp; -extern Lisp_Object Qnumberp, Qnumber_or_marker_p; - -extern Lisp_Object Qbuffer, Qinteger, Qsymbol; - -extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; - -EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST; - -/* Defined in data.c. */ extern Lisp_Object indirect_function (Lisp_Object); extern Lisp_Object find_symbol_value (Lisp_Object); +enum Arith_Comparison { + ARITH_EQUAL, + ARITH_NOTEQUAL, + ARITH_LESS, + ARITH_GRTR, + ARITH_LESS_OR_EQUAL, + ARITH_GRTR_OR_EQUAL +}; +extern Lisp_Object arithcompare (Lisp_Object num1, Lisp_Object num2, + enum Arith_Comparison comparison); /* Convert the integer I to an Emacs representation, either the integer itself, or a cons of two or three integers, or if all else fails a float. @@ -3311,7 +3441,6 @@ extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *); extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object); extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object); -extern _Noreturn Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *); extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, bool); extern void syms_of_data (void); @@ -3322,7 +3451,6 @@ extern void syms_of_cmds (void); extern void keys_of_cmds (void); /* Defined in coding.c. */ -extern Lisp_Object Qcharset; extern Lisp_Object detect_coding_system (const unsigned char *, ptrdiff_t, ptrdiff_t, bool, bool, Lisp_Object); extern void init_coding (void); @@ -3330,11 +3458,8 @@ extern void init_coding_once (void); extern void syms_of_coding (void); /* Defined in character.c. */ -EXFUN (Fmax_char, 0) ATTRIBUTE_CONST; extern ptrdiff_t chars_in_text (const unsigned char *, ptrdiff_t); extern ptrdiff_t multibyte_chars_in_text (const unsigned char *, ptrdiff_t); -extern int multibyte_char_to_unibyte (int) ATTRIBUTE_CONST; -extern int multibyte_char_to_unibyte_safe (int) ATTRIBUTE_CONST; extern void syms_of_character (void); /* Defined in charset.c. */ @@ -3344,23 +3469,15 @@ extern void syms_of_charset (void); /* Structure forward declarations. */ struct charset; -/* Defined in composite.c. */ -extern void syms_of_composite (void); - /* Defined in syntax.c. */ extern void init_syntax_once (void); extern void syms_of_syntax (void); /* Defined in fns.c. */ -extern Lisp_Object QCrehash_size, QCrehash_threshold; enum { NEXT_ALMOST_PRIME_LIMIT = 11 }; -EXFUN (Fidentity, 1) ATTRIBUTE_CONST; extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST; extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t); extern void sweep_weak_hash_tables (void); -extern Lisp_Object Qcursor_in_echo_area; -extern Lisp_Object Qstring_lessp; -extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq; EMACS_UINT hash_string (char const *, ptrdiff_t); EMACS_UINT sxhash (Lisp_Object, int); Lisp_Object make_hash_table (struct hash_table_test, Lisp_Object, Lisp_Object, @@ -3369,7 +3486,8 @@ ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, EMACS_UINT); extern struct hash_table_test hashtest_eql, hashtest_equal; - +extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object, + ptrdiff_t, ptrdiff_t *, ptrdiff_t *); extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); @@ -3387,7 +3505,6 @@ extern Lisp_Object string_make_unibyte (Lisp_Object); extern void syms_of_fns (void); /* Defined in floatfns.c. */ -extern double extract_float (Lisp_Object); extern void syms_of_floatfns (void); extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y); @@ -3400,14 +3517,11 @@ extern void init_fringe_once (void); #endif /* HAVE_WINDOW_SYSTEM */ /* Defined in image.c. */ -extern Lisp_Object QCascent, QCmargin, QCrelief; -extern Lisp_Object QCconversion; extern int x_bitmap_mask (struct frame *, ptrdiff_t); extern void reset_image_types (void); extern void syms_of_image (void); /* Defined in insdel.c. */ -extern Lisp_Object Qinhibit_modification_hooks; extern void move_gap_both (ptrdiff_t, ptrdiff_t); extern _Noreturn void buffer_overflow (void); extern void make_gap (ptrdiff_t); @@ -3442,6 +3556,7 @@ extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t, extern void modify_text (ptrdiff_t, ptrdiff_t); extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *); extern void prepare_to_modify_buffer_1 (ptrdiff_t, ptrdiff_t, ptrdiff_t *); +extern void invalidate_buffer_caches (struct buffer *, ptrdiff_t, ptrdiff_t); extern void signal_after_change (ptrdiff_t, ptrdiff_t, ptrdiff_t); extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); @@ -3457,60 +3572,40 @@ extern void syms_of_insdel (void); && (defined __FreeBSD__ || defined GNU_LINUX || defined __MINGW32__)) _Noreturn void __executable_start (void); #endif -extern Lisp_Object selected_frame; extern Lisp_Object Vwindow_system; extern Lisp_Object sit_for (Lisp_Object, bool, int); -extern void init_display (void); -extern void syms_of_display (void); /* Defined in xdisp.c. */ -extern Lisp_Object Qinhibit_point_motion_hooks; -extern Lisp_Object Qinhibit_redisplay, Qdisplay; -extern Lisp_Object Qmenu_bar_update_hook; -extern Lisp_Object Qwindow_scroll_functions; -extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; -extern Lisp_Object Qimage, Qtext, Qboth, Qboth_horiz, Qtext_image_horiz; -extern Lisp_Object Qspace, Qcenter, QCalign_to; -extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow; -extern Lisp_Object Qleft_margin, Qright_margin; -extern Lisp_Object Qglyphless_char; -extern Lisp_Object QCdata, QCfile; -extern Lisp_Object QCmap; -extern Lisp_Object Qrisky_local_variable; -extern struct frame *last_glyphless_glyph_frame; -extern int last_glyphless_glyph_face_id; -extern int last_glyphless_glyph_merged_face_id; -extern int noninteractive_need_newline; +extern bool noninteractive_need_newline; extern Lisp_Object echo_area_buffer[2]; -extern void add_to_log (const char *, Lisp_Object, Lisp_Object); +extern void add_to_log (char const *, ...); +extern void vadd_to_log (char const *, va_list); extern void check_message_stack (void); -extern void setup_echo_area_for_printing (int); +extern void setup_echo_area_for_printing (bool); extern bool push_message (void); extern void pop_message_unwind (void); extern Lisp_Object restore_message_unwind (Lisp_Object); extern void restore_message (void); extern Lisp_Object current_message (void); -extern void clear_message (int, int); +extern void clear_message (bool, bool); extern void message (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); extern void message1 (const char *); extern void message1_nolog (const char *); extern void message3 (Lisp_Object); extern void message3_nolog (Lisp_Object); extern void message_dolog (const char *, ptrdiff_t, bool, bool); -extern void message_with_string (const char *, Lisp_Object, int); +extern void message_with_string (const char *, Lisp_Object, bool); extern void message_log_maybe_newline (void); extern void update_echo_area (void); extern void truncate_echo_area (ptrdiff_t); extern void redisplay (void); -extern void redisplay_preserve_echo_area (int); -extern void prepare_menu_bars (void); void set_frame_cursor_types (struct frame *, Lisp_Object); extern void syms_of_xdisp (void); extern void init_xdisp (void); extern Lisp_Object safe_eval (Lisp_Object); -extern int pos_visible_p (struct window *, ptrdiff_t, int *, - int *, int *, int *, int *, int *); +extern bool pos_visible_p (struct window *, ptrdiff_t, int *, + int *, int *, int *, int *, int *); /* Defined in xsettings.c. */ extern void syms_of_xsettings (void); @@ -3518,6 +3613,10 @@ extern void syms_of_xsettings (void); /* Defined in vm-limit.c. */ extern void memory_warnings (void *, void (*warnfun) (const char *)); +/* Defined in character.c. */ +extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t, + ptrdiff_t *, ptrdiff_t *); + /* Defined in alloc.c. */ extern void check_pure_size (void); extern void free_misc (Lisp_Object); @@ -3527,12 +3626,10 @@ extern _Noreturn void memory_full (size_t); extern _Noreturn void buffer_memory_full (ptrdiff_t); extern bool survives_gc_p (Lisp_Object); extern void mark_object (Lisp_Object); -#if defined REL_ALLOC && !defined SYSTEM_MALLOC +#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern void refill_memory_reserve (void); #endif -#if GC_MARK_STACK extern void mark_stack (char *, char *); -#endif extern void flush_stack_call_func (void (*func) (void *arg), void *arg); extern const char *pending_malloc_warning; extern Lisp_Object zero_vector; @@ -3550,25 +3647,27 @@ extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...); /* Build a frequently used 2/3/4-integer lists. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object list2i (EMACS_INT x, EMACS_INT y) { return list2 (make_number (x), make_number (y)); } -LISP_INLINE Lisp_Object +INLINE Lisp_Object list3i (EMACS_INT x, EMACS_INT y, EMACS_INT w) { return list3 (make_number (x), make_number (y), make_number (w)); } -LISP_INLINE Lisp_Object +INLINE Lisp_Object list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h) { return list4 (make_number (x), make_number (y), make_number (w), make_number (h)); } +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 make_formatted_string (char *, const char *, ...) @@ -3577,14 +3676,14 @@ extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t); /* Make unibyte string from C string when the length isn't known. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object build_unibyte_string (const char *str) { return make_unibyte_string (str, strlen (str)); } extern Lisp_Object make_multibyte_string (const char *, ptrdiff_t, ptrdiff_t); -extern Lisp_Object make_event_array (int, Lisp_Object *); +extern Lisp_Object make_event_array (ptrdiff_t, Lisp_Object *); extern Lisp_Object make_uninit_string (EMACS_INT); extern Lisp_Object make_uninit_multibyte_string (EMACS_INT, EMACS_INT); extern Lisp_Object make_string_from_bytes (const char *, ptrdiff_t, ptrdiff_t); @@ -3595,7 +3694,7 @@ extern Lisp_Object make_pure_c_string (const char *, ptrdiff_t); /* Make a string allocated in pure space, use STR as string data. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object build_pure_c_string (const char *str) { return make_pure_c_string (str, strlen (str)); @@ -3604,7 +3703,7 @@ build_pure_c_string (const char *str) /* Make a string from the data at STR, treating it as multibyte if the data warrants. */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object build_string (const char *str) { return make_string (str, strlen (str)); @@ -3612,8 +3711,6 @@ build_string (const char *str) extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object); extern void make_byte_code (struct Lisp_Vector *); -extern Lisp_Object Qautomatic_gc; -extern Lisp_Object Qchar_table_extra_slots; extern struct Lisp_Vector *allocate_vector (EMACS_INT); /* Make an uninitialized vector for SIZE objects. NOTE: you must @@ -3625,7 +3722,7 @@ extern struct Lisp_Vector *allocate_vector (EMACS_INT); ASET (v, 1, Ffunction_can_gc ()); ASET (v, 2, obj1); */ -LISP_INLINE Lisp_Object +INLINE Lisp_Object make_uninit_vector (ptrdiff_t size) { Lisp_Object v; @@ -3636,16 +3733,39 @@ make_uninit_vector (ptrdiff_t size) return v; } -extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); -#define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ - ((typ*) \ - allocate_pseudovector \ - (VECSIZE (typ), PSEUDOVECSIZE (typ, field), tag)) -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 terminal *allocate_terminal (void); +/* Like above, but special for sub char-tables. */ + +INLINE Lisp_Object +make_uninit_sub_char_table (int depth, int min_char) +{ + int slots = SUB_CHAR_TABLE_OFFSET + chartab_size[depth]; + Lisp_Object v = make_uninit_vector (slots); + + XSETPVECTYPE (XVECTOR (v), PVEC_SUB_CHAR_TABLE); + XSUB_CHAR_TABLE (v)->depth = depth; + XSUB_CHAR_TABLE (v)->min_char = min_char; + return v; +} + +extern struct Lisp_Vector *allocate_pseudovector (int, int, int, + enum pvec_type); + +/* Allocate partially initialized pseudovector where all Lisp_Object + slots are set to Qnil but the rest (if any) is left uninitialized. */ + +#define ALLOCATE_PSEUDOVECTOR(type, field, tag) \ + ((type *) allocate_pseudovector (VECSIZE (type), \ + PSEUDOVECSIZE (type, field), \ + PSEUDOVECSIZE (type, field), tag)) + +/* Allocate fully initialized pseudovector where all Lisp_Object + slots are set to Qnil and the rest (if any) is zeroed. */ + +#define ALLOCATE_ZEROED_PSEUDOVECTOR(type, field, tag) \ + ((type *) allocate_pseudovector (VECSIZE (type), \ + PSEUDOVECSIZE (type, field), \ + VECSIZE (type), tag)) + extern bool gc_in_progress; extern bool abort_on_gc; extern Lisp_Object make_float (double); @@ -3672,26 +3792,23 @@ extern int valid_lisp_object_p (Lisp_Object); #ifdef GC_CHECK_CONS_LIST extern void check_cons_list (void); #else -LISP_INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); } +INLINE void (check_cons_list) (void) { lisp_h_check_cons_list (); } #endif #ifdef REL_ALLOC /* Defined in ralloc.c. */ -extern void *r_alloc (void **, size_t); +extern void *r_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_free (void **); -extern void *r_re_alloc (void **, size_t); +extern void *r_re_alloc (void **, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void r_alloc_reset_variable (void **, void **); extern void r_alloc_inhibit_buffer_relocation (int); #endif /* Defined in chartab.c. */ extern Lisp_Object copy_char_table (Lisp_Object); -extern Lisp_Object char_table_ref (Lisp_Object, int); extern Lisp_Object char_table_ref_and_range (Lisp_Object, int, int *, int *); -extern void char_table_set (Lisp_Object, int, Lisp_Object); extern void char_table_set_range (Lisp_Object, int, int, Lisp_Object); -extern int char_table_translate (Lisp_Object, int); extern void map_char_table (void (*) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object); @@ -3705,17 +3822,14 @@ extern void syms_of_chartab (void); /* Defined in print.c. */ extern Lisp_Object Vprin1_to_string_buffer; extern void debug_print (Lisp_Object) EXTERNALLY_VISIBLE; -extern Lisp_Object Qstandard_output; -extern Lisp_Object Qexternal_debugging_output; extern void temp_output_buffer_setup (const char *); extern int print_level; -extern Lisp_Object Qprint_escape_newlines; -extern void write_string (const char *, int); +extern void write_string (const char *); extern void print_error_message (Lisp_Object, Lisp_Object, const char *, Lisp_Object); extern Lisp_Object internal_with_output_to_temp_buffer (const char *, Lisp_Object (*) (Lisp_Object), Lisp_Object); -enum FLOAT_TO_STRING_BUFSIZE { FLOAT_TO_STRING_BUFSIZE = 350 }; +#define FLOAT_TO_STRING_BUFSIZE 350 extern int float_to_string (char *, double); extern void init_print_once (void); extern void syms_of_print (void); @@ -3733,21 +3847,20 @@ extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char const *, ptrdiff_t, ATTRIBUTE_FORMAT_PRINTF (5, 0); /* Defined in lread.c. */ -extern Lisp_Object 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 intern_1 (const char *, ptrdiff_t); extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t); +extern Lisp_Object intern_driver (Lisp_Object, Lisp_Object, Lisp_Object); +extern void init_symbol (Lisp_Object, Lisp_Object); extern Lisp_Object oblookup (Lisp_Object, const char *, ptrdiff_t, ptrdiff_t); -LISP_INLINE void +INLINE void LOADHIST_ATTACH (Lisp_Object x) { if (initialized) Vcurrent_load_list = Fcons (x, Vcurrent_load_list); } extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object *, Lisp_Object); + Lisp_Object *, Lisp_Object, bool); extern Lisp_Object string_to_number (char const *, int, bool); extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), Lisp_Object); @@ -3756,30 +3869,24 @@ extern void init_obarray (void); extern void init_lread (void); extern void syms_of_lread (void); -LISP_INLINE Lisp_Object +INLINE Lisp_Object intern (const char *str) { return intern_1 (str, strlen (str)); } -LISP_INLINE Lisp_Object +INLINE Lisp_Object intern_c_string (const char *str) { return intern_c_string_1 (str, strlen (str)); } /* Defined in eval.c. */ -extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qmacro; -extern Lisp_Object Qinhibit_quit, Qinternal_interpreter_environment, Qclosure; -extern Lisp_Object Qand_rest; extern Lisp_Object Vautoload_queue; +extern Lisp_Object Vrun_hooks; extern Lisp_Object Vsignaling_function; extern Lisp_Object inhibit_lisp_code; -extern int handling_signal; -#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ - || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS) -extern void mark_catchlist (struct catchtag *); -#endif + /* To run a normal hook, use the appropriate function from the list below. The calling convention: @@ -3787,7 +3894,7 @@ extern void mark_catchlist (struct catchtag *); call1 (Vrun_hooks, Qmy_funny_hook); should no longer be used. */ -extern Lisp_Object Vrun_hooks; +extern void run_hook (Lisp_Object); extern void run_hook_with_args_2 (Lisp_Object, Lisp_Object, Lisp_Object); extern Lisp_Object run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args, Lisp_Object (*funcall) @@ -3834,6 +3941,7 @@ extern _Noreturn void verror (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); extern void un_autoload (Lisp_Object); extern Lisp_Object call_debugger (Lisp_Object arg); +extern void *near_C_stack_top (void); extern void init_eval_once (void); extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); @@ -3841,8 +3949,7 @@ extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object); extern void init_eval (void); extern void syms_of_eval (void); extern void unwind_body (Lisp_Object); -extern void record_in_backtrace (Lisp_Object function, - Lisp_Object *args, ptrdiff_t nargs); +extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t); extern void mark_specpdl (union specbinding *first, union specbinding *ptr); extern void get_backtrace (Lisp_Object array); Lisp_Object backtrace_top_function (void); @@ -3854,9 +3961,7 @@ extern bool let_shadows_global_binding_p (Lisp_Object symbol); extern void mark_threads (void); /* Defined in editfns.c. */ -extern Lisp_Object Qfield; extern void insert1 (Lisp_Object); -extern Lisp_Object format2 (const char *, Lisp_Object, Lisp_Object); extern Lisp_Object save_excursion_save (void); extern Lisp_Object save_restriction_save (void); extern void save_excursion_restore (Lisp_Object); @@ -3865,9 +3970,8 @@ extern _Noreturn void time_overflow (void); extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool); -extern void init_editfns (void); +extern void init_editfns (bool); 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); @@ -3881,7 +3985,7 @@ extern bool overlay_touches_p (ptrdiff_t); extern Lisp_Object other_buffer_safely (Lisp_Object); extern Lisp_Object get_truename_buffer (Lisp_Object); extern void init_buffer_once (void); -extern void init_buffer (void); +extern void init_buffer (int); extern void syms_of_buffer (void); extern void keys_of_buffer (void); @@ -3902,31 +4006,23 @@ extern void syms_of_marker (void); /* Defined in fileio.c. */ -extern Lisp_Object Qfile_error; -extern Lisp_Object Qfile_notify_error; -extern Lisp_Object Qfile_exists_p; -extern Lisp_Object Qfile_directory_p; -extern Lisp_Object Qinsert_file_contents; -extern Lisp_Object Qfile_name_history; extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); extern Lisp_Object write_region (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int); -EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ extern void close_file_unwind (int); extern void fclose_unwind (void *); extern void restore_point_unwind (Lisp_Object); extern _Noreturn void report_file_errno (const char *, Lisp_Object, int); extern _Noreturn void report_file_error (const char *, Lisp_Object); +extern _Noreturn void report_file_notify_error (const char *, Lisp_Object); extern bool internal_delete_file (Lisp_Object); extern Lisp_Object emacs_readlinkat (int, const char *); extern bool file_directory_p (const char *); -extern bool file_accessible_directory_p (const char *); +extern bool file_accessible_directory_p (Lisp_Object); extern void init_fileio (void); extern void syms_of_fileio (void); extern Lisp_Object make_temp_name (Lisp_Object, bool); -extern Lisp_Object Qdelete_file; -extern bool check_existing (const char *); /* Defined in search.c. */ extern void shrink_regexp_cache (void); @@ -3936,16 +4032,30 @@ struct re_registers; extern struct re_pattern_buffer *compile_pattern (Lisp_Object, struct re_registers *, Lisp_Object, bool, bool); -extern ptrdiff_t fast_string_match (Lisp_Object, Lisp_Object); +extern ptrdiff_t fast_string_match_internal (Lisp_Object, Lisp_Object, + Lisp_Object); + +INLINE ptrdiff_t +fast_string_match (Lisp_Object regexp, Lisp_Object string) +{ + return fast_string_match_internal (regexp, string, Qnil); +} + +INLINE ptrdiff_t +fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string) +{ + return fast_string_match_internal (regexp, string, Vascii_canon_table); +} + extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *, ptrdiff_t); -extern ptrdiff_t fast_string_match_ignore_case (Lisp_Object, Lisp_Object); extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, Lisp_Object); extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool); -extern EMACS_INT scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, - EMACS_INT, bool); +extern ptrdiff_t scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, + ptrdiff_t, bool); +extern ptrdiff_t 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, @@ -3955,7 +4065,6 @@ extern void clear_regexp_cache (void); /* Defined in minibuf.c. */ -extern Lisp_Object Qcompletion_ignore_case; extern Lisp_Object Vminibuffer_list; extern Lisp_Object last_minibuf_string; extern Lisp_Object get_minibuffer (EMACS_INT); @@ -3964,14 +4073,10 @@ extern void syms_of_minibuf (void); /* Defined in callint.c. */ -extern Lisp_Object Qminus, Qplus; -extern Lisp_Object Qwhen; -extern Lisp_Object Qmouse_leave_buffer_hook; extern void syms_of_callint (void); /* Defined in casefiddle.c. */ -extern Lisp_Object Qidentity; extern void syms_of_casefiddle (void); extern void keys_of_casefiddle (void); @@ -3985,11 +4090,11 @@ extern void syms_of_casetab (void); extern Lisp_Object echo_message_buffer; extern struct kboard *echo_kboard; extern void cancel_echoing (void); -extern Lisp_Object Qdisabled, QCfilter; -extern Lisp_Object Qup, Qdown, Qbottom; -extern Lisp_Object Qtop; extern Lisp_Object last_undo_boundary; extern bool input_pending; +#ifdef HAVE_STACK_OVERFLOW_HANDLING +extern sigjmp_buf return_to_command_loop; +#endif extern Lisp_Object menu_bar_items (Lisp_Object); extern Lisp_Object tool_bar_items (Lisp_Object, int *); extern void discard_mouse_events (void); @@ -4003,6 +4108,7 @@ extern bool detect_input_pending_run_timers (bool); extern void safe_run_hooks (Lisp_Object); extern void cmd_error_internal (Lisp_Object, const char *); extern Lisp_Object command_loop_1 (void); +extern Lisp_Object read_menu_command (void); extern Lisp_Object recursive_edit_1 (void); extern void record_auto_save (void); extern void force_auto_save_soon (void); @@ -4017,14 +4123,10 @@ extern bool indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT); extern void syms_of_indent (void); /* Defined in frame.c. */ -extern Lisp_Object Qonly, Qnone; -extern Lisp_Object Qvisible; extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); -#if HAVE_NS || defined WINDOWSNT extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); -#endif extern void frames_discard_buffer (Lisp_Object); extern void syms_of_frame (void); @@ -4034,11 +4136,9 @@ extern int initial_argc; #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) extern bool display_arg; #endif -extern Lisp_Object decode_env_path (const char *, const char *); +extern Lisp_Object decode_env_path (const char *, const char *, bool); extern Lisp_Object empty_unibyte_string, empty_multibyte_string; -extern Lisp_Object Qfile_name_handler_alist; extern _Noreturn void terminate_due_to_signal (int, int); -extern Lisp_Object Qkill_emacs; #ifdef WINDOWSNT extern Lisp_Object Vlibrary_cache; #endif @@ -4047,9 +4147,9 @@ void fixup_locale (void); void synchronize_system_messages_locale (void); void synchronize_system_time_locale (void); #else -LISP_INLINE void fixup_locale (void) {} -LISP_INLINE void synchronize_system_messages_locale (void) {} -LISP_INLINE void synchronize_system_time_locale (void) {} +INLINE void fixup_locale (void) {} +INLINE void synchronize_system_messages_locale (void) {} +INLINE void synchronize_system_time_locale (void) {} #endif extern void shut_down_emacs (int, Lisp_Object); @@ -4060,9 +4160,16 @@ extern bool noninteractive; extern bool no_site_lisp; /* Pipe used to send exit notification to the daemon parent at - startup. */ + startup. On Windows, we use a kernel event instead. */ +#ifndef WINDOWSNT extern int daemon_pipe[2]; #define IS_DAEMON (daemon_pipe[1] != 0) +#define DAEMON_RUNNING (daemon_pipe[1] >= 0) +#else /* WINDOWSNT */ +extern void *w32_daemon_event; +#define IS_DAEMON (w32_daemon_event != NULL) +#define DAEMON_RUNNING (w32_daemon_event != INVALID_HANDLE_VALUE) +#endif /* True if handling a fatal error already. */ extern bool fatal_error_in_progress; @@ -4073,13 +4180,9 @@ extern bool inhibit_window_system; extern bool running_asynch_code; /* Defined in process.c. */ -extern Lisp_Object QCtype, Qlocal; -extern Lisp_Object Qprocessp; extern void kill_buffer_processes (Lisp_Object); -extern bool wait_reading_process_output (intmax_t, int, int, bool, - Lisp_Object, - struct Lisp_Process *, - int); +extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object, + struct Lisp_Process *, int); /* Max value for the first argument of wait_reading_process_output. */ #if __GNUC__ == 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) /* Work around a bug in GCC 3.4.2, known to be fixed in GCC 4.6.3. @@ -4088,6 +4191,9 @@ extern bool wait_reading_process_output (intmax_t, int, int, bool, #else # define WAIT_READING_MAX INTMAX_MAX #endif +#ifdef HAVE_TIMERFD +extern void add_timer_wait_descriptor (int); +#endif extern void add_keyboard_wait_descriptor (int); extern void delete_keyboard_wait_descriptor (int); #ifdef HAVE_GPM @@ -4109,7 +4215,18 @@ extern void set_initial_environment (void); extern void syms_of_callproc (void); /* Defined in doc.c. */ -extern Lisp_Object Qfunction_documentation; +enum text_quoting_style + { + /* Use curved single quotes ‘like this’. */ + CURVE_QUOTING_STYLE, + + /* Use grave accent and apostrophe `like this'. */ + GRAVE_QUOTING_STYLE, + + /* Use apostrophes 'like this'. */ + STRAIGHT_QUOTING_STYLE + }; +extern enum text_quoting_style text_quoting_style (void); extern Lisp_Object read_doc_string (Lisp_Object); extern Lisp_Object get_doc_string (Lisp_Object, bool, bool); extern void syms_of_doc (void); @@ -4117,10 +4234,7 @@ extern int read_bytecode_char (bool); /* Defined in bytecode.c. */ extern void syms_of_bytecode (void); -#if BYTE_MARK_STACK -extern void mark_byte_stack (struct byte_stack *); -#endif -extern void unmark_byte_stack (struct byte_stack *); +extern void relocate_byte_stack (struct byte_stack *); extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, ptrdiff_t, Lisp_Object *); @@ -4129,24 +4243,17 @@ extern void init_macros (void); extern void syms_of_macros (void); /* Defined in undo.c. */ -extern Lisp_Object Qapply; -extern Lisp_Object Qinhibit_read_only; extern void truncate_undo_list (struct buffer *); -extern void record_marker_adjustment (Lisp_Object, ptrdiff_t); extern void record_insert (ptrdiff_t, ptrdiff_t); -extern void record_delete (ptrdiff_t, Lisp_Object); +extern void record_delete (ptrdiff_t, Lisp_Object, bool); extern void record_first_change (void); extern void record_change (ptrdiff_t, ptrdiff_t); extern void record_property_change (ptrdiff_t, ptrdiff_t, Lisp_Object, Lisp_Object, Lisp_Object); extern void syms_of_undo (void); -/* Defined in textprop.c. */ -extern Lisp_Object Qfont, Qmouse_face; -extern Lisp_Object Qinsert_in_front_hooks, Qinsert_behind_hooks; -extern Lisp_Object Qfront_sticky, Qrear_nonsticky; -extern Lisp_Object Qminibuffer_prompt; +/* Defined in textprop.c. */ extern void report_interval_modification (Lisp_Object, Lisp_Object); /* Defined in menu.c. */ @@ -4167,12 +4274,9 @@ extern char *get_current_dir_name (void); #endif extern void stuff_char (char c); extern void init_foreground_group (void); -extern void init_sigio (int); extern void sys_subshell (void); extern void sys_suspend (void); extern void discard_tty_input (void); -extern void block_tty_out_signal (void); -extern void unblock_tty_out_signal (void); extern void init_sys_modes (struct tty_display_info *); extern void reset_sys_modes (struct tty_display_info *); extern void init_all_sys_modes (void); @@ -4188,9 +4292,9 @@ extern _Noreturn void emacs_abort (void) NO_INLINE; extern int emacs_open (const char *, int, int); extern int emacs_pipe (int[2]); extern int emacs_close (int); -extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); -extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); -extern ptrdiff_t emacs_write_sig (int, char const *, ptrdiff_t); +extern ptrdiff_t emacs_read (int, void *, ptrdiff_t); +extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t); +extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t); extern void emacs_perror (char const *); extern void unlock_all_files (void); @@ -4198,6 +4302,7 @@ extern void lock_file (Lisp_Object); extern void unlock_file (Lisp_Object); extern void unlock_buffer (struct buffer *); extern void syms_of_filelock (void); +extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); /* Defined in sound.c. */ extern void syms_of_sound (void); @@ -4232,9 +4337,6 @@ extern void init_font (void); #ifdef HAVE_WINDOW_SYSTEM /* Defined in fontset.c. */ extern void syms_of_fontset (void); - -/* Defined in xfns.c, w32fns.c, or macfns.c. */ -extern Lisp_Object Qfont_param; #endif /* Defined in gfilenotify.c */ @@ -4254,16 +4356,6 @@ extern void syms_of_w32notify (void); #endif /* Defined in xfaces.c. */ -extern Lisp_Object Qdefault, Qtool_bar, Qfringe; -extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor; -extern Lisp_Object Qmode_line_inactive; -extern Lisp_Object Qface; -extern Lisp_Object Qnormal; -extern Lisp_Object QCfamily, QCweight, QCslant; -extern Lisp_Object QCheight, QCname, QCwidth, QCforeground, QCbackground; -extern Lisp_Object Qextra_light, Qlight, Qsemi_light, Qsemi_bold; -extern Lisp_Object Qbold, Qextra_bold, Qultra_bold; -extern Lisp_Object Qoblique, Qitalic; extern Lisp_Object Vface_alternative_font_family_alist; extern Lisp_Object Vface_alternative_font_registry_alist; extern void syms_of_xfaces (void); @@ -4279,6 +4371,7 @@ extern void syms_of_xsmfns (void); 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 */ @@ -4300,6 +4393,7 @@ extern void syms_of_decompress (void); #ifdef HAVE_DBUS /* Defined in dbusbind.c. */ +void init_dbusbind (void); void syms_of_dbusbind (void); #endif @@ -4314,33 +4408,49 @@ extern void syms_of_profiler (void); /* Defined in msdos.c, w32.c. */ extern char *emacs_root_dir (void); #endif /* DOS_NT */ - -/* True means Emacs has already been initialized. - Used during startup to detect startup of dumped Emacs. */ -extern bool initialized; + +/* Defined in lastfile.c. */ +extern char my_edata[]; +extern char my_endbss[]; +extern char *my_endbss_static; /* True means ^G can quit instantly. */ extern bool immediate_quit; -extern void *xmalloc (size_t); -extern void *xzalloc (size_t); -extern void *xrealloc (void *, size_t); +extern void *xmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xzalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); +extern void *xrealloc (void *, size_t) ATTRIBUTE_ALLOC_SIZE ((2)); extern void xfree (void *); -extern void *xnmalloc (ptrdiff_t, ptrdiff_t); -extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t); +extern void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2)); +extern void *xnrealloc (void *, ptrdiff_t, ptrdiff_t) + ATTRIBUTE_ALLOC_SIZE ((2,3)); extern void *xpalloc (void *, ptrdiff_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t); -extern char *xstrdup (const char *); -extern char *xlispstrdup (Lisp_Object); -extern void xputenv (const char *); +extern char *xstrdup (const char *) ATTRIBUTE_MALLOC; +extern char *xlispstrdup (Lisp_Object) ATTRIBUTE_MALLOC; +extern void dupstring (char **, char const *); + +/* Make DEST a copy of STRING's data. Return a pointer to DEST's terminating + null byte. This is like stpcpy, except the source is a Lisp string. */ + +INLINE char * +lispstpcpy (char *dest, Lisp_Object string) +{ + ptrdiff_t len = SBYTES (string); + memcpy (dest, SDATA (string), len + 1); + return dest + len; +} -extern char *egetenv (const char *); +extern void xputenv (const char *); -/* Copy Lisp string to temporary (allocated on stack) C string. */ +extern char *egetenv_internal (const char *, ptrdiff_t); -#define xlispstrdupa(string) \ - memcpy (alloca (SBYTES (string) + 1), \ - SSDATA (string), SBYTES (string) + 1) +INLINE char * +egetenv (const char *var) +{ + /* When VAR is a string literal, strlen can be optimized away. */ + return egetenv_internal (var, strlen (var)); +} /* Set up the name of the machine we're running on. */ extern void init_system_name (void); @@ -4362,16 +4472,19 @@ extern void init_system_name (void); enum MAX_ALLOCA { MAX_ALLOCA = 16 * 1024 }; -extern void *record_xmalloc (size_t); +extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1)); #define USE_SAFE_ALLOCA \ - ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = 0 + ptrdiff_t sa_avail = MAX_ALLOCA; \ + ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false + +#define AVAIL_ALLOCA(size) (sa_avail -= (size), alloca (size)) /* SAFE_ALLOCA allocates a simple buffer. */ -#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \ - ? alloca (size) \ - : (sa_must_free = 1, record_xmalloc (size))) +#define SAFE_ALLOCA(size) ((size) <= sa_avail \ + ? AVAIL_ALLOCA (size) \ + : (sa_must_free = true, record_xmalloc (size))) /* SAFE_NALLOCA sets BUF to a newly allocated array of MULTIPLIER * NITEMS items, each of the same type as *BUF. MULTIPLIER must @@ -4379,55 +4492,196 @@ extern void *record_xmalloc (size_t); #define SAFE_NALLOCA(buf, multiplier, nitems) \ do { \ - if ((nitems) <= MAX_ALLOCA / sizeof *(buf) / (multiplier)) \ - (buf) = alloca (sizeof *(buf) * (multiplier) * (nitems)); \ + if ((nitems) <= sa_avail / sizeof *(buf) / (multiplier)) \ + (buf) = AVAIL_ALLOCA (sizeof *(buf) * (multiplier) * (nitems)); \ else \ { \ (buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \ - sa_must_free = 1; \ + sa_must_free = true; \ record_unwind_protect_ptr (xfree, buf); \ } \ - } while (0) + } while (false) + +/* SAFE_ALLOCA_STRING allocates a C copy of a Lisp string. */ + +#define SAFE_ALLOCA_STRING(ptr, string) \ + do { \ + (ptr) = SAFE_ALLOCA (SBYTES (string) + 1); \ + memcpy (ptr, SDATA (string), SBYTES (string) + 1); \ + } while (false) /* SAFE_FREE frees xmalloced memory and enables GC as needed. */ #define SAFE_FREE() \ do { \ if (sa_must_free) { \ - sa_must_free = 0; \ + sa_must_free = false; \ unbind_to (sa_count, Qnil); \ } \ - } while (0) + } while (false) +/* Return floor (NBYTES / WORD_SIZE). */ + +INLINE ptrdiff_t +lisp_word_count (ptrdiff_t nbytes) +{ + if (-1 >> 1 == -1) + switch (word_size + 0) + { + case 2: return nbytes >> 1; + case 4: return nbytes >> 2; + case 8: return nbytes >> 3; + case 16: return nbytes >> 4; + default: break; + } + return nbytes / word_size - (nbytes % word_size < 0); +} + /* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects. */ #define SAFE_ALLOCA_LISP(buf, nelt) \ do { \ - if ((nelt) < MAX_ALLOCA / word_size) \ - buf = alloca ((nelt) * word_size); \ - else if ((nelt) < min (PTRDIFF_MAX, SIZE_MAX) / word_size) \ + if ((nelt) <= lisp_word_count (sa_avail)) \ + (buf) = AVAIL_ALLOCA ((nelt) * word_size); \ + else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \ { \ Lisp_Object arg_; \ - buf = xmalloc ((nelt) * word_size); \ + (buf) = xmalloc ((nelt) * word_size); \ arg_ = make_save_memory (buf, nelt); \ - sa_must_free = 1; \ + sa_must_free = true; \ record_unwind_protect (free_save_value, arg_); \ } \ else \ memory_full (SIZE_MAX); \ - } while (0) + } while (false) + + +/* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate + 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. + + This feature is experimental and requires careful debugging. + Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */ + +#ifndef USE_STACK_LISP_OBJECTS +# define USE_STACK_LISP_OBJECTS true +#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_String +{ + struct Lisp_String s; + double d; intmax_t i; void *p; +}; + +/* 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. */ + +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 +# define verify_ascii(str) (str) +#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. + FIXME: Unroll the loop body so we don't need `n'. */ +#define FOR_EACH_TAIL(hare, list, tortoise, n) \ + for ((tortoise) = (hare) = (list), (n) = true; \ + CONSP (hare); \ + (hare = XCDR (hare), (n) = !(n), \ + ((n) \ + ? (EQ (hare, tortoise) \ + ? xsignal1 (Qcircular_list, list) \ + : (void) 0) \ + /* Move tortoise before the next iteration, in case */ \ + /* the next iteration does an Fsetcdr. */ \ + : (void) ((tortoise) = XCDR (tortoise))))) /* Do a `for' loop over alist values. */ #define FOR_EACH_ALIST_VALUE(head_var, list_var, value_var) \ - for (list_var = head_var; \ - (CONSP (list_var) && (value_var = XCDR (XCAR (list_var)), 1)); \ - list_var = XCDR (list_var)) + for ((list_var) = (head_var); \ + (CONSP (list_var) && ((value_var) = XCDR (XCAR (list_var)), true)); \ + (list_var) = XCDR (list_var)) /* Check whether it's time for GC, and run it if so. */ -LISP_INLINE void +INLINE void maybe_gc (void) { if ((consing_since_gc > gc_cons_threshold @@ -4437,7 +4691,7 @@ maybe_gc (void) Fgarbage_collect (); } -LISP_INLINE bool +INLINE bool functionp (Lisp_Object object) { if (SYMBOLP (object) && !NILP (Ffboundp (object))) @@ -4459,14 +4713,14 @@ functionp (Lisp_Object object) if (SUBRP (object)) return XSUBR (object)->max_args != UNEVALLED; else if (COMPILEDP (object)) - return 1; + return true; else if (CONSP (object)) { Lisp_Object car = XCAR (object); return EQ (car, Qlambda) || EQ (car, Qclosure); } else - return 0; + return false; } INLINE_HEADER_END |
