1 /*** emodules-ng.c -- Dynamic Loader routines (via ltdl)
3 * Copyright (C) 2007 Sebastian Freundt
5 * Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 #include "emodules-ng.h"
45 #if defined HAVE_SYS_STAT_H
46 # include <sys/stat.h>
49 #if defined HAVE_LTDL_H /* go ltdl */
52 # error "Bugger! No code to dlopen() things"
55 #define EMODNG_INIT "init"
56 #define EMODNG_REINIT "reinit"
57 #define EMODNG_DEINIT "deinit"
59 /* this is internal administration */
60 static lt_dlhandle meself = NULL;
61 static emodng_t emods = NULL;
63 typedef struct emod_epcell_s /* endpoint cell */ *emod_epcell_t;
64 static emod_epcell_t emod_endpoints = NULL;
66 struct emod_epcell_s {
71 /* Do we do our work quietly? */
72 int load_modules_quietly;
75 Lisp_Object Vmodule_load_path, Vmodule_extensions;
77 /* lt_dlsym() violates ISO C, so confide the breakage into this function to
79 typedef void(*emodng_f)(void);
82 lt_dlhandle loaded_by;
83 struct emodng_lby_s *next;
92 struct emodng_lby_s *lby;
95 emodng_deinit_f deinitf;
96 emodng_reinit_f reinitf;
106 /* navigation info */
110 static Lisp_Object emodng_load_unwind(Lisp_Object unwind_ptr);
111 static Lisp_Object emodng_unload_unwind(Lisp_Object unwind_ptr);
112 static emodng_t emodng_load(const char *name, lt_dlhandle);
113 static bool emodng_unload(const char *name);
114 static void _emodng_open(emodng_t emod);
115 static void _emodng_close(emodng_t emod);
116 static void _emodng_init(emodng_t emod);
117 static void _emodng_deinit(emodng_t emod);
118 static void _emodng_docs(emodng_t emod);
119 static inline emodng_t _emodng_open_dep(emodng_t emod, const char *dep)
120 __attribute__((always_inline));
121 static inline void _emodng_close_dep(emodng_t emod, emodng_t dep)
122 __attribute__((always_inline));
125 /* some inlines and helper funs */
126 static inline emodng_f
127 lt_dlfun(lt_dlhandle handle, const char *symbol)
128 __attribute__((always_inline));
129 static inline emodng_f
130 lt_dlfun(lt_dlhandle handle, const char *symbol)
132 void *tmp = lt_dlsym(handle, symbol);
133 return (emodng_f)(long int)tmp;
136 #if defined HAVE_STAT || 1
138 __file_exists_p(const char *filename)
141 return stat(filename, &_stbuf) == 0;
143 #endif /* HAVE_STAT */
146 __emodng_open_append_exts(const char *filename)
148 /* append all specified extensions */
149 size_t nname = strlen(filename);
150 char name[nname + /*length of longest extension:*/24];
151 /* note to myself: better check that length! */
152 char *p = xstpncpy(name, filename, nname+1);
153 size_t remain = name + sizeof(name) - p;
155 for (Lisp_Object ext = Vmodule_extensions;
156 CONSP(ext); ext = XCDR(ext)) {
157 if (UNLIKELY(!STRINGP(XCAR(ext)))) {
161 xstrncpy(p, (const char*)XSTRING_DATA(XCAR(ext)),
164 if (__file_exists_p(name)) {
165 EMOD_DEBUG_LOADER("trying %s\n", name);
166 return lt_dlopen(name);
173 __emodng_open_prepend_paths(const char *filename)
175 /* append all specified extensions */
176 size_t nfilename = strlen(filename);
178 /* we used to use Vmodule_load_path here */
179 for (Lisp_Object path = Vload_path;
180 CONSP(path); path = XCDR(path)) {
181 if (LIKELY((STRINGP(XCAR(path))))) {
182 char name[(size_t)XSTRING_LENGTH(XCAR(path))
183 + 1 /*for the slash*/
184 + nfilename /*for the module's actual name*/
185 + 1 /*for the terminating \0 char*/];
186 /* note that we assume here that filename already
187 * carries the correct extension
188 * see __emodng_open_prepend_paths_append_exts for
189 * cope with all the combinations */
192 (const char*)XSTRING_DATA(XCAR(path)),
196 xstrncpy(p, filename, name + sizeof(name) - p);
198 if (__file_exists_p(name)) {
199 EMOD_DEBUG_LOADER("trying %s\n", name);
200 return lt_dlopen(name);
208 __emodng_open_prepend_paths_append_exts(const char *filename)
210 /* append all specified extensions */
211 size_t nfilename = strlen(filename);
213 /* we used to use Vmodule_load_path here */
214 for (Lisp_Object path = Vload_path;
215 CONSP(path); path = XCDR(path)) {
216 if (LIKELY((STRINGP(XCAR(path))))) {
217 char name[(size_t)XSTRING_LENGTH(XCAR(path))
218 + 1 /*for the slash*/
219 + nfilename /*for the module's actual name*/
220 + 24 /* for the length of the extension
221 * BETTER CHECK THAT */
222 + 1 /*for the terminating \0 char*/];
223 /* note that we assume here that filename already
224 * carries the correct extension
225 * see __emodng_open_prepend_paths_append_exts for
226 * cope with all the combinations */
227 char *p = xstpncpy(name,
228 (const char*)XSTRING_DATA(XCAR(path)),
235 remain = name+sizeof(name)-p;
236 p = xstpncpy(p, filename, remain);
237 remain = name+sizeof(name)-p;
239 /* append all extensions now */
240 for (Lisp_Object ext = Vmodule_extensions;
241 CONSP(ext); ext = XCDR(ext)) {
242 if (UNLIKELY(!STRINGP(XCAR(ext)))) {
246 xstrncpy(p,(const char*)XSTRING_DATA(XCAR(ext)),
249 if (__file_exists_p(name)) {
250 EMOD_DEBUG_LOADER("trying \"%s\"\n",
252 return lt_dlopen(name);
261 __emodng_open(emodng_t emod)
263 /* obtain some info to massage the name of the emod */
264 /* determine if emod->name is an absolute filename */
265 bool abso_path_p = emod->name[0] == '/';
266 /* determine if emod->name is a relative filename */
268 strncmp(emod->name, "./", 2) == 0 ||
269 strncmp(emod->name, "../", 3) == 0;
270 /* determine if emod->name carries an extension already
271 * we search backward to an occurrence of '.' and forward for a '/'
272 * to make sure it really belongs to the last path component */
273 char *ext_compo = strrchr(emod->name, '.');
274 bool has_ext_p = ext_compo != NULL && strchr(ext_compo, '/') == NULL;
276 if (LIKELY(!abso_path_p && !rel_path_p && !has_ext_p)) {
277 /* append both extension and paths */
278 emod->dl = __emodng_open_prepend_paths_append_exts(emod->name);
279 } else if (!abso_path_p && !rel_path_p) {
280 /* just append paths */
281 emod->dl = __emodng_open_prepend_paths(emod->name);
282 } else if (has_ext_p) {
283 /* fully featured file name, just dlopen() it */
284 emod->dl = lt_dlopen(emod->name);
285 } else if (!has_ext_p) {
286 /* file name with path but sans extension */
287 emod->dl = __emodng_open_append_exts(emod->name);
289 /* actually we should cater with those relative file names
290 * more thoroughly, I'm not sure what './' means in libltdl speak */
295 __emodng_find_or_create(emodng_t in)
297 /* try to find the emodule specified by in or create one
298 * if it cannot be found */
299 const lt_dlinfo *info;
302 /* get module info */
303 info = lt_dlgetinfo(in->dl);
305 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
306 info->filename, info->name, info->ref_count);
308 for (emodng_t e = emods; e; e = e->next) {
310 strcmp(info->name, e->truename) == 0) {
316 /* otherwise we have to create this */
317 new = xnew(struct emodng_s);
319 new->truename = xstrdup(info->name);
320 new->filename = xstrdup(info->filename);
321 new->name = xstrdup(in->name);
323 new->openedp = new->initialisedp = new->docsloadedp = false;
325 new->deps = in->deps;
326 new->ndeps = in->ndeps;
333 __emodng_find(const char *name)
335 /* try to find the emodule named `name', return its pointer or NULL */
338 for (e = emods; e; e = e->next) {
339 if (strcmp(name, e->truename) == 0) {
349 /* get module info */
350 #ifdef EMOD_DEBUG_FLAG
352 const lt_dlinfo *info = lt_dlgetinfo(e->dl);
354 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
355 info->filename, info->name, info->ref_count);
362 __emodng_remove(emodng_t emod)
364 /* dehorstify this ... */
365 if (UNLIKELY(emod == NULL)) {
369 /* if emod was the top of the list, just kick it */
370 if (emods && emod == emods) {
375 for (emodng_t e = emods; e; e = e->next) {
376 if (e->next && e->next->dl == emod->dl) {
377 e->next = emod->next;
385 emod_endpoint_p(emodng_t emod)
387 /* a VERY sloppy approach */
388 for (emod_epcell_t ee = emod_endpoints; ee; ee = ee->next) {
389 if (ee->emod == emod) {
397 _register_endpoint(emodng_t emod)
399 emod_epcell_t new = xnew(struct emod_epcell_s);
402 new->next = emod_endpoints;
403 emod_endpoints = new;
408 _unregister_endpoint(emodng_t emod)
410 /* very unlikely, but dehorstify anyway */
411 if (UNLIKELY(emod == NULL)) {
415 /* maybe we're lucky today and deal with the topmost entry ... */
416 if (emod_endpoints && emod_endpoints->emod == emod) {
417 emod_epcell_t free_me = emod_endpoints;
418 emod_endpoints = emod_endpoints->next;
423 /* ... gah, what a fooking mess, traverse the list */
424 for (emod_epcell_t e = emod_endpoints; e && e->next; e = e->next) {
425 if (e->next->emod == emod) {
426 emod_epcell_t free_me = e->next;
427 e->next = e->next->next;
436 free_emodng(emodng_t emod)
438 xfree(emod->truename);
439 xfree(emod->filename);
448 /* we divide the load phase into two actual phases, open and init
449 * similarly unload is actually deinit and close (yes, in that order, horst)
450 * it is just because we make sure about dependencies and things */
452 emodng_load(const char *name, lt_dlhandle caller)
454 /* this is the loader chain which opens->inits->imports docs */
455 struct emodng_s _emod = {.name = name};
459 _emodng_open(&_emod);
460 if (UNLIKELY(_emod.dl == NULL)) {
464 /* set up a real emodng_t object and put it into our global emod list */
465 emod = __emodng_find_or_create(&_emod);
466 emod->openedp = true;
475 _emodng_open(emodng_t emod)
477 const char **emoddeps;
479 EMOD_DEBUG_LOADER("loading %s\n", emod->name);
482 /* check that we're really using a valid handle */
483 if (UNLIKELY(emod->dl == NULL)) {
484 error("Opening dynamic module \"%s\": %s",
485 emod->name, lt_dlerror());
491 /* checking dependencies */
492 if (LIKELY((emoddeps =
493 (const char**)lt_dlsym(emod->dl, "dependencies")) ||
495 (const char**)lt_dlsym(emod->dl, "deps")))) {
499 /* count the deps manually */
500 for (const char **deps = emoddeps, *dep = *deps;
501 dep; dep = *++deps, ndeps++);
507 /* create a big array of deps */
508 EMOD_DEBUG_LOADER("found %lu deps\n",
509 (long unsigned int)ndeps);
510 ed = emod->deps = xnew_array(emodng_t, emod->ndeps = ndeps);
512 /* load the other modules (deps) first */
513 for (const char **deps = emoddeps, *dep = *deps;
514 dep; dep = *++deps) {
515 *ed++ = _emodng_open_dep(emod, dep);
518 EMOD_DEBUG_LOADER("no deps found ... "
519 "hope this is right\n");
525 _emodng_init(emodng_t emod)
527 /* calls initialiser code in the module */
528 if (emod->initialisedp) {
529 EMOD_DEBUG_LOADER("already initialised\n");
533 EMOD_DEBUG_LOADER("initialising %s\n", emod->truename);
534 if (LIKELY((emod->initf =
535 (emodng_init_f)lt_dlfun(emod->dl, "init")) != NULL)) {
536 EMOD_DEBUG_LOADER("found init() ... calling now\n");
537 (*emod->initf)(emod);
539 EMOD_DEBUG_LOADER("no init() function found ... "
540 "hope this is right\n");
542 emod->initialisedp = true;
547 _emodng_docs(emodng_t emod)
549 /* because we're lisp, we have to care for documentation strings of our loaded
550 stuff, thus call a function docs() if present */
551 if (emod->docsloadedp) {
552 EMOD_DEBUG_LOADER("already loaded doc strings\n");
556 EMOD_DEBUG_LOADER("loading docs from %s\n", emod->name);
557 if (LIKELY((emod->docsf =
558 (emodng_docs_f)lt_dlfun(emod->dl, "docs")) != NULL)) {
559 EMOD_DEBUG_LOADER("found docs() ... calling now\n");
560 (*emod->docsf)(emod);
562 EMOD_DEBUG_LOADER("no docs() function found ... "
563 "hope this is right\n");
565 emod->docsloadedp = true;
569 static inline emodng_t
570 _emodng_open_dep(emodng_t emod, const char *dep)
572 EMOD_DEBUG_LOADER("module \"%s\" depends upon \"%s\", "
573 "hence loading \"%s\"\n",
574 emod->name, dep, dep);
575 return emodng_load(dep, emod->dl);
580 emodng_unload(const char *name)
582 emodng_t e = __emodng_find(name);
586 } else if (!emod_endpoint_p(e)) {
587 error("Module %s is referenced by other modules\n",
592 _unregister_endpoint(e);
600 _emodng_close(emodng_t emod)
602 const lt_dlinfo *info;
604 /* get module info */
605 info = lt_dlgetinfo(emod->dl);
607 EMOD_DEBUG_LOADER("trying to unload %s (%d)\n",
608 emod->name, info->ref_count);
610 lt_dlclose(emod->dl);
612 /* close all the dep modules too */
613 for (size_t i = 0; i < emod->ndeps; i++) {
614 _emodng_close_dep(emod, emod->deps[i]);
617 if (info->ref_count == 0) {
618 EMOD_DEBUG_LOADER("kicking %s from the list of loaded mods\n",
620 __emodng_remove(emod);
627 _emodng_deinit(emodng_t emod)
629 /* calls deinitialiser code in the module */
630 EMOD_DEBUG_LOADER("deinitialising %s\n", emod->truename);
631 if (LIKELY((emod->deinitf =
632 (emodng_init_f)lt_dlfun(emod->dl, "deinit")) != NULL)) {
633 EMOD_DEBUG_LOADER("found deinit() ... calling now\n");
634 (*emod->deinitf)(emod);
636 EMOD_DEBUG_LOADER("no deinit() function found ... "
637 "hope this is right\n");
639 emod->initialisedp = false;
644 _emodng_close_dep(emodng_t emod, emodng_t dep)
646 if (UNLIKELY(dep == NULL)) {
650 EMOD_DEBUG_LOADER("module \"%s\" depended upon \"%s\", "
651 "hence unloading \"%s\"\n",
652 emod->name, dep->name, dep->truename);
658 /* unwind code in case something's wrong */
660 emodng_load_unwind(Lisp_Object unw)
662 lt_dlhandle mod_handle = get_dynacat(unw);
664 /* if the handle's still vivid, drown him */
666 lt_dlclose(mod_handle);
672 emodng_unload_unwind(Lisp_Object unw)
674 lt_dlhandle SXE_UNUSED(mod_handle) = get_dynacat(unw);
676 /* if the handle's still vivid, drown him */
681 DEFUN("load-module-file", Fload_module_file, 1, 3, "FLoad dynamic module: ", /*
682 Load in a C Emacs Extension module named FILE.
683 The optional NAME and VERSION are used to identify specific modules.
685 This function is similar in intent to `load-file' except that it loads
686 in pre-compiled C or C++ code, using dynamic shared objects. If NAME
687 is specified, then the module is only loaded if its internal name
688 matches the NAME specified. If VERSION is specified, then the module
689 is only loaded if it matches that VERSION. This function will check
690 to make sure that the same module is not loaded twice. Modules are
691 searched for in the same way as Lisp files, except for the file
692 extension. For a list of valid extensions, see: `module-extensions'
694 All symbols in the shared module must be completely resolved in order
695 for this function to be successful. Any modules which the specified
696 FILE depends on will be automatically loaded. You can determine which
697 modules have been loaded as dynamic shared objects by examining the
698 return value of the function `list-modules'.
700 It is possible, although unwise, to unload modules using `unload-module'.
701 The preferred mechanism for unloading or reloading modules is to quit
702 SXEmacs, and then reload those new or changed modules that are required.
704 Messages informing you of the progress of the load are displayed unless
705 the variable `load-modules-quietly' is non-NIL.
707 (file, unused1, unused2))
710 const char *mod_name;
711 int speccount = specpdl_depth();
712 struct dynacat_s unw = {.ptr = NULL};
713 Lisp_Object lunw = (Lisp_Object)(long)&unw;
717 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
718 file = Fexpand_file_name(file, Qnil);
719 mod_name = (const char*)XSTRING_DATA(file);
721 record_unwind_protect(emodng_load_unwind, lunw);
722 result = emodng_load(mod_name, meself);
723 unbind_to(speccount, Qnil);
726 _register_endpoint(result);
732 DEFUN("unload-module", Funload_module, 1, 1, 0, /*
733 BAD JU-JU! Attempt to unload the emodule named FOO.
735 This is a dangerous operation and you should think twice before doing
736 it. Unloading an emodule can often result in a non-responsive,
737 non-working, or just plain dead SXEmacs session. It is simply not
738 worth the risk. Save your buffers and restart SXEmacs, it really is
741 One last little gotcha... FOO is the _internal_ name of the emodule.
742 The internal name is listed in `list-modules'.
747 const char *mod_name;
748 int speccount = specpdl_depth();
749 struct dynacat_s unw = {.ptr = NULL};
750 Lisp_Object lunw = (Lisp_Object)(long)&unw;
754 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
755 mod_name = (const char*)XSTRING_DATA(foo);
757 record_unwind_protect(emodng_unload_unwind, lunw);
758 result = emodng_unload(mod_name);
759 unbind_to(speccount, Qnil);
761 return result ? Qt : Qnil;
764 DEFUN("list-loaded-modules", Flist_loaded_modules, 0, 0, 0, /*
765 Return a list of loaded modules.
769 Lisp_Object mlist = Qnil;
771 for (emodng_t e = emods; e; e = e->next) {
772 mlist = Fcons(build_string(e->truename), mlist);
778 emodng_doc_subr(const char *symname, const char *doc)
780 Bytecount len = xstrlen(symname);
781 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
784 if (SYMBOLP(sym) && SUBRP(XSYMBOL(sym)->function)) {
785 EMOD_DEBUG_LOADER("trying to install docs for #'%s\n", symname);
786 subr = XSUBR(XSYMBOL(sym)->function);
788 subr->doc = xstrdup(doc);
792 } else if (!SUBRP(sym)) {
793 EMOD_CRITICAL("Bollocks! #'%s is not a subr\n", symname);
794 } else if (!SYMBOLP(sym)) {
795 EMOD_CRITICAL("Bloody 'ell, #'%s is not even a symbol\n",
799 * FIXME: I wish there was some way to avoid the xstrdup(). Is it
800 * possible to just set a pointer to the string, or somehow create a
801 * symbol whose value we can point to the constant string? Can someone
808 emodng_doc_sym(const char *symname, const char *doc)
810 Bytecount len = xstrlen(symname);
811 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
815 EMOD_DEBUG_LOADER("trying to install docs for '%s\n", symname);
818 docstr = build_string(doc);
820 Fput(sym, Qvariable_documentation, docstr);
822 } else if (!SYMBOLP(sym)) {
823 EMOD_CRITICAL("wrong doc specification\n");
828 #if defined USE_LTDL_SEARCHPATH
830 _adapt_load_path(Lisp_Object sym, Lisp_Object *val,
831 Lisp_Object in_object, int flags)
836 /* traverse once to obtain the overall length */
837 for (len = 0, ls = *val; CONSP(ls); ls = XCDR(ls)) {
838 if (LIKELY((STRINGP(XCAR(ls))))) {
839 len += XSTRING_LENGTH(XCAR(ls)) + /*for colon*/1;
842 /* C99 we need ya! traverse to fill the searchpath */
843 if (LIKELY(len > 0)) {
844 char sp[len], *p = sp;
846 for (ls = *val; CONSP(ls); ls = XCDR(ls)) {
847 Lisp_Object lse = XCAR(ls);
848 if (LIKELY((STRINGP(lse)))) {
850 (const char*)XSTRING_DATA(lse),
856 lt_dlsetsearchpath(sp);
858 lt_dlsetsearchpath(NULL);
860 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
868 DEFSUBR(Fload_module_file);
869 DEFSUBR(Funload_module);
870 DEFSUBR(Flist_loaded_modules);
874 reinit_vars_of_emodng(void)
877 meself = lt_dlopen(NULL);
879 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
880 #ifdef LTDL_SYSSEARCHPATH
881 EMOD_DEBUG_LOADER("sys path %s\n", LTDL_SYSSEARCHPATH);
889 DEFVAR_BOOL("load-modules-quietly", &load_modules_quietly /*
890 *Set to t if module loading is to be silent.
892 Normally, when loading dynamic modules, Emacs will inform you of its
893 progress, and will display the module name and version if the module
894 is loaded correctly. Setting this variable to `t' will suppress these
895 messages. This would normally only be done if `load-module' was being
896 called by a Lisp function.
898 load_modules_quietly = 0;
900 #if defined USE_LTDL_SEARCHPATH
901 DEFVAR_LISP_MAGIC("module-load-path", &Vmodule_load_path /*
902 *List of directories to search for dynamic modules to load.
903 Each element is a string (directory name) or nil (try default directory).
905 Note that elements of this list *may not* begin with "~", so you must
906 call `expand-file-name' on them before adding them to this list.
908 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
909 to default specified the file `paths.h' when SXEmacs was built. If there
910 were no paths specified in `paths.h', then SXEmacs chooses a default
911 value for this variable by looking around in the file-system near the
912 directory in which the SXEmacs executable resides.
914 Due to the nature of dynamic modules, the path names should almost always
915 refer to architecture-dependent directories. It is unwise to attempt to
916 store dynamic modules in a heterogenous environment. Some environments
917 are similar enough to each other that SXEmacs will be unable to determine
918 the correctness of a dynamic module, which can have unpredictable results
919 when a dynamic module is loaded.
922 #else /* !USE_LTDL_SEARCHPATH */
923 DEFVAR_LISP("module-load-path", &Vmodule_load_path /*
924 *List of directories to search for dynamic modules to load.
925 Each element is a string (directory name) or nil (try default directory).
927 Note that elements of this list *may not* begin with "~", so you must
928 call `expand-file-name' on them before adding them to this list.
930 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
931 to default specified the file `paths.h' when SXEmacs was built. If there
932 were no paths specified in `paths.h', then SXEmacs chooses a default
933 value for this variable by looking around in the file-system near the
934 directory in which the SXEmacs executable resides.
936 Due to the nature of dynamic modules, the path names should almost always
937 refer to architecture-dependent directories. It is unwise to attempt to
938 store dynamic modules in a heterogenous environment. Some environments
939 are similar enough to each other that SXEmacs will be unable to determine
940 the correctness of a dynamic module, which can have unpredictable results
941 when a dynamic module is loaded.
944 Vmodule_load_path = Qnil;
946 DEFVAR_LISP("module-extensions", &Vmodule_extensions /*
947 *List of filename extensions to use when searching for dynamic modules.
950 list5(build_string(".la"),
952 build_string(".ell"),
953 build_string(".dll"),
954 build_string(".dylib"));
956 Fprovide(intern("modules"));
958 reinit_vars_of_emodng();
961 /* emodules-ng.c ends here */