OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
-OPTION_DEFAULT_IFAVAILABLE([modules],[don't compile with dynamic modules support])
+OPTION_DEFAULT_ON([modules],[don't compile with dynamic modules support])
OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
OPTION_DEFAULT_OFF([cygwin32-native-compilation],[use native compilation on 32-bit Cygwin])
OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input])
esac
fi
-if test "${with_modules}" != "no"; then
- # __attribute__ ((cleanup)) is required for dynamic modules to
- # work.
- AC_CACHE_CHECK([for working __attribute__((cleanup))],
- [emacs_cv_attribute_cleanup],
- [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
-
- extern int exit ();
-
- cleanup_func_1 (k)
- int *k;
- {
- exit (*k - 100);
- }
-
- cleanup_func ()
- {
- int k __attribute__((cleanup (cleanup_func_1))) = 100;
- }
-
- ]], [[cleanup_func (); return 1;]])],
- [emacs_cv_attribute_cleanup=yes],
- [emacs_cv_attribute_cleanup=no],
- [AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- cleanup_func_1 (k)
- int *k;
- {
- return *k;
- };
- cleanup_func ()
- {
- int k __attribute__((cleanup (cleanup_func_1))) = 100;
- }]],
- [[cleanup_func ()]])],
- [emacs_cv_attribute_cleanup="guessing yes"],
- [emacs_cv_attribute_cleanup=no])])])
-
- if test "$emacs_cv_attribute_cleanup" = "no"; then
- if test "${with_modules}" = "ifavailable"; then
- AC_MSG_WARN([your compiler does not support cleanup attributes,
-and as a result dynamic modules have been disabled])
- else
- AC_MSG_ERROR([your compiler is missing the cleanup attribute
-required for dynamic modules to work])
- fi
- else
- case $opsys in
- gnu|gnu-linux)
- LIBMODULES="-ldl"
- HAVE_MODULES=yes
- ;;
- cygwin|mingw32|darwin)
- HAVE_MODULES=yes
- ;;
- *)
- # BSD systems have dlopen in libc.
- AC_CHECK_FUNC([dlopen], [HAVE_MODULES=yes])
- ;;
- esac
-
- if test "${HAVE_MODULES}" = no; then
- AC_MSG_ERROR([Dynamic modules are not supported on your system])
- else
- SAVE_LIBS=$LIBS
- LIBS="$LIBS $LIBMODULES"
- AC_CHECK_FUNCS([dladdr dlfunc])
- LIBS=$SAVE_LIBS
- fi
- fi
-fi
+AS_IF([test "x$with_modules" != "xno"],
+ [AS_CASE(["$opsys"],
+ [gnu|gnu-linux],
+ [LIBMODULES="-ldl"
+ HAVE_MODULES=yes],
+ [cygwin|mingw32|darwin],
+ [HAVE_MODULES=yes],
+ # BSD systems have dlopen in libc.
+ [AC_CHECK_FUNC([dlopen], [HAVE_MODULES=yes])])
+
+ AS_IF([test "x$HAVE_MODULES" = "xno"],
+ [AS_IF([test "$with_modules" = "ifavailable"],
+ [AC_MSG_WARN([Dynamic modules are not supported on your system])],
+ [AC_MSG_ERROR([Dynamic modules are not supported on your system])])],
+ [SAVE_LIBS=$LIBS
+ LIBS="$LIBS $LIBMODULES"
+ AC_CHECK_FUNCS([dladdr dlfunc])
+ LIBS=$SAVE_LIBS])])
+
+AS_IF([test "x$HAVE_MODULES" = xyes],
+ [MODULES_OBJ="emacs-module.o"
+ NEED_DYNLIB=yes
+ AC_DEFINE([HAVE_MODULES], [1], [Define to 1 if dynamic modules are enabled])
+ AC_DEFINE_UNQUOTED([MODULES_SUFFIX], ["$MODULES_SUFFIX"],
+ [System extension for dynamic libraries])
+ AS_IF([test -n "$MODULES_SECONDARY_SUFFIX"],
+ [AC_DEFINE_UNQUOTED([MODULES_SECONDARY_SUFFIX],
+ ["$MODULES_SECONDARY_SUFFIX"],
+ [Alternative system extension for dynamic libraries.])])])
-if test "${HAVE_MODULES}" = yes; then
- MODULES_OBJ="emacs-module.o"
- NEED_DYNLIB=yes
- AC_DEFINE([HAVE_MODULES], [1], [Define to 1 if dynamic modules are enabled])
- AC_DEFINE_UNQUOTED([MODULES_SUFFIX], ["$MODULES_SUFFIX"],
- [System extension for dynamic libraries])
- if test -n "${MODULES_SECONDARY_SUFFIX}"; then
- AC_DEFINE_UNQUOTED([MODULES_SECONDARY_SUFFIX],
- ["$MODULES_SECONDARY_SUFFIX"],
- [Alternative system extension for dynamic libraries.])
- fi
-fi
AC_SUBST([MODULES_OBJ])
AC_SUBST([LIBMODULES])
AC_SUBST([HAVE_MODULES])
/* 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. This is an extension provided
- by GCC and similar compilers; configure prevents module.c from
- being compiled when it is not present.
+ pushed. All code following this point should use
+ MODULE_INTERNAL_CLEANUP before each return.
The do-while forces uses of the macro to be followed by a semicolon.
This macro cannot enclose its entire body inside a do-while, as the
return retval; \
} \
struct handler *internal_cleanup \
- __attribute__ ((cleanup (module_reset_handlerlist))) \
= internal_handler; \
if (sys_setjmp (internal_cleanup->jmp)) \
{ \
module_handle_nonlocal_exit (env, \
internal_cleanup->nonlocal_exit, \
internal_cleanup->val); \
+ module_reset_handlerlist (&internal_cleanup); \
return retval; \
} \
do { } while (false)
+#define MODULE_INTERNAL_CLEANUP \
+ module_reset_handlerlist (&internal_cleanup)
+
\f
/* Implementation of runtime and environment functions.
Emacs functions, by placing the macro
MODULE_HANDLE_NONLOCAL_EXIT right after the above 2 tests.
- 5. Do NOT use 'eassert' for checking validity of user code in the
+ 5. Finally, any code which expands MODULE_HANDLE_NONLOCAL_EXIT
+ should use MODULE_INTERNAL_CLEANUP prior to returning.
+
+ 6. Do NOT use 'eassert' for checking validity of user code in the
module. Instead, make those checks part of the code, and if the
check fails, call 'module_non_local_exit_signal_1' or
'module_non_local_exit_throw_1' to report the error. This is
bool overflow = INT_ADD_WRAPV (ref->refcount, 1, &ref->refcount);
if (overflow)
overflow_error ();
+ MODULE_INTERNAL_CLEANUP;
return &ref->value;
}
else
Lisp_Object value;
XSETPSEUDOVECTOR (value, ref, PVEC_OTHER);
hash_put (h, new_obj, value, hashcode);
+ MODULE_INTERNAL_CLEANUP;
return &ref->value;
}
}
if (--ref->refcount == 0)
hash_remove_from_table (h, obj);
}
+
+ MODULE_INTERNAL_CLEANUP;
}
static enum emacs_funcall_exit
module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
emacs_function func, const char *docstring, void *data)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
if (! (0 <= min_arity
XSET_MODULE_FUNCTION (result, function);
eassert (MODULE_FUNCTIONP (result));
- return lisp_to_value (env, result);
+ value = lisp_to_value (env, result);
+ MODULE_INTERNAL_CLEANUP;
+ return value;
}
static emacs_finalizer
MODULE_FUNCTION_BEGIN (NULL);
Lisp_Object lisp = value_to_lisp (arg);
CHECK_MODULE_FUNCTION (lisp);
+ MODULE_INTERNAL_CLEANUP;
return XMODULE_FUNCTION (lisp)->finalizer;
}
Lisp_Object lisp = value_to_lisp (arg);
CHECK_MODULE_FUNCTION (lisp);
XMODULE_FUNCTION (lisp)->finalizer = fin;
+ MODULE_INTERNAL_CLEANUP;
}
void
/* Normalize (interactive nil) to (interactive). */
XMODULE_FUNCTION (lisp_fun)->interactive_form
= NILP (lisp_spec) ? list1 (Qinteractive) : list2 (Qinteractive, lisp_spec);
+ MODULE_INTERNAL_CLEANUP;
}
Lisp_Object
newargs[1 + i] = value_to_lisp (args[i]);
emacs_value result = lisp_to_value (env, Ffuncall (nargs1, newargs));
SAFE_FREE ();
+ MODULE_INTERNAL_CLEANUP;
return result;
}
static emacs_value
module_intern (emacs_env *env, const char *name)
{
+ emacs_value tem;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, intern (name));
+ tem = lisp_to_value (env, intern (name));
+ MODULE_INTERNAL_CLEANUP;
+ return tem;
}
static emacs_value
module_type_of (emacs_env *env, emacs_value arg)
{
+ emacs_value tem;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, Ftype_of (value_to_lisp (arg)));
+ tem = lisp_to_value (env, Ftype_of (value_to_lisp (arg)));
+ MODULE_INTERNAL_CLEANUP;
+ return tem;
}
static bool
intmax_t i;
if (! integer_to_intmax (lisp, &i))
xsignal1 (Qoverflow_error, lisp);
+ MODULE_INTERNAL_CLEANUP;
return i;
}
static emacs_value
module_make_integer (emacs_env *env, intmax_t n)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, make_int (n));
+ value = lisp_to_value (env, make_int (n));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static double
MODULE_FUNCTION_BEGIN (0);
Lisp_Object lisp = value_to_lisp (arg);
CHECK_TYPE (FLOATP (lisp), Qfloatp, lisp);
+ MODULE_INTERNAL_CLEANUP;
+
return XFLOAT_DATA (lisp);
}
static emacs_value
module_make_float (emacs_env *env, double d)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, make_float (d));
+ value = lisp_to_value (env, make_float (d));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static bool
if (buf == NULL)
{
*len = required_buf_size;
+ MODULE_INTERNAL_CLEANUP;
return true;
}
*len = required_buf_size;
memcpy (buf, SDATA (lisp_str_utf8), raw_size + 1);
+ MODULE_INTERNAL_CLEANUP;
return true;
}
static emacs_value
module_make_string (emacs_env *env, const char *str, ptrdiff_t len)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
if (! (0 <= len && len <= STRING_BYTES_BOUND))
overflow_error ();
Lisp_Object lstr
= len == 0 ? empty_multibyte_string : module_decode_utf_8 (str, len);
- return lisp_to_value (env, lstr);
+ value = lisp_to_value (env, lstr);
+ MODULE_INTERNAL_CLEANUP;
+ return value;
}
static emacs_value
module_make_unibyte_string (emacs_env *env, const char *str, ptrdiff_t length)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
if (! (0 <= length && length <= STRING_BYTES_BOUND))
overflow_error ();
Lisp_Object lstr
= length == 0 ? empty_unibyte_string : make_unibyte_string (str, length);
- return lisp_to_value (env, lstr);
+ value = lisp_to_value (env, lstr);
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static emacs_value
module_make_user_ptr (emacs_env *env, emacs_finalizer fin, void *ptr)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, make_user_ptr (fin, ptr));
+ value = lisp_to_value (env, make_user_ptr (fin, ptr));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static void *
MODULE_FUNCTION_BEGIN (NULL);
Lisp_Object lisp = value_to_lisp (arg);
CHECK_USER_PTR (lisp);
+ MODULE_INTERNAL_CLEANUP;
+
return XUSER_PTR (lisp)->p;
}
Lisp_Object lisp = value_to_lisp (arg);
CHECK_USER_PTR (lisp);
XUSER_PTR (lisp)->p = ptr;
+ MODULE_INTERNAL_CLEANUP;
}
static emacs_finalizer
MODULE_FUNCTION_BEGIN (NULL);
Lisp_Object lisp = value_to_lisp (arg);
CHECK_USER_PTR (lisp);
+ MODULE_INTERNAL_CLEANUP;
return XUSER_PTR (lisp)->finalizer;
}
Lisp_Object lisp = value_to_lisp (arg);
CHECK_USER_PTR (lisp);
XUSER_PTR (lisp)->finalizer = fin;
+ MODULE_INTERNAL_CLEANUP;
}
static void
Lisp_Object lisp = value_to_lisp (vector);
check_vec_index (lisp, index);
ASET (lisp, index, value_to_lisp (value));
+ MODULE_INTERNAL_CLEANUP;
}
static emacs_value
module_vec_get (emacs_env *env, emacs_value vector, ptrdiff_t index)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
Lisp_Object lisp = value_to_lisp (vector);
check_vec_index (lisp, index);
- return lisp_to_value (env, AREF (lisp, index));
+ value = lisp_to_value (env, AREF (lisp, index));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static ptrdiff_t
MODULE_FUNCTION_BEGIN (0);
Lisp_Object lisp = value_to_lisp (vector);
CHECK_VECTOR (lisp);
+ MODULE_INTERNAL_CLEANUP;
+
return ASIZE (lisp);
}
static enum emacs_process_input_result
module_process_input (emacs_env *env)
{
+ enum emacs_process_input_result rc;
+
MODULE_FUNCTION_BEGIN (emacs_process_input_quit);
maybe_quit ();
- return emacs_process_input_continue;
+ rc = emacs_process_input_continue;
+ MODULE_INTERNAL_CLEANUP;
+ return rc;
}
static struct timespec
module_extract_time (emacs_env *env, emacs_value arg)
{
+ struct timespec value;
+
MODULE_FUNCTION_BEGIN ((struct timespec) {0});
- return lisp_time_argument (value_to_lisp (arg));
+ value = lisp_time_argument (value_to_lisp (arg));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
static emacs_value
module_make_time (emacs_env *env, struct timespec time)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
- return lisp_to_value (env, timespec_to_lisp (time));
+ value = lisp_to_value (env, timespec_to_lisp (time));
+ MODULE_INTERNAL_CLEANUP;
+
+ return value;
}
/*
EMACS_INT x = XFIXNUM (o);
*sign = (0 < x) - (x < 0);
if (x == 0 || count == NULL)
- return true;
+ {
+ MODULE_INTERNAL_CLEANUP;
+ return true;
+ }
/* As a simplification we don't check how many array elements
are exactly required, but use a reasonable static upper
bound. For most architectures exactly one element should
if (magnitude == NULL)
{
*count = required;
+ MODULE_INTERNAL_CLEANUP;
return true;
}
if (*count < required)
verify (required * bits < PTRDIFF_MAX);
for (ptrdiff_t i = 0; i < required; ++i)
magnitude[i] = (emacs_limb_t) (u >> (i * bits));
+ MODULE_INTERNAL_CLEANUP;
return true;
}
const mpz_t *x = xbignum_val (o);
*sign = mpz_sgn (*x);
if (count == NULL)
- return true;
+ {
+ MODULE_INTERNAL_CLEANUP;
+ return true;
+ }
size_t required_size = (mpz_sizeinbase (*x, 2) + numb - 1) / numb;
eassert (required_size <= PTRDIFF_MAX);
ptrdiff_t required = (ptrdiff_t) required_size;
if (magnitude == NULL)
{
*count = required;
+ MODULE_INTERNAL_CLEANUP;
return true;
}
if (*count < required)
size_t written;
mpz_export (magnitude, &written, order, size, endian, nails, *x);
eassert (written == required_size);
+ MODULE_INTERNAL_CLEANUP;
return true;
}
module_make_big_integer (emacs_env *env, int sign,
ptrdiff_t count, const emacs_limb_t *magnitude)
{
+ emacs_value value;
+
MODULE_FUNCTION_BEGIN (NULL);
if (sign == 0)
- return lisp_to_value (env, make_fixed_natnum (0));
+ {
+ value = lisp_to_value (env, make_fixed_natnum (0));
+ MODULE_INTERNAL_CLEANUP;
+ return value;
+ }
enum { order = -1, size = sizeof *magnitude, endian = 0, nails = 0 };
mpz_import (mpz[0], count, order, size, endian, nails, magnitude);
if (sign < 0)
mpz_neg (mpz[0], mpz[0]);
- return lisp_to_value (env, make_integer_mpz ());
+ value = lisp_to_value (env, make_integer_mpz ());
+ MODULE_INTERNAL_CLEANUP;
+ return value;
}
static int
module_open_channel (emacs_env *env, emacs_value pipe_process)
{
+ int rc;
+
MODULE_FUNCTION_BEGIN (-1);
- return open_channel_for_module (value_to_lisp (pipe_process));
+ rc = open_channel_for_module (value_to_lisp (pipe_process));
+ MODULE_INTERNAL_CLEANUP;
+
+ return rc;
}
\f