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 */
332 const lt_dlinfo *info;
335 for (e = emods; e; e = e->next) {
336 if (strcmp(name, e->truename) == 0) {
346 /* get module info */
347 info = lt_dlgetinfo(e->dl);
349 EMOD_DEBUG_LOADER("modinfo %s %s %d\n",
350 info->filename, info->name, info->ref_count);
356 __emodng_remove(emodng_t emod)
358 /* dehorstify this ... */
359 if (UNLIKELY(emod == NULL)) {
363 /* if emod was the top of the list, just kick it */
364 if (emods && emod == emods) {
369 for (emodng_t e = emods; e; e = e->next) {
370 if (e->next && e->next->dl == emod->dl) {
371 e->next = emod->next;
379 emod_endpoint_p(emodng_t emod)
381 /* a VERY sloppy approach */
382 for (emod_epcell_t ee = emod_endpoints; ee; ee = ee->next) {
383 if (ee->emod == emod) {
391 _register_endpoint(emodng_t emod)
393 emod_epcell_t new = xnew(struct emod_epcell_s);
396 new->next = emod_endpoints;
397 emod_endpoints = new;
402 _unregister_endpoint(emodng_t emod)
404 /* very unlikely, but dehorstify anyway */
405 if (UNLIKELY(emod == NULL)) {
409 /* maybe we're lucky today and deal with the topmost entry ... */
410 if (emod_endpoints && emod_endpoints->emod == emod) {
411 emod_epcell_t free_me = emod_endpoints;
412 emod_endpoints = emod_endpoints->next;
417 /* ... gah, what a fooking mess, traverse the list */
418 for (emod_epcell_t e = emod_endpoints; e && e->next; e = e->next) {
419 if (e->next->emod == emod) {
420 emod_epcell_t free_me = e->next;
421 e->next = e->next->next;
430 free_emodng(emodng_t emod)
432 xfree(emod->truename);
433 xfree(emod->filename);
442 /* we divide the load phase into two actual phases, open and init
443 * similarly unload is actually deinit and close (yes, in that order, horst)
444 * it is just because we make sure about dependencies and things */
446 emodng_load(const char *name, lt_dlhandle caller)
448 /* this is the loader chain which opens->inits->imports docs */
449 struct emodng_s _emod = {.name = name};
453 _emodng_open(&_emod);
454 if (UNLIKELY(_emod.dl == NULL)) {
458 /* set up a real emodng_t object and put it into our global emod list */
459 emod = __emodng_find_or_create(&_emod);
460 emod->openedp = true;
469 _emodng_open(emodng_t emod)
471 const char **emoddeps;
473 EMOD_DEBUG_LOADER("loading %s\n", emod->name);
476 /* check that we're really using a valid handle */
477 if (UNLIKELY(emod->dl == NULL)) {
478 error("Opening dynamic module \"%s\": %s",
479 emod->name, lt_dlerror());
485 /* checking dependencies */
486 if (LIKELY((emoddeps =
487 (const char**)lt_dlsym(emod->dl, "dependencies")) ||
489 (const char**)lt_dlsym(emod->dl, "deps")))) {
493 /* count the deps manually */
494 for (const char **deps = emoddeps, *dep = *deps;
495 dep; dep = *++deps, ndeps++);
501 /* create a big array of deps */
502 EMOD_DEBUG_LOADER("found %lu deps\n",
503 (long unsigned int)ndeps);
504 ed = emod->deps = xnew_array(emodng_t, emod->ndeps = ndeps);
506 /* load the other modules (deps) first */
507 for (const char **deps = emoddeps, *dep = *deps;
508 dep; dep = *++deps) {
509 *ed++ = _emodng_open_dep(emod, dep);
512 EMOD_DEBUG_LOADER("no deps found ... "
513 "hope this is right\n");
519 _emodng_init(emodng_t emod)
521 /* calls initialiser code in the module */
522 if (emod->initialisedp) {
523 EMOD_DEBUG_LOADER("already initialised\n");
527 EMOD_DEBUG_LOADER("initialising %s\n", emod->truename);
528 if (LIKELY((emod->initf =
529 (emodng_init_f)lt_dlfun(emod->dl, "init")) != NULL)) {
530 EMOD_DEBUG_LOADER("found init() ... calling now\n");
531 (*emod->initf)(emod);
533 EMOD_DEBUG_LOADER("no init() function found ... "
534 "hope this is right\n");
536 emod->initialisedp = true;
541 _emodng_docs(emodng_t emod)
543 /* because we're lisp, we have to care for documentation strings of our loaded
544 stuff, thus call a function docs() if present */
545 if (emod->docsloadedp) {
546 EMOD_DEBUG_LOADER("already loaded doc strings\n");
550 EMOD_DEBUG_LOADER("loading docs from %s\n", emod->name);
551 if (LIKELY((emod->docsf =
552 (emodng_docs_f)lt_dlfun(emod->dl, "docs")) != NULL)) {
553 EMOD_DEBUG_LOADER("found docs() ... calling now\n");
554 (*emod->docsf)(emod);
556 EMOD_DEBUG_LOADER("no docs() function found ... "
557 "hope this is right\n");
559 emod->docsloadedp = true;
563 static inline emodng_t
564 _emodng_open_dep(emodng_t emod, const char *dep)
566 EMOD_DEBUG_LOADER("module \"%s\" depends upon \"%s\", "
567 "hence loading \"%s\"\n",
568 emod->name, dep, dep);
569 return emodng_load(dep, emod->dl);
574 emodng_unload(const char *name)
576 emodng_t e = __emodng_find(name);
580 } else if (!emod_endpoint_p(e)) {
581 error("Module %s is referenced by other modules\n",
586 _unregister_endpoint(e);
594 _emodng_close(emodng_t emod)
596 const lt_dlinfo *info;
598 /* get module info */
599 info = lt_dlgetinfo(emod->dl);
601 EMOD_DEBUG_LOADER("trying to unload %s (%d)\n",
602 emod->name, info->ref_count);
604 lt_dlclose(emod->dl);
606 /* close all the dep modules too */
607 for (size_t i = 0; i < emod->ndeps; i++) {
608 _emodng_close_dep(emod, emod->deps[i]);
611 if (info->ref_count == 0) {
612 EMOD_DEBUG_LOADER("kicking %s from the list of loaded mods\n",
614 __emodng_remove(emod);
621 _emodng_deinit(emodng_t emod)
623 /* calls deinitialiser code in the module */
624 EMOD_DEBUG_LOADER("deinitialising %s\n", emod->truename);
625 if (LIKELY((emod->deinitf =
626 (emodng_init_f)lt_dlfun(emod->dl, "deinit")) != NULL)) {
627 EMOD_DEBUG_LOADER("found deinit() ... calling now\n");
628 (*emod->deinitf)(emod);
630 EMOD_DEBUG_LOADER("no deinit() function found ... "
631 "hope this is right\n");
633 emod->initialisedp = false;
638 _emodng_close_dep(emodng_t emod, emodng_t dep)
640 if (UNLIKELY(dep == NULL)) {
644 EMOD_DEBUG_LOADER("module \"%s\" depended upon \"%s\", "
645 "hence unloading \"%s\"\n",
646 emod->name, dep->name, dep->truename);
652 /* unwind code in case something's wrong */
654 emodng_load_unwind(Lisp_Object unw)
656 lt_dlhandle mod_handle = get_dynacat(unw);
658 /* if the handle's still vivid, drown him */
660 lt_dlclose(mod_handle);
666 emodng_unload_unwind(Lisp_Object unw)
668 lt_dlhandle UNUSED(mod_handle) = get_dynacat(unw);
670 /* if the handle's still vivid, drown him */
675 DEFUN("load-module-file", Fload_module_file, 1, 3, "FLoad dynamic module: ", /*
676 Load in a C Emacs Extension module named FILE.
677 The optional NAME and VERSION are used to identify specific modules.
679 This function is similar in intent to `load-file' except that it loads
680 in pre-compiled C or C++ code, using dynamic shared objects. If NAME
681 is specified, then the module is only loaded if its internal name
682 matches the NAME specified. If VERSION is specified, then the module
683 is only loaded if it matches that VERSION. This function will check
684 to make sure that the same module is not loaded twice. Modules are
685 searched for in the same way as Lisp files, except for the file
686 extension. For a list of valid extensions, see: `module-extensions'
688 All symbols in the shared module must be completely resolved in order
689 for this function to be successful. Any modules which the specified
690 FILE depends on will be automatically loaded. You can determine which
691 modules have been loaded as dynamic shared objects by examining the
692 return value of the function `list-modules'.
694 It is possible, although unwise, to unload modules using `unload-module'.
695 The preferred mechanism for unloading or reloading modules is to quit
696 SXEmacs, and then reload those new or changed modules that are required.
698 Messages informing you of the progress of the load are displayed unless
699 the variable `load-modules-quietly' is non-NIL.
701 (file, unused1, unused2))
704 const char *mod_name;
705 int speccount = specpdl_depth();
706 struct dynacat_s unw = {.ptr = NULL};
707 Lisp_Object lunw = (Lisp_Object)(long)&unw;
711 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
712 file = Fexpand_file_name(file, Qnil);
713 mod_name = (const char*)XSTRING_DATA(file);
715 record_unwind_protect(emodng_load_unwind, lunw);
716 result = emodng_load(mod_name, meself);
717 unbind_to(speccount, Qnil);
720 _register_endpoint(result);
726 DEFUN("unload-module", Funload_module, 1, 1, 0, /*
727 BAD JU-JU! Attempt to unload the emodule named FOO.
729 This is a dangerous operation and you should think twice before doing
730 it. Unloading an emodule can often result in a non-responsive,
731 non-working, or just plain dead SXEmacs session. It is simply not
732 worth the risk. Save your buffers and restart SXEmacs, it really is
735 One last little gotcha... FOO is the _internal_ name of the emodule.
736 The internal name is listed in `list-modules'.
741 const char *mod_name;
742 int speccount = specpdl_depth();
743 struct dynacat_s unw = {.ptr = NULL};
744 Lisp_Object lunw = (Lisp_Object)(long)&unw;
748 set_lheader_implementation(&unw.lheader, &lrecord_dynacat);
749 mod_name = (const char*)XSTRING_DATA(foo);
751 record_unwind_protect(emodng_unload_unwind, lunw);
752 result = emodng_unload(mod_name);
753 unbind_to(speccount, Qnil);
755 return result ? Qt : Qnil;
758 DEFUN("list-loaded-modules", Flist_loaded_modules, 0, 0, 0, /*
759 Return a list of loaded modules.
763 Lisp_Object mlist = Qnil;
765 for (emodng_t e = emods; e; e = e->next) {
766 mlist = Fcons(build_string(e->truename), mlist);
772 emodng_doc_subr(const char *symname, const char *doc)
774 Bytecount len = xstrlen(symname);
775 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
778 if (SYMBOLP(sym) && SUBRP(XSYMBOL(sym)->function)) {
779 EMOD_DEBUG_LOADER("trying to install docs for #'%s\n", symname);
780 subr = XSUBR(XSYMBOL(sym)->function);
782 subr->doc = xstrdup(doc);
786 } else if (!SUBRP(sym)) {
787 EMOD_CRITICAL("Bollocks! #'%s is not a subr\n", symname);
788 } else if (!SYMBOLP(sym)) {
789 EMOD_CRITICAL("Bloody 'ell, #'%s is not even a symbol\n",
793 * FIXME: I wish there was some way to avoid the xstrdup(). Is it
794 * possible to just set a pointer to the string, or somehow create a
795 * symbol whose value we can point to the constant string? Can someone
802 emodng_doc_sym(const char *symname, const char *doc)
804 Bytecount len = xstrlen(symname);
805 Lisp_Object sym = oblookup(Vobarray, (const Bufbyte *)symname, len);
809 EMOD_DEBUG_LOADER("trying to install docs for '%s\n", symname);
812 docstr = build_string(doc);
814 Fput(sym, Qvariable_documentation, docstr);
816 } else if (!SYMBOLP(sym)) {
817 EMOD_CRITICAL("wrong doc specification\n");
822 #if defined USE_LTDL_SEARCHPATH
824 _adapt_load_path(Lisp_Object sym, Lisp_Object *val,
825 Lisp_Object in_object, int flags)
830 /* traverse once to obtain the overall length */
831 for (len = 0, ls = *val; CONSP(ls); ls = XCDR(ls)) {
832 if (LIKELY((STRINGP(XCAR(ls))))) {
833 len += XSTRING_LENGTH(XCAR(ls)) + /*for colon*/1;
836 /* C99 we need ya! traverse to fill the searchpath */
837 if (LIKELY(len > 0)) {
838 char sp[len], *p = sp;
840 for (ls = *val; CONSP(ls); ls = XCDR(ls)) {
841 Lisp_Object lse = XCAR(ls);
842 if (LIKELY((STRINGP(lse)))) {
844 (const char*)XSTRING_DATA(lse),
845 XSTRING_LENGTH(lse));
850 lt_dlsetsearchpath(sp);
852 lt_dlsetsearchpath(NULL);
854 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
862 DEFSUBR(Fload_module_file);
863 DEFSUBR(Funload_module);
864 DEFSUBR(Flist_loaded_modules);
868 reinit_vars_of_emodng(void)
871 meself = lt_dlopen(NULL);
873 EMOD_DEBUG_LOADER("load path %s\n", lt_dlgetsearchpath());
874 #ifdef LTDL_SYSSEARCHPATH
875 EMOD_DEBUG_LOADER("sys path %s\n", LTDL_SYSSEARCHPATH);
883 DEFVAR_BOOL("load-modules-quietly", &load_modules_quietly /*
884 *Set to t if module loading is to be silent.
886 Normally, when loading dynamic modules, Emacs will inform you of its
887 progress, and will display the module name and version if the module
888 is loaded correctly. Setting this variable to `t' will suppress these
889 messages. This would normally only be done if `load-module' was being
890 called by a Lisp function.
892 load_modules_quietly = 0;
894 #if defined USE_LTDL_SEARCHPATH
895 DEFVAR_LISP_MAGIC("module-load-path", &Vmodule_load_path /*
896 *List of directories to search for dynamic modules to load.
897 Each element is a string (directory name) or nil (try default directory).
899 Note that elements of this list *may not* begin with "~", so you must
900 call `expand-file-name' on them before adding them to this list.
902 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
903 to default specified the file `paths.h' when SXEmacs was built. If there
904 were no paths specified in `paths.h', then SXEmacs chooses a default
905 value for this variable by looking around in the file-system near the
906 directory in which the SXEmacs executable resides.
908 Due to the nature of dynamic modules, the path names should almost always
909 refer to architecture-dependent directories. It is unwise to attempt to
910 store dynamic modules in a heterogenous environment. Some environments
911 are similar enough to each other that SXEmacs will be unable to determine
912 the correctness of a dynamic module, which can have unpredictable results
913 when a dynamic module is loaded.
916 #else /* !USE_LTDL_SEARCHPATH */
917 DEFVAR_LISP("module-load-path", &Vmodule_load_path /*
918 *List of directories to search for dynamic modules to load.
919 Each element is a string (directory name) or nil (try default directory).
921 Note that elements of this list *may not* begin with "~", so you must
922 call `expand-file-name' on them before adding them to this list.
924 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise
925 to default specified the file `paths.h' when SXEmacs was built. If there
926 were no paths specified in `paths.h', then SXEmacs chooses a default
927 value for this variable by looking around in the file-system near the
928 directory in which the SXEmacs executable resides.
930 Due to the nature of dynamic modules, the path names should almost always
931 refer to architecture-dependent directories. It is unwise to attempt to
932 store dynamic modules in a heterogenous environment. Some environments
933 are similar enough to each other that SXEmacs will be unable to determine
934 the correctness of a dynamic module, which can have unpredictable results
935 when a dynamic module is loaded.
938 Vmodule_load_path = Qnil;
940 DEFVAR_LISP("module-extensions", &Vmodule_extensions /*
941 *List of filename extensions to use when searching for dynamic modules.
944 list5(build_string(".la"),
946 build_string(".ell"),
947 build_string(".dll"),
948 build_string(".dylib"));
950 Fprovide(intern("modules"));
952 reinit_vars_of_emodng();
955 /* emodules-ng.c ends here */