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 xstrncpy(p, (const char*)XSTRING_DATA(XCAR(ext)),
161 name + sizeof(name) - p);
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)-2));
195 xstrncpy(p, filename, name + sizeof(name) - p);
197 if (__file_exists_p(name)) {
198 EMOD_DEBUG_LOADER("trying %s\n", name);
199 return lt_dlopen(name);
207 __emodng_open_prepend_paths_append_exts(const char *filename)
209 /* append all specified extensions */
210 size_t nfilename = strlen(filename);
212 /* we used to use Vmodule_load_path here */
213 for (Lisp_Object path = Vload_path;
214 CONSP(path); path = XCDR(path)) {
215 if (LIKELY((STRINGP(XCAR(path))))) {
216 char name[(size_t)XSTRING_LENGTH(XCAR(path))
217 + 1 /*for the slash*/
218 + nfilename /*for the module's actual name*/
219 + 24 /* for the length of the extension
220 * BETTER CHECK THAT */
221 + 1 /*for the terminating \0 char*/];
222 /* note that we assume here that filename already
223 * carries the correct extension
224 * see __emodng_open_prepend_paths_append_exts for
225 * cope with all the combinations */
228 (const char*)XSTRING_DATA(XCAR(path)),
229 (size_t)XSTRING_LENGTH(XCAR(path))-2);
234 p = xstpncpy(p, filename, name + sizeof(name) - p);
236 /* append all extensions now */
237 for (Lisp_Object ext = Vmodule_extensions;
238 CONSP(ext); ext = XCDR(ext)) {
239 if (UNLIKELY(!STRINGP(XCAR(ext)))) {
243 xstrncpy(p,(const char*)XSTRING_DATA(XCAR(ext)),
244 name + sizeof(name) - p);
246 if (__file_exists_p(name)) {
247 EMOD_DEBUG_LOADER("trying \"%s\"\n",
249 return lt_dlopen(name);
258 __emodng_open(emodng_t emod)
260 /* obtain some info to massage the name of the emod */
261 /* determine if emod->name is an absolute filename */
262 bool abso_path_p = emod->name[0] == '/';
263 /* determine if emod->name is a relative filename */
265 strncmp(emod->name, "./", 2) == 0 ||
266 strncmp(emod->name, "../", 3) == 0;
267 /* determine if emod->name carries an extension already
268 * we search backward to an occurrence of '.' and forward for a '/'
269 * to make sure it really belongs to the last path component */
270 char *ext_compo = strrchr(emod->name, '.');
271 bool has_ext_p = ext_compo != NULL && strchr(ext_compo, '/') == NULL;
273 if (LIKELY(!abso_path_p && !rel_path_p && !has_ext_p)) {
274 /* append both extension and paths */
275 emod->dl = __emodng_open_prepend_paths_append_exts(emod->name);
276 } else if (!abso_path_p && !rel_path_p) {
277 /* just append paths */
278 emod->dl = __emodng_open_prepend_paths(emod->name);
279 } else if (has_ext_p) {
280 /* fully featured file name, just dlopen() it */
281 emod->dl = lt_dlopen(emod->name);
282 } else if (!has_ext_p) {
283 /* file name with path but sans extension */
284 emod->dl = __emodng_open_append_exts(emod->name);
286 /* actually we should cater with those relative file names
287 * more thoroughly, I'm not sure what './' means in libltdl speak */
292 __emodng_find_or_create(emodng_t in)
294 /* try to find the emodule specified by in or create one
295 * if it cannot be found */
296 const lt_dlinfo *info;
299 /* get module info */
300 info = lt_dlgetinfo(in->dl);
302 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
303 info->filename, info->name, info->ref_count);
305 for (emodng_t e = emods; e; e = e->next) {
307 strcmp(info->name, e->truename) == 0) {
313 /* otherwise we have to create this */
314 new = xnew(struct emodng_s);
316 new->truename = xstrdup(info->name);
317 new->filename = xstrdup(info->filename);
318 new->name = xstrdup(in->name);
320 new->openedp = new->initialisedp = new->docsloadedp = false;
322 new->deps = in->deps;
323 new->ndeps = in->ndeps;
330 __emodng_find(const char *name)
332 /* try to find the emodule named `name', return its pointer or NULL */
335 for (e = emods; e; e = e->next) {
336 if (strcmp(name, e->truename) == 0) {
346 /* get module info */
347 #ifdef EMOD_DEBUG_FLAG
349 const lt_dlinfo *info = lt_dlgetinfo(e->dl);
351 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
352 info->filename, info->name, info->ref_count);
359 __emodng_remove(emodng_t emod)
361 /* dehorstify this ... */
362 if (UNLIKELY(emod == NULL)) {
366 /* if emod was the top of the list, just kick it */
367 if (emods && emod == emods) {
372 for (emodng_t e = emods; e; e = e->next) {
373 if (e->next && e->next->dl == emod->dl) {
374 e->next = emod->next;
382 emod_endpoint_p(emodng_t emod)
384 /* a VERY sloppy approach */
385 for (emod_epcell_t ee = emod_endpoints; ee; ee = ee->next) {
386 if (ee->emod == emod) {
394 _register_endpoint(emodng_t emod)
396 emod_epcell_t new = xnew(struct emod_epcell_s);
399 new->next = emod_endpoints;
400 emod_endpoints = new;
405 _unregister_endpoint(emodng_t emod)
407 /* very unlikely, but dehorstify anyway */
408 if (UNLIKELY(emod == NULL)) {
412 /* maybe we're lucky today and deal with the topmost entry ... */
413 if (emod_endpoints && emod_endpoints->emod == emod) {
414 emod_epcell_t free_me = emod_endpoints;
415 emod_endpoints = emod_endpoints->next;
420 /* ... gah, what a fooking mess, traverse the list */
421 for (emod_epcell_t e = emod_endpoints; e && e->next; e = e->next) {
422 if (e->next->emod == emod) {
423 emod_epcell_t free_me = e->next;
424 e->next = e->next->next;
433 free_emodng(emodng_t emod)
435 xfree(emod->truename);
436 xfree(emod->filename);
445 /* we divide the load phase into two actual phases, open and init
446 * similarly unload is actually deinit and close (yes, in that order, horst)
447 * it is just because we make sure about dependencies and things */
449 emodng_load(const char *name, lt_dlhandle caller)
451 /* this is the loader chain which opens->inits->imports docs */
452 struct emodng_s _emod = {.name = name};
456 _emodng_open(&_emod);
457 if (UNLIKELY(_emod.dl == NULL)) {
461 /* set up a real emodng_t object and put it into our global emod list */
462 emod = __emodng_find_or_create(&_emod);
463 emod->openedp = true;
472 _emodng_open(emodng_t emod)
474 const char **emoddeps;
476 EMOD_DEBUG_LOADER("loading %s\n", emod->name);
479 /* check that we're really using a valid handle */
480 if (UNLIKELY(emod->dl == NULL)) {
481 error("Opening dynamic module \"%s\": %s",
482 emod->name, lt_dlerror());
488 /* checking dependencies */
489 if (LIKELY((emoddeps =
490 (const char**)lt_dlsym(emod->dl, "dependencies")) ||
492 (const char**)lt_dlsym(emod->dl, "deps")))) {
496 /* count the deps manually */
497 for (const char **deps = emoddeps, *dep = *deps;
498 dep; dep = *++deps, ndeps++);
504 /* create a big array of deps */
505 EMOD_DEBUG_LOADER("found %lu deps\n",
506 (long unsigned int)ndeps);
507 ed = emod->deps = xnew_array(emodng_t, emod->ndeps = ndeps);
509 /* load the other modules (deps) first */
510 for (const char **deps = emoddeps, *dep = *deps;
511 dep; dep = *++deps) {
512 *ed++ = _emodng_open_dep(emod, dep);
515 EMOD_DEBUG_LOADER("no deps found ... "
516 "hope this is right\n");
522 _emodng_init(emodng_t emod)
524 /* calls initialiser code in the module */
525 if (emod->initialisedp) {
526 EMOD_DEBUG_LOADER("already initialised\n");
530 EMOD_DEBUG_LOADER("initialising %s\n", emod->truename);
531 if (LIKELY((emod->initf =
532 (emodng_init_f)lt_dlfun(emod->dl, "init")) != NULL)) {
533 EMOD_DEBUG_LOADER("found init() ... calling now\n");
534 (*emod->initf)(emod);
536 EMOD_DEBUG_LOADER("no init() function found ... "
537 "hope this is right\n");
539 emod->initialisedp = true;
544 _emodng_docs(emodng_t emod)
546 /* because we're lisp, we have to care for documentation strings of our loaded
547 stuff, thus call a function docs() if present */
548 if (emod->docsloadedp) {
549 EMOD_DEBUG_LOADER("already loaded doc strings\n");
553 EMOD_DEBUG_LOADER("loading docs from %s\n", emod->name);
554 if (LIKELY((emod->docsf =
555 (emodng_docs_f)lt_dlfun(emod->dl, "docs")) != NULL)) {
556 EMOD_DEBUG_LOADER("found docs() ... calling now\n");
557 (*emod->docsf)(emod);
559 EMOD_DEBUG_LOADER("no docs() function found ... "
560 "hope this is right\n");
562 emod->docsloadedp = true;
566 static inline emodng_t
567 _emodng_open_dep(emodng_t emod, const char *dep)
569 EMOD_DEBUG_LOADER("module \"%s\" depends upon \"%s\", "
570 "hence loading \"%s\"\n",
571 emod->name, dep, dep);
572 return emodng_load(dep, emod->dl);
577 emodng_unload(const char *name)
579 emodng_t e = __emodng_find(name);
583 } else if (!emod_endpoint_p(e)) {
584 error("Module %s is referenced by other modules\n",
589 _unregister_endpoint(e);
597 _emodng_close(emodng_t emod)
599 const lt_dlinfo *info;
601 /* get module info */
602 info = lt_dlgetinfo(emod->dl);
604 EMOD_DEBUG_LOADER("trying to unload %s (%d)\n",
605 emod->name, info->ref_count);
607 lt_dlclose(emod->dl);
609 /* close all the dep modules too */
610 for (size_t i = 0; i < emod->ndeps; i++) {
611 _emodng_close_dep(emod, emod->deps[i]);
614 if (info->ref_count == 0) {
615 EMOD_DEBUG_LOADER("kicking %s from the list of loaded mods\n",
617 __emodng_remove(emod);
624 _emodng_deinit(emodng_t emod)
626 /* calls deinitialiser code in the module */
627 EMOD_DEBUG_LOADER("deinitialising %s\n", emod->truename);
628 if (LIKELY((emod->deinitf =
629 (emodng_init_f)lt_dlfun(emod->dl, "deinit")) != NULL)) {
630 EMOD_DEBUG_LOADER("found deinit() ... calling now\n");
631 (*emod->deinitf)(emod);
633 EMOD_DEBUG_LOADER("no deinit() function found ... "
634 "hope this is right\n");
636 emod->initialisedp = false;
641 _emodng_close_dep(emodng_t emod, emodng_t dep)
643 if (UNLIKELY(dep == NULL)) {
647 EMOD_DEBUG_LOADER("module \"%s\" depended upon \"%s\", "
648 "hence unloading \"%s\"\n",
649 emod->name, dep->name, dep->truename);
655 /* unwind code in case something's wrong */
657 emodng_load_unwind(Lisp_Object unw)
659 lt_dlhandle mod_handle = get_dynacat(unw);
661 /* if the handle's still vivid, drown him */
663 lt_dlclose(mod_handle);
669 emodng_unload_unwind(Lisp_Object unw)
671 lt_dlhandle SXE_UNUSED(mod_handle) = get_dynacat(unw);
673 /* if the handle's still vivid, drown him */
678 DEFUN("load-module-file", Fload_module_file, 1, 3, "FLoad dynamic module: ", /*
679 Load in a C Emacs Extension module named FILE.
680 The optional NAME and VERSION are used to identify specific modules.
682 This function is similar in intent to `load-file' except that it loads
683 in pre-compiled C or C++ code, using dynamic shared objects. If NAME
684 is specified, then the module is only loaded if its internal name
685 matches the NAME specified. If VERSION is specified, then the module
686 is only loaded if it matches that VERSION. This function will check
687 to make sure that the same module is not loaded twice. Modules are
688 searched for in the same way as Lisp files, except for the file
689 extension. For a list of valid extensions, see: `module-extensions'
691 All symbols in the shared module must be completely resolved in order
692 for this function to be successful. Any modules which the specified
693 FILE depends on will be automatically loaded. You can determine which
694 modules have been loaded as dynamic shared objects by examining the
695 return value of the function `list-modules'.
697 It is possible, although unwise, to unload modules using `unload-module'.
698 The preferred mechanism for unloading or reloading modules is to quit
699 SXEmacs, and then reload those new or changed modules that are required.
701 Messages informing you of the progress of the load are displayed unless
702 the variable `load-modules-quietly' is non-NIL.
704 (file, unused1, unused2))
707 const char *mod_name;
708 int speccount = specpdl_depth();
709 struct dynacat_s unw = {.ptr = NULL};
710 Lisp_Object lunw = (Lisp_Object)(long)&unw;
714 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
715 file = Fexpand_file_name(file, Qnil);
716 mod_name = (const char*)XSTRING_DATA(file);
718 record_unwind_protect(emodng_load_unwind, lunw);
719 result = emodng_load(mod_name, meself);
720 unbind_to(speccount, Qnil);
723 _register_endpoint(result);
729 DEFUN("unload-module", Funload_module, 1, 1, 0, /*
730 BAD JU-JU! Attempt to unload the emodule named FOO.
732 This is a dangerous operation and you should think twice before doing
733 it. Unloading an emodule can often result in a non-responsive,
734 non-working, or just plain dead SXEmacs session. It is simply not
735 worth the risk. Save your buffers and restart SXEmacs, it really is
738 One last little gotcha... FOO is the _internal_ name of the emodule.
739 The internal name is listed in `list-modules'.
744 const char *mod_name;
745 int speccount = specpdl_depth();
746 struct dynacat_s unw = {.ptr = NULL};
747 Lisp_Object lunw = (Lisp_Object)(long)&unw;
751 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
752 mod_name = (const char*)XSTRING_DATA(foo);
754 record_unwind_protect(emodng_unload_unwind, lunw);
755 result = emodng_unload(mod_name);
756 unbind_to(speccount, Qnil);
758 return result ? Qt : Qnil;
761 DEFUN("list-loaded-modules", Flist_loaded_modules, 0, 0, 0, /*
762 Return a list of loaded modules.
766 Lisp_Object mlist = Qnil;
768 for (emodng_t e = emods; e; e = e->next) {
769 mlist = Fcons(build_string(e->truename), mlist);
775 emodng_doc_subr(const char *symname, const char *doc)
777 Bytecount len = xstrlen(symname);
778 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
781 if (SYMBOLP(sym) && SUBRP(XSYMBOL(sym)->function)) {
782 EMOD_DEBUG_LOADER("trying to install docs for #'%s\n", symname);
783 subr = XSUBR(XSYMBOL(sym)->function);
785 subr->doc = xstrdup(doc);
789 } else if (!SUBRP(sym)) {
790 EMOD_CRITICAL("Bollocks! #'%s is not a subr\n", symname);
791 } else if (!SYMBOLP(sym)) {
792 EMOD_CRITICAL("Bloody 'ell, #'%s is not even a symbol\n",
796 * FIXME: I wish there was some way to avoid the xstrdup(). Is it
797 * possible to just set a pointer to the string, or somehow create a
798 * symbol whose value we can point to the constant string? Can someone
805 emodng_doc_sym(const char *symname, const char *doc)
807 Bytecount len = xstrlen(symname);
808 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
812 EMOD_DEBUG_LOADER("trying to install docs for '%s\n", symname);
815 docstr = build_string(doc);
817 Fput(sym, Qvariable_documentation, docstr);
819 } else if (!SYMBOLP(sym)) {
820 EMOD_CRITICAL("wrong doc specification\n");
825 #if defined USE_LTDL_SEARCHPATH
827 _adapt_load_path(Lisp_Object sym, Lisp_Object *val,
828 Lisp_Object in_object, int flags)
833 /* traverse once to obtain the overall length */
834 for (len = 0, ls = *val; CONSP(ls); ls = XCDR(ls)) {
835 if (LIKELY((STRINGP(XCAR(ls))))) {
836 len += XSTRING_LENGTH(XCAR(ls)) + /*for colon*/1;
839 /* C99 we need ya! traverse to fill the searchpath */
840 if (LIKELY(len > 0)) {
841 char sp[len], *p = sp;
843 for (ls = *val; CONSP(ls); ls = XCDR(ls)) {
844 Lisp_Object lse = XCAR(ls);
845 if (LIKELY((STRINGP(lse)))) {
847 (const char*)XSTRING_DATA(lse),
848 XSTRING_LENGTH(lse));
853 lt_dlsetsearchpath(sp);
855 lt_dlsetsearchpath(NULL);
857 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
865 DEFSUBR(Fload_module_file);
866 DEFSUBR(Funload_module);
867 DEFSUBR(Flist_loaded_modules);
871 reinit_vars_of_emodng(void)
874 meself = lt_dlopen(NULL);
876 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
877 #ifdef LTDL_SYSSEARCHPATH
878 EMOD_DEBUG_LOADER("sys path %s\n", LTDL_SYSSEARCHPATH);
886 DEFVAR_BOOL("load-modules-quietly", &load_modules_quietly /*
887 *Set to t if module loading is to be silent.
889 Normally, when loading dynamic modules, Emacs will inform you of its
890 progress, and will display the module name and version if the module
891 is loaded correctly. Setting this variable to `t' will suppress these
892 messages. This would normally only be done if `load-module' was being
893 called by a Lisp function.
895 load_modules_quietly = 0;
897 #if defined USE_LTDL_SEARCHPATH
898 DEFVAR_LISP_MAGIC("module-load-path", &Vmodule_load_path /*
899 *List of directories to search for dynamic modules to load.
900 Each element is a string (directory name) or nil (try default directory).
902 Note that elements of this list *may not* begin with "~", so you must
903 call `expand-file-name' on them before adding them to this list.
905 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
906 to default specified the file `paths.h' when SXEmacs was built. If there
907 were no paths specified in `paths.h', then SXEmacs chooses a default
908 value for this variable by looking around in the file-system near the
909 directory in which the SXEmacs executable resides.
911 Due to the nature of dynamic modules, the path names should almost always
912 refer to architecture-dependent directories. It is unwise to attempt to
913 store dynamic modules in a heterogenous environment. Some environments
914 are similar enough to each other that SXEmacs will be unable to determine
915 the correctness of a dynamic module, which can have unpredictable results
916 when a dynamic module is loaded.
919 #else /* !USE_LTDL_SEARCHPATH */
920 DEFVAR_LISP("module-load-path", &Vmodule_load_path /*
921 *List of directories to search for dynamic modules to load.
922 Each element is a string (directory name) or nil (try default directory).
924 Note that elements of this list *may not* begin with "~", so you must
925 call `expand-file-name' on them before adding them to this list.
927 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
928 to default specified the file `paths.h' when SXEmacs was built. If there
929 were no paths specified in `paths.h', then SXEmacs chooses a default
930 value for this variable by looking around in the file-system near the
931 directory in which the SXEmacs executable resides.
933 Due to the nature of dynamic modules, the path names should almost always
934 refer to architecture-dependent directories. It is unwise to attempt to
935 store dynamic modules in a heterogenous environment. Some environments
936 are similar enough to each other that SXEmacs will be unable to determine
937 the correctness of a dynamic module, which can have unpredictable results
938 when a dynamic module is loaded.
941 Vmodule_load_path = Qnil;
943 DEFVAR_LISP("module-extensions", &Vmodule_extensions /*
944 *List of filename extensions to use when searching for dynamic modules.
947 list5(build_string(".la"),
949 build_string(".ell"),
950 build_string(".dll"),
951 build_string(".dylib"));
953 Fprovide(intern("modules"));
955 reinit_vars_of_emodng();
958 /* emodules-ng.c ends here */