/* Fundamental definitions for GNU Emacs Lisp interpreter.
-Copyright (C) 1985-1987, 1993-1995, 1997-2013 Free Software Foundation, Inc.
+Copyright (C) 1985-1987, 1993-1995, 1997-2015 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
#include <setjmp.h>
#include <stdalign.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stddef.h>
#include <float.h>
#include <inttypes.h>
/* Define a TYPE constant ID as an externally visible name. Use like this:
+ #define ID_val (some integer preprocessor expression)
+ #if ENUMABLE (ID_val)
+ DEFINE_GDB_SYMBOL_ENUM (ID)
+ #else
DEFINE_GDB_SYMBOL_BEGIN (TYPE, ID)
- #define ID something
+ # define ID ID_val
DEFINE_GDB_SYMBOL_END (ID)
+ #endif
This hack is for the benefit of compilers that do not make macro
definitions visible to the debugger. It's used for symbols that
.gdbinit needs, symbols whose values may not fit in 'int' (where an
- enum would suffice). */
+ enum would suffice).
+
+ Some GCC versions before GCC 4.2 omit enums in debugging output;
+ see GCC bug 23336. So don't use enums with older GCC. */
+
+#if !defined __GNUC__ || 4 < __GNUC__ + (2 <= __GNUC_MINOR__)
+# define ENUMABLE(val) (INT_MIN <= (val) && (val) <= INT_MAX)
+#else
+# define ENUMABLE(val) 0
+#endif
+
+/* On AIX 7.1 ENUMABLE should return true when possible, otherwise the
+ linker can optimize the symbols away, making it harder to debug.
+ This was discovered only late in the release process, so to play it
+ safe for now, non-AIX platforms do not use enums for debugging symbols.
+ FIXME: remove this comment and the following four lines of code. */
+#ifndef _AIX
+# undef ENUMABLE
+# define ENUMABLE(val) 0
+#endif
+
+#define DEFINE_GDB_SYMBOL_ENUM(id) enum { id = id##_val };
#if defined MAIN_PROGRAM
# define DEFINE_GDB_SYMBOL_BEGIN(type, id) type const id EXTERNALLY_VISIBLE
# define DEFINE_GDB_SYMBOL_END(id) = id;
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
-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
+# if INTPTR_MAX <= 0
+# error "INTPTR_MAX misconfigured"
+# elif INTPTR_MAX <= INT_MAX && !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 && !defined WIDE_EMACS_INT
typedef long int EMACS_INT;
typedef unsigned long EMACS_UINT;
# define EMACS_INT_MAX LONG_MAX
# define pI "l"
+# 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"
# 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
for COND to call external functions or access volatile storage. */
#ifndef ENABLE_CHECKING
-# define eassert(cond) ((void) (0 && (cond))) /* Check that COND compiles. */
+# define eassert(cond) ((void) (false && (cond))) /* Check COND compiles. */
# define eassume(cond) assume (cond)
#else /* ENABLE_CHECKING */
On hosts where pointers-as-ints do not exceed VAL_MAX, 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. */
+ So, default USE_LSB_TAG to true only on hosts where it might be useful. */
# if VAL_MAX < UINTPTR_MAX
-# define USE_LSB_TAG 1
+# define USE_LSB_TAG true
# 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
+enum enum_USE_LSB_TAG { USE_LSB_TAG = true };
+# define USE_LSB_TAG true
#else
-enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
-# define USE_LSB_TAG 0
+enum enum_USE_LSB_TAG { USE_LSB_TAG = false };
+# define USE_LSB_TAG false
#endif
#ifndef alignas
(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))
+ ((void *) (intptr_t) ((XLI (a) & VALMASK) | (DATA_SEG_BITS & ~VALMASK)))
#define lisp_h_XSYMBOL(a) \
(eassert (SYMBOLP (a)), (struct Lisp_Symbol *) XUNTAG (a, Lisp_Symbol))
#ifndef GC_CHECK_CONS_LIST
/* 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))
#define LISP_INITIALLY_ZERO {0}
#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 };
+enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false };
#endif /* CHECK_LISP_OBJECT_TYPE */
/* Convert a Lisp_Object to the corresponding EMACS_INT and vice versa.
/* In the size word of a vector, this bit means the vector has been marked. */
+#define ARRAY_MARK_FLAG_val PTRDIFF_MIN
+#if ENUMABLE (ARRAY_MARK_FLAG_val)
+DEFINE_GDB_SYMBOL_ENUM (ARRAY_MARK_FLAG)
+#else
DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, ARRAY_MARK_FLAG)
-#define ARRAY_MARK_FLAG PTRDIFF_MIN
+# define ARRAY_MARK_FLAG ARRAY_MARK_FLAG_val
DEFINE_GDB_SYMBOL_END (ARRAY_MARK_FLAG)
+#endif
/* In the size word of a struct Lisp_Vector, this bit means it's really
some other vector-like object. */
+#define PSEUDOVECTOR_FLAG_val (PTRDIFF_MAX - PTRDIFF_MAX / 2)
+#if ENUMABLE (PSEUDOVECTOR_FLAG_val)
+DEFINE_GDB_SYMBOL_ENUM (PSEUDOVECTOR_FLAG)
+#else
DEFINE_GDB_SYMBOL_BEGIN (ptrdiff_t, PSEUDOVECTOR_FLAG)
-#define PSEUDOVECTOR_FLAG (PTRDIFF_MAX - PTRDIFF_MAX / 2)
+# define PSEUDOVECTOR_FLAG PSEUDOVECTOR_FLAG_val
DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG)
+#endif
/* In a pseudovector, the size field actually contains a word with one
PSEUDOVECTOR_FLAG bit set, and one of the following values extracted
/* Used to extract pseudovector subtype information. */
PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
- PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS,
+ PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS
};
\f
/* These functions extract various sorts of values from a Lisp_Object.
XCONS (tem) is the struct Lisp_Cons * pointing to the memory for
that cons. */
+/* Mask for the value (as opposed to the type bits) of a Lisp object. */
+#define VALMASK_val (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX)
+#if ENUMABLE (VALMASK_val)
+DEFINE_GDB_SYMBOL_ENUM (VALMASK)
+#else
DEFINE_GDB_SYMBOL_BEGIN (EMACS_INT, VALMASK)
-#define VALMASK (USE_LSB_TAG ? - (1 << GCTYPEBITS) : VAL_MAX)
+# define VALMASK VALMASK_val
DEFINE_GDB_SYMBOL_END (VALMASK)
+#endif
/* Largest and smallest representable fixnum values. These are the C
values. They are macros for use in static initializers. */
/* 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
+/* 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. */
((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. */
/* 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
struct Lisp_Symbol
{
- unsigned gcmarkbit : 1;
+ bool_bf gcmarkbit : 1;
/* Indicates where the value can be found:
0 : it's a plain var, the value is in the `value' field.
enum symbol_interned. */
unsigned interned : 2;
- /* Non-zero means that this variable has been explicitly declared
+ /* True means that this variable has been explicitly declared
special (with `defvar' etc), and shouldn't be lexically bound. */
- unsigned declared_special : 1;
+ 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;
LISP_MACRO_DEFUN (SYMBOL_CONSTANT_P, int, (Lisp_Object sym), (sym))
#define DEFSYM(sym, name) \
- do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (0)
+ do { (sym) = intern_c_string ((name)); staticpro (&(sym)); } while (false)
\f
/***********************************************************************
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
struct Lisp_Misc_Any /* Supertype of all Misc types. */
{
ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_??? */
- unsigned gcmarkbit : 1;
+ bool_bf gcmarkbit : 1;
unsigned spacer : 15;
};
struct Lisp_Marker
{
ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Marker */
- unsigned gcmarkbit : 1;
+ 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
*/
{
ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Overlay */
- unsigned gcmarkbit : 1;
+ bool_bf gcmarkbit : 1;
unsigned spacer : 15;
struct Lisp_Overlay *next;
Lisp_Object start;
struct Lisp_Save_Value
{
ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Save_Value */
- unsigned gcmarkbit : 1;
+ 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
struct Lisp_Free
{
ENUM_BF (Lisp_Misc_Type) type : 16; /* = Lisp_Misc_Free */
- unsigned gcmarkbit : 1;
+ bool_bf gcmarkbit : 1;
unsigned spacer : 15;
union Lisp_Misc *chain;
};
/* 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 */
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. */
PSEUDOVECTORP (Lisp_Object a, int code)
{
if (! VECTORLIKEP (a))
- return 0;
+ return false;
else
{
/* Converting to struct vectorlike_header * avoids aliasing issues. */
{
CHECK_TYPE (WINDOWP (x), Qwindowp, x);
}
+#ifdef subprocesses
INLINE void
CHECK_PROCESS (Lisp_Object x)
{
CHECK_TYPE (PROCESSP (x), Qprocessp, x);
}
+#endif
INLINE void
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)
INLINE double
XFLOATINT (Lisp_Object n)
CHECK_TYPE (FLOATP (x) || INTEGERP (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 (INTEGERP (x) || FLOATP (x), Qnumber_or_marker_p, x); \
+ } while (false)
/* 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. */
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)
\f
/* Save and restore the instruction and environment pointers,
without affecting the signal mask. */
} let;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
- unsigned debug_on_exit : 1;
+ bool_bf debug_on_exit : 1;
Lisp_Object function;
Lisp_Object *args;
ptrdiff_t nargs;
/* Most global vars are reset to their value via the specpdl mechanism,
but a few others are handled by storing their value here. */
-#if 1 /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but they're defined later. */
+#if true /* GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, but defined later. */
struct gcpro *gcpro;
#endif
sys_jmp_buf jmp;
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.
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))
\f
#define GCPRO6(varname1, varname2, varname3, varname4, varname5, varname6) \
((void) gcpro6, (void) gcpro5, (void) gcpro4, (void) gcpro3, (void) gcpro2, \
(void) gcpro1)
+#define GCPRO7(a, b, c, d, e, f, g) (GCPRO6 (a, b, c, d, e, f), (void) gcpro7)
#define UNGCPRO ((void) 0)
#else /* GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS */
gcpro6.next = &gcpro5; gcpro6.var = &varname6; gcpro6.nvars = 1; \
gcprolist = &gcpro6; }
+#define GCPRO7(a, b, c, d, e, f, g) \
+ {gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \
+ gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \
+ gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \
+ gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \
+ gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \
+ gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \
+ gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \
+ gcprolist = &gcpro7; }
+
#define UNGCPRO (gcprolist = gcpro1.next)
#else
gcpro6.level = gcpro_level++; \
gcprolist = &gcpro6; }
+#define GCPRO7(a, b, c, d, e, f, g) \
+ {gcpro1.next = gcprolist; gcpro1.var = &(a); gcpro1.nvars = 1; \
+ gcpro1.level = gcpro_level; \
+ gcpro2.next = &gcpro1; gcpro2.var = &(b); gcpro2.nvars = 1; \
+ gcpro3.next = &gcpro2; gcpro3.var = &(c); gcpro3.nvars = 1; \
+ gcpro4.next = &gcpro3; gcpro4.var = &(d); gcpro4.nvars = 1; \
+ gcpro5.next = &gcpro4; gcpro5.var = &(e); gcpro5.nvars = 1; \
+ gcpro6.next = &gcpro5; gcpro6.var = &(f); gcpro6.nvars = 1; \
+ gcpro7.next = &gcpro6; gcpro7.var = &(g); gcpro7.nvars = 1; \
+ gcpro7.level = gcpro_level++; \
+ gcprolist = &gcpro7; }
+
#define UNGCPRO \
- ((--gcpro_level != gcpro1.level) \
- ? (emacs_abort (), 0) \
- : ((gcprolist = gcpro1.next), 0))
+ (--gcpro_level != gcpro1.level \
+ ? emacs_abort () \
+ : (void) (gcprolist = gcpro1.next))
#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 \
+ do \
{ \
Lisp_Object ret_ungc_val; \
ret_ungc_val = (expr); \
UNGCPRO; \
return ret_ungc_val; \
} \
-while (0)
+ while (false)
/* Call staticpro (&var) to protect static variable `var'. */
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);
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);
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 (void);
extern void get_backtrace (Lisp_Object array);
Lisp_Object backtrace_top_function (void);
/* Defined in frame.c. */
extern Lisp_Object Qonly, Qnone;
extern Lisp_Object Qvisible;
+extern void set_frame_param (struct frame *, Lisp_Object, Lisp_Object);
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
-#if HAVE_NS || defined WINDOWSNT
+#if HAVE_NS || HAVE_NTGUI
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
#endif
extern void frames_discard_buffer (Lisp_Object);
/* 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,
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,
extern char *xstrdup (const char *);
extern char *xlispstrdup (Lisp_Object);
+extern void dupstring (char **, char const *);
extern void xputenv (const char *);
extern char *egetenv (const char *);
extern void *record_xmalloc (size_t);
#define USE_SAFE_ALLOCA \
- ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = 0
+ ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false
/* SAFE_ALLOCA allocates a simple buffer. */
#define SAFE_ALLOCA(size) ((size) < MAX_ALLOCA \
? alloca (size) \
- : (sa_must_free = 1, record_xmalloc (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
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_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)
/* 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); \
+ (buf) = 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)
+
+/* 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. */
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