aboutsummaryrefslogtreecommitdiffstats
path: root/test/data
diff options
context:
space:
mode:
Diffstat (limited to 'test/data')
-rw-r--r--test/data/emacs-module/mod-test.c111
1 files changed, 97 insertions, 14 deletions
diff --git a/test/data/emacs-module/mod-test.c b/test/data/emacs-module/mod-test.c
index 2891b73c1a0..b579c8a6278 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -33,10 +33,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
33#include <gmp.h> 33#include <gmp.h>
34#else 34#else
35#include "mini-gmp.h" 35#include "mini-gmp.h"
36#define EMACS_MODULE_HAVE_MPZ_T
37#endif 36#endif
38 37
39#define EMACS_MODULE_GMP
40#include <emacs-module.h> 38#include <emacs-module.h>
41 39
42#include "timespec.h" 40#include "timespec.h"
@@ -66,6 +64,8 @@ int plugin_is_GPL_compatible;
66# error "INTPTR_MAX too large" 64# error "INTPTR_MAX too large"
67#endif 65#endif
68 66
67/* Smoke test to verify that EMACS_LIMB_MAX is defined. */
68_Static_assert (0 < EMACS_LIMB_MAX, "EMACS_LIMB_MAX missing or incorrect");
69 69
70/* Always return symbol 't'. */ 70/* Always return symbol 't'. */
71static emacs_value 71static emacs_value
@@ -372,23 +372,106 @@ Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
372 return env->make_time (env, time); 372 return env->make_time (env, time);
373} 373}
374 374
375static void
376memory_full (emacs_env *env)
377{
378 const char *message = "Memory exhausted";
379 emacs_value data = env->make_string (env, message, strlen (message));
380 env->non_local_exit_signal (env, env->intern (env, "error"),
381 env->funcall (env, env->intern (env, "list"), 1,
382 &data));
383}
384
385enum
386{
387 max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
388 / sizeof (emacs_limb_t))
389};
390
391static bool
392extract_big_integer (emacs_env *env, emacs_value arg, mpz_t result)
393{
394 int sign;
395 ptrdiff_t count;
396 bool success = env->extract_big_integer (env, arg, &sign, &count, NULL);
397 if (!success)
398 return false;
399 if (sign == 0)
400 {
401 mpz_set_ui (result, 0);
402 return true;
403 }
404 enum { order = -1, size = sizeof (unsigned long), endian = 0, nails = 0 };
405 assert (0 < count && count <= max_count);
406 emacs_limb_t *magnitude = malloc (count * size);
407 if (magnitude == NULL)
408 {
409 memory_full (env);
410 return false;
411 }
412 success = env->extract_big_integer (env, arg, NULL, &count, magnitude);
413 assert (success);
414 mpz_import (result, count, order, size, endian, nails, magnitude);
415 free (magnitude);
416 if (sign < 0)
417 mpz_neg (result, result);
418 return true;
419}
420
421static emacs_value
422make_big_integer (emacs_env *env, const mpz_t value)
423{
424 if (mpz_sgn (value) == 0)
425 return env->make_integer (env, 0);
426 /* See
427 https://gmplib.org/manual/Integer-Import-and-Export.html#index-Export. */
428 enum
429 {
430 order = -1,
431 size = sizeof (emacs_limb_t),
432 endian = 0,
433 nails = 0,
434 numb = 8 * size - nails
435 };
436 size_t count = (mpz_sizeinbase (value, 2) + numb - 1) / numb;
437 if (max_count < count)
438 {
439 memory_full (env);
440 return NULL;
441 }
442 emacs_limb_t *magnitude = malloc (count * size);
443 if (magnitude == NULL)
444 {
445 memory_full (env);
446 return NULL;
447 }
448 size_t written;
449 mpz_export (magnitude, &written, order, size, endian, nails, value);
450 assert (written == count);
451 assert (count <= PTRDIFF_MAX);
452 emacs_value result = env->make_big_integer (env, mpz_sgn (value),
453 (ptrdiff_t) count, magnitude);
454 free (magnitude);
455 return result;
456}
457
375static emacs_value 458static emacs_value
376Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) { 459Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
377 assert (nargs == 1); 460 assert (nargs == 1);
378 struct timespec time = env->extract_time (env, args[0]); 461 struct timespec time = env->extract_time (env, args[0]);
379 struct emacs_mpz nanoseconds; 462 mpz_t nanoseconds;
380 assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX); 463 assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
381 mpz_init_set_si (nanoseconds.value, time.tv_sec); 464 mpz_init_set_si (nanoseconds, time.tv_sec);
382#ifdef __MINGW32__ 465#ifdef __MINGW32__
383 _Static_assert (1000000000 <= ULONG_MAX, "unsupported architecture"); 466 _Static_assert (1000000000 <= ULONG_MAX, "unsupported architecture");
384#else 467#else
385 static_assert (1000000000 <= ULONG_MAX, "unsupported architecture"); 468 static_assert (1000000000 <= ULONG_MAX, "unsupported architecture");
386#endif 469#endif
387 mpz_mul_ui (nanoseconds.value, nanoseconds.value, 1000000000); 470 mpz_mul_ui (nanoseconds, nanoseconds, 1000000000);
388 assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX); 471 assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
389 mpz_add_ui (nanoseconds.value, nanoseconds.value, time.tv_nsec); 472 mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec);
390 emacs_value result = env->make_big_integer (env, &nanoseconds); 473 emacs_value result = make_big_integer (env, nanoseconds);
391 mpz_clear (nanoseconds.value); 474 mpz_clear (nanoseconds);
392 return result; 475 return result;
393} 476}
394 477
@@ -398,12 +481,12 @@ Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
398{ 481{
399 assert (nargs == 1); 482 assert (nargs == 1);
400 emacs_value arg = args[0]; 483 emacs_value arg = args[0];
401 struct emacs_mpz value; 484 mpz_t value;
402 mpz_init (value.value); 485 mpz_init (value);
403 env->extract_big_integer (env, arg, &value); 486 extract_big_integer (env, arg, value);
404 mpz_mul_ui (value.value, value.value, 2); 487 mpz_mul_ui (value, value, 2);
405 emacs_value result = env->make_big_integer (env, &value); 488 emacs_value result = make_big_integer (env, value);
406 mpz_clear (value.value); 489 mpz_clear (value);
407 return result; 490 return result;
408} 491}
409 492