summaryrefslogtreecommitdiff
path: root/src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/module.c')
-rw-r--r--src/module.c731
1 files changed, 346 insertions, 385 deletions
diff --git a/src/module.c b/src/module.c
index 4069b881394..35a9f48eb12 100644
--- a/src/module.c
+++ b/src/module.c
@@ -30,285 +30,193 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "verify.h"
-/* Feature tests */
+/* Feature tests. */
-enum {
- /* 1 if we have __attribute__((cleanup(...))), 0 otherwise */
- module_has_cleanup =
+/* True if __attribute__ ((cleanup (...))) works, false otherwise. */
#ifdef HAVE_VAR_ATTRIBUTE_CLEANUP
- 1
+enum { module_has_cleanup = true };
#else
- 0
+enum { module_has_cleanup = false };
#endif
-};
/* Handle to the main thread. Used to verify that modules call us in
- the right thread. */
-#if defined(HAVE_THREADS_H)
-#include <threads.h>
+ the right thread. */
+#ifdef HAVE_THREADS_H
+# include <threads.h>
static thrd_t main_thread;
-#elif defined(HAVE_PTHREAD)
-#include <pthread.h>
+#elif defined HAVE_PTHREAD
+# include <pthread.h>
static pthread_t main_thread;
-#elif defined(WINDOWSNT)
-#include <windows.h>
-/* On Windows, we store both a handle to the main thread and the
+#elif defined WINDOWSNT
+# include <windows.h>
+/* On Windows, store both a handle to the main thread and the
thread ID because the latter can be reused when a thread
- terminates. */
+ terminates. */
static HANDLE main_thread;
static DWORD main_thread_id;
#endif
-/* Implementation of runtime and environment functions */
-
-static emacs_env* module_get_environment (struct emacs_runtime *ert);
-
-static emacs_value module_make_global_ref (emacs_env *env,
- emacs_value ref);
-static void module_free_global_ref (emacs_env *env,
- emacs_value ref);
-static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *env);
-static void module_non_local_exit_clear (emacs_env *env);
-static enum emacs_funcall_exit module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data);
-static void module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data);
-static void module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value);
-static emacs_value module_make_function (emacs_env *env,
- int min_arity,
- int max_arity,
- emacs_subr subr,
- const char *documentation,
- void *data);
-static emacs_value module_funcall (emacs_env *env,
- emacs_value fun,
- int nargs,
- emacs_value args[]);
-static emacs_value module_intern (emacs_env *env, const char *name);
-static emacs_value module_type_of (emacs_env *env, emacs_value value);
-static bool module_is_not_nil (emacs_env *env, emacs_value value);
-static bool module_eq (emacs_env *env, emacs_value a, emacs_value b);
-static int64_t module_extract_integer (emacs_env *env, emacs_value n);
-static emacs_value module_make_integer (emacs_env *env, int64_t n);
-static emacs_value module_make_float (emacs_env *env, double d);
-static double module_extract_float (emacs_env *env, emacs_value f);
-static bool module_copy_string_contents (emacs_env *env,
- emacs_value value,
- char *buffer,
- size_t* length);
-static emacs_value module_make_string (emacs_env *env, const char *str, size_t lenght);
-static emacs_value module_make_user_ptr (emacs_env *env,
- emacs_finalizer_function fin,
- void *ptr);
-static void* module_get_user_ptr (emacs_env *env, emacs_value uptr);
-static void module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr);
-static emacs_finalizer_function module_get_user_finalizer (emacs_env *env, emacs_value uptr);
-static void module_set_user_finalizer (emacs_env *env,
- emacs_value uptr,
- emacs_finalizer_function fin);
-
-
-/* Helper functions */
-
-/* If checking is enabled, abort if the current thread is not the
- Emacs main thread. */
-static void check_main_thread (void);
-
-/* Internal versions of `module_non_local_exit_signal' and `module_non_local_exit_throw'. */
-static void module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, Lisp_Object data);
-static void module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag, Lisp_Object value);
-
-/* Module version of `wrong_type_argument'. */
-static void module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value);
-
-/* Signal an out-of-memory condition to the caller. */
-static void module_out_of_memory (emacs_env *env);
-
-/* Signal arguments are out of range. */
-static void module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2);
-
-
-/* Value conversion */
-
-/* Converts an `emacs_value' to the corresponding internal object.
- Never fails. */
-static Lisp_Object value_to_lisp (emacs_value v);
-
-/* Converts an internal object to an `emacs_value'. Allocates storage
- from the environment; returns NULL if allocation fails. */
-static emacs_value lisp_to_value (emacs_env *env, Lisp_Object o);
-
-
-/* Memory management */
+/* Memory management. */
/* An `emacs_value' is just a pointer to a structure holding an
- internal Lisp object. */
+ internal Lisp object. */
struct emacs_value_tag { Lisp_Object v; };
/* Local value objects use a simple fixed-sized block allocation
scheme without explicit deallocation. All local values are
- deallocated when the lifetime of their environment ends. We keep
+ deallocated when the lifetime of their environment ends. Keep
track of a current frame from which new values are allocated,
- appending further dynamically-allocated frames if necessary. */
+ appending further dynamically-allocated frames if necessary. */
enum { value_frame_size = 512 };
-/* A block from which `emacs_value' object can be allocated. */
-struct emacs_value_frame {
- /* Storage for values */
+/* A block from which `emacs_value' object can be allocated. */
+struct emacs_value_frame
+{
+ /* Storage for values. */
struct emacs_value_tag objects[value_frame_size];
- /* Index of the next free value in `objects' */
+ /* Index of the next free value in `objects'. */
size_t offset;
- /* Pointer to next frame, if any */
+ /* Pointer to next frame, if any. */
struct emacs_value_frame *next;
};
-/* Must be called for each frame before it can be used for
- allocation. */
-static void initialize_frame (struct emacs_value_frame *frame);
-
/* A structure that holds an initial frame (so that the first local
values require no dynamic allocation) and keeps track of the
- current frame. */
-static struct emacs_value_storage {
+ current frame. */
+static struct emacs_value_storage
+{
struct emacs_value_frame initial;
struct emacs_value_frame *current;
} global_storage;
-/* Must be called for any storage object before it can be used for
- allocation. */
-static void initialize_storage (struct emacs_value_storage *storage);
-
-/* Must be called for any initialized storage object before its
- lifetime ends. Frees all dynamically-allocated frames. */
-static void finalize_storage (struct emacs_value_storage *storage);
-
-/* Allocates a new value from STORAGE and stores OBJ in it. Returns
- NULL if allocations fails and uses ENV for non local exit reporting. */
-static emacs_value allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
- Lisp_Object obj);
-
-/* Private runtime and environment members */
+/* Private runtime and environment members. */
/* The private part of an environment stores the current non local exit state
and holds the `emacs_value' objects allocated during the lifetime
- of the environment. */
-struct emacs_env_private {
+ of the environment. */
+struct emacs_env_private
+{
enum emacs_funcall_exit pending_non_local_exit;
- /* Dedicated storage for non-local exit symbol and data so that we always
- have storage available for them, even in an out-of-memory
- situation. */
+ /* Dedicated storage for non-local exit symbol and data so that
+ storage is always available for them, even in an out-of-memory
+ situation. */
struct emacs_value_tag non_local_exit_symbol, non_local_exit_data;
struct emacs_value_storage storage;
};
-/* Combines public and private parts in one structure. This structure
- is used whenever an environment is created. */
-struct env_storage {
+/* Combine public and private parts in one structure. This structure
+ is used whenever an environment is created. */
+struct env_storage
+{
emacs_env pub;
struct emacs_env_private priv;
};
-/* Must be called before the environment can be used. */
-static void initialize_environment (struct env_storage *env);
-
-/* Must be called before the lifetime of the environment object
- ends. */
-static void finalize_environment (struct env_storage *env);
-
/* The private parts of an `emacs_runtime' object contain the initial
- environment. */
-struct emacs_runtime_private {
+ environment. */
+struct emacs_runtime_private
+{
struct env_storage environment;
};
-/* Convenience macros for non-local exit handling */
-/* Emacs uses setjmp(3) and longjmp(3) for non-local exits, but we
- can't allow module frames to be skipped because they are in general
- not prepared for long jumps (e.g. the behavior in C++ is undefined
- if objects with nontrivial destructors would be skipped).
- Therefore we catch all non-local exits. There are two kinds of
- non-local exits: `signal' and `throw'. The macros in this section
- can be used to catch both. We use macros so that we don't have to
- write lots of additional variants of `internal_condition_case'
- etc. and don't have to worry about passing information to the
- handler functions. */
+/* Forward declarations. */
-/* Called on `signal'. ERR will be a cons cell (SYMBOL . DATA), which
- gets stored in the environment. Sets the pending non-local exit flag. */
-static void module_handle_signal (emacs_env *env, Lisp_Object err);
+struct module_fun_env;
-/* Called on `throw'. TAG_VAL will be a cons cell (TAG . VALUE),
- which gets stored in the environment. Sets the pending non-local exit
- flag. */
-static void module_handle_throw (emacs_env *env, Lisp_Object tag_val);
+static Lisp_Object module_format_fun_env (const struct module_fun_env *);
+static Lisp_Object value_to_lisp (emacs_value);
+static emacs_value allocate_emacs_value (emacs_env *, struct emacs_value_storage *, Lisp_Object);
+static emacs_value lisp_to_value (emacs_env *, Lisp_Object);
+static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *);
+static void check_main_thread (void);
+static void finalize_environment (struct env_storage *);
+static void initialize_environment (struct env_storage *);
+static void module_args_out_of_range (emacs_env *, Lisp_Object, Lisp_Object);
+static void module_handle_signal (emacs_env *, const Lisp_Object);
+static void module_handle_throw (emacs_env *, Lisp_Object);
+static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object);
+static void module_non_local_exit_throw_1 (emacs_env *, Lisp_Object, Lisp_Object);
+static void module_out_of_memory (emacs_env *);
+static void module_reset_handlerlist (const int *);
+static void module_wrong_type (emacs_env *, Lisp_Object, Lisp_Object);
-/* Must be called after setting up a handler immediately before
- returning from the function. See the comments in lisp.h and the
- code in eval.c for details. The macros below arrange for this
- function to be called automatically. DUMMY is ignored. */
-static void module_reset_handlerlist (const int *dummy);
+
+/* Convenience macros for non-local exit handling. */
+
+/* Emacs uses setjmp and longjmp for non-local exits, but
+ module frames cannot be skipped because they are in general
+ not prepared for long jumps (e.g., the behavior in C++ is undefined
+ if objects with nontrivial destructors would be skipped).
+ Therefore, catch all non-local exits. There are two kinds of
+ non-local exits: `signal' and `throw'. The macros in this section
+ can be used to catch both. Use macros to avoid additional variants
+ of `internal_condition_case' etc., and to avoid worrying about
+ passing information to the handler functions. */
/* Place this macro at the beginning of a function returning a number
or a pointer to handle signals. The function must have an ENV
parameter. The function will return 0 (or NULL) if a signal is
- caught. */
-#define MODULE_HANDLE_SIGNALS MODULE_HANDLE_SIGNALS_RETURN(0)
+ caught. */
+#define MODULE_HANDLE_SIGNALS MODULE_HANDLE_SIGNALS_RETURN (0)
/* Place this macro at the beginning of a function returning void to
- handle signals. The function must have an ENV parameter. */
-#define MODULE_HANDLE_SIGNALS_VOID MODULE_HANDLE_SIGNALS_RETURN()
+ handle signals. The function must have an ENV parameter. */
+#define MODULE_HANDLE_SIGNALS_VOID MODULE_HANDLE_SIGNALS_RETURN ()
#define MODULE_HANDLE_SIGNALS_RETURN(retval) \
- MODULE_SETJMP(CONDITION_CASE, module_handle_signal, retval)
+ MODULE_SETJMP (CONDITION_CASE, module_handle_signal, retval)
/* Place this macro at the beginning of a function returning a pointer
to handle non-local exits via `throw'. The function must have an
ENV parameter. The function will return NULL if a `throw' is
- caught. */
+ caught. */
#define MODULE_HANDLE_THROW \
- MODULE_SETJMP(CATCHER_ALL, module_handle_throw, NULL)
-
-#define MODULE_SETJMP(handlertype, handlerfunc, retval) \
- MODULE_SETJMP_1(handlertype, handlerfunc, retval, \
- internal_handler_##handlertype, \
- internal_cleanup_##handlertype)
-
-#define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \
- eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \
- struct handler *c; \
- /* It is very important that pushing the handler doesn't itself raise a \
- signal. */ \
- if (!push_handler_nosignal(&c, Qt, handlertype)) { \
- module_out_of_memory(env); \
- return retval; \
- } \
- verify(module_has_cleanup); \
- /* We can install the cleanup only after the handler has been pushed. Use \
- __attribute__((cleanup)) to avoid non-local-exit-prone manual cleanup. */ \
- const int dummy __attribute__((cleanup(module_reset_handlerlist))); \
- if (sys_setjmp(c->jmp)) { \
- (handlerfunc)(env, c->val); \
- return retval; \
- } \
- /* Force the macro to be followed by a semicolon. */ \
- do { \
- } while (0)
+ MODULE_SETJMP (CATCHER_ALL, module_handle_throw, NULL)
+
+#define MODULE_SETJMP(handlertype, handlerfunc, retval) \
+ MODULE_SETJMP_1 (handlertype, handlerfunc, retval, \
+ internal_handler_##handlertype, \
+ internal_cleanup_##handlertype)
+
+/* It is very important that pushing the handler doesn't itself raise
+ a signal. Install the cleanup only after the handler has been
+ pushed. Use __attribute__ ((cleanup)) to avoid
+ non-local-exit-prone manual cleanup. */
+#define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \
+ do { \
+ eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \
+ struct handler *c; \
+ if (!push_handler_nosignal (&c, Qt, handlertype)) \
+ { \
+ module_out_of_memory (env); \
+ return retval; \
+ } \
+ verify (module_has_cleanup); \
+ const int dummy __attribute__ ((cleanup (module_reset_handlerlist))); \
+ if (sys_setjmp (c->jmp)) \
+ { \
+ (handlerfunc) (env, c->val); \
+ return retval; \
+ } \
+ } while (false)
-/* Function environments */
+/* Function environments. */
/* A function environment is an auxiliary structure used by
`module_make_function' to store information about a module
function. It is stored in a save pointer and retrieved by
`module-call'. Its members correspond to the arguments given to
- `module_make_function'. */
+ `module_make_function'. */
struct module_fun_env
{
@@ -317,34 +225,30 @@ struct module_fun_env
void *data;
};
-/* Returns a string object that contains a user-friendly
- representation of the function environment. */
-static Lisp_Object module_format_fun_env (const struct module_fun_env *env);
-
-/* Holds the function definition of `module-call'. `module-call' is
- uninterned because user code couldn't meaningfully use it, so we
- have to keep its definition around somewhere else. */
+/* The function definition of `module-call'. `module-call' is
+ uninterned because user code couldn't meaningfully use it, so keep
+ its definition around somewhere else. */
static Lisp_Object module_call_func;
-/* Implementation of runtime and environment functions */
+/* Implementation of runtime and environment functions. */
-/* We catch signals and throws only if the code can actually signal or
- throw. */
+/* Catch signals and throws only if the code can actually signal or
+ throw. If checking is enabled, abort if the current thread is not
+ the Emacs main thread. */
-static emacs_env* module_get_environment (struct emacs_runtime *ert)
+static emacs_env *
+module_get_environment (struct emacs_runtime *ert)
{
check_main_thread ();
return &ert->private_members->environment.pub;
}
-/*
- * To make global refs (GC-protected global values) we keep a hash
- * that maps global Lisp objects to reference counts.
- */
+/* To make global refs (GC-protected global values) keep a hash that
+ maps global Lisp objects to reference counts. */
-static emacs_value module_make_global_ref (emacs_env *env,
- emacs_value ref)
+static emacs_value
+module_make_global_ref (emacs_env *env, emacs_value ref)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -376,12 +280,12 @@ static emacs_value module_make_global_ref (emacs_env *env,
return allocate_emacs_value (env, &global_storage, new_obj);
}
-static void module_free_global_ref (emacs_env *env,
- emacs_value ref)
+static void
+module_free_global_ref (emacs_env *env, emacs_value ref)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
- /* TODO: This probably never signals. */
+ /* TODO: This probably never signals. */
MODULE_HANDLE_SIGNALS_VOID;
eassert (HASH_TABLE_P (Vmodule_refs_hash));
struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
@@ -407,19 +311,22 @@ static void module_free_global_ref (emacs_env *env,
}
}
-static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *env)
+static enum emacs_funcall_exit
+module_non_local_exit_check (emacs_env *env)
{
check_main_thread ();
return env->private_members->pending_non_local_exit;
}
-static void module_non_local_exit_clear (emacs_env *env)
+static void
+module_non_local_exit_clear (emacs_env *env)
{
check_main_thread ();
env->private_members->pending_non_local_exit = emacs_funcall_exit_return;
}
-static enum emacs_funcall_exit module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
+static enum emacs_funcall_exit
+module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
{
check_main_thread ();
struct emacs_env_private *const p = env->private_members;
@@ -431,42 +338,36 @@ static enum emacs_funcall_exit module_non_local_exit_get (emacs_env *env, emacs_
return p->pending_non_local_exit;
}
-/*
- * Like for `signal', DATA must be a list
- */
-static void module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
+/* Like for `signal', DATA must be a list. */
+static void
+module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
- module_non_local_exit_signal_1 (env, value_to_lisp (sym), value_to_lisp (data));
+ module_non_local_exit_signal_1 (env, value_to_lisp (sym),
+ value_to_lisp (data));
}
-static void module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
+static void
+module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
- module_non_local_exit_throw_1 (env, value_to_lisp (tag), value_to_lisp (value));
+ module_non_local_exit_throw_1 (env, value_to_lisp (tag),
+ value_to_lisp (value));
}
-/*
- * A module function is lambda function that calls `module-call',
- * passing the function pointer of the module function along with the
- * module emacs_env pointer as arguments.
- *
- * (function
- * (lambda
- * (&rest arglist)
- * (module-call
- * envobj
- * arglist)))
- *
- */
-static emacs_value module_make_function (emacs_env *env,
- int min_arity,
- int max_arity,
- emacs_subr subr,
- const char *const documentation,
- void *data)
+/* A module function is lambda function that calls `module-call',
+ passing the function pointer of the module function along with the
+ module emacs_env pointer as arguments.
+
+ (function (lambda (&rest arglist)
+ (module-call envobj arglist))) */
+
+static emacs_value
+module_make_function (emacs_env *env, int min_arity, int max_arity,
+ emacs_subr subr, const char *const documentation,
+ void *data)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -475,15 +376,15 @@ static emacs_value module_make_function (emacs_env *env,
if (min_arity > MOST_POSITIVE_FIXNUM || max_arity > MOST_POSITIVE_FIXNUM)
xsignal0 (Qoverflow_error);
- if (min_arity < 0 ||
- (max_arity >= 0 && max_arity < min_arity) ||
- (max_arity < 0 && max_arity != emacs_variadic_function))
+ if (min_arity < 0
+ || (max_arity >= 0 && max_arity < min_arity)
+ || (max_arity < 0 && max_arity != emacs_variadic_function))
xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity));
Lisp_Object envobj;
- /* XXX: This should need to be freed when envobj is GC'd */
- struct module_fun_env *envptr = xzalloc (sizeof (*envptr));
+ /* XXX: This should need to be freed when envobj is GC'd. */
+ struct module_fun_env *envptr = xzalloc (sizeof *envptr);
envptr->min_arity = min_arity;
envptr->max_arity = max_arity;
envptr->subr = subr;
@@ -500,20 +401,16 @@ static emacs_value module_make_function (emacs_env *env,
return lisp_to_value (env, ret);
}
-static emacs_value module_funcall (emacs_env *env,
- emacs_value fun,
- int nargs,
- emacs_value args[])
+static emacs_value
+module_funcall (emacs_env *env, emacs_value fun, int nargs, emacs_value args[])
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
MODULE_HANDLE_SIGNALS;
MODULE_HANDLE_THROW;
- /*
- * Make a new Lisp_Object array starting with the function as the
- * first arg, because that's what Ffuncall takes
- */
+ /* Make a new Lisp_Object array starting with the function as the
+ first arg, because that's what Ffuncall takes. */
Lisp_Object newargs[nargs + 1];
newargs[0] = value_to_lisp (fun);
for (int i = 0; i < nargs; i++)
@@ -521,7 +418,8 @@ static emacs_value module_funcall (emacs_env *env,
return lisp_to_value (env, Ffuncall (nargs + 1, newargs));
}
-static emacs_value module_intern (emacs_env *env, const char *name)
+static emacs_value
+module_intern (emacs_env *env, const char *name)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -529,28 +427,32 @@ static emacs_value module_intern (emacs_env *env, const char *name)
return lisp_to_value (env, intern (name));
}
-static emacs_value module_type_of (emacs_env *env, emacs_value value)
+static emacs_value
+module_type_of (emacs_env *env, emacs_value value)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
return lisp_to_value (env, Ftype_of (value_to_lisp (value)));
}
-static bool module_is_not_nil (emacs_env *env, emacs_value value)
+static bool
+module_is_not_nil (emacs_env *env, emacs_value value)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
return ! NILP (value_to_lisp (value));
}
-static bool module_eq (emacs_env *env, emacs_value a, emacs_value b)
+static bool
+module_eq (emacs_env *env, emacs_value a, emacs_value b)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
return EQ (value_to_lisp (a), value_to_lisp (b));
}
-static int64_t module_extract_integer (emacs_env *env, emacs_value n)
+static int64_t
+module_extract_integer (emacs_env *env, emacs_value n)
{
verify (INT64_MIN <= MOST_NEGATIVE_FIXNUM);
verify (INT64_MAX >= MOST_POSITIVE_FIXNUM);
@@ -565,7 +467,8 @@ static int64_t module_extract_integer (emacs_env *env, emacs_value n)
return XINT (l);
}
-static emacs_value module_make_integer (emacs_env *env, int64_t n)
+static emacs_value
+module_make_integer (emacs_env *env, int64_t n)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -582,7 +485,8 @@ static emacs_value module_make_integer (emacs_env *env, int64_t n)
return lisp_to_value (env, make_number (n));
}
-static double module_extract_float (emacs_env *env, emacs_value f)
+static double
+module_extract_float (emacs_env *env, emacs_value f)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -595,7 +499,8 @@ static double module_extract_float (emacs_env *env, emacs_value f)
return XFLOAT_DATA (lisp);
}
-static emacs_value module_make_float (emacs_env *env, double d)
+static emacs_value
+module_make_float (emacs_env *env, double d)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -603,10 +508,9 @@ static emacs_value module_make_float (emacs_env *env, double d)
return lisp_to_value (env, make_float (d));
}
-static bool module_copy_string_contents (emacs_env *env,
- emacs_value value,
- char *buffer,
- size_t* length)
+static bool
+module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer,
+ size_t *length)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -620,10 +524,8 @@ static bool module_copy_string_contents (emacs_env *env,
size_t raw_size = SBYTES (lisp_str);
- /*
- * Emacs internal encoding is more-or-less UTF8, let's assume utf8
- * encoded emacs string are the same byte size.
- */
+ /* Emacs internal encoding is more-or-less UTF8, let's assume utf8
+ encoded emacs string are the same byte size. */
if (!buffer || length == 0 || *length-1 < raw_size)
{
@@ -640,7 +542,8 @@ static bool module_copy_string_contents (emacs_env *env,
return true;
}
-static emacs_value module_make_string (emacs_env *env, const char *str, size_t length)
+static emacs_value
+module_make_string (emacs_env *env, const char *str, size_t length)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -650,19 +553,19 @@ static emacs_value module_make_string (emacs_env *env, const char *str, size_t l
module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
return NULL;
}
- /* Assume STR is utf8 encoded */
+ /* Assume STR is utf8 encoded. */
return lisp_to_value (env, make_string (str, length));
}
-static emacs_value module_make_user_ptr (emacs_env *env,
- emacs_finalizer_function fin,
- void *ptr)
+static emacs_value
+module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr)
{
check_main_thread ();
return lisp_to_value (env, make_user_ptr (fin, ptr));
}
-static void* module_get_user_ptr (emacs_env *env, emacs_value uptr)
+static void *
+module_get_user_ptr (emacs_env *env, emacs_value uptr)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -675,7 +578,8 @@ static void* module_get_user_ptr (emacs_env *env, emacs_value uptr)
return XUSER_PTR (lisp)->p;
}
-static void module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
+static void
+module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -684,7 +588,8 @@ static void module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
XUSER_PTR (lisp)->p = ptr;
}
-static emacs_finalizer_function module_get_user_finalizer (emacs_env *env, emacs_value uptr)
+static emacs_finalizer_function
+module_get_user_finalizer (emacs_env *env, emacs_value uptr)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -697,9 +602,9 @@ static emacs_finalizer_function module_get_user_finalizer (emacs_env *env, emacs
return XUSER_PTR (lisp)->finalizer;
}
-static void module_set_user_finalizer (emacs_env *env,
- emacs_value uptr,
- emacs_finalizer_function fin)
+static void
+module_set_user_finalizer (emacs_env *env, emacs_value uptr,
+ emacs_finalizer_function fin)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -708,10 +613,8 @@ static void module_set_user_finalizer (emacs_env *env,
XUSER_PTR (lisp)->finalizer = fin;
}
-static void module_vec_set (emacs_env *env,
- emacs_value vec,
- size_t i,
- emacs_value val)
+static void
+module_vec_set (emacs_env *env, emacs_value vec, size_t i, emacs_value val)
{
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -734,11 +637,10 @@ static void module_vec_set (emacs_env *env,
ASET (lvec, i, value_to_lisp (val));
}
-static emacs_value module_vec_get (emacs_env *env,
- emacs_value vec,
- size_t i)
+static emacs_value
+module_vec_get (emacs_env *env, emacs_value vec, size_t i)
{
- /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits */
+ /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits. */
verify (PTRDIFF_MAX <= SIZE_MAX);
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -753,7 +655,7 @@ static emacs_value module_vec_get (emacs_env *env,
module_wrong_type (env, Qvectorp, lvec);
return NULL;
}
- /* Prevent error-prone comparison between types of different signedness. */
+ /* Prevent error-prone comparison between types of different signedness. */
const size_t size = ASIZE (lvec);
eassert (size >= 0);
if (i >= size)
@@ -766,10 +668,10 @@ static emacs_value module_vec_get (emacs_env *env,
return lisp_to_value (env, AREF (lvec, i));
}
-static size_t module_vec_size (emacs_env *env,
- emacs_value vec)
+static size_t
+module_vec_size (emacs_env *env, emacs_value vec)
{
- /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits */
+ /* Type of ASIZE (lvec) is ptrdiff_t, make sure it fits. */
verify (PTRDIFF_MAX <= SIZE_MAX);
check_main_thread ();
eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
@@ -784,7 +686,7 @@ static size_t module_vec_size (emacs_env *env,
}
-/* Subroutines */
+/* Subroutines. */
DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
doc: /* Load module FILE. */)
@@ -836,28 +738,30 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
DEFUN ("module-call", Fmodule_call, Smodule_call, 2, 2, 0,
doc: /* Internal function to call a module function.
ENVOBJ is a save pointer to a module_fun_env structure.
-ARGLIST is a list of arguments passed to SUBRPTR. */)
+ARGLIST is a list of arguments passed to SUBRPTR. */)
(Lisp_Object envobj, Lisp_Object arglist)
{
- const struct module_fun_env *const envptr =
- (const struct module_fun_env *) XSAVE_POINTER (envobj, 0);
+ const struct module_fun_env *const envptr = XSAVE_POINTER (envobj, 0);
const EMACS_INT len = XINT (Flength (arglist));
eassert (len >= 0);
if (len > MOST_POSITIVE_FIXNUM)
xsignal0 (Qoverflow_error);
- if (len > INT_MAX || len < envptr->min_arity || (envptr->max_arity >= 0 && len > envptr->max_arity))
- xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr), make_number (len));
+ if (len > INT_MAX || len < envptr->min_arity
+ || (envptr->max_arity >= 0 && len > envptr->max_arity))
+ xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr),
+ make_number (len));
struct env_storage env;
initialize_environment (&env);
- emacs_value *args = xzalloc (len * sizeof (*args));
+ emacs_value *args = xzalloc (len * sizeof *args);
int i;
for (i = 0; i < len; i++)
{
args[i] = lisp_to_value (&env.pub, XCAR (arglist));
- if (! args[i]) memory_full (sizeof *args[i]);
+ if (! args[i])
+ memory_full (sizeof *args[i]);
arglist = XCDR (arglist);
}
@@ -868,11 +772,12 @@ ARGLIST is a list of arguments passed to SUBRPTR. */)
{
case emacs_funcall_exit_return:
finalize_environment (&env);
- if (ret == NULL) xsignal1 (Qinvalid_module_call, module_format_fun_env (envptr));
+ if (ret == NULL)
+ xsignal1 (Qinvalid_module_call, module_format_fun_env (envptr));
return value_to_lisp (ret);
case emacs_funcall_exit_signal:
{
- const Lisp_Object symbol = value_to_lisp (&env.priv.non_local_exit_symbol);
+ Lisp_Object symbol = value_to_lisp (&env.priv.non_local_exit_symbol);
const Lisp_Object data = value_to_lisp (&env.priv.non_local_exit_data);
finalize_environment (&env);
xsignal (symbol, data);
@@ -888,24 +793,27 @@ ARGLIST is a list of arguments passed to SUBRPTR. */)
}
-/* Helper functions */
+/* Helper functions. */
-static void check_main_thread (void)
+static void
+check_main_thread (void)
{
-#if defined(HAVE_THREADS_H)
- eassert (thrd_equal (thdr_current (), main_thread);
-#elif defined(HAVE_PTHREAD)
+#ifdef HAVE_THREADS_H
+ eassert (thrd_equal (thdr_current (), main_thread));
+#elif defined HAVE_PTHREAD
eassert (pthread_equal (pthread_self (), main_thread));
-#elif defined(WINDOWSNT)
+#elif defined WINDOWSNT
/* CompareObjectHandles would be perfect, but is only available in
Windows 10. Also check whether the thread is still running to
- protect against thread identifier reuse. */
+ protect against thread identifier reuse. */
eassert (GetCurrentThreadId () == main_thread_id
&& WaitForSingleObject (main_thread, 0) == WAIT_TIMEOUT);
#endif
}
-static void module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, Lisp_Object data)
+static void
+module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym,
+ Lisp_Object data)
{
struct emacs_env_private *const p = env->private_members;
eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
@@ -914,7 +822,9 @@ static void module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, Lis
p->non_local_exit_data.v = data;
}
-static void module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag, Lisp_Object value)
+static void
+module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag,
+ Lisp_Object value)
{
struct emacs_env_private *const p = env->private_members;
eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
@@ -923,53 +833,77 @@ static void module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag, Lisp
p->non_local_exit_data.v = value;
}
-static void module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value)
+/* Module version of `wrong_type_argument'. */
+static void
+module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value)
{
- module_non_local_exit_signal_1 (env, Qwrong_type_argument, list2 (predicate, value));
+ module_non_local_exit_signal_1 (env, Qwrong_type_argument,
+ list2 (predicate, value));
}
-static void module_out_of_memory (emacs_env *env)
+/* Signal an out-of-memory condition to the caller. */
+static void
+module_out_of_memory (emacs_env *env)
{
- // TODO: Reimplement this so it works even if memory-signal-data has been modified.
- module_non_local_exit_signal_1 (env, XCAR (Vmemory_signal_data), XCDR (Vmemory_signal_data));
+ /* TODO: Reimplement this so it works even if memory-signal-data has
+ been modified. */
+ module_non_local_exit_signal_1 (env, XCAR (Vmemory_signal_data),
+ XCDR (Vmemory_signal_data));
}
-static void module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2)
+/* Signal arguments are out of range. */
+static void
+module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2)
{
module_non_local_exit_signal_1 (env, Qargs_out_of_range, list2 (a1, a2));
}
-/* Value conversion */
+/* Value conversion. */
-static Lisp_Object value_to_lisp (emacs_value v)
+/* Convert an `emacs_value' to the corresponding internal object.
+ Never fails. */
+static Lisp_Object
+value_to_lisp (emacs_value v)
{
return v->v;
}
-static emacs_value lisp_to_value (emacs_env *env, Lisp_Object o)
+/* Convert an internal object to an `emacs_value'. Allocate storage
+ from the environment; return NULL if allocation fails. */
+static emacs_value
+lisp_to_value (emacs_env *env, Lisp_Object o)
{
struct emacs_env_private *const p = env->private_members;
- if (p->pending_non_local_exit != emacs_funcall_exit_return) return NULL;
+ if (p->pending_non_local_exit != emacs_funcall_exit_return)
+ return NULL;
return allocate_emacs_value (env, &p->storage, o);
}
-/* Memory management */
+/* Memory management. */
-static void initialize_frame (struct emacs_value_frame *frame)
+/* Must be called for each frame before it can be used for allocation. */
+static void
+initialize_frame (struct emacs_value_frame *frame)
{
frame->offset = 0;
frame->next = NULL;
}
-static void initialize_storage (struct emacs_value_storage *storage)
+/* Must be called for any storage object before it can be used for
+ allocation. */
+static void
+initialize_storage (struct emacs_value_storage *storage)
{
initialize_frame (&storage->initial);
storage->current = &storage->initial;
}
-static void finalize_storage (struct emacs_value_storage *storage)
+/* Must be called for any initialized storage object before its
+ lifetime ends. Free all dynamically-allocated frames. */
+static void
+finalize_storage (struct emacs_value_storage *storage)
{
struct emacs_value_frame *next = storage->initial.next;
while (next != NULL)
@@ -980,8 +914,11 @@ static void finalize_storage (struct emacs_value_storage *storage)
}
}
-static emacs_value allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
- Lisp_Object obj)
+/* Allocate a new value from STORAGE and stores OBJ in it. Return
+ NULL if allocations fails and use ENV for non local exit reporting. */
+static emacs_value
+allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
+ Lisp_Object obj)
{
eassert (storage->current);
eassert (storage->current->offset < value_frame_size);
@@ -1004,46 +941,50 @@ static emacs_value allocate_emacs_value (emacs_env *env, struct emacs_value_stor
}
/* Mark all objects allocated from local environments so that they
- don't get garbage-collected. */
+ don't get garbage-collected. */
void mark_modules (void)
{
for (Lisp_Object tem = Vmodule_environments; CONSP (tem); tem = XCDR (tem))
{
const struct env_storage *const env = XSAVE_POINTER (tem, 0);
- for (const struct emacs_value_frame *frame = &env->priv.storage.initial; frame != NULL; frame = frame->next)
+ for (const struct emacs_value_frame *frame = &env->priv.storage.initial;
+ frame != NULL;
+ frame = frame->next)
for (size_t i = 0; i < frame->offset; ++i)
mark_object (frame->objects[i].v);
}
}
-/* Environment lifetime management */
+/* Environment lifetime management. */
-static void initialize_environment (struct env_storage *env)
+/* Must be called before the environment can be used. */
+static void
+initialize_environment (struct env_storage *env)
{
env->priv.pending_non_local_exit = emacs_funcall_exit_return;
initialize_storage (&env->priv.storage);
- env->pub.size = sizeof env->pub;
+ env->pub.size = sizeof env->pub;
env->pub.private_members = &env->priv;
env->pub.make_global_ref = module_make_global_ref;
env->pub.free_global_ref = module_free_global_ref;
- env->pub.non_local_exit_check = module_non_local_exit_check;
- env->pub.non_local_exit_clear = module_non_local_exit_clear;
- env->pub.non_local_exit_get = module_non_local_exit_get;
- env->pub.non_local_exit_signal = module_non_local_exit_signal;
- env->pub.non_local_exit_throw = module_non_local_exit_throw;
- env->pub.make_function = module_make_function;
- env->pub.funcall = module_funcall;
- env->pub.intern = module_intern;
- env->pub.type_of = module_type_of;
- env->pub.is_not_nil = module_is_not_nil;
- env->pub.eq = module_eq;
- env->pub.extract_integer = module_extract_integer;
- env->pub.make_integer = module_make_integer;
+ env->pub.non_local_exit_check = module_non_local_exit_check;
+ env->pub.non_local_exit_clear = module_non_local_exit_clear;
+ env->pub.non_local_exit_get = module_non_local_exit_get;
+ env->pub.non_local_exit_signal = module_non_local_exit_signal;
+ env->pub.non_local_exit_throw = module_non_local_exit_throw;
+ env->pub.make_function = module_make_function;
+ env->pub.funcall = module_funcall;
+ env->pub.intern = module_intern;
+ env->pub.type_of = module_type_of;
+ env->pub.is_not_nil = module_is_not_nil;
+ env->pub.eq = module_eq;
+ env->pub.extract_integer = module_extract_integer;
+ env->pub.make_integer = module_make_integer;
env->pub.extract_float = module_extract_float;
- env->pub.make_float = module_make_float;
+ env->pub.make_float = module_make_float;
env->pub.copy_string_contents = module_copy_string_contents;
- env->pub.make_string = module_make_string;
+ env->pub.make_string = module_make_string;
env->pub.make_user_ptr = module_make_user_ptr;
env->pub.get_user_ptr = module_get_user_ptr;
env->pub.set_user_ptr = module_set_user_ptr;
@@ -1055,36 +996,53 @@ static void initialize_environment (struct env_storage *env)
Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments);
}
-static void finalize_environment (struct env_storage *env)
+/* Must be called before the lifetime of the environment object
+ ends. */
+static void
+finalize_environment (struct env_storage *env)
{
finalize_storage (&env->priv.storage);
Vmodule_environments = XCDR (Vmodule_environments);
}
-/* Non-local exit handling */
+/* Non-local exit handling. */
-static void module_reset_handlerlist(const int *dummy)
+/* Must be called after setting up a handler immediately before
+ returning from the function. See the comments in lisp.h and the
+ code in eval.c for details. The macros below arrange for this
+ function to be called automatically. DUMMY is ignored. */
+static void
+module_reset_handlerlist (const int *dummy)
{
handlerlist = handlerlist->next;
}
-static void module_handle_signal (emacs_env *const env, const Lisp_Object err)
+/* Called on `signal'. ERR is a pair (SYMBOL . DATA), which gets
+ stored in the environment. Set the pending non-local exit flag. */
+static void
+module_handle_signal (emacs_env *const env, const Lisp_Object err)
{
module_non_local_exit_signal_1 (env, XCAR (err), XCDR (err));
}
-static void module_handle_throw (emacs_env *const env, const Lisp_Object tag_val)
+/* Called on `throw'. TAG_VAL is a pair (TAG . VALUE), which gets
+ stored in the environment. Set the pending non-local exit flag. */
+static void
+module_handle_throw (emacs_env *const env, const Lisp_Object tag_val)
{
module_non_local_exit_throw_1 (env, XCAR (tag_val), XCDR (tag_val));
}
-/* Function environments */
+/* Function environments. */
-static Lisp_Object module_format_fun_env (const struct module_fun_env *const env)
+/* Return a string object that contains a user-friendly
+ representation of the function environment. */
+static Lisp_Object
+module_format_fun_env (const struct module_fun_env *const env)
{
- /* Try to print a function name if possible. */
+ /* Try to print a function name if possible. */
const char *path, *sym;
if (dynlib_addr (env->subr, &path, &sym))
{
@@ -1108,26 +1066,28 @@ static Lisp_Object module_format_fun_env (const struct module_fun_env *const env
}
-/* Segment initializer */
+/* Segment initializer. */
-void syms_of_module (void)
+void
+syms_of_module (void)
{
DEFSYM (Qmodule_refs_hash, "module-refs-hash");
DEFVAR_LISP ("module-refs-hash", Vmodule_refs_hash,
doc: /* Module global referrence table. */);
- Vmodule_refs_hash = make_hash_table (hashtest_eq, make_number (DEFAULT_HASH_SIZE),
- make_float (DEFAULT_REHASH_SIZE),
- make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil);
+ Vmodule_refs_hash
+ = make_hash_table (hashtest_eq, make_number (DEFAULT_HASH_SIZE),
+ make_float (DEFAULT_REHASH_SIZE),
+ make_float (DEFAULT_REHASH_THRESHOLD),
+ Qnil);
Funintern (Qmodule_refs_hash, Qnil);
DEFSYM (Qmodule_environments, "module-environments");
DEFVAR_LISP ("module-environments", Vmodule_environments,
- doc: /* List of active module environments. */);
+ doc: /* List of active module environments. */);
Vmodule_environments = Qnil;
/* Unintern `module-environments' because it is only used
- internally. */
+ internally. */
Funintern (Qmodule_environments, Qnil);
DEFSYM (Qmodule_load_failed, "module-load-failed");
@@ -1151,7 +1111,7 @@ void syms_of_module (void)
initialize_storage (&global_storage);
/* Unintern `module-refs-hash' because it is internal-only and Lisp
- code or modules should not access it. */
+ code or modules should not access it. */
Funintern (Qmodule_refs_hash, Qnil);
defsubr (&Smodule_load);
@@ -1159,39 +1119,40 @@ void syms_of_module (void)
/* Don't call defsubr on `module-call' because that would intern it,
but `module-call' is an internal function that users cannot
meaningfully use. Instead, assign its definition to a private
- variable. */
+ variable. */
XSETPVECTYPE (&Smodule_call, PVEC_SUBR);
XSETSUBR (module_call_func, &Smodule_call);
}
/* Unlike syms_of_module, this initializer is called even from an
- * initialized (dumped) Emacs. */
+ initialized (dumped) Emacs. */
-void module_init (void)
+void
+module_init (void)
{
/* It is not guaranteed that dynamic initializers run in the main thread,
- therefore we detect the main thread here. */
-#if defined(HAVE_THREADS_H)
+ therefore detect the main thread here. */
+#ifdef HAVE_THREADS_H
main_thread = thrd_current ();
-#elif defined(HAVE_PTHREAD)
+#elif defined HAVE_PTHREAD
main_thread = pthread_self ();
-#elif defined(WINDOWSNT)
+#elif defined WINDOWSNT
/* This calls APIs that are only available on Vista and later. */
-#if 0
- /* GetCurrentProcess returns a pseudohandle, which we have to duplicate. */
- if (! DuplicateHandle (GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &main_thread,
+# if false
+ /* GetCurrentProcess returns a pseudohandle, which must be duplicated. */
+ if (! DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+ GetCurrentProcess (), &main_thread,
SYNCHRONIZE | THREAD_QUERY_INFORMATION,
FALSE, 0))
emacs_abort ();
-#else
- /* GetCurrentThread returns a pseudohandle, which we have to duplicate. */
+# else
+ /* GetCurrentThread returns a pseudohandle, which must be duplicated. */
HANDLE th = GetCurrentThread ();
if (!DuplicateHandle (GetCurrentProcess (), th,
GetCurrentProcess (), &main_thread, 0, FALSE,
DUPLICATE_SAME_ACCESS))
emacs_abort ();
main_thread_id = GetCurrentThreadId ();
-#endif
+# endif
#endif
}