Mercurial > hg > xemacs-beta
annotate src/emodules.c @ 4742:4cf435fcebbc
Make #'letf not error if handed a #'values form.
lisp/ChangeLog addition:
2009-11-14 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (letf):
Check whether arguments to #'values are bound, and make them
unbound after evaluating BODY; document the limitations of this
macro.
tests/ChangeLog addition:
2009-11-14 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Don't call Known-Bug-Expect-Failure now that the particular letf
bug it tickled is fixed.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Sat, 14 Nov 2009 11:43:09 +0000 |
| parents | 726060ee587c |
| children | 19a72041c5ed |
| rev | line source |
|---|---|
| 428 | 1 /* emodules.c - Support routines for dynamic module loading |
| 2 (C) Copyright 1998, 1999 J. Kean Johnston. All rights reserved. | |
| 3 | |
| 4 This file is part of XEmacs. | |
| 5 | |
| 6 XEmacs is free software; you can redistribute it and/or modify it | |
| 7 under the terms of the GNU General Public License as published by the | |
| 8 Free Software Foundation; either version 2, or (at your option) any | |
| 9 later version. | |
| 10 | |
| 11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 for more details. | |
| 15 | |
| 16 You should have received a copy of the GNU General Public License | |
| 17 along with XEmacs; see the file COPYING. If not, write to | |
| 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 19 Boston, MA 02111-1307, USA. */ | |
| 20 | |
| 21 #include "emodules.h" | |
| 22 #include "sysdll.h" | |
| 2078 | 23 #ifdef HAVE_LTDL |
| 24 #include <ltdl.h> | |
| 25 #endif | |
| 428 | 26 |
| 1750 | 27 /* Load path */ |
| 28 static Lisp_Object Vmodule_load_path; | |
| 29 | |
| 30 /* Module lFile extensions */ | |
| 31 static Lisp_Object Vmodule_extensions; | |
| 32 | |
| 428 | 33 #ifdef HAVE_SHLIB |
| 34 | |
| 35 /* CE-Emacs version number */ | |
| 36 Lisp_Object Vmodule_version; | |
| 37 | |
| 38 /* Do we do our work quietly? */ | |
| 39 int load_modules_quietly; | |
| 40 | |
| 996 | 41 /* Set this while unloading a module. This should NOT be made set by users, |
| 42 as it allows the unbinding of symbol-value-forward variables. */ | |
| 43 int unloading_module; | |
| 44 | |
| 564 | 45 Lisp_Object Qdll_error; |
| 996 | 46 Lisp_Object Qmodule, Qunload_module, module_tag; |
| 564 | 47 |
| 428 | 48 typedef struct _emodules_list |
| 49 { | |
| 996 | 50 int used; /* Is this slot used? */ |
| 1706 | 51 CIbyte *soname; /* Name of the shared object loaded (full path) */ |
| 52 CIbyte *modname; /* The name of the module */ | |
| 53 CIbyte *modver; /* The module version string */ | |
| 54 CIbyte *modtitle; /* How the module announces itself */ | |
| 996 | 55 void (*unload)(void); /* Module cleanup function to run before unloading */ |
| 56 dll_handle dlhandle; /* Dynamic lib handle */ | |
| 428 | 57 } emodules_list; |
| 58 | |
| 59 static int emodules_depth; | |
| 60 static dll_handle dlhandle; | |
| 61 static emodules_list *modules; | |
| 62 static int modnum; | |
| 63 | |
| 1706 | 64 static int find_make_module (const CIbyte *mod, const CIbyte *name, |
| 65 const CIbyte *ver, int make_or_find); | |
| 428 | 66 static Lisp_Object module_load_unwind (Lisp_Object); |
| 67 static void attempt_module_delete (int mod); | |
| 68 | |
| 69 DEFUN ("load-module", Fload_module, 1, 3, "FLoad dynamic module: ", /* | |
| 70 Load in a C Emacs Extension module named FILE. | |
| 71 The optional NAME and VERSION are used to identify specific modules. | |
| 72 | |
| 996 | 73 DO NOT USE THIS FUNCTION in your programs. Use `require' instead. |
| 74 | |
| 428 | 75 This function is similar in intent to `load' except that it loads in |
| 76 pre-compiled C or C++ code, using dynamic shared objects. If NAME is | |
| 77 specified, then the module is only loaded if its internal name matches | |
| 78 the NAME specified. If VERSION is specified, then the module is only | |
| 79 loaded if it matches that VERSION. This function will check to make | |
| 80 sure that the same module is not loaded twice. Modules are searched | |
| 81 for in the same way as Lisp files, except that the valid file | |
| 1632 | 82 extensions are `.so', `.dll', `.ell', or `.dylib'. |
| 428 | 83 |
| 84 All symbols in the shared module must be completely resolved in order | |
| 85 for this function to be successful. Any modules which the specified | |
| 86 FILE depends on will be automatically loaded. You can determine which | |
| 87 modules have been loaded as dynamic shared objects by examining the | |
| 88 return value of the function `list-modules'. | |
| 89 | |
| 996 | 90 It is possible, although unwise, to unload modules using `unload-feature'. |
| 442 | 91 The preferred mechanism for unloading or reloading modules is to quit |
| 428 | 92 XEmacs, and then reload those new or changed modules that are required. |
| 93 | |
| 94 Messages informing you of the progress of the load are displayed unless | |
| 95 the variable `load-modules-quietly' is non-NIL. | |
| 96 */ | |
| 444 | 97 (file, name, version)) |
| 428 | 98 { |
|
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
99 const CIbyte *mod, *mname, *mver; |
| 428 | 100 int speccount = specpdl_depth(); |
| 101 | |
| 102 CHECK_STRING(file); | |
| 103 | |
| 1706 | 104 mod = (CIbyte *) XSTRING_DATA (file); |
| 428 | 105 |
| 106 if (NILP (name)) | |
| 107 mname = ""; | |
| 108 else | |
| 1706 | 109 mname = (CIbyte *) XSTRING_DATA (name); |
| 428 | 110 |
| 111 if (NILP (version)) | |
| 112 mver = ""; | |
| 113 else | |
| 1706 | 114 mver = (CIbyte *) XSTRING_DATA (version); |
| 428 | 115 |
| 116 dlhandle = 0; | |
| 117 record_unwind_protect (module_load_unwind, make_int(modnum)); | |
| 118 emodules_load (mod, mname, mver); | |
| 771 | 119 unbind_to (speccount); |
| 428 | 120 |
| 121 return Qt; | |
| 122 } | |
| 123 | |
| 996 | 124 DEFUN ("unload-module", Funload_module, 1, 3, 0, /* |
| 125 Unload a module previously loaded with load-module. | |
| 428 | 126 |
| 996 | 127 DO NOT USE THIS FUNCTION in your programs. Use `unload-feature' instead. |
| 428 | 128 |
| 129 As with load-module, this function requires at least the module FILE, and | |
| 130 optionally the module NAME and VERSION to unload. It may not be possible | |
| 131 for the module to be unloaded from memory, as there may be Lisp objects | |
| 442 | 132 referring to variables inside the module code. However, once you have |
| 428 | 133 requested a module to be unloaded, it will be unloaded from memory as |
| 134 soon as the last reference to symbols within the module is destroyed. | |
| 135 */ | |
| 444 | 136 (file, name, version)) |
| 428 | 137 { |
| 138 int x; | |
|
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
139 const CIbyte *mod, *mname, *mver; |
| 996 | 140 Lisp_Object foundname = Qnil; |
| 141 struct gcpro gcpro1; | |
| 428 | 142 |
| 143 CHECK_STRING(file); | |
| 144 | |
| 996 | 145 GCPRO1 (foundname); |
| 146 if (locate_file (Vmodule_load_path, file, Vmodule_extensions, &foundname, 0) | |
| 147 < 0) | |
| 148 return Qt; | |
| 1706 | 149 mod = (CIbyte *) XSTRING_DATA (foundname); |
| 996 | 150 UNGCPRO; |
| 428 | 151 |
| 152 if (NILP (name)) | |
| 153 mname = ""; | |
| 154 else | |
| 1706 | 155 mname = (CIbyte *) XSTRING_DATA (name); |
| 428 | 156 |
| 157 if (NILP (version)) | |
| 158 mver = ""; | |
| 159 else | |
| 1706 | 160 mver = (CIbyte *) XSTRING_DATA (version); |
| 428 | 161 |
| 162 x = find_make_module (mod, mname, mver, 1); | |
| 163 if (x != -1) | |
| 996 | 164 { |
| 165 if (modules[x].unload != NULL) | |
| 166 modules[x].unload (); | |
| 167 attempt_module_delete (x); | |
| 168 } | |
| 428 | 169 return Qt; |
| 170 } | |
| 171 | |
| 172 DEFUN ("list-modules", Flist_modules, 0, 0, "", /* | |
| 173 Produce a list of loaded dynamic modules. | |
| 174 | |
| 175 This function will return a list of all the loaded dynamic modules. | |
| 176 Each element in the list is a list in the form (SONAME NAME VER DESC), | |
| 177 where SONAME is the name of the shared object that was loaded, NAME | |
| 178 is the internal module name, VER is the version of the module, and DESC | |
| 179 is how the module describes itself. | |
| 180 | |
| 181 This function returns a list, so you will need to assign the return value | |
| 182 to a variable and then examine the variable with `describe-variable'. | |
| 183 For example: | |
| 184 | |
| 185 (setq mylist (list-modules)) | |
| 186 (describe-variable 'mylist) | |
| 187 | |
| 188 | |
| 189 NOTE: It is possible for the same module to be loaded more than once, | |
| 190 at different versions. However, you should never see the same module, | |
| 191 with the same name and version, loaded more than once. If you do, this | |
| 192 is a bug, and you are encouraged to report it. | |
| 193 */ | |
| 194 ()) | |
| 195 { | |
| 196 Lisp_Object mlist = Qnil; | |
| 197 int i; | |
| 198 | |
| 199 for (i = 0; i < modnum; i++) | |
| 200 { | |
| 201 if (modules[i].used == 1) | |
| 202 mlist = Fcons (list4 (build_string (modules[i].soname), | |
| 203 build_string (modules[i].modname), | |
| 204 build_string (modules[i].modver), | |
| 205 build_string (modules[i].modtitle)), mlist); | |
| 206 } | |
| 207 | |
| 208 return mlist; | |
| 209 } | |
| 210 | |
| 211 static int | |
| 1706 | 212 find_make_module (const CIbyte *mod, const CIbyte *name, const CIbyte *ver, |
| 213 int mof) | |
| 428 | 214 { |
| 215 int i, fs = -1; | |
| 216 | |
| 217 for (i = 0; i < modnum; i++) | |
| 218 { | |
| 219 if (fs == -1 && modules[i].used == 0) | |
| 220 fs = i; | |
| 221 if (strcmp (modules[i].soname, mod) == 0) | |
| 222 { | |
| 223 if (name && name[0] && strcmp (modules[i].modname, name)) | |
| 224 continue; | |
| 225 if (ver && ver[0] && strcmp (modules[i].modver, ver)) | |
| 226 continue; | |
| 227 return i; /* Found a match */ | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 if (mof) | |
| 232 return fs; | |
| 233 | |
| 234 if (fs != -1) | |
| 235 return fs; /* First free slot */ | |
| 236 | |
| 237 /* | |
| 442 | 238 * We only get here if we haven't found a free slot and the module was |
| 428 | 239 * not previously loaded. |
| 240 */ | |
| 1706 | 241 if (modules == NULL) |
| 2367 | 242 modules = xnew (emodules_list); |
| 428 | 243 modnum++; |
| 2367 | 244 XREALLOC_ARRAY (modules, emodules_list, modnum); |
| 428 | 245 |
| 246 fs = modnum - 1; | |
| 2367 | 247 memset (&modules[fs], 0, sizeof (emodules_list)); |
| 428 | 248 return fs; |
| 249 } | |
| 250 | |
| 251 static void | |
| 252 attempt_module_delete (int mod) | |
| 253 { | |
| 254 if (dll_close (modules[mod].dlhandle) == 0) | |
| 255 { | |
| 1726 | 256 xfree (modules[mod].soname, CIbyte *); |
| 257 xfree (modules[mod].modname, CIbyte *); | |
| 258 xfree (modules[mod].modver, CIbyte *); | |
| 259 xfree (modules[mod].modtitle, CIbyte *); | |
| 428 | 260 modules[mod].dlhandle = 0; |
| 261 modules[mod].used = 0; | |
| 262 } | |
| 263 else if (modules[mod].used > 1) | |
| 264 modules[mod].used = 1; /* We couldn't delete it - it stays */ | |
| 265 } | |
| 266 | |
| 267 static Lisp_Object | |
| 268 module_load_unwind (Lisp_Object upto) | |
| 269 { | |
| 270 int x,l=0; | |
| 271 | |
| 272 /* | |
| 273 * First close off the current handle if it is open. | |
| 274 */ | |
| 275 if (dlhandle != 0) | |
| 276 dll_close (dlhandle); | |
| 277 dlhandle = 0; | |
| 278 | |
| 279 if (CONSP (upto)) | |
| 280 { | |
| 281 if (INTP (XCAR (upto))) | |
| 282 l = XINT (XCAR (upto)); | |
| 853 | 283 free_cons (upto); |
| 428 | 284 } |
| 285 else | |
| 286 l = XINT (upto); | |
| 287 | |
| 288 /* | |
| 289 * Here we need to go through and dlclose() (IN REVERSE ORDER!) any | |
| 290 * modules that were loaded as part of this load chain. We only mark | |
| 291 * the slots as closed if the dlclose() succeeds. | |
| 292 */ | |
| 293 for (x = modnum-1; x >= l; x--) | |
| 294 { | |
| 295 if (modules[x].used > 1) | |
| 296 attempt_module_delete (x); | |
| 297 } | |
| 298 emodules_depth = 0; | |
| 299 | |
| 300 return Qnil; | |
| 301 } | |
| 302 | |
| 303 /* | |
| 304 * Do the actual grunt-work of loading in a module. We first try and | |
| 305 * dlopen() the module. If that fails, we have an error and we bail | |
| 306 * out immediately. If the dlopen() succeeds, we need to check for the | |
| 442 | 307 * existence of certain special symbols. |
| 428 | 308 * |
| 309 * All modules will have complete access to the variables and functions | |
| 310 * defined within XEmacs itself. It is up to the module to declare any | |
| 311 * variables or functions it uses, however. Modules will also have access | |
| 312 * to other functions and variables in other loaded modules, unless they | |
| 313 * are defined as STATIC. | |
| 314 * | |
| 315 * We need to be very careful with how we load modules. If we encounter an | |
| 316 * error along the way, we need to back out completely to the point at | |
| 442 | 317 * which the user started. Since we can be called recursively, we need to |
| 428 | 318 * take care with marking modules as loaded. When we first start loading |
| 319 * modules, we set the counter to zero. As we enter the function each time, | |
| 442 | 320 * we increment the counter, and before we leave we decrement it. When |
| 428 | 321 * we get back down to 0, we know we are at the end of the chain and we |
| 322 * can mark all the modules in the list as loaded. | |
| 323 * | |
| 324 * When we signal an error, we need to be sure to unwind all modules loaded | |
| 325 * thus far (but only for this module chain). It is assumed that if any | |
| 326 * modules in a chain fail, then they all do. This is logical, considering | |
| 442 | 327 * that the only time we recurse is when we have dependent modules. So in |
| 428 | 328 * the error handler we take great care to close off the module chain before |
| 329 * we call "error" and let the Fmodule_load unwind_protect() function handle | |
| 330 * the cleaning up. | |
| 331 */ | |
| 332 void | |
| 1706 | 333 emodules_load (const CIbyte *module, const CIbyte *modname, |
| 334 const CIbyte *modver) | |
| 428 | 335 { |
| 2367 | 336 /* !!#### Needs serious work */ |
| 996 | 337 Lisp_Object old_load_list; |
| 428 | 338 Lisp_Object filename; |
| 996 | 339 Lisp_Object foundname, lisp_modname; |
| 340 int x, mpx; | |
| 1706 | 341 CIbyte *soname; |
| 342 const CIbyte **f; | |
| 442 | 343 const long *ellcc_rev; |
| 1706 | 344 CIbyte *mver, *mname, *mtitle, *symname; |
| 428 | 345 void (*modload)(void) = 0; |
| 346 void (*modsyms)(void) = 0; | |
| 347 void (*modvars)(void) = 0; | |
| 348 void (*moddocs)(void) = 0; | |
| 996 | 349 void (*modunld)(void) = 0; |
| 428 | 350 emodules_list *mp; |
| 996 | 351 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 428 | 352 |
| 353 filename = Qnil; | |
| 354 foundname = Qnil; | |
| 355 | |
| 356 emodules_depth++; | |
| 357 dlhandle = 0; | |
| 358 | |
| 1706 | 359 if (module == NULL || module[0] == '\0') |
| 563 | 360 invalid_argument ("Empty module name", Qunbound); |
| 428 | 361 |
| 996 | 362 GCPRO4(filename, foundname, old_load_list, lisp_modname); |
| 363 filename = build_string (module); | |
| 364 if (locate_file (Vmodule_load_path, filename, Vmodule_extensions, | |
| 365 &foundname, 0) < 0) | |
| 563 | 366 signal_error (Qdll_error, "Cannot open dynamic module", filename); |
| 428 | 367 |
| 1706 | 368 LISP_STRING_TO_EXTERNAL (foundname, soname, Qfile_name); |
| 996 | 369 lisp_modname = call1 (Qfile_name_sans_extension, |
| 370 Ffile_name_nondirectory (foundname)); | |
| 428 | 371 |
| 1706 | 372 dlhandle = dll_open (foundname); |
| 373 if (dlhandle == NULL) | |
| 563 | 374 { |
| 1811 | 375 signal_error (Qdll_error, "Opening dynamic module", dll_error ()); |
| 563 | 376 } |
| 428 | 377 |
| 442 | 378 ellcc_rev = (const long *)dll_variable (dlhandle, "emodule_compiler"); |
| 1706 | 379 if (ellcc_rev == NULL || *ellcc_rev <= 0L) |
| 563 | 380 signal_error (Qdll_error, "Invalid dynamic module: Missing symbol `emodule_compiler'", Qunbound); |
| 428 | 381 if (*ellcc_rev > EMODULES_REVISION) |
| 563 | 382 signal_ferror (Qdll_error, "Invalid dynamic module: Unsupported version `%ld(%ld)'", *ellcc_rev, EMODULES_REVISION); |
| 428 | 383 |
| 1706 | 384 f = (const CIbyte **) dll_variable (dlhandle, "emodule_name"); |
| 385 if (f == NULL || *f == NULL) | |
| 563 | 386 signal_error (Qdll_error, "Invalid dynamic module: Missing symbol `emodule_name'", Qunbound); |
| 428 | 387 |
| 1706 | 388 mname = (CIbyte *) ALLOCA (strlen (*f) + 1); |
| 428 | 389 strcpy (mname, *f); |
| 390 if (mname[0] == '\0') | |
| 563 | 391 signal_error (Qdll_error, "Invalid dynamic module: Empty value for `emodule_name'", Qunbound); |
| 428 | 392 |
| 1706 | 393 f = (const CIbyte **) dll_variable (dlhandle, "emodule_version"); |
| 394 if (f == NULL || *f == NULL) | |
| 563 | 395 signal_error (Qdll_error, "Missing symbol `emodule_version': Invalid dynamic module", Qunbound); |
| 428 | 396 |
| 1706 | 397 mver = (CIbyte *) ALLOCA (strlen (*f) + 1); |
| 428 | 398 strcpy (mver, *f); |
| 399 | |
| 1706 | 400 f = (const CIbyte **) dll_variable (dlhandle, "emodule_title"); |
| 401 if (f == NULL || *f == NULL) | |
| 563 | 402 signal_error (Qdll_error, "Invalid dynamic module: Missing symbol `emodule_title'", Qunbound); |
| 428 | 403 |
| 1706 | 404 mtitle = (CIbyte *) ALLOCA (strlen (*f) + 1); |
| 428 | 405 strcpy (mtitle, *f); |
| 406 | |
| 1706 | 407 symname = (CIbyte *) ALLOCA (strlen (mname) + 15); |
| 428 | 408 |
| 409 strcpy (symname, "modules_of_"); | |
| 410 strcat (symname, mname); | |
| 411 modload = (void (*)(void))dll_function (dlhandle, symname); | |
| 412 /* | |
| 442 | 413 * modload is optional. If the module doesn't require other modules it can |
| 428 | 414 * be left out. |
| 415 */ | |
| 416 | |
| 417 strcpy (symname, "syms_of_"); | |
| 418 strcat (symname, mname); | |
| 419 modsyms = (void (*)(void))dll_function (dlhandle, symname); | |
| 1706 | 420 if (modsyms == NULL) |
| 563 | 421 { |
| 422 missing_symbol: | |
| 423 signal_error (Qdll_error, "Invalid dynamic module: Missing symbol", | |
| 424 build_string (symname)); | |
| 425 } | |
| 428 | 426 |
| 427 strcpy (symname, "vars_of_"); | |
| 428 strcat (symname, mname); | |
| 429 modvars = (void (*)(void))dll_function (dlhandle, symname); | |
| 1706 | 430 if (modvars == NULL) |
| 563 | 431 goto missing_symbol; |
| 428 | 432 |
| 433 strcpy (symname, "docs_of_"); | |
| 434 strcat (symname, mname); | |
| 435 moddocs = (void (*)(void))dll_function (dlhandle, symname); | |
| 1706 | 436 if (moddocs == NULL) |
| 563 | 437 goto missing_symbol; |
| 428 | 438 |
| 996 | 439 /* Now look for the optional unload function. */ |
| 440 strcpy (symname, "unload_"); | |
| 441 strcat (symname, mname); | |
| 442 modunld = (void (*)(void))dll_function (dlhandle, symname); | |
| 443 | |
| 428 | 444 if (modname && modname[0] && strcmp (modname, mname)) |
| 563 | 445 signal_error (Qdll_error, "Module name mismatch", Qunbound); |
| 428 | 446 |
| 447 if (modver && modver[0] && strcmp (modver, mver)) | |
| 563 | 448 signal_error (Qdll_error, "Module version mismatch", Qunbound); |
| 428 | 449 |
| 450 /* | |
| 451 * Attempt to make a new slot for this module. If this really is the | |
| 452 * first time we are loading this module, the used member will be 0. | |
| 453 * If that is non-zero, we know that we have a previously loaded module | |
| 442 | 454 * of the same name and version, and we don't need to go any further. |
| 428 | 455 */ |
| 456 mpx = find_make_module (soname, mname, mver, 0); | |
| 457 mp = &modules[mpx]; | |
| 458 if (mp->used > 0) | |
| 459 { | |
| 460 emodules_depth--; | |
| 461 dll_close (dlhandle); | |
| 806 | 462 dlhandle = 0; /* Zero this out before module_load_unwind runs */ |
| 428 | 463 return; |
| 464 } | |
| 465 | |
| 466 if (!load_modules_quietly) | |
| 467 message ("Loading %s v%s (%s)", mname, mver, mtitle); | |
| 468 | |
| 469 /* | |
| 470 * We have passed the basic initialization, and can now add this | |
| 471 * module to the list of modules. | |
| 472 */ | |
| 473 mp->used = emodules_depth + 1; | |
| 474 mp->soname = xstrdup (soname); | |
| 475 mp->modname = xstrdup (mname); | |
| 476 mp->modver = xstrdup (mver); | |
| 477 mp->modtitle = xstrdup (mtitle); | |
| 478 mp->dlhandle = dlhandle; | |
| 996 | 479 mp->unload = modunld; |
| 428 | 480 dlhandle = 0; |
| 481 | |
| 996 | 482 old_load_list = Vcurrent_load_list; |
| 483 Vcurrent_load_list = Qnil; | |
| 484 LOADHIST_ATTACH (lisp_modname); | |
| 485 LOADHIST_ATTACH (module_tag); | |
| 486 | |
| 428 | 487 /* |
| 488 * Now we need to call the module init function and perform the various | |
| 489 * startup tasks. | |
| 490 */ | |
| 491 if (modload != 0) | |
| 492 (*modload)(); | |
| 493 | |
| 494 /* | |
| 495 * Now we can get the module to initialize its symbols, and then its | |
| 496 * variables, and lastly the documentation strings. | |
| 497 */ | |
| 498 (*modsyms)(); | |
| 499 (*modvars)(); | |
| 500 (*moddocs)(); | |
| 501 | |
| 502 if (!load_modules_quietly) | |
| 503 message ("Loaded module %s v%s (%s)", mname, mver, mtitle); | |
| 504 | |
| 996 | 505 Vload_history = Fcons (Fnreverse (Vcurrent_load_list), Vload_history); |
| 506 Vcurrent_load_list = old_load_list; | |
| 507 UNGCPRO; | |
| 428 | 508 |
| 509 emodules_depth--; | |
| 510 if (emodules_depth == 0) | |
| 511 { | |
| 512 /* | |
| 513 * We have reached the end of the load chain. We now go through the | |
| 514 * list of loaded modules and mark all the valid modules as just | |
| 515 * that. | |
| 516 */ | |
| 517 for (x = 0; x < modnum; x++) | |
| 518 if (modules[x].used > 1) | |
| 519 modules[x].used = 1; | |
| 520 } | |
| 521 } | |
| 522 | |
| 523 void | |
| 442 | 524 emodules_doc_subr(const char *symname, const char *doc) |
| 428 | 525 { |
| 526 Bytecount len = strlen (symname); | |
| 867 | 527 Lisp_Object sym = oblookup (Vobarray, (const Ibyte *)symname, len); |
| 440 | 528 Lisp_Subr *subr; |
| 428 | 529 |
| 1632 | 530 /* Skip autoload cookies */ |
| 531 if (SYMBOLP (sym) && SUBRP (XSYMBOL (sym)->function)) | |
| 428 | 532 { |
| 1632 | 533 subr = XSUBR (XSYMBOL (sym)->function); |
| 428 | 534 subr->doc = xstrdup (doc); |
| 535 } | |
| 536 /* | |
| 537 * FIXME: I wish there was some way to avoid the xstrdup(). Is it | |
| 538 * possible to just set a pointer to the string, or somehow create a | |
| 539 * symbol whose value we can point to the constant string? Can someone | |
| 540 * look into this? | |
| 541 */ | |
| 542 } | |
| 543 | |
| 544 void | |
| 442 | 545 emodules_doc_sym (const char *symname, const char *doc) |
| 428 | 546 { |
| 547 Bytecount len = strlen (symname); | |
| 867 | 548 Lisp_Object sym = oblookup (Vobarray, (const Ibyte *)symname, len); |
| 428 | 549 Lisp_Object docstr; |
| 550 struct gcpro gcpro1; | |
| 551 | |
| 552 if (SYMBOLP(sym)) | |
| 553 { | |
| 554 docstr = build_string (doc); | |
| 555 GCPRO1(docstr); | |
| 556 Fput (sym, Qvariable_documentation, docstr); | |
| 557 UNGCPRO; | |
| 558 } | |
| 559 } | |
| 560 | |
| 561 | |
| 562 void | |
| 563 syms_of_module (void) | |
| 564 { | |
| 564 | 565 DEFERROR_STANDARD (Qdll_error, Qerror); |
| 996 | 566 DEFSYMBOL (Qmodule); |
| 567 DEFSYMBOL (Qunload_module); | |
| 428 | 568 DEFSUBR(Fload_module); |
| 569 DEFSUBR(Flist_modules); | |
| 570 DEFSUBR(Funload_module); | |
| 996 | 571 module_tag = Fcons (Qmodule, Qnil); |
| 572 staticpro (&module_tag); | |
| 573 Fput (Qunload_module, Qdisabled, Qt); | |
| 428 | 574 } |
| 575 | |
| 576 void | |
| 577 reinit_vars_of_module (void) | |
| 578 { | |
| 579 emodules_depth = 0; | |
| 1706 | 580 modules = NULL; |
| 428 | 581 modnum = 0; |
| 582 } | |
| 583 | |
| 1750 | 584 #endif /* HAVE_SHLIB */ |
| 585 | |
| 428 | 586 void |
| 587 vars_of_module (void) | |
| 588 { | |
| 1750 | 589 #ifdef HAVE_SHLIB |
| 590 Fprovide (intern ("modules")); | |
| 591 | |
| 2078 | 592 #ifdef HAVE_LTDL |
| 593 lt_dlinit (); | |
| 594 lt_dlmalloc = (lt_ptr (*) (size_t)) xmalloc; | |
| 595 lt_dlrealloc = (lt_ptr (*) (lt_ptr, size_t)) xrealloc; | |
| 596 lt_dlfree = (void (*) (lt_ptr)) xfree_1; | |
| 597 #endif | |
| 598 | |
| 428 | 599 DEFVAR_LISP ("module-version", &Vmodule_version /* |
| 600 Emacs dynamic loading mechanism version, as a string. | |
| 601 | |
| 602 This string is in the form XX.YY.ppp, where XX is the major version | |
| 603 number, YY is the minor version number, and ppp is the patch level. | |
| 442 | 604 This variable can be used to distinguish between different versions of |
| 428 | 605 the dynamic loading technology used in Emacs, if required. It is not |
| 606 a given that this value will be the same as the Emacs version number. | |
| 607 */ ); | |
| 608 Vmodule_version = build_string (EMODULES_VERSION); | |
| 609 | |
| 610 DEFVAR_BOOL ("load-modules-quietly", &load_modules_quietly /* | |
| 611 *Set to t if module loading is to be silent. | |
| 612 | |
| 613 Normally, when loading dynamic modules, Emacs will inform you of its | |
| 614 progress, and will display the module name and version if the module | |
| 615 is loaded correctly. Setting this variable to `t' will suppress these | |
| 616 messages. This would normally only be done if `load-module' was being | |
| 617 called by a Lisp function. | |
| 618 */); | |
| 1733 | 619 load_modules_quietly = 0; |
| 428 | 620 |
| 1750 | 621 DEFVAR_BOOL ("unloading-module", &unloading_module /* |
| 622 Used internally by `unload-feature'. Do not set this variable. | |
| 623 Danger, danger, Will Robinson! | |
| 624 */); | |
| 625 unloading_module = 0; | |
| 626 | |
| 627 #endif /* HAVE_SHLIB */ | |
| 628 | |
| 428 | 629 DEFVAR_LISP ("module-load-path", &Vmodule_load_path /* |
| 630 *List of directories to search for dynamic modules to load. | |
| 631 Each element is a string (directory name) or nil (try default directory). | |
| 632 | |
| 633 Note that elements of this list *may not* begin with "~", so you must | |
| 442 | 634 call `expand-file-name' on them before adding them to this list. |
| 428 | 635 |
| 636 Initialized based on EMACSMODULEPATH environment variable, if any, otherwise | |
| 637 to default specified the file `paths.h' when XEmacs was built. If there | |
| 638 were no paths specified in `paths.h', then XEmacs chooses a default | |
| 639 value for this variable by looking around in the file-system near the | |
| 640 directory in which the XEmacs executable resides. | |
| 641 | |
| 642 Due to the nature of dynamic modules, the path names should almost always | |
| 442 | 643 refer to architecture-dependent directories. It is unwise to attempt to |
| 644 store dynamic modules in a heterogenous environment. Some environments | |
| 428 | 645 are similar enough to each other that XEmacs will be unable to determine |
| 646 the correctness of a dynamic module, which can have unpredictable results | |
| 647 when a dynamic module is loaded. | |
| 648 */); | |
| 1733 | 649 Vmodule_load_path = Qnil; |
| 428 | 650 |
| 1733 | 651 DEFVAR_LISP ("module-extensions", &Vmodule_extensions /* |
| 652 *List of filename extensions to use when searching for dynamic modules. | |
| 653 */); | |
| 654 Vmodule_extensions = list5 (build_string (".ell"), | |
| 996 | 655 build_string (".so"), |
| 1381 | 656 build_string (".dll"), |
| 1733 | 657 build_string (".dylib"), |
| 658 build_string ("")); | |
| 428 | 659 } |
