This source file includes following definitions.
- Fmod_test_return_t
- sum
- Fmod_test_sum
- Fmod_test_signal
- Fmod_test_throw
- Fmod_test_non_local_exit_funcall
- Fmod_test_globref_make
- Fmod_test_globref_free
- Fmod_test_globref_invalid_free
- Fmod_test_globref_reordered
- Fmod_test_string_a_to_b
- Fmod_test_return_unibyte
- Fmod_test_userptr_make
- Fmod_test_userptr_get
- Fmod_test_vector_fill
- Fmod_test_vector_eq
- Fmod_test_invalid_store
- Fmod_test_invalid_load
- Fmod_test_invalid_store_copy
- invalid_finalizer
- Fmod_test_invalid_finalizer
- signal_system_error
- signal_errno
- timespec_le
- Fmod_test_sleep_until
- Fmod_test_add_nanosecond
- signal_error
- memory_full
- extract_big_integer
- make_big_integer
- Fmod_test_nanoseconds
- Fmod_test_double
- finalizer
- Fmod_test_make_function_with_finalizer
- Fmod_test_function_finalizer_calls
- sleep_for_half_second
- write_to_pipe
- Fmod_test_async_pipe
- Fmod_test_identity
- Fmod_test_funcall
- Fmod_test_make_string
- provide
- bind_function
- emacs_module_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "config.h"
21
22 #undef NDEBUG
23 #include <assert.h>
24
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32
33 #ifdef WINDOWSNT
34
35
36 uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
37 # if !defined __x86_64__
38 # define ALIGN_STACK __attribute__((force_align_arg_pointer))
39 # endif
40 # include <windows.h>
41 #else
42 # include <pthread.h>
43 # include <unistd.h>
44 #endif
45
46 #include <gmp.h>
47 #include <emacs-module.h>
48
49 int plugin_is_GPL_compatible;
50
51 #if INTPTR_MAX <= 0
52 # error "INTPTR_MAX misconfigured"
53 #elif INTPTR_MAX <= INT_MAX || INTPTR_MAX <= LONG_MAX
54 # define pT "ld"
55 # define pZ "lu"
56 # define T_TYPE long
57 # define Z_TYPE unsigned long
58 #elif INTPTR_MAX <= INT64_MAX
59 # ifdef __MINGW32__
60 # define pT "lld"
61 # define pZ "llu"
62 # define T_TYPE long long
63 # define Z_TYPE unsigned long long
64 # else
65 # define pT "ld"
66 # define pZ "lu"
67 # define T_TYPE long
68 # define Z_TYPE unsigned long
69 # endif
70 #else
71 # error "INTPTR_MAX too large"
72 #endif
73
74
75 static emacs_value
76 Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
77 void *data)
78 {
79 return env->intern (env, "t");
80 }
81
82
83 static intmax_t
84 sum (intmax_t a, intmax_t b)
85 {
86 return a + b;
87 }
88
89 static emacs_value
90 Fmod_test_sum (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
91 {
92 assert (nargs == 2);
93 assert ((uintptr_t) data == 0x1234);
94
95 intmax_t a = env->extract_integer (env, args[0]);
96 intmax_t b = env->extract_integer (env, args[1]);
97
98 intmax_t r = sum (a, b);
99
100 return env->make_integer (env, r);
101 }
102
103
104
105 static emacs_value
106 Fmod_test_signal (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
107 void *data)
108 {
109 assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
110 env->non_local_exit_signal (env, env->intern (env, "error"),
111 env->make_integer (env, 56));
112 return NULL;
113 }
114
115
116
117 static emacs_value
118 Fmod_test_throw (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
119 void *data)
120 {
121 assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
122 env->non_local_exit_throw (env, env->intern (env, "tag"),
123 env->make_integer (env, 65));
124 return NULL;
125 }
126
127
128
129
130 static emacs_value
131 Fmod_test_non_local_exit_funcall (emacs_env *env, ptrdiff_t nargs,
132 emacs_value args[], void *data)
133 {
134 assert (nargs == 1);
135 emacs_value result = env->funcall (env, args[0], 0, NULL);
136 emacs_value non_local_exit_symbol, non_local_exit_data;
137 enum emacs_funcall_exit code
138 = env->non_local_exit_get (env, &non_local_exit_symbol,
139 &non_local_exit_data);
140 switch (code)
141 {
142 case emacs_funcall_exit_return:
143 return result;
144 case emacs_funcall_exit_signal:
145 {
146 env->non_local_exit_clear (env);
147 emacs_value Flist = env->intern (env, "list");
148 emacs_value list_args[] = {env->intern (env, "signal"),
149 non_local_exit_symbol, non_local_exit_data};
150 return env->funcall (env, Flist, 3, list_args);
151 }
152 case emacs_funcall_exit_throw:
153 {
154 env->non_local_exit_clear (env);
155 emacs_value Flist = env->intern (env, "list");
156 emacs_value list_args[] = {env->intern (env, "throw"),
157 non_local_exit_symbol, non_local_exit_data};
158 return env->funcall (env, Flist, 3, list_args);
159 }
160 }
161
162
163 return env->intern (env, "nil");;
164 }
165
166
167
168 static emacs_value
169 Fmod_test_globref_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
170 void *data)
171 {
172
173 char str[26 * 100];
174 for (int i = 0; i < sizeof str; i++)
175 str[i] = 'a' + (i % 26);
176
177
178 emacs_value lisp_str = env->make_string (env, str, sizeof str);
179 return env->make_global_ref (env, lisp_str);
180 }
181
182
183 static emacs_value
184 Fmod_test_globref_free (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
185 void *data)
186 {
187 emacs_value refs[10];
188 for (int i = 0; i < 10; i++)
189 {
190 refs[i] = env->make_global_ref (env, args[i % nargs]);
191 }
192 for (int i = 0; i < 10; i++)
193 {
194 env->free_global_ref (env, refs[i]);
195 }
196 return env->intern (env, "ok");
197 }
198
199
200
201
202
203 static emacs_value
204 Fmod_test_globref_invalid_free (emacs_env *env, ptrdiff_t nargs,
205 emacs_value *args, void *data)
206 {
207 emacs_value local = env->make_integer (env, 9876);
208 env->make_global_ref (env, local);
209 env->free_global_ref (env, local);
210 return env->intern (env, "nil");
211 }
212
213
214
215 static emacs_value
216 Fmod_test_globref_reordered (emacs_env *env, ptrdiff_t nargs,
217 emacs_value *args, void *data)
218 {
219 emacs_value booleans[2] = {
220 env->intern (env, "nil"),
221 env->intern (env, "t"),
222 };
223 emacs_value local = env->intern (env, "foo");
224 emacs_value globals[4] = {
225 env->make_global_ref (env, local),
226 env->make_global_ref (env, local),
227 env->make_global_ref (env, env->intern (env, "foo")),
228 env->make_global_ref (env, env->intern (env, "bar")),
229 };
230 emacs_value elements[4];
231 for (int i = 0; i < 4; ++i)
232 elements[i] = booleans[env->eq (env, globals[i], local)];
233 emacs_value ret = env->funcall (env, env->intern (env, "list"), 4, elements);
234 env->free_global_ref (env, globals[2]);
235 env->free_global_ref (env, globals[1]);
236 env->free_global_ref (env, globals[3]);
237 env->free_global_ref (env, globals[0]);
238 return ret;
239 }
240
241
242
243
244 static emacs_value
245 Fmod_test_string_a_to_b (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
246 void *data)
247 {
248 emacs_value lisp_str = args[0];
249 ptrdiff_t size = 0;
250 char * buf = NULL;
251
252 env->copy_string_contents (env, lisp_str, buf, &size);
253 buf = malloc (size);
254 env->copy_string_contents (env, lisp_str, buf, &size);
255
256 for (ptrdiff_t i = 0; i + 1 < size; i++)
257 if (buf[i] == 'a')
258 buf[i] = 'b';
259
260 emacs_value ret = env->make_string (env, buf, size - 1);
261 free (buf);
262 return ret;
263 }
264
265
266
267 static emacs_value
268 Fmod_test_return_unibyte (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
269 void *data)
270 {
271 const char *string = "foo\x00zot";
272 return env->make_unibyte_string (env, string, 7);
273 }
274
275
276
277
278
279 struct super_struct
280 {
281 int amazing_int;
282 char large_unused_buffer[512];
283 };
284
285 static void signal_errno (emacs_env *, char const *);
286
287
288
289 static emacs_value
290 Fmod_test_userptr_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
291 void *data)
292 {
293 struct super_struct *p = calloc (1, sizeof *p);
294 if (!p)
295 {
296 signal_errno (env, "calloc");
297 return NULL;
298 }
299 p->amazing_int = env->extract_integer (env, args[0]);
300 return env->make_user_ptr (env, free, p);
301 }
302
303
304 static emacs_value
305 Fmod_test_userptr_get (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
306 void *data)
307 {
308 struct super_struct *p = env->get_user_ptr (env, args[0]);
309 return env->make_integer (env, p->amazing_int);
310 }
311
312
313
314 static emacs_value
315 Fmod_test_vector_fill (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
316 void *data)
317 {
318 emacs_value vec = args[0];
319 emacs_value val = args[1];
320 ptrdiff_t size = env->vec_size (env, vec);
321 for (ptrdiff_t i = 0; i < size; i++)
322 env->vec_set (env, vec, i, val);
323 return env->intern (env, "t");
324 }
325
326
327
328
329 static emacs_value
330 Fmod_test_vector_eq (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
331 void *data)
332 {
333 emacs_value vec = args[0];
334 emacs_value val = args[1];
335 ptrdiff_t size = env->vec_size (env, vec);
336 for (ptrdiff_t i = 0; i < size; i++)
337 if (!env->eq (env, env->vec_get (env, vec, i), val))
338 return env->intern (env, "nil");
339 return env->intern (env, "t");
340 }
341
342 static emacs_value invalid_stored_value;
343
344
345
346
347
348
349
350 static emacs_value
351 Fmod_test_invalid_store (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
352 void *data)
353 {
354 return invalid_stored_value = env->make_integer (env, 123);
355 }
356
357 static emacs_value
358 Fmod_test_invalid_load (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
359 void *data)
360 {
361 return invalid_stored_value;
362 }
363
364
365
366
367
368
369 static emacs_value global_copy_of_invalid_stored_value;
370
371 static emacs_value
372 Fmod_test_invalid_store_copy (emacs_env *env, ptrdiff_t nargs,
373 emacs_value *args, void *data)
374 {
375 emacs_value local = Fmod_test_invalid_store (env, 0, NULL, NULL);
376 return global_copy_of_invalid_stored_value
377 = env->make_global_ref (env, local);
378 }
379
380
381
382
383
384 static emacs_env *current_env;
385
386 static void
387 invalid_finalizer (void *ptr)
388 {
389 current_env->intern (current_env, "nil");
390 }
391
392 static emacs_value
393 Fmod_test_invalid_finalizer (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
394 void *data)
395 {
396 current_env = env;
397 env->make_user_ptr (env, invalid_finalizer, NULL);
398 return env->intern (env, "nil");
399 }
400
401 static void
402 signal_system_error (emacs_env *env, int error, const char *function)
403 {
404 const char *message = strerror (error);
405 emacs_value message_value = env->make_string (env, message, strlen (message));
406 emacs_value symbol = env->intern (env, "file-error");
407 emacs_value elements[2]
408 = {env->make_string (env, function, strlen (function)), message_value};
409 emacs_value data = env->funcall (env, env->intern (env, "list"), 2, elements);
410 env->non_local_exit_signal (env, symbol, data);
411 }
412
413 static void
414 signal_errno (emacs_env *env, const char *function)
415 {
416 signal_system_error (env, errno, function);
417 }
418
419 #ifdef CLOCK_REALTIME
420
421
422 static bool
423 timespec_le (struct timespec a, struct timespec b)
424 {
425 return (a.tv_sec < b.tv_sec
426 || (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec));
427 }
428
429
430
431
432 static emacs_value
433 Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
434 void *data)
435 {
436 assert (nargs == 2);
437 const struct timespec until = env->extract_time (env, args[0]);
438 if (env->non_local_exit_check (env))
439 return NULL;
440 const bool process_input = env->is_not_nil (env, args[1]);
441 const struct timespec amount = { .tv_nsec = 10000000 };
442 while (true)
443 {
444 struct timespec now;
445 if (clock_gettime (CLOCK_REALTIME, &now) != 0)
446 return NULL;
447 if (timespec_le (until, now))
448 break;
449 if (nanosleep (&amount, NULL) && errno != EINTR)
450 {
451 signal_errno (env, "nanosleep");
452 return NULL;
453 }
454 if ((process_input
455 && env->process_input (env) == emacs_process_input_quit)
456 || env->should_quit (env))
457 return NULL;
458 }
459 return env->intern (env, "finished");
460 }
461 #endif
462
463 static emacs_value
464 Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
465 void *data)
466 {
467 assert (nargs == 1);
468 struct timespec time = env->extract_time (env, args[0]);
469 assert (time.tv_nsec >= 0);
470 assert (time.tv_nsec < 2000000000);
471 time.tv_nsec++;
472 return env->make_time (env, time);
473 }
474
475 static void
476 signal_error (emacs_env *env, const char *message)
477 {
478 emacs_value data = env->make_string (env, message, strlen (message));
479 env->non_local_exit_signal (env, env->intern (env, "error"),
480 env->funcall (env, env->intern (env, "list"), 1,
481 &data));
482 }
483
484 static void
485 memory_full (emacs_env *env)
486 {
487 signal_error (env, "Memory exhausted");
488 }
489
490 enum
491 {
492 max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
493 / sizeof (emacs_limb_t))
494 };
495
496 static bool
497 extract_big_integer (emacs_env *env, emacs_value arg, mpz_t result)
498 {
499 int sign;
500 ptrdiff_t count;
501 bool success = env->extract_big_integer (env, arg, &sign, &count, NULL);
502 if (!success)
503 return false;
504 if (sign == 0)
505 {
506 mpz_set_ui (result, 0);
507 return true;
508 }
509 enum { order = -1, size = sizeof (emacs_limb_t), endian = 0, nails = 0 };
510 assert (0 < count && count <= max_count);
511 emacs_limb_t *magnitude = malloc (count * size);
512 if (magnitude == NULL)
513 {
514 memory_full (env);
515 return false;
516 }
517 success = env->extract_big_integer (env, arg, NULL, &count, magnitude);
518 assert (success);
519 mpz_import (result, count, order, size, endian, nails, magnitude);
520 free (magnitude);
521 if (sign < 0)
522 mpz_neg (result, result);
523 return true;
524 }
525
526 static emacs_value
527 make_big_integer (emacs_env *env, const mpz_t value)
528 {
529 if (mpz_sgn (value) == 0)
530 return env->make_integer (env, 0);
531
532
533 enum
534 {
535 order = -1,
536 size = sizeof (emacs_limb_t),
537 endian = 0,
538 nails = 0,
539 numb = 8 * size - nails
540 };
541 size_t count = (mpz_sizeinbase (value, 2) + numb - 1) / numb;
542 if (max_count < count)
543 {
544 memory_full (env);
545 return NULL;
546 }
547 emacs_limb_t *magnitude = malloc (count * size);
548 if (magnitude == NULL)
549 {
550 memory_full (env);
551 return NULL;
552 }
553 size_t written;
554 mpz_export (magnitude, &written, order, size, endian, nails, value);
555 assert (written == count);
556 assert (count <= PTRDIFF_MAX);
557 emacs_value result = env->make_big_integer (env, mpz_sgn (value),
558 (ptrdiff_t) count, magnitude);
559 free (magnitude);
560 return result;
561 }
562
563 #ifdef CLOCK_REALTIME
564 static emacs_value
565 Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
566 assert (nargs == 1);
567 struct timespec time = env->extract_time (env, args[0]);
568 mpz_t nanoseconds;
569 assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
570 mpz_init_set_si (nanoseconds, time.tv_sec);
571 mpz_mul_ui (nanoseconds, nanoseconds, 1000000000);
572 assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
573 mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec);
574 emacs_value result = make_big_integer (env, nanoseconds);
575 mpz_clear (nanoseconds);
576 return result;
577 }
578 #endif
579
580 static emacs_value
581 Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
582 void *data)
583 {
584 assert (nargs == 1);
585 emacs_value arg = args[0];
586 mpz_t value;
587 mpz_init (value);
588 extract_big_integer (env, arg, value);
589 mpz_mul_ui (value, value, 2);
590 emacs_value result = make_big_integer (env, value);
591 mpz_clear (value);
592 return result;
593 }
594
595 static int function_data;
596 static int finalizer_calls_with_correct_data;
597 static int finalizer_calls_with_incorrect_data;
598
599 static void
600 finalizer (void *data)
601 {
602 if (data == &function_data)
603 ++finalizer_calls_with_correct_data;
604 else
605 ++finalizer_calls_with_incorrect_data;
606 }
607
608 static emacs_value
609 Fmod_test_make_function_with_finalizer (emacs_env *env, ptrdiff_t nargs,
610 emacs_value *args, void *data)
611 {
612 emacs_value fun
613 = env->make_function (env, 2, 2, Fmod_test_sum, NULL, &function_data);
614 env->set_function_finalizer (env, fun, finalizer);
615 if (env->get_function_finalizer (env, fun) != finalizer)
616 signal_error (env, "Invalid finalizer");
617 return fun;
618 }
619
620 static emacs_value
621 Fmod_test_function_finalizer_calls (emacs_env *env, ptrdiff_t nargs,
622 emacs_value *args, void *data)
623 {
624 emacs_value Flist = env->intern (env, "list");
625 emacs_value list_args[]
626 = {env->make_integer (env, finalizer_calls_with_correct_data),
627 env->make_integer (env, finalizer_calls_with_incorrect_data)};
628 return env->funcall (env, Flist, 2, list_args);
629 }
630
631 static void
632 sleep_for_half_second (void)
633 {
634
635 #ifdef WINDOWSNT
636 Sleep (500);
637 #else
638 const struct timespec sleep = { .tv_nsec = 500000000 };
639 if (nanosleep (&sleep, NULL) != 0)
640 perror ("nanosleep");
641 #endif
642 }
643
644 #ifdef WINDOWSNT
645 static void ALIGN_STACK
646 #else
647 static void *
648 #endif
649 write_to_pipe (void *arg)
650 {
651
652
653 sleep_for_half_second ();
654 FILE *stream = arg;
655
656
657 if (fputs ("data from thread", stream) < 0)
658 perror ("fputs");
659 if (fclose (stream) != 0)
660 perror ("close");
661 #ifndef WINDOWSNT
662 return NULL;
663 #endif
664 }
665
666 static emacs_value
667 Fmod_test_async_pipe (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
668 void *data)
669 {
670 assert (nargs == 1);
671 int fd = env->open_channel (env, args[0]);
672 if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
673 return NULL;
674 FILE *stream = fdopen (fd, "w");
675 if (stream == NULL)
676 {
677 signal_errno (env, "fdopen");
678 return NULL;
679 }
680 #ifdef WINDOWSNT
681 uintptr_t thd = _beginthread (write_to_pipe, 0, stream);
682 int error = (thd == (uintptr_t)-1L) ? errno : 0;
683 #else
684 pthread_t thread;
685 int error
686 = pthread_create (&thread, NULL, write_to_pipe, stream);
687 #endif
688 if (error != 0)
689 {
690 signal_system_error (env, error, "thread create");
691 if (fclose (stream) != 0)
692 perror ("fclose");
693 return NULL;
694 }
695 return env->intern (env, "nil");
696 }
697
698 static emacs_value
699 Fmod_test_identity (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
700 void *data)
701 {
702 assert (nargs == 1);
703 return args[0];
704 }
705
706 static emacs_value
707 Fmod_test_funcall (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
708 void *data)
709 {
710 assert (0 < nargs);
711 return env->funcall (env, args[0], nargs - 1, args + 1);
712 }
713
714 static emacs_value
715 Fmod_test_make_string (emacs_env *env, ptrdiff_t nargs,
716 emacs_value *args, void *data)
717 {
718 assert (nargs == 2);
719 intmax_t length_arg = env->extract_integer (env, args[0]);
720 if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
721 return args[0];
722 if (length_arg < 0 || SIZE_MAX < length_arg)
723 {
724 signal_error (env, "Invalid string length");
725 return args[0];
726 }
727 size_t length = (size_t) length_arg;
728 bool multibyte = env->is_not_nil (env, args[1]);
729 char *buffer = length == 0 ? NULL : malloc (length);
730 if (buffer == NULL && length != 0)
731 {
732 memory_full (env);
733 return args[0];
734 }
735 memset (buffer, 'a', length);
736 emacs_value ret = multibyte ? env->make_string (env, buffer, length)
737 : env->make_unibyte_string (env, buffer, length);
738 free (buffer);
739 return ret;
740 }
741
742
743
744
745 static void
746 provide (emacs_env *env, const char *feature)
747 {
748 emacs_value Qfeat = env->intern (env, feature);
749 emacs_value Qprovide = env->intern (env, "provide");
750 emacs_value args[] = { Qfeat };
751
752 env->funcall (env, Qprovide, 1, args);
753 }
754
755
756 static void
757 bind_function (emacs_env *env, const char *name, emacs_value Sfun)
758 {
759 emacs_value Qdefalias = env->intern (env, "defalias");
760 emacs_value Qsym = env->intern (env, name);
761 emacs_value args[] = { Qsym, Sfun };
762
763 env->funcall (env, Qdefalias, 2, args);
764 }
765
766
767 int
768 emacs_module_init (struct emacs_runtime *ert)
769 {
770
771
772 assert (0 < EMACS_LIMB_MAX);
773 assert (1000000000 <= ULONG_MAX);
774
775
776
777 char dummy[EMACS_MAJOR_VERSION];
778 assert (27 <= sizeof dummy);
779
780 if (ert->size < sizeof *ert)
781 {
782 fprintf (stderr, "Runtime size of runtime structure (%"pT" bytes) "
783 "smaller than compile-time size (%"pZ" bytes)",
784 (T_TYPE) ert->size, (Z_TYPE) sizeof (*ert));
785 return 1;
786 }
787
788 emacs_env *env = ert->get_environment (ert);
789
790 if (env->size < sizeof *env)
791 {
792 fprintf (stderr, "Runtime size of environment structure (%"pT" bytes) "
793 "smaller than compile-time size (%"pZ" bytes)",
794 (T_TYPE) env->size, (Z_TYPE) sizeof (*env));
795 return 2;
796 }
797
798 #define DEFUN(lsym, csym, amin, amax, doc, data) \
799 bind_function (env, lsym, \
800 env->make_function (env, amin, amax, csym, doc, data))
801
802 DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL);
803 DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)",
804 (void *) (uintptr_t) 0x1234);
805 DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL);
806 DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL);
807 DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall,
808 1, 1, NULL, NULL);
809 DEFUN ("mod-test-globref-make", Fmod_test_globref_make, 0, 0, NULL, NULL);
810 DEFUN ("mod-test-globref-free", Fmod_test_globref_free, 4, 4, NULL, NULL);
811 DEFUN ("mod-test-globref-invalid-free", Fmod_test_globref_invalid_free, 0, 0,
812 NULL, NULL);
813 DEFUN ("mod-test-globref-reordered", Fmod_test_globref_reordered, 0, 0, NULL,
814 NULL);
815 DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
816 DEFUN ("mod-test-return-unibyte", Fmod_test_return_unibyte, 0, 0, NULL, NULL);
817 DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
818 DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
819 DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
820 DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq, 2, 2, NULL, NULL);
821 DEFUN ("mod-test-invalid-store", Fmod_test_invalid_store, 0, 0, NULL, NULL);
822 DEFUN ("mod-test-invalid-store-copy", Fmod_test_invalid_store_copy, 0, 0,
823 NULL, NULL);
824 DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
825 DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
826 NULL, NULL);
827 #ifdef CLOCK_REALTIME
828 DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
829 #endif
830 DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL);
831 #ifdef CLOCK_REALTIME
832 DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
833 #endif
834 DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
835 DEFUN ("mod-test-make-function-with-finalizer",
836 Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL);
837 DEFUN ("mod-test-function-finalizer-calls",
838 Fmod_test_function_finalizer_calls, 0, 0, NULL, NULL);
839 DEFUN ("mod-test-async-pipe", Fmod_test_async_pipe, 1, 1, NULL, NULL);
840 DEFUN ("mod-test-funcall", Fmod_test_funcall, 1, emacs_variadic_function,
841 NULL, NULL);
842 DEFUN ("mod-test-make-string", Fmod_test_make_string, 2, 2, NULL, NULL);
843
844 #undef DEFUN
845
846 emacs_value constant_fn
847 = env->make_function (env, 0, 0, Fmod_test_return_t, NULL, NULL);
848 env->make_interactive (env, constant_fn, env->intern (env, "nil"));
849 bind_function (env, "mod-test-return-t-int", constant_fn);
850
851 emacs_value identity_fn
852 = env->make_function (env, 1, 1, Fmod_test_identity, NULL, NULL);
853 const char *interactive_spec = "i";
854 env->make_interactive (env, identity_fn,
855 env->make_string (env, interactive_spec,
856 strlen (interactive_spec)));
857 bind_function (env, "mod-test-identity", identity_fn);
858
859
860
861 int count = 10000;
862 for (int i = 0; i < count; ++i)
863 env->make_integer (env, i);
864
865 provide (env, "mod-test");
866 return 0;
867 }