/* emacs-module.c - Module loading and runtime implementation
-Copyright (C) 2015 Free Software Foundation, Inc.
+Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
\f
/* Feature tests. */
-/* True if __attribute__ ((cleanup (...))) works, false otherwise. */
-#ifdef HAVE_VAR_ATTRIBUTE_CLEANUP
+#if __has_attribute (cleanup)
enum { module_has_cleanup = true };
#else
enum { module_has_cleanup = false };
&& INTPTR_MAX == EMACS_INT_MAX)
};
+/* Function prototype for module user-pointer finalizers. These
+ should not throw C++ exceptions, so emacs-module.h declares the
+ corresponding interfaces with EMACS_NOEXCEPT. There is only C code
+ in this module, though, so this constraint is not enforced here. */
+typedef void (*emacs_finalizer_function) (void *);
+
\f
/* Private runtime and environment members. */
struct emacs_runtime_private
{
/* FIXME: Ideally, we would just define "struct emacs_runtime_private"
- * as a synonym of "emacs_env", but I don't know how to do that in C. */
+ as a synonym of "emacs_env", but I don't know how to do that in C. */
emacs_env pub;
};
\f
\f
/* Convenience macros for non-local exit handling. */
+/* FIXME: The following implementation for non-local exit handling
+ does not support recovery from stack overflow, see sysdep.c. */
+
/* 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
struct emacs_env_private *p = env->private_members;
if (p->pending_non_local_exit != emacs_funcall_exit_return)
{
- /* FIXME: We cannot call lisp_to_value here because that can
- exit non-locally. */
+ /* FIXME: lisp_to_value can exit non-locally. */
*sym = lisp_to_value (p->non_local_exit_symbol);
*data = lisp_to_value (p->non_local_exit_data);
}
check_main_thread ();
if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
return false;
- /* Assume that NILP never exits non-locally. */
return ! NILP (value_to_lisp (value));
}
check_main_thread ();
if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
return false;
- /* Assume that EQ never exits non-locally. */
return EQ (value_to_lisp (a), value_to_lisp (b));
}
}
/* If V was computed from lisp_to_value (O), then return O.
- Must never fail or exit non-locally. */
+ Exits non-locally only if the stack overflows. */
static Lisp_Object
value_to_lisp (emacs_value v)
{
#endif
/* Convert O to an emacs_value. Allocate storage if needed; this can
- signal if memory is exhausted. Must be injective. */
+ signal if memory is exhausted. Must be an injective function. */
static emacs_value
lisp_to_value (Lisp_Object o)
{