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);
154 for (Lisp_Object ext = Vmodule_extensions;
155 CONSP(ext); ext = XCDR(ext)) {
156 if (UNLIKELY(!STRINGP(XCAR(ext)))) {
160 strncpy(p, (const char*)XSTRING_DATA(XCAR(ext)),
161 (size_t)XSTRING_LENGTH(XCAR(ext))+1);
163 if (__file_exists_p(name)) {
164 EMOD_DEBUG_LOADER("trying %s\n", name);
165 return lt_dlopen(name);
172 __emodng_open_prepend_paths(const char *filename)
174 /* append all specified extensions */
175 size_t nfilename = strlen(filename);
177 /* we used to use Vmodule_load_path here */
178 for (Lisp_Object path = Vload_path;
179 CONSP(path); path = XCDR(path)) {
180 if (LIKELY((STRINGP(XCAR(path))))) {
181 char name[(size_t)XSTRING_LENGTH(XCAR(path))
182 + 1 /*for the slash*/
183 + nfilename /*for the module's actual name*/
184 + 1 /*for the terminating \0 char*/];
185 /* note that we assume here that filename already
186 * carries the correct extension
187 * see __emodng_open_prepend_paths_append_exts for
188 * cope with all the combinations */
191 (const char*)XSTRING_DATA(XCAR(path)),
192 (size_t)XSTRING_LENGTH(XCAR(path)));
194 strncpy(p, filename, nfilename+1);
196 if (__file_exists_p(name)) {
197 EMOD_DEBUG_LOADER("trying %s\n", name);
198 return lt_dlopen(name);
206 __emodng_open_prepend_paths_append_exts(const char *filename)
208 /* append all specified extensions */
209 size_t nfilename = strlen(filename);
211 /* we used to use Vmodule_load_path here */
212 for (Lisp_Object path = Vload_path;
213 CONSP(path); path = XCDR(path)) {
214 if (LIKELY((STRINGP(XCAR(path))))) {
215 char name[(size_t)XSTRING_LENGTH(XCAR(path))
216 + 1 /*for the slash*/
217 + nfilename /*for the module's actual name*/
218 + 24 /* for the length of the extension
219 * BETTER CHECK THAT */
220 + 1 /*for the terminating \0 char*/];
221 /* note that we assume here that filename already
222 * carries the correct extension
223 * see __emodng_open_prepend_paths_append_exts for
224 * cope with all the combinations */
227 (const char*)XSTRING_DATA(XCAR(path)),
228 (size_t)XSTRING_LENGTH(XCAR(path)));
232 p = xstpncpy(p, filename, nfilename);
234 /* append all extensions now */
235 for (Lisp_Object ext = Vmodule_extensions;
236 CONSP(ext); ext = XCDR(ext)) {
237 if (UNLIKELY(!STRINGP(XCAR(ext)))) {
242 (const char*)XSTRING_DATA(XCAR(ext)),
243 (size_t)XSTRING_LENGTH(XCAR(ext))+1);
245 if (__file_exists_p(name)) {
246 EMOD_DEBUG_LOADER("trying \"%s\"\n",
248 return lt_dlopen(name);
257 __emodng_open(emodng_t emod)
259 /* obtain some info to massage the name of the emod */
260 /* determine if emod->name is an absolute filename */
261 bool abso_path_p = emod->name[0] == '/';
262 /* determine if emod->name is a relative filename */
264 strncmp(emod->name, "./", 2) == 0 ||
265 strncmp(emod->name, "../", 3) == 0;
266 /* determine if emod->name carries an extension already
267 * we search backward to an occurrence of '.' and forward for a '/'
268 * to make sure it really belongs to the last path component */
269 char *ext_compo = strrchr(emod->name, '.');
270 bool has_ext_p = ext_compo != NULL && strchr(ext_compo, '/') == NULL;
272 if (LIKELY(!abso_path_p && !rel_path_p && !has_ext_p)) {
273 /* append both extension and paths */
274 emod->dl = __emodng_open_prepend_paths_append_exts(emod->name);
275 } else if (!abso_path_p && !rel_path_p) {
276 /* just append paths */
277 emod->dl = __emodng_open_prepend_paths(emod->name);
278 } else if (has_ext_p) {
279 /* fully featured file name, just dlopen() it */
280 emod->dl = lt_dlopen(emod->name);
281 } else if (!has_ext_p) {
282 /* file name with path but sans extension */
283 emod->dl = __emodng_open_append_exts(emod->name);
285 /* actually we should cater with those relative file names
286 * more thoroughly, I'm not sure what './' means in libltdl speak */
291 __emodng_find_or_create(emodng_t in)
293 /* try to find the emodule specified by in or create one
294 * if it cannot be found */
295 const lt_dlinfo *info;
298 /* get module info */
299 info = lt_dlgetinfo(in->dl);
301 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
302 info->filename, info->name, info->ref_count);
304 for (emodng_t e = emods; e; e = e->next) {
306 strcmp(info->name, e->truename) == 0) {
312 /* otherwise we have to create this */
313 new = xnew(struct emodng_s);
315 new->truename = xstrdup(info->name);
316 new->filename = xstrdup(info->filename);
317 new->name = xstrdup(in->name);
319 new->openedp = new->initialisedp = new->docsloadedp = false;
321 new->deps = in->deps;
322 new->ndeps = in->ndeps;
329 __emodng_find(const char *name)
331 /* try to find the emodule named `name', return its pointer or NULL */
334 for (e = emods; e; e = e->next) {
335 if (strcmp(name, e->truename) == 0) {
345 /* get module info */
346 #ifdef EMOD_DEBUG_FLAG
348 const lt_dlinfo *info = lt_dlgetinfo(e->dl);
350 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
351 info->filename, info->name, info->ref_count);
358 __emodng_remove(emodng_t emod)
360 /* dehorstify this ... */
361 if (UNLIKELY(emod == NULL)) {
365 /* if emod was the top of the list, just kick it */
366 if (emods && emod == emods) {
371 for (emodng_t e = emods; e; e = e->next) {
372 if (e->next && e->next->dl == emod->dl) {
373 e->next = emod->next;
381 emod_endpoint_p(emodng_t emod)
383 /* a VERY sloppy approach */
384 for (emod_epcell_t ee = emod_endpoints; ee; ee = ee->next) {
385 if (ee->emod == emod) {
393 _register_endpoint(emodng_t emod)
395 emod_epcell_t new = xnew(struct emod_epcell_s);
398 new->next = emod_endpoints;
399 emod_endpoints = new;
404 _unregister_endpoint(emodng_t emod)
406 /* very unlikely, but dehorstify anyway */
407 if (UNLIKELY(emod == NULL)) {
411 /* maybe we're lucky today and deal with the topmost entry ... */
412 if (emod_endpoints && emod_endpoints->emod == emod) {
413 emod_epcell_t free_me = emod_endpoints;
414 emod_endpoints = emod_endpoints->next;
419 /* ... gah, what a fooking mess, traverse the list */
420 for (emod_epcell_t e = emod_endpoints; e && e->next; e = e->next) {
421 if (e->next->emod == emod) {
422 emod_epcell_t free_me = e->next;
423 e->next = e->next->next;
432 free_emodng(emodng_t emod)
434 xfree(emod->truename);
435 xfree(emod->filename);
444 /* we divide the load phase into two actual phases, open and init
445 * similarly unload is actually deinit and close (yes, in that order, horst)
446 * it is just because we make sure about dependencies and things */
448 emodng_load(const char *name, lt_dlhandle caller)
450 /* this is the loader chain which opens->inits->imports docs */
451 struct emodng_s _emod = {.name = name};
455 _emodng_open(&_emod);
456 if (UNLIKELY(_emod.dl == NULL)) {
460 /* set up a real emodng_t object and put it into our global emod list */
461 emod = __emodng_find_or_create(&_emod);
462 emod->openedp = true;
471 _emodng_open(emodng_t emod)
473 const char **emoddeps;
475 EMOD_DEBUG_LOADER("loading %s\n", emod->name);
478 /* check that we're really using a valid handle */
479 if (UNLIKELY(emod->dl == NULL)) {
480 error("Opening dynamic module \"%s\": %s",
481 emod->name, lt_dlerror());
487 /* checking dependencies */
488 if (LIKELY((emoddeps =
489 (const char**)lt_dlsym(emod->dl, "dependencies")) ||
491 (const char**)lt_dlsym(emod->dl, "deps")))) {
495 /* count the deps manually */
496 for (const char **deps = emoddeps, *dep = *deps;
497 dep; dep = *++deps, ndeps++);
503 /* create a big array of deps */
504 EMOD_DEBUG_LOADER("found %lu deps\n",
505 (long unsigned int)ndeps);
506 ed = emod->deps = xnew_array(emodng_t, emod->ndeps = ndeps);
508 /* load the other modules (deps) first */
509 for (const char **deps = emoddeps, *dep = *deps;
510 dep; dep = *++deps) {
511 *ed++ = _emodng_open_dep(emod, dep);
514 EMOD_DEBUG_LOADER("no deps found ... "
515 "hope this is right\n");
521 _emodng_init(emodng_t emod)
523 /* calls initialiser code in the module */
524 if (emod->initialisedp) {
525 EMOD_DEBUG_LOADER("already initialised\n");
529 EMOD_DEBUG_LOADER("initialising %s\n", emod->truename);
530 if (LIKELY((emod->initf =
531 (emodng_init_f)lt_dlfun(emod->dl, "init")) != NULL)) {
532 EMOD_DEBUG_LOADER("found init() ... calling now\n");
533 (*emod->initf)(emod);
535 EMOD_DEBUG_LOADER("no init() function found ... "
536 "hope this is right\n");
538 emod->initialisedp = true;
543 _emodng_docs(emodng_t emod)
545 /* because we're lisp, we have to care for documentation strings of our loaded
546 stuff, thus call a function docs() if present */
547 if (emod->docsloadedp) {
548 EMOD_DEBUG_LOADER("already loaded doc strings\n");
552 EMOD_DEBUG_LOADER("loading docs from %s\n", emod->name);
553 if (LIKELY((emod->docsf =
554 (emodng_docs_f)lt_dlfun(emod->dl, "docs")) != NULL)) {
555 EMOD_DEBUG_LOADER("found docs() ... calling now\n");
556 (*emod->docsf)(emod);
558 EMOD_DEBUG_LOADER("no docs() function found ... "
559 "hope this is right\n");
561 emod->docsloadedp = true;
565 static inline emodng_t
566 _emodng_open_dep(emodng_t emod, const char *dep)
568 EMOD_DEBUG_LOADER("module \"%s\" depends upon \"%s\", "
569 "hence loading \"%s\"\n",
570 emod->name, dep, dep);
571 return emodng_load(dep, emod->dl);
576 emodng_unload(const char *name)
578 emodng_t e = __emodng_find(name);
582 } else if (!emod_endpoint_p(e)) {
583 error("Module %s is referenced by other modules\n",
588 _unregister_endpoint(e);
596 _emodng_close(emodng_t emod)
598 const lt_dlinfo *info;
600 /* get module info */
601 info = lt_dlgetinfo(emod->dl);
603 EMOD_DEBUG_LOADER("trying to unload %s (%d)\n",
604 emod->name, info->ref_count);
606 lt_dlclose(emod->dl);
608 /* close all the dep modules too */
609 for (size_t i = 0; i < emod->ndeps; i++) {
610 _emodng_close_dep(emod, emod->deps[i]);
613 if (info->ref_count == 0) {
614 EMOD_DEBUG_LOADER("kicking %s from the list of loaded mods\n",
616 __emodng_remove(emod);
623 _emodng_deinit(emodng_t emod)
625 /* calls deinitialiser code in the module */
626 EMOD_DEBUG_LOADER("deinitialising %s\n", emod->truename);
627 if (LIKELY((emod->deinitf =
628 (emodng_init_f)lt_dlfun(emod->dl, "deinit")) != NULL)) {
629 EMOD_DEBUG_LOADER("found deinit() ... calling now\n");
630 (*emod->deinitf)(emod);
632 EMOD_DEBUG_LOADER("no deinit() function found ... "
633 "hope this is right\n");
635 emod->initialisedp = false;
640 _emodng_close_dep(emodng_t emod, emodng_t dep)
642 if (UNLIKELY(dep == NULL)) {
646 EMOD_DEBUG_LOADER("module \"%s\" depended upon \"%s\", "
647 "hence unloading \"%s\"\n",
648 emod->name, dep->name, dep->truename);
654 /* unwind code in case something's wrong */
656 emodng_load_unwind(Lisp_Object unw)
658 lt_dlhandle mod_handle = get_dynacat(unw);
660 /* if the handle's still vivid, drown him */
662 lt_dlclose(mod_handle);
668 emodng_unload_unwind(Lisp_Object unw)
670 lt_dlhandle SXE_UNUSED(mod_handle) = get_dynacat(unw);
672 /* if the handle's still vivid, drown him */
677 DEFUN("load-module-file", Fload_module_file, 1, 3, "FLoad dynamic module: ", /*
678 Load in a C Emacs Extension module named FILE.
679 The optional NAME and VERSION are used to identify specific modules.
681 This function is similar in intent to `load-file' except that it loads
682 in pre-compiled C or C++ code, using dynamic shared objects. If NAME
683 is specified, then the module is only loaded if its internal name
684 matches the NAME specified. If VERSION is specified, then the module
685 is only loaded if it matches that VERSION. This function will check
686 to make sure that the same module is not loaded twice. Modules are
687 searched for in the same way as Lisp files, except for the file
688 extension. For a list of valid extensions, see: `module-extensions'
690 All symbols in the shared module must be completely resolved in order
691 for this function to be successful. Any modules which the specified
692 FILE depends on will be automatically loaded. You can determine which
693 modules have been loaded as dynamic shared objects by examining the
694 return value of the function `list-modules'.
696 It is possible, although unwise, to unload modules using `unload-module'.
697 The preferred mechanism for unloading or reloading modules is to quit
698 SXEmacs, and then reload those new or changed modules that are required.
700 Messages informing you of the progress of the load are displayed unless
701 the variable `load-modules-quietly' is non-NIL.
703 (file, unused1, unused2))
706 const char *mod_name;
707 int speccount = specpdl_depth();
708 struct dynacat_s unw = {.ptr = NULL};
709 Lisp_Object lunw = (Lisp_Object)(long)&unw;
713 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
714 file = Fexpand_file_name(file, Qnil);
715 mod_name = (const char*)XSTRING_DATA(file);
717 record_unwind_protect(emodng_load_unwind, lunw);
718 result = emodng_load(mod_name, meself);
719 unbind_to(speccount, Qnil);
722 _register_endpoint(result);
728 DEFUN("unload-module", Funload_module, 1, 1, 0, /*
729 BAD JU-JU! Attempt to unload the emodule named FOO.
731 This is a dangerous operation and you should think twice before doing
732 it. Unloading an emodule can often result in a non-responsive,
733 non-working, or just plain dead SXEmacs session. It is simply not
734 worth the risk. Save your buffers and restart SXEmacs, it really is
737 One last little gotcha... FOO is the _internal_ name of the emodule.
738 The internal name is listed in `list-modules'.
743 const char *mod_name;
744 int speccount = specpdl_depth();
745 struct dynacat_s unw = {.ptr = NULL};
746 Lisp_Object lunw = (Lisp_Object)(long)&unw;
750 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
751 mod_name = (const char*)XSTRING_DATA(foo);
753 record_unwind_protect(emodng_unload_unwind, lunw);
754 result = emodng_unload(mod_name);
755 unbind_to(speccount, Qnil);
757 return result ? Qt : Qnil;
760 DEFUN("list-loaded-modules", Flist_loaded_modules, 0, 0, 0, /*
761 Return a list of loaded modules.
765 Lisp_Object mlist = Qnil;
767 for (emodng_t e = emods; e; e = e->next) {
768 mlist = Fcons(build_string(e->truename), mlist);
774 emodng_doc_subr(const char *symname, const char *doc)
776 Bytecount len = xstrlen(symname);
777 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
780 if (SYMBOLP(sym) && SUBRP(XSYMBOL(sym)->function)) {
781 EMOD_DEBUG_LOADER("trying to install docs for #'%s\n", symname);
782 subr = XSUBR(XSYMBOL(sym)->function);
784 subr->doc = xstrdup(doc);
788 } else if (!SUBRP(sym)) {
789 EMOD_CRITICAL("Bollocks! #'%s is not a subr\n", symname);
790 } else if (!SYMBOLP(sym)) {
791 EMOD_CRITICAL("Bloody 'ell, #'%s is not even a symbol\n",
795 * FIXME: I wish there was some way to avoid the xstrdup(). Is it
796 * possible to just set a pointer to the string, or somehow create a
797 * symbol whose value we can point to the constant string? Can someone
804 emodng_doc_sym(const char *symname, const char *doc)
806 Bytecount len = xstrlen(symname);
807 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
811 EMOD_DEBUG_LOADER("trying to install docs for '%s\n", symname);
814 docstr = build_string(doc);
816 Fput(sym, Qvariable_documentation, docstr);
818 } else if (!SYMBOLP(sym)) {
819 EMOD_CRITICAL("wrong doc specification\n");
824 #if defined USE_LTDL_SEARCHPATH
826 _adapt_load_path(Lisp_Object sym, Lisp_Object *val,
827 Lisp_Object in_object, int flags)
832 /* traverse once to obtain the overall length */
833 for (len = 0, ls = *val; CONSP(ls); ls = XCDR(ls)) {
834 if (LIKELY((STRINGP(XCAR(ls))))) {
835 len += XSTRING_LENGTH(XCAR(ls)) + /*for colon*/1;
838 /* C99 we need ya! traverse to fill the searchpath */
839 if (LIKELY(len > 0)) {
840 char sp[len], *p = sp;
842 for (ls = *val; CONSP(ls); ls = XCDR(ls)) {
843 Lisp_Object lse = XCAR(ls);
844 if (LIKELY((STRINGP(lse)))) {
846 (const char*)XSTRING_DATA(lse),
847 XSTRING_LENGTH(lse));
852 lt_dlsetsearchpath(sp);
854 lt_dlsetsearchpath(NULL);
856 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
864 DEFSUBR(Fload_module_file);
865 DEFSUBR(Funload_module);
866 DEFSUBR(Flist_loaded_modules);
870 reinit_vars_of_emodng(void)
873 meself = lt_dlopen(NULL);
875 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
876 #ifdef LTDL_SYSSEARCHPATH
877 EMOD_DEBUG_LOADER("sys path %s\n", LTDL_SYSSEARCHPATH);
885 DEFVAR_BOOL("load-modules-quietly", &load_modules_quietly /*
886 *Set to t if module loading is to be silent.
888 Normally, when loading dynamic modules, Emacs will inform you of its
889 progress, and will display the module name and version if the module
890 is loaded correctly. Setting this variable to `t' will suppress these
891 messages. This would normally only be done if `load-module' was being
892 called by a Lisp function.
894 load_modules_quietly = 0;
896 #if defined USE_LTDL_SEARCHPATH
897 DEFVAR_LISP_MAGIC("module-load-path", &Vmodule_load_path /*
898 *List of directories to search for dynamic modules to load.
899 Each element is a string (directory name) or nil (try default directory).
901 Note that elements of this list *may not* begin with "~", so you must
902 call `expand-file-name' on them before adding them to this list.
904 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
905 to default specified the file `paths.h' when SXEmacs was built. If there
906 were no paths specified in `paths.h', then SXEmacs chooses a default
907 value for this variable by looking around in the file-system near the
908 directory in which the SXEmacs executable resides.
910 Due to the nature of dynamic modules, the path names should almost always
911 refer to architecture-dependent directories. It is unwise to attempt to
912 store dynamic modules in a heterogenous environment. Some environments
913 are similar enough to each other that SXEmacs will be unable to determine
914 the correctness of a dynamic module, which can have unpredictable results
915 when a dynamic module is loaded.
918 #else /* !USE_LTDL_SEARCHPATH */
919 DEFVAR_LISP("module-load-path", &Vmodule_load_path /*
920 *List of directories to search for dynamic modules to load.
921 Each element is a string (directory name) or nil (try default directory).
923 Note that elements of this list *may not* begin with "~", so you must
924 call `expand-file-name' on them before adding them to this list.
926 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
927 to default specified the file `paths.h' when SXEmacs was built. If there
928 were no paths specified in `paths.h', then SXEmacs chooses a default
929 value for this variable by looking around in the file-system near the
930 directory in which the SXEmacs executable resides.
932 Due to the nature of dynamic modules, the path names should almost always
933 refer to architecture-dependent directories. It is unwise to attempt to
934 store dynamic modules in a heterogenous environment. Some environments
935 are similar enough to each other that SXEmacs will be unable to determine
936 the correctness of a dynamic module, which can have unpredictable results
937 when a dynamic module is loaded.
940 Vmodule_load_path = Qnil;
942 DEFVAR_LISP("module-extensions", &Vmodule_extensions /*
943 *List of filename extensions to use when searching for dynamic modules.
946 list5(build_string(".la"),
948 build_string(".ell"),
949 build_string(".dll"),
950 build_string(".dylib"));
952 Fprovide(intern("modules"));
954 reinit_vars_of_emodng();
957 /* emodules-ng.c ends here */