emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Require full GMP for big integer module functions.


From: Philipp Stephani
Subject: [PATCH] Require full GMP for big integer module functions.
Date: Thu, 25 Apr 2019 19:09:04 +0200

This allows mini-gmp to not stay binary-compatible with full GMP.

* src/emacs-module.h.in: Don’t check EMACS_MODULE_HAVE_MPZ_T macro.

* src/emacs-module.c: Define EMACS_MODULE_GMP only if GMP is
available.
(module_extract_big_integer, module_make_big_integer):
Implement only if GMP is available.  Otherwise signal an error.
(syms_of_module): Define new error ‘unimplemented’.

* test/Makefile.in ($(test_module)): Remove support for mini-gmp.

* test/data/emacs-module/mod-test.c (EMACS_MODULE_GMP)
(Fmod_test_nanoseconds, Fmod_test_double): Define only if GMP is
available.

* test/src/emacs-module-tests.el (mod-test-nanoseconds)
(mod-test-double): Skip if GMP is unavailable.

* doc/lispref/internals.texi (Module Values): Document changed
behavior.
---
 doc/lispref/internals.texi        |  6 +++++-
 src/emacs-module.c                | 19 +++++++++++++++----
 src/emacs-module.h.in             |  2 +-
 test/Makefile.in                  |  3 +--
 test/data/emacs-module/mod-test.c | 11 +++++++----
 test/src/emacs-module-tests.el    | 10 ++++++++++
 6 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index 5ae71afbef..a8bf2ee31b 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1519,7 +1519,8 @@ Module Values
 @end deftp
 
 @noindent
-Then you can use the following additional functions:
+If Emacs itself is compiled with GMP support, you can use the
+following additional functions:
 
 @deftypefn Function bool extract_big_integer (emacs_env address@hidden, 
emacs_value @var{arg}, struct emacs_mpz address@hidden)
 This function, which is available since Emacs 27, extracts the
@@ -1543,6 +1544,9 @@ Module Values
 or similar.
 @end deftypefn
 
+If Emacs is compiled without GMP support, these functions will signal
+an error of type @code{unimplemented}.
+
 The following example uses GMP to calculate the next probable prime
 after a given integer:
 
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 0b7b3d6ffb..3d9d9e5757 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -70,12 +70,10 @@ To add a new module function, proceed as follows:
 
 #include <config.h>
 
-#ifndef HAVE_GMP
-#include "mini-gmp.h"
-#define EMACS_MODULE_HAVE_MPZ_T
+#ifdef HAVE_GMP
+#define EMACS_MODULE_GMP
 #endif
 
-#define EMACS_MODULE_GMP
 #include "emacs-module.h"
 
 #include <stdarg.h>
@@ -788,20 +786,28 @@ module_extract_big_integer (emacs_env *env, emacs_value 
value,
                             struct emacs_mpz *result)
 {
   MODULE_FUNCTION_BEGIN ();
+#ifdef HAVE_GMP
   Lisp_Object o = value_to_lisp (value);
   CHECK_INTEGER (o);
   if (FIXNUMP (o))
     mpz_set_intmax (result->value, XFIXNUM (o));
   else
     mpz_set (result->value, XBIGNUM (o)->value);
+#else
+  xsignal0 (Qunimplemented);
+#endif
 }
 
 static emacs_value
 module_make_big_integer (emacs_env *env, const struct emacs_mpz *value)
 {
   MODULE_FUNCTION_BEGIN (NULL);
+#ifdef HAVE_GMP
   mpz_set (mpz[0], value->value);
   return lisp_to_value (env, make_integer_mpz ());
+#else
+  xsignal0 (Qunimplemented);
+#endif
 }
 
 
@@ -1384,6 +1390,11 @@ syms_of_module (void)
   Fput (Qinvalid_arity, Qerror_message,
         build_pure_c_string ("Invalid function arity"));
 
+  DEFSYM (Qunimplemented, "unimplemented");
+  Fput (Qunimplemented, Qerror_conditions, pure_list (Qunimplemented, Qerror));
+  Fput (Qunimplemented, Qerror_message,
+        build_pure_c_string ("Function not implemented"));
+
   DEFSYM (Qmodule_function_p, "module-function-p");
 
   defsubr (&Smodule_load);
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index fbc62a61ef..e61aadfc3a 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -28,7 +28,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include <stdbool.h>
 #endif
 
-#if defined EMACS_MODULE_GMP && !defined EMACS_MODULE_HAVE_MPZ_T
+#ifdef EMACS_MODULE_GMP
 #include <gmp.h>
 #endif
 
diff --git a/test/Makefile.in b/test/Makefile.in
index ec20a427ba..2282ccd951 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -257,7 +257,6 @@ FPIC_CFLAGS =
 HYBRID_MALLOC = @HYBRID_MALLOC@
 LIBEGNU_ARCHIVE = ../lib/lib$(if $(HYBRID_MALLOC),e)gnu.a
 GMP_LIB = @GMP_LIB@
-GMP_OBJ = $(if @GMP_OBJ@, ../src/@GMP_OBJ@)
 
 # Note: emacs-module.h is generated from emacs-module.h.in, hence we
 # look in ../src, not $(srcdir)/../src.
@@ -270,7 +269,7 @@ src/emacs-module-tests.log:
 $(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h 
$(LIBEGNU_ARCHIVE)
        $(AM_V_at)${MKDIR_P} $(dir $@)
        $(AM_V_CCLD)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \
-         -o $@ $< $(LIBEGNU_ARCHIVE) $(GMP_LIB) $(GMP_OBJ)
+         -o $@ $< $(LIBEGNU_ARCHIVE) $(GMP_LIB)
 endif
 
 ## Check that there is no 'automated' subdirectory, which would
diff --git a/test/data/emacs-module/mod-test.c 
b/test/data/emacs-module/mod-test.c
index b7007bd80f..a264c0170f 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -29,12 +29,9 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_GMP
 #include <gmp.h>
-#else
-#include "mini-gmp.h"
-#define EMACS_MODULE_HAVE_MPZ_T
+#define EMACS_MODULE_GMP
 #endif
 
-#define EMACS_MODULE_GMP
 #include <emacs-module.h>
 
 #include "timespec.h"
@@ -386,6 +383,8 @@ Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, 
emacs_value *args,
   return env->make_time (env, time);
 }
 
+#ifdef HAVE_GMP
+
 static emacs_value
 Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, 
void *data) {
   assert (nargs == 1);
@@ -417,6 +416,8 @@ Fmod_test_double (emacs_env *env, ptrdiff_t nargs, 
emacs_value *args,
   return result;
 }
 
+#endif /* HAVE_GMP */
+
 /* Lisp utilities for easier readability (simple wrappers).  */
 
 /* Provide FEATURE to Emacs.  */
@@ -486,8 +487,10 @@ emacs_module_init (struct emacs_runtime *ert)
          NULL, NULL);
   DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
   DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, 
NULL);
+#ifdef HAVE_GMP
   DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
   DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
+#endif
 
 #undef DEFUN
 
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 173b63670f..fcd122626e 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -344,6 +344,9 @@ module--test-assertion
 
 (ert-deftest mod-test-nanoseconds ()
   "Test truncation when converting to `struct timespec'."
+  ;; `mod-test-nanoseconds' is not defined if the test module was
+  ;; compiled without GMP support.
+  (skip-unless (fboundp 'mod-test-nanoseconds))
   (dolist (test-case '((0 . 0)
                        (-1 . -1000000000)
                        ((1 . 1000000000) . 1)
@@ -362,10 +365,17 @@ module--test-assertion
         (should (eq (mod-test-nanoseconds input) expected))))))
 
 (ert-deftest mod-test-double ()
+  ;; `mod-test-double' is not defined if the test module was compiled
+  ;; without GMP support.
+  (skip-unless (fboundp 'mod-test-double))
   (dolist (input (list 0 1 2 -1 42 12345678901234567890
                        most-positive-fixnum (1+ most-positive-fixnum)
                        most-negative-fixnum (1- most-negative-fixnum)))
     (ert-info ((format "input: %d" input))
       (should (= (mod-test-double input) (* 2 input))))))
 
+;; Prevent compiler warnings for conditionally-defined functions.
+(declare-function mod-test-nanoseconds "mod-test.so" (arg))
+(declare-function mod-test-double "mod-test.so" (arg))
+
 ;;; emacs-module-tests.el ends here
-- 
2.20.1 (Apple Git-117)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]