]> code.delx.au - gnu-emacs/blob - src/emacs-module.c
1a5e253c969c0ba6a41b124e17c55b945bc0b304
[gnu-emacs] / src / emacs-module.c
1 /* emacs-module.c - Module loading and runtime implementation
2
3 Copyright (C) 2015 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include <config.h>
21
22 #include "emacs-module.h"
23
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "lisp.h"
31 #include "dynlib.h"
32 #include "coding.h"
33 #include "verify.h"
34
35 \f
36 /* Feature tests. */
37
38 /* True if __attribute__ ((cleanup (...))) works, false otherwise. */
39 #ifdef HAVE_VAR_ATTRIBUTE_CLEANUP
40 enum { module_has_cleanup = true };
41 #else
42 enum { module_has_cleanup = false };
43 #endif
44
45 /* Handle to the main thread. Used to verify that modules call us in
46 the right thread. */
47 #ifdef HAVE_THREADS_H
48 # include <threads.h>
49 static thrd_t main_thread;
50 #elif defined HAVE_PTHREAD
51 # include <pthread.h>
52 static pthread_t main_thread;
53 #elif defined WINDOWSNT
54 #include <windows.h>
55 #include "w32term.h"
56 static DWORD main_thread;
57 #endif
58
59 \f
60 /* Memory management. */
61
62 /* An `emacs_value' is just a pointer to a structure holding an
63 internal Lisp object. */
64 struct emacs_value_tag { Lisp_Object v; };
65
66 /* Local value objects use a simple fixed-sized block allocation
67 scheme without explicit deallocation. All local values are
68 deallocated when the lifetime of their environment ends. Keep
69 track of a current frame from which new values are allocated,
70 appending further dynamically-allocated frames if necessary. */
71
72 enum { value_frame_size = 512 };
73
74 /* A block from which `emacs_value' object can be allocated. */
75 struct emacs_value_frame
76 {
77 /* Storage for values. */
78 struct emacs_value_tag objects[value_frame_size];
79
80 /* Index of the next free value in `objects'. */
81 int offset;
82
83 /* Pointer to next frame, if any. */
84 struct emacs_value_frame *next;
85 };
86
87 /* A structure that holds an initial frame (so that the first local
88 values require no dynamic allocation) and keeps track of the
89 current frame. */
90 static struct emacs_value_storage
91 {
92 struct emacs_value_frame initial;
93 struct emacs_value_frame *current;
94 } global_storage;
95
96 \f
97 /* Private runtime and environment members. */
98
99 /* The private part of an environment stores the current non local exit state
100 and holds the `emacs_value' objects allocated during the lifetime
101 of the environment. */
102 struct emacs_env_private
103 {
104 enum emacs_funcall_exit pending_non_local_exit;
105
106 /* Dedicated storage for non-local exit symbol and data so that
107 storage is always available for them, even in an out-of-memory
108 situation. */
109 struct emacs_value_tag non_local_exit_symbol, non_local_exit_data;
110
111 struct emacs_value_storage storage;
112 };
113
114 /* Combine public and private parts in one structure. This structure
115 is used whenever an environment is created. */
116 struct env_storage
117 {
118 emacs_env pub;
119 struct emacs_env_private priv;
120 };
121
122 /* The private parts of an `emacs_runtime' object contain the initial
123 environment. */
124 struct emacs_runtime_private
125 {
126 struct env_storage environment;
127 };
128
129 \f
130
131 /* Forward declarations. */
132
133 struct module_fun_env;
134
135 static Lisp_Object module_format_fun_env (const struct module_fun_env *);
136 static Lisp_Object value_to_lisp (emacs_value);
137 static emacs_value allocate_emacs_value (emacs_env *, struct emacs_value_storage *, Lisp_Object);
138 static emacs_value lisp_to_value (emacs_env *, Lisp_Object);
139 static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *);
140 static void check_main_thread (void);
141 static void finalize_environment (struct env_storage *);
142 static void initialize_environment (struct env_storage *);
143 static void module_args_out_of_range (emacs_env *, Lisp_Object, Lisp_Object);
144 static void module_handle_signal (emacs_env *, Lisp_Object);
145 static void module_handle_throw (emacs_env *, Lisp_Object);
146 static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object);
147 static void module_non_local_exit_throw_1 (emacs_env *, Lisp_Object, Lisp_Object);
148 static void module_out_of_memory (emacs_env *);
149 static void module_reset_handlerlist (const int *);
150 static void module_wrong_type (emacs_env *, Lisp_Object, Lisp_Object);
151
152 \f
153 /* Convenience macros for non-local exit handling. */
154
155 /* Emacs uses setjmp and longjmp for non-local exits, but
156 module frames cannot be skipped because they are in general
157 not prepared for long jumps (e.g., the behavior in C++ is undefined
158 if objects with nontrivial destructors would be skipped).
159 Therefore, catch all non-local exits. There are two kinds of
160 non-local exits: `signal' and `throw'. The macros in this section
161 can be used to catch both. Use macros to avoid additional variants
162 of `internal_condition_case' etc., and to avoid worrying about
163 passing information to the handler functions. */
164
165 /* Place this macro at the beginning of a function returning a number
166 or a pointer to handle signals. The function must have an ENV
167 parameter. The function will return 0 (or NULL) if a signal is
168 caught. */
169 #define MODULE_HANDLE_SIGNALS MODULE_HANDLE_SIGNALS_RETURN (0)
170
171 /* Place this macro at the beginning of a function returning void to
172 handle signals. The function must have an ENV parameter. */
173 #define MODULE_HANDLE_SIGNALS_VOID MODULE_HANDLE_SIGNALS_RETURN ()
174
175 #define MODULE_HANDLE_SIGNALS_RETURN(retval) \
176 MODULE_SETJMP (CONDITION_CASE, module_handle_signal, retval)
177
178 /* Place this macro at the beginning of a function returning a pointer
179 to handle non-local exits via `throw'. The function must have an
180 ENV parameter. The function will return NULL if a `throw' is
181 caught. */
182 #define MODULE_HANDLE_THROW \
183 MODULE_SETJMP (CATCHER_ALL, module_handle_throw, NULL)
184
185 #define MODULE_SETJMP(handlertype, handlerfunc, retval) \
186 MODULE_SETJMP_1 (handlertype, handlerfunc, retval, \
187 internal_handler_##handlertype, \
188 internal_cleanup_##handlertype)
189
190 /* It is very important that pushing the handler doesn't itself raise
191 a signal. Install the cleanup only after the handler has been
192 pushed. Use __attribute__ ((cleanup)) to avoid
193 non-local-exit-prone manual cleanup.
194
195 The do-while forces uses of the macro to be followed by a semicolon.
196 This macro cannot enclose its entire body inside a do-while, as the
197 code after the macro may longjmp back into the macro, which means
198 its local variable C must stay live in later code. */
199
200 #define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \
201 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \
202 struct handler *c = push_handler_nosignal (Qt, handlertype); \
203 if (!c) \
204 { \
205 module_out_of_memory (env); \
206 return retval; \
207 } \
208 verify (module_has_cleanup); \
209 int dummy __attribute__ ((cleanup (module_reset_handlerlist))); \
210 if (sys_setjmp (c->jmp)) \
211 { \
212 (handlerfunc) (env, c->val); \
213 return retval; \
214 } \
215 do { } while (false)
216
217 \f
218 /* Function environments. */
219
220 /* A function environment is an auxiliary structure used by
221 `module_make_function' to store information about a module
222 function. It is stored in a save pointer and retrieved by
223 `module-call'. Its members correspond to the arguments given to
224 `module_make_function'. */
225
226 struct module_fun_env
227 {
228 ptrdiff_t min_arity, max_arity;
229 emacs_subr subr;
230 void *data;
231 };
232
233 /* The function definition of `module-call'. `module-call' is
234 uninterned because user code couldn't meaningfully use it, so keep
235 its definition around somewhere else. */
236 static Lisp_Object module_call_func;
237
238 \f
239 /* Implementation of runtime and environment functions. */
240
241 /* Catch signals and throws only if the code can actually signal or
242 throw. If checking is enabled, abort if the current thread is not
243 the Emacs main thread. */
244
245 static emacs_env *
246 module_get_environment (struct emacs_runtime *ert)
247 {
248 check_main_thread ();
249 return &ert->private_members->environment.pub;
250 }
251
252 /* To make global refs (GC-protected global values) keep a hash that
253 maps global Lisp objects to reference counts. */
254
255 static emacs_value
256 module_make_global_ref (emacs_env *env, emacs_value ref)
257 {
258 check_main_thread ();
259 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
260 MODULE_HANDLE_SIGNALS;
261 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
262 Lisp_Object new_obj = value_to_lisp (ref);
263 EMACS_UINT hashcode;
264 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
265
266 if (i >= 0)
267 {
268 Lisp_Object value = HASH_VALUE (h, i);
269 EMACS_INT refcount = XFASTINT (value) + 1;
270 if (refcount > MOST_POSITIVE_FIXNUM)
271 {
272 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
273 return NULL;
274 }
275 value = make_natnum (refcount);
276 set_hash_value_slot (h, i, value);
277 }
278 else
279 {
280 hash_put (h, new_obj, make_natnum (1), hashcode);
281 }
282
283 return allocate_emacs_value (env, &global_storage, new_obj);
284 }
285
286 static void
287 module_free_global_ref (emacs_env *env, emacs_value ref)
288 {
289 check_main_thread ();
290 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
291 /* TODO: This probably never signals. */
292 /* FIXME: Wait a minute. Shouldn't this function report an error if
293 the hash lookup fails? */
294 MODULE_HANDLE_SIGNALS_VOID;
295 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
296 Lisp_Object obj = value_to_lisp (ref);
297 EMACS_UINT hashcode;
298 ptrdiff_t i = hash_lookup (h, obj, &hashcode);
299
300 if (i >= 0)
301 {
302 Lisp_Object value = HASH_VALUE (h, i);
303 EMACS_INT refcount = XFASTINT (value) - 1;
304 if (refcount > 0)
305 {
306 value = make_natnum (refcount);
307 set_hash_value_slot (h, i, value);
308 }
309 else
310 hash_remove_from_table (h, value);
311 }
312 }
313
314 static enum emacs_funcall_exit
315 module_non_local_exit_check (emacs_env *env)
316 {
317 check_main_thread ();
318 return env->private_members->pending_non_local_exit;
319 }
320
321 static void
322 module_non_local_exit_clear (emacs_env *env)
323 {
324 check_main_thread ();
325 env->private_members->pending_non_local_exit = emacs_funcall_exit_return;
326 }
327
328 static enum emacs_funcall_exit
329 module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
330 {
331 check_main_thread ();
332 struct emacs_env_private *p = env->private_members;
333 if (p->pending_non_local_exit != emacs_funcall_exit_return)
334 {
335 *sym = &p->non_local_exit_symbol;
336 *data = &p->non_local_exit_data;
337 }
338 return p->pending_non_local_exit;
339 }
340
341 /* Like for `signal', DATA must be a list. */
342 static void
343 module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
344 {
345 check_main_thread ();
346 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
347 module_non_local_exit_signal_1 (env, value_to_lisp (sym),
348 value_to_lisp (data));
349 }
350
351 static void
352 module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
353 {
354 check_main_thread ();
355 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
356 module_non_local_exit_throw_1 (env, value_to_lisp (tag),
357 value_to_lisp (value));
358 }
359
360 /* A module function is lambda function that calls `module-call',
361 passing the function pointer of the module function along with the
362 module emacs_env pointer as arguments.
363
364 (function (lambda (&rest arglist)
365 (module-call envobj arglist))) */
366
367 static emacs_value
368 module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
369 emacs_subr subr, const char *documentation,
370 void *data)
371 {
372 check_main_thread ();
373 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
374 MODULE_HANDLE_SIGNALS;
375
376 if (! (0 <= min_arity
377 && (max_arity < 0
378 ? max_arity == emacs_variadic_function
379 : min_arity <= max_arity)))
380 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity));
381
382 /* FIXME: This should be freed when envobj is GC'd. */
383 struct module_fun_env *envptr = xmalloc (sizeof *envptr);
384 envptr->min_arity = min_arity;
385 envptr->max_arity = max_arity;
386 envptr->subr = subr;
387 envptr->data = data;
388
389 Lisp_Object envobj = make_save_ptr (envptr);
390 Lisp_Object doc;
391 if (documentation == NULL)
392 doc = Qnil;
393 else
394 {
395 ptrdiff_t nbytes = strlen (documentation);
396 doc = make_unibyte_string (documentation, nbytes);
397 doc = code_convert_string_norecord (doc, Qutf_8, false);
398 }
399
400 Lisp_Object ret = list4 (Qlambda,
401 list2 (Qand_rest, Qargs),
402 doc,
403 list3 (module_call_func,
404 envobj,
405 Qargs));
406
407 return lisp_to_value (env, ret);
408 }
409
410 static emacs_value
411 module_funcall (emacs_env *env, emacs_value fun, ptrdiff_t nargs,
412 emacs_value args[])
413 {
414 check_main_thread ();
415 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
416 MODULE_HANDLE_SIGNALS;
417 MODULE_HANDLE_THROW;
418
419 /* Make a new Lisp_Object array starting with the function as the
420 first arg, because that's what Ffuncall takes. */
421 Lisp_Object *newargs;
422 USE_SAFE_ALLOCA;
423 SAFE_ALLOCA_LISP (newargs, nargs + 1);
424 newargs[0] = value_to_lisp (fun);
425 for (ptrdiff_t i = 0; i < nargs; i++)
426 newargs[1 + i] = value_to_lisp (args[i]);
427 emacs_value result = lisp_to_value (env, Ffuncall (nargs + 1, newargs));
428 SAFE_FREE ();
429 return result;
430 }
431
432 static emacs_value
433 module_intern (emacs_env *env, const char *name)
434 {
435 check_main_thread ();
436 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
437 MODULE_HANDLE_SIGNALS;
438 return lisp_to_value (env, intern (name));
439 }
440
441 static emacs_value
442 module_type_of (emacs_env *env, emacs_value value)
443 {
444 check_main_thread ();
445 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
446 return lisp_to_value (env, Ftype_of (value_to_lisp (value)));
447 }
448
449 static bool
450 module_is_not_nil (emacs_env *env, emacs_value value)
451 {
452 check_main_thread ();
453 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
454 return ! NILP (value_to_lisp (value));
455 }
456
457 static bool
458 module_eq (emacs_env *env, emacs_value a, emacs_value b)
459 {
460 check_main_thread ();
461 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
462 return EQ (value_to_lisp (a), value_to_lisp (b));
463 }
464
465 static intmax_t
466 module_extract_integer (emacs_env *env, emacs_value n)
467 {
468 check_main_thread ();
469 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
470 Lisp_Object l = value_to_lisp (n);
471 if (! INTEGERP (l))
472 {
473 module_wrong_type (env, Qintegerp, l);
474 return 0;
475 }
476 return XINT (l);
477 }
478
479 static emacs_value
480 module_make_integer (emacs_env *env, intmax_t n)
481 {
482 check_main_thread ();
483 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
484 if (! (MOST_NEGATIVE_FIXNUM <= n && n <= MOST_POSITIVE_FIXNUM))
485 {
486 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
487 return NULL;
488 }
489 return lisp_to_value (env, make_number (n));
490 }
491
492 static double
493 module_extract_float (emacs_env *env, emacs_value f)
494 {
495 check_main_thread ();
496 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
497 Lisp_Object lisp = value_to_lisp (f);
498 if (! FLOATP (lisp))
499 {
500 module_wrong_type (env, Qfloatp, lisp);
501 return 0;
502 }
503 return XFLOAT_DATA (lisp);
504 }
505
506 static emacs_value
507 module_make_float (emacs_env *env, double d)
508 {
509 check_main_thread ();
510 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
511 MODULE_HANDLE_SIGNALS;
512 return lisp_to_value (env, make_float (d));
513 }
514
515 static bool
516 module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer,
517 ptrdiff_t *length)
518 {
519 check_main_thread ();
520 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
521 MODULE_HANDLE_SIGNALS;
522 Lisp_Object lisp_str = value_to_lisp (value);
523 if (! STRINGP (lisp_str))
524 {
525 module_wrong_type (env, Qstringp, lisp_str);
526 return false;
527 }
528
529 Lisp_Object lisp_str_utf8 = ENCODE_UTF_8 (lisp_str);
530 ptrdiff_t raw_size = SBYTES (lisp_str_utf8);
531 if (raw_size == PTRDIFF_MAX)
532 {
533 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
534 return false;
535 }
536 ptrdiff_t required_buf_size = raw_size + 1;
537
538 eassert (length != NULL);
539
540 if (buffer == NULL)
541 {
542 *length = required_buf_size;
543 return true;
544 }
545
546 eassert (*length >= 0);
547
548 if (*length < required_buf_size)
549 {
550 *length = required_buf_size;
551 module_non_local_exit_signal_1 (env, Qargs_out_of_range, Qnil);
552 return false;
553 }
554
555 *length = required_buf_size;
556 memcpy (buffer, SDATA (lisp_str_utf8), raw_size + 1);
557
558 return true;
559 }
560
561 static emacs_value
562 module_make_string (emacs_env *env, const char *str, ptrdiff_t length)
563 {
564 check_main_thread ();
565 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
566 MODULE_HANDLE_SIGNALS;
567 if (length > STRING_BYTES_BOUND)
568 {
569 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
570 return NULL;
571 }
572 Lisp_Object lstr = make_unibyte_string (str, length);
573 return lisp_to_value (env,
574 code_convert_string_norecord (lstr, Qutf_8, false));
575 }
576
577 static emacs_value
578 module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr)
579 {
580 check_main_thread ();
581 return lisp_to_value (env, make_user_ptr (fin, ptr));
582 }
583
584 static void *
585 module_get_user_ptr (emacs_env *env, emacs_value uptr)
586 {
587 check_main_thread ();
588 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
589 Lisp_Object lisp = value_to_lisp (uptr);
590 if (! USER_PTRP (lisp))
591 {
592 module_wrong_type (env, Quser_ptr, lisp);
593 return NULL;
594 }
595 return XUSER_PTR (lisp)->p;
596 }
597
598 static void
599 module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
600 {
601 check_main_thread ();
602 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
603 Lisp_Object lisp = value_to_lisp (uptr);
604 if (! USER_PTRP (lisp))
605 module_wrong_type (env, Quser_ptr, lisp);
606 XUSER_PTR (lisp)->p = ptr;
607 }
608
609 static emacs_finalizer_function
610 module_get_user_finalizer (emacs_env *env, emacs_value uptr)
611 {
612 check_main_thread ();
613 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
614 Lisp_Object lisp = value_to_lisp (uptr);
615 if (! USER_PTRP (lisp))
616 {
617 module_wrong_type (env, Quser_ptr, lisp);
618 return NULL;
619 }
620 return XUSER_PTR (lisp)->finalizer;
621 }
622
623 static void
624 module_set_user_finalizer (emacs_env *env, emacs_value uptr,
625 emacs_finalizer_function fin)
626 {
627 check_main_thread ();
628 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
629 Lisp_Object lisp = value_to_lisp (uptr);
630 if (! USER_PTRP (lisp))
631 module_wrong_type (env, Quser_ptr, lisp);
632 XUSER_PTR (lisp)->finalizer = fin;
633 }
634
635 static void
636 module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val)
637 {
638 check_main_thread ();
639 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
640 Lisp_Object lvec = value_to_lisp (vec);
641 if (! VECTORP (lvec))
642 {
643 module_wrong_type (env, Qvectorp, lvec);
644 return;
645 }
646 if (! (0 <= i && i < ASIZE (lvec)))
647 {
648 if (MOST_NEGATIVE_FIXNUM <= i && i <= MOST_POSITIVE_FIXNUM)
649 module_args_out_of_range (env, lvec, make_number (i));
650 else
651 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
652 return;
653 }
654 ASET (lvec, i, value_to_lisp (val));
655 }
656
657 static emacs_value
658 module_vec_get (emacs_env *env, emacs_value vec, ptrdiff_t i)
659 {
660 check_main_thread ();
661 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
662 Lisp_Object lvec = value_to_lisp (vec);
663 if (! VECTORP (lvec))
664 {
665 module_wrong_type (env, Qvectorp, lvec);
666 return NULL;
667 }
668 if (! (0 <= i && i < ASIZE (lvec)))
669 {
670 if (MOST_NEGATIVE_FIXNUM <= i && i <= MOST_POSITIVE_FIXNUM)
671 module_args_out_of_range (env, lvec, make_number (i));
672 else
673 module_non_local_exit_signal_1 (env, Qoverflow_error, Qnil);
674 return NULL;
675 }
676 return lisp_to_value (env, AREF (lvec, i));
677 }
678
679 static ptrdiff_t
680 module_vec_size (emacs_env *env, emacs_value vec)
681 {
682 check_main_thread ();
683 eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return);
684 Lisp_Object lvec = value_to_lisp (vec);
685 if (! VECTORP (lvec))
686 {
687 module_wrong_type (env, Qvectorp, lvec);
688 return 0;
689 }
690 return ASIZE (lvec);
691 }
692
693 \f
694 /* Subroutines. */
695
696 DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
697 doc: /* Load module FILE. */)
698 (Lisp_Object file)
699 {
700 dynlib_handle_ptr handle;
701 emacs_init_function module_init;
702 void *gpl_sym;
703
704 CHECK_STRING (file);
705 handle = dynlib_open (SSDATA (file));
706 if (!handle)
707 error ("Cannot load file %s: %s", SDATA (file), dynlib_error ());
708
709 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible");
710 if (!gpl_sym)
711 error ("Module %s is not GPL compatible", SDATA (file));
712
713 module_init = (emacs_init_function) dynlib_sym (handle, "emacs_module_init");
714 if (!module_init)
715 error ("Module %s does not have an init function.", SDATA (file));
716
717 struct emacs_runtime_private priv;
718 struct emacs_runtime pub =
719 {
720 .size = sizeof pub,
721 .private_members = &priv,
722 .get_environment = module_get_environment
723 };
724 initialize_environment (&priv.environment);
725 int r = module_init (&pub);
726 finalize_environment (&priv.environment);
727
728 if (r != 0)
729 {
730 if (! (MOST_NEGATIVE_FIXNUM <= r && r <= MOST_POSITIVE_FIXNUM))
731 xsignal0 (Qoverflow_error);
732 xsignal2 (Qmodule_load_failed, file, make_number (r));
733 }
734
735 return Qt;
736 }
737
738 DEFUN ("module-call", Fmodule_call, Smodule_call, 2, 2, 0,
739 doc: /* Internal function to call a module function.
740 ENVOBJ is a save pointer to a module_fun_env structure.
741 ARGLIST is a list of arguments passed to SUBRPTR. */)
742 (Lisp_Object envobj, Lisp_Object arglist)
743 {
744 struct module_fun_env *envptr = XSAVE_POINTER (envobj, 0);
745 EMACS_INT len = XFASTINT (Flength (arglist));
746 eassume (0 <= envptr->min_arity);
747 if (! (envptr->min_arity <= len
748 && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity)))
749 xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr),
750 make_number (len));
751
752 struct env_storage env;
753 initialize_environment (&env);
754
755 emacs_value *args = xnmalloc (len, sizeof *args);
756
757 for (ptrdiff_t i = 0; i < len; i++)
758 {
759 args[i] = lisp_to_value (&env.pub, XCAR (arglist));
760 if (! args[i])
761 memory_full (sizeof *args[i]);
762 arglist = XCDR (arglist);
763 }
764
765 emacs_value ret = envptr->subr (&env.pub, len, args, envptr->data);
766 xfree (args);
767
768 switch (env.priv.pending_non_local_exit)
769 {
770 case emacs_funcall_exit_return:
771 finalize_environment (&env);
772 if (ret == NULL)
773 xsignal1 (Qinvalid_module_call, module_format_fun_env (envptr));
774 return value_to_lisp (ret);
775 case emacs_funcall_exit_signal:
776 {
777 Lisp_Object symbol = value_to_lisp (&env.priv.non_local_exit_symbol);
778 Lisp_Object data = value_to_lisp (&env.priv.non_local_exit_data);
779 finalize_environment (&env);
780 xsignal (symbol, data);
781 }
782 case emacs_funcall_exit_throw:
783 {
784 Lisp_Object tag = value_to_lisp (&env.priv.non_local_exit_symbol);
785 Lisp_Object value = value_to_lisp (&env.priv.non_local_exit_data);
786 finalize_environment (&env);
787 Fthrow (tag, value);
788 }
789 default:
790 eassume (false);
791 }
792 }
793
794 \f
795 /* Helper functions. */
796
797 static void
798 check_main_thread (void)
799 {
800 #ifdef HAVE_THREADS_H
801 eassert (thrd_equal (thdr_current (), main_thread));
802 #elif defined HAVE_PTHREAD
803 eassert (pthread_equal (pthread_self (), main_thread));
804 #elif defined WINDOWSNT
805 eassert (GetCurrentThreadId () == main_thread);
806 #endif
807 }
808
809 static void
810 module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym,
811 Lisp_Object data)
812 {
813 struct emacs_env_private *p = env->private_members;
814 eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
815 p->pending_non_local_exit = emacs_funcall_exit_signal;
816 p->non_local_exit_symbol.v = sym;
817 p->non_local_exit_data.v = data;
818 }
819
820 static void
821 module_non_local_exit_throw_1 (emacs_env *env, Lisp_Object tag,
822 Lisp_Object value)
823 {
824 struct emacs_env_private *p = env->private_members;
825 eassert (p->pending_non_local_exit == emacs_funcall_exit_return);
826 p->pending_non_local_exit = emacs_funcall_exit_throw;
827 p->non_local_exit_symbol.v = tag;
828 p->non_local_exit_data.v = value;
829 }
830
831 /* Module version of `wrong_type_argument'. */
832 static void
833 module_wrong_type (emacs_env *env, Lisp_Object predicate, Lisp_Object value)
834 {
835 module_non_local_exit_signal_1 (env, Qwrong_type_argument,
836 list2 (predicate, value));
837 }
838
839 /* Signal an out-of-memory condition to the caller. */
840 static void
841 module_out_of_memory (emacs_env *env)
842 {
843 /* TODO: Reimplement this so it works even if memory-signal-data has
844 been modified. */
845 module_non_local_exit_signal_1 (env, XCAR (Vmemory_signal_data),
846 XCDR (Vmemory_signal_data));
847 }
848
849 /* Signal arguments are out of range. */
850 static void
851 module_args_out_of_range (emacs_env *env, Lisp_Object a1, Lisp_Object a2)
852 {
853 module_non_local_exit_signal_1 (env, Qargs_out_of_range, list2 (a1, a2));
854 }
855
856 \f
857 /* Value conversion. */
858
859 /* Convert an `emacs_value' to the corresponding internal object.
860 Never fails. */
861 static Lisp_Object
862 value_to_lisp (emacs_value v)
863 {
864 return v->v;
865 }
866
867 /* Convert an internal object to an `emacs_value'. Allocate storage
868 from the environment; return NULL if allocation fails. */
869 static emacs_value
870 lisp_to_value (emacs_env *env, Lisp_Object o)
871 {
872 struct emacs_env_private *p = env->private_members;
873 if (p->pending_non_local_exit != emacs_funcall_exit_return)
874 return NULL;
875 return allocate_emacs_value (env, &p->storage, o);
876 }
877
878 \f
879 /* Memory management. */
880
881 /* Must be called for each frame before it can be used for allocation. */
882 static void
883 initialize_frame (struct emacs_value_frame *frame)
884 {
885 frame->offset = 0;
886 frame->next = NULL;
887 }
888
889 /* Must be called for any storage object before it can be used for
890 allocation. */
891 static void
892 initialize_storage (struct emacs_value_storage *storage)
893 {
894 initialize_frame (&storage->initial);
895 storage->current = &storage->initial;
896 }
897
898 /* Must be called for any initialized storage object before its
899 lifetime ends. Free all dynamically-allocated frames. */
900 static void
901 finalize_storage (struct emacs_value_storage *storage)
902 {
903 struct emacs_value_frame *next = storage->initial.next;
904 while (next != NULL)
905 {
906 struct emacs_value_frame *current = next;
907 next = current->next;
908 free (current);
909 }
910 }
911
912 /* Allocate a new value from STORAGE and stores OBJ in it. Return
913 NULL if allocation fails and use ENV for non local exit reporting. */
914 static emacs_value
915 allocate_emacs_value (emacs_env *env, struct emacs_value_storage *storage,
916 Lisp_Object obj)
917 {
918 eassert (storage->current);
919 eassert (storage->current->offset < value_frame_size);
920 eassert (! storage->current->next);
921 if (storage->current->offset == value_frame_size - 1)
922 {
923 storage->current->next = malloc (sizeof *storage->current->next);
924 if (! storage->current->next)
925 {
926 module_out_of_memory (env);
927 return NULL;
928 }
929 initialize_frame (storage->current->next);
930 storage->current = storage->current->next;
931 }
932 emacs_value value = storage->current->objects + storage->current->offset;
933 value->v = obj;
934 ++storage->current->offset;
935 return value;
936 }
937
938 /* Mark all objects allocated from local environments so that they
939 don't get garbage-collected. */
940 void mark_modules (void)
941 {
942 for (Lisp_Object tem = Vmodule_environments; CONSP (tem); tem = XCDR (tem))
943 {
944 struct env_storage *env = XSAVE_POINTER (tem, 0);
945 for (struct emacs_value_frame *frame = &env->priv.storage.initial;
946 frame != NULL;
947 frame = frame->next)
948 for (int i = 0; i < frame->offset; ++i)
949 mark_object (frame->objects[i].v);
950 }
951 }
952
953 \f
954 /* Environment lifetime management. */
955
956 /* Must be called before the environment can be used. */
957 static void
958 initialize_environment (struct env_storage *env)
959 {
960 env->priv.pending_non_local_exit = emacs_funcall_exit_return;
961 initialize_storage (&env->priv.storage);
962 env->pub.size = sizeof env->pub;
963 env->pub.private_members = &env->priv;
964 env->pub.make_global_ref = module_make_global_ref;
965 env->pub.free_global_ref = module_free_global_ref;
966 env->pub.non_local_exit_check = module_non_local_exit_check;
967 env->pub.non_local_exit_clear = module_non_local_exit_clear;
968 env->pub.non_local_exit_get = module_non_local_exit_get;
969 env->pub.non_local_exit_signal = module_non_local_exit_signal;
970 env->pub.non_local_exit_throw = module_non_local_exit_throw;
971 env->pub.make_function = module_make_function;
972 env->pub.funcall = module_funcall;
973 env->pub.intern = module_intern;
974 env->pub.type_of = module_type_of;
975 env->pub.is_not_nil = module_is_not_nil;
976 env->pub.eq = module_eq;
977 env->pub.extract_integer = module_extract_integer;
978 env->pub.make_integer = module_make_integer;
979 env->pub.extract_float = module_extract_float;
980 env->pub.make_float = module_make_float;
981 env->pub.copy_string_contents = module_copy_string_contents;
982 env->pub.make_string = module_make_string;
983 env->pub.make_user_ptr = module_make_user_ptr;
984 env->pub.get_user_ptr = module_get_user_ptr;
985 env->pub.set_user_ptr = module_set_user_ptr;
986 env->pub.get_user_finalizer = module_get_user_finalizer;
987 env->pub.set_user_finalizer = module_set_user_finalizer;
988 env->pub.vec_set = module_vec_set;
989 env->pub.vec_get = module_vec_get;
990 env->pub.vec_size = module_vec_size;
991 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments);
992 }
993
994 /* Must be called before the lifetime of the environment object
995 ends. */
996 static void
997 finalize_environment (struct env_storage *env)
998 {
999 finalize_storage (&env->priv.storage);
1000 Vmodule_environments = XCDR (Vmodule_environments);
1001 }
1002
1003 \f
1004 /* Non-local exit handling. */
1005
1006 /* Must be called after setting up a handler immediately before
1007 returning from the function. See the comments in lisp.h and the
1008 code in eval.c for details. The macros below arrange for this
1009 function to be called automatically. DUMMY is ignored. */
1010 static void
1011 module_reset_handlerlist (const int *dummy)
1012 {
1013 handlerlist = handlerlist->next;
1014 }
1015
1016 /* Called on `signal'. ERR is a pair (SYMBOL . DATA), which gets
1017 stored in the environment. Set the pending non-local exit flag. */
1018 static void
1019 module_handle_signal (emacs_env *env, Lisp_Object err)
1020 {
1021 module_non_local_exit_signal_1 (env, XCAR (err), XCDR (err));
1022 }
1023
1024 /* Called on `throw'. TAG_VAL is a pair (TAG . VALUE), which gets
1025 stored in the environment. Set the pending non-local exit flag. */
1026 static void
1027 module_handle_throw (emacs_env *env, Lisp_Object tag_val)
1028 {
1029 module_non_local_exit_throw_1 (env, XCAR (tag_val), XCDR (tag_val));
1030 }
1031
1032 \f
1033 /* Function environments. */
1034
1035 /* Return a string object that contains a user-friendly
1036 representation of the function environment. */
1037 static Lisp_Object
1038 module_format_fun_env (const struct module_fun_env *env)
1039 {
1040 /* Try to print a function name if possible. */
1041 const char *path, *sym;
1042 char buffer[256];
1043 char *buf = buffer;
1044 ptrdiff_t bufsize = sizeof buffer;
1045 ptrdiff_t size
1046 = (dynlib_addr (env->subr, &path, &sym)
1047 ? exprintf (&buf, &bufsize, buffer, -1,
1048 "#<module function %s from %s>", sym, path)
1049 : exprintf (&buf, &bufsize, buffer, -1,
1050 "#<module function at %p>", env->subr));
1051 Lisp_Object unibyte_result = make_unibyte_string (buffer, size);
1052 if (buf != buffer)
1053 xfree (buf);
1054 return code_convert_string_norecord (unibyte_result, Qutf_8, false);
1055 }
1056
1057 \f
1058 /* Segment initializer. */
1059
1060 void
1061 syms_of_module (void)
1062 {
1063 DEFSYM (Qmodule_refs_hash, "module-refs-hash");
1064 DEFVAR_LISP ("module-refs-hash", Vmodule_refs_hash,
1065 doc: /* Module global referrence table. */);
1066
1067 Vmodule_refs_hash
1068 = make_hash_table (hashtest_eq, make_number (DEFAULT_HASH_SIZE),
1069 make_float (DEFAULT_REHASH_SIZE),
1070 make_float (DEFAULT_REHASH_THRESHOLD),
1071 Qnil);
1072 Funintern (Qmodule_refs_hash, Qnil);
1073
1074 DEFSYM (Qmodule_environments, "module-environments");
1075 DEFVAR_LISP ("module-environments", Vmodule_environments,
1076 doc: /* List of active module environments. */);
1077 Vmodule_environments = Qnil;
1078 /* Unintern `module-environments' because it is only used
1079 internally. */
1080 Funintern (Qmodule_environments, Qnil);
1081
1082 DEFSYM (Qmodule_load_failed, "module-load-failed");
1083 Fput (Qmodule_load_failed, Qerror_conditions,
1084 listn (CONSTYPE_PURE, 2, Qmodule_load_failed, Qerror));
1085 Fput (Qmodule_load_failed, Qerror_message,
1086 build_pure_c_string ("Module load failed"));
1087
1088 DEFSYM (Qinvalid_module_call, "invalid-module-call");
1089 Fput (Qinvalid_module_call, Qerror_conditions,
1090 listn (CONSTYPE_PURE, 2, Qinvalid_module_call, Qerror));
1091 Fput (Qinvalid_module_call, Qerror_message,
1092 build_pure_c_string ("Invalid module call"));
1093
1094 DEFSYM (Qinvalid_arity, "invalid-arity");
1095 Fput (Qinvalid_arity, Qerror_conditions,
1096 listn (CONSTYPE_PURE, 2, Qinvalid_arity, Qerror));
1097 Fput (Qinvalid_arity, Qerror_message,
1098 build_pure_c_string ("Invalid function arity"));
1099
1100 initialize_storage (&global_storage);
1101
1102 /* Unintern `module-refs-hash' because it is internal-only and Lisp
1103 code or modules should not access it. */
1104 Funintern (Qmodule_refs_hash, Qnil);
1105
1106 defsubr (&Smodule_load);
1107
1108 /* Don't call defsubr on `module-call' because that would intern it,
1109 but `module-call' is an internal function that users cannot
1110 meaningfully use. Instead, assign its definition to a private
1111 variable. */
1112 XSETPVECTYPE (&Smodule_call, PVEC_SUBR);
1113 XSETSUBR (module_call_func, &Smodule_call);
1114 }
1115
1116 /* Unlike syms_of_module, this initializer is called even from an
1117 initialized (dumped) Emacs. */
1118
1119 void
1120 module_init (void)
1121 {
1122 /* It is not guaranteed that dynamic initializers run in the main thread,
1123 therefore detect the main thread here. */
1124 #ifdef HAVE_THREADS_H
1125 main_thread = thrd_current ();
1126 #elif defined HAVE_PTHREAD
1127 main_thread = pthread_self ();
1128 #elif defined WINDOWSNT
1129 /* The 'main' function already recorded the main thread's thread ID,
1130 so we need just to use it . */
1131 main_thread = dwMainThreadId;
1132 #endif
1133 }