aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAurélien Aptel2014-12-02 16:17:10 -0500
committerTed Zlatanov2014-12-04 19:54:16 -0500
commitae901ddbfff04e8b1b0d63c452a6ca3f4c81fb17 (patch)
treeb806504944c633be45255321d1203bbcc2504781 /src
parentdd601050e7db69f322eea09d99751d8e6363b153 (diff)
downloademacs-old-branches/dynamic-modules-rc2.tar.gz
emacs-old-branches/dynamic-modules-rc2.zip
* configure.ac: Add libtool support and module Makefiles. * src/Makefile.in: Support libtool. * src/alloc.c (mark_object): Mark the doc field of Lisp_Subr as object. * src/doc.c (doc_is_from_module_p, get_doc_string, reread_doc_file) (store_function_docstring, build_file_p, Fsnarf_documentation): Support docstrings for external modules. * src/lisp.h: Make the doc field of Lisp_Subr a Lisp_Object. * src/lread.c (Fget_load_suffixes, Fload_module, string_suffixes_p) (string_suffix_p, Fload, intern_c_string_1, defsubr) (syms_of_lread): Add loading of external modules and the docstrings of their functions. * modules/curl: New module. * modules/elisp: New module. * modules/fmod: New module. * modules/opaque: New module. * modules/yaml: New module.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog17
-rw-r--r--src/Makefile.in4
-rw-r--r--src/alloc.c1
-rw-r--r--src/doc.c139
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c162
6 files changed, 250 insertions, 75 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 7dc2b928f1e..c344a0f9433 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
12014-12-02 Aurélien Aptel <aurelien.aptel@gmail.com>
2
3 * lread.c (Fget_load_suffixes, Fload_module, string_suffixes_p)
4 (string_suffix_p, Fload, intern_c_string_1, defsubr)
5 (syms_of_lread): Add loading of external modules and the
6 docstrings of their functions.
7
8 * lisp.h: Make the doc field of Lisp_Subr a Lisp_Object.
9
10 * doc.c (doc_is_from_module_p, get_doc_string, reread_doc_file)
11 (store_function_docstring, build_file_p, Fsnarf_documentation):
12 Support docstrings for external modules.
13
14 * alloc.c (mark_object): Mark the doc field of Lisp_Subr as object.
15
16 * Makefile.in: Support libtool.
17
12014-12-02 Eli Zaretskii <eliz@gnu.org> 182014-12-02 Eli Zaretskii <eliz@gnu.org>
2 19
3 * bidi.c (bidi_find_first_overridden): New function. 20 * bidi.c (bidi_find_first_overridden): New function.
diff --git a/src/Makefile.in b/src/Makefile.in
index 00ac04aa836..d3468d1d1e3 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -224,6 +224,8 @@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
224 224
225LIBZ = @LIBZ@ 225LIBZ = @LIBZ@
226 226
227LIBLTDL = @LIBLTDL@
228
227XRANDR_LIBS = @XRANDR_LIBS@ 229XRANDR_LIBS = @XRANDR_LIBS@
228XRANDR_CFLAGS = @XRANDR_CFLAGS@ 230XRANDR_CFLAGS = @XRANDR_CFLAGS@
229 231
@@ -425,7 +427,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
425 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 427 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
426 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 428 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
427 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ 429 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
428 $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) 430 $(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBLTDL)
429 431
430all: emacs$(EXEEXT) $(OTHER_FILES) 432all: emacs$(EXEEXT) $(OTHER_FILES)
431.PHONY: all 433.PHONY: all
diff --git a/src/alloc.c b/src/alloc.c
index 1019c2af6cc..f15b978d52d 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6348,6 +6348,7 @@ mark_object (Lisp_Object arg)
6348 break; 6348 break;
6349 6349
6350 case PVEC_SUBR: 6350 case PVEC_SUBR:
6351 mark_object (XSUBR (obj)->doc);
6351 break; 6352 break;
6352 6353
6353 case PVEC_FREE: 6354 case PVEC_FREE:
diff --git a/src/doc.c b/src/doc.c
index 1b87c23e949..5290b5d277a 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -56,6 +56,15 @@ read_bytecode_char (bool unreadflag)
56 return *read_bytecode_pointer++; 56 return *read_bytecode_pointer++;
57} 57}
58 58
59/* A module doc file must have a doc extension */
60static bool
61doc_is_from_module_p (const char* path)
62{
63 int len = strlen (path);
64 return len > 4 && (strcmp (path + len - 4, ".doc") == 0
65 || (strcmp (path + len - 4, ".DOC") == 0));
66}
67
59/* Extract a doc string from a file. FILEPOS says where to get it. 68/* Extract a doc string from a file. FILEPOS says where to get it.
60 If it is an integer, use that position in the standard DOC file. 69 If it is an integer, use that position in the standard DOC file.
61 If it is (FILE . INTEGER), use FILE as the file name 70 If it is (FILE . INTEGER), use FILE as the file name
@@ -109,11 +118,11 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
109 return Qnil; 118 return Qnil;
110 119
111 /* Put the file name in NAME as a C string. 120 /* Put the file name in NAME as a C string.
112 If it is relative, combine it with Vdoc_directory. */ 121 If it is relative and not from a module, combine it with Vdoc_directory. */
113 122
114 tem = Ffile_name_absolute_p (file); 123 tem = Ffile_name_absolute_p (file);
115 file = ENCODE_FILE (file); 124 file = ENCODE_FILE (file);
116 if (NILP (tem)) 125 if (NILP (tem) && !doc_is_from_module_p (SSDATA (file)))
117 { 126 {
118 Lisp_Object docdir = ENCODE_FILE (Vdoc_directory); 127 Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
119 minsize = SCHARS (docdir); 128 minsize = SCHARS (docdir);
@@ -211,7 +220,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
211 SAFE_FREE (); 220 SAFE_FREE ();
212 221
213 /* Sanity checking. */ 222 /* Sanity checking. */
214 if (CONSP (filepos)) 223 if (CONSP (filepos) && !doc_is_from_module_p (name))
215 { 224 {
216 int test = 1; 225 int test = 1;
217 /* A dynamic docstring should be either at the very beginning of a "#@ 226 /* A dynamic docstring should be either at the very beginning of a "#@
@@ -321,7 +330,7 @@ reread_doc_file (Lisp_Object file)
321#endif 330#endif
322 331
323 if (NILP (file)) 332 if (NILP (file))
324 Fsnarf_documentation (Vdoc_file_name); 333 Fsnarf_documentation (Vdoc_file_name, Qnil);
325 else 334 else
326 Fload (file, Qt, Qt, Qt, Qnil); 335 Fload (file, Qt, Qt, Qt, Qnil);
327 336
@@ -356,14 +365,16 @@ string is passed through `substitute-command-keys'. */)
356 fun = XCDR (fun); 365 fun = XCDR (fun);
357 if (SUBRP (fun)) 366 if (SUBRP (fun))
358 { 367 {
359 if (XSUBR (fun)->doc == 0) 368 Lisp_Object subrdoc = XSUBR (fun)->doc;
360 return Qnil; 369
361 /* FIXME: This is not portable, as it assumes that string 370 if (NILP (subrdoc))
362 pointers have the top bit clear. */ 371 return Qnil;
363 else if ((intptr_t) XSUBR (fun)->doc >= 0) 372 else if (STRINGP (subrdoc))
364 doc = build_string (XSUBR (fun)->doc); 373 return subrdoc;
374 else if (INTEGERP (subrdoc) || CONSP (subrdoc))
375 doc = subrdoc;
365 else 376 else
366 doc = make_number ((intptr_t) XSUBR (fun)->doc); 377 error ("invalid value in subr doc field");
367 } 378 }
368 else if (COMPILEDP (fun)) 379 else if (COMPILEDP (fun))
369 { 380 {
@@ -495,7 +506,7 @@ aren't strings. */)
495/* Scanning the DOC files and placing docstring offsets into functions. */ 506/* Scanning the DOC files and placing docstring offsets into functions. */
496 507
497static void 508static void
498store_function_docstring (Lisp_Object obj, ptrdiff_t offset) 509store_function_docstring (Lisp_Object obj, Lisp_Object filename, ptrdiff_t offset, bool module)
499{ 510{
500 /* Don't use indirect_function here, or defaliases will apply their 511 /* Don't use indirect_function here, or defaliases will apply their
501 docstrings to the base functions (Bug#2603). */ 512 docstrings to the base functions (Bug#2603). */
@@ -506,8 +517,8 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
506 /* Lisp_Subrs have a slot for it. */ 517 /* Lisp_Subrs have a slot for it. */
507 if (SUBRP (fun)) 518 if (SUBRP (fun))
508 { 519 {
509 intptr_t negative_offset = - offset; 520 Lisp_Object neg = make_number (-offset); /* XXX: no sure why.. */
510 XSUBR (fun)->doc = (char *) negative_offset; 521 XSUBR (fun)->doc = module ? Fcons (filename, neg) : neg;
511 } 522 }
512 523
513 /* If it's a lisp form, stick it in the form. */ 524 /* If it's a lisp form, stick it in the form. */
@@ -526,7 +537,7 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
526 XSETCAR (tem, make_number (offset)); 537 XSETCAR (tem, make_number (offset));
527 } 538 }
528 else if (EQ (tem, Qmacro)) 539 else if (EQ (tem, Qmacro))
529 store_function_docstring (XCDR (fun), offset); 540 store_function_docstring (XCDR (fun), filename, offset, module);
530 } 541 }
531 542
532 /* Bytecode objects sometimes have slots for it. */ 543 /* Bytecode objects sometimes have slots for it. */
@@ -542,9 +553,24 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
542 } 553 }
543} 554}
544 555
556static bool
557build_file_p (const char* file, ptrdiff_t len)
558{
559 /* file can be longer than len, can't use xstrdup */
560 char *ofile = xmalloc (len + 1);
561 memcpy (ofile, file, len);
562 ofile[len] = 0;
563
564 if (ofile[len-1] == 'c')
565 ofile[len-1] = 'o';
566
567 bool res = NILP (Fmember (build_string (ofile), Vbuild_files));
568 xfree (ofile);
569 return res;
570}
545 571
546DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation, 572DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation,
547 1, 1, 0, 573 1, 2, 0,
548 doc: /* Used during Emacs initialization to scan the `etc/DOC...' file. 574 doc: /* Used during Emacs initialization to scan the `etc/DOC...' file.
549This searches the `etc/DOC...' file for doc strings and 575This searches the `etc/DOC...' file for doc strings and
550records them in function and variable definitions. 576records them in function and variable definitions.
@@ -552,7 +578,7 @@ The function takes one argument, FILENAME, a string;
552it specifies the file name (without a directory) of the DOC file. 578it specifies the file name (without a directory) of the DOC file.
553That file is found in `../etc' now; later, when the dumped Emacs is run, 579That file is found in `../etc' now; later, when the dumped Emacs is run,
554the same file name is found in the `doc-directory'. */) 580the same file name is found in the `doc-directory'. */)
555 (Lisp_Object filename) 581 (Lisp_Object filename, Lisp_Object module)
556{ 582{
557 int fd; 583 int fd;
558 char buf[1024 + 1]; 584 char buf[1024 + 1];
@@ -573,22 +599,48 @@ the same file name is found in the `doc-directory'. */)
573 599
574 CHECK_STRING (filename); 600 CHECK_STRING (filename);
575 601
576 if 602 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
603 if (NILP (Vbuild_files))
604 {
605 static char const *const buildobj[] =
606 {
607 #include "buildobj.h"
608 };
609 int i = ARRAYELTS (buildobj);
610 while (0 <= --i)
611 Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
612 Vbuild_files = Fpurecopy (Vbuild_files);
613 }
614
615 if (NILP (module))
616 {
617 /* If we're not processing a module doc, the doc file becomes
618 the "global" DOC file */
619 Vdoc_file_name = filename;
620
621 if
577#ifndef CANNOT_DUMP 622#ifndef CANNOT_DUMP
578 (!NILP (Vpurify_flag)) 623 (!NILP (Vpurify_flag))
579#else /* CANNOT_DUMP */ 624#else /* CANNOT_DUMP */
580 (0) 625 (0)
581#endif /* CANNOT_DUMP */ 626#endif /* CANNOT_DUMP */
582 { 627 {
583 static char const sibling_etc[] = "../etc/"; 628 static char const sibling_etc[] = "../etc/";
584 dirname = sibling_etc; 629 dirname = sibling_etc;
585 dirlen = sizeof sibling_etc - 1; 630 dirlen = sizeof sibling_etc - 1;
631 }
632 else
633 {
634 CHECK_STRING (Vdoc_directory);
635 dirname = SSDATA (Vdoc_directory);
636 dirlen = SBYTES (Vdoc_directory);
637 }
586 } 638 }
587 else 639 else
588 { 640 {
589 CHECK_STRING (Vdoc_directory); 641 static char const empty_prefix_dir[] = "";
590 dirname = SSDATA (Vdoc_directory); 642 dirname = empty_prefix_dir;
591 dirlen = SBYTES (Vdoc_directory); 643 dirlen = 0;
592 } 644 }
593 645
594 count = SPECPDL_INDEX (); 646 count = SPECPDL_INDEX ();
@@ -597,18 +649,6 @@ the same file name is found in the `doc-directory'. */)
597 strcpy (name, dirname); 649 strcpy (name, dirname);
598 strcat (name, SSDATA (filename)); /*** Add this line ***/ 650 strcat (name, SSDATA (filename)); /*** Add this line ***/
599 651
600 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
601 if (NILP (Vbuild_files))
602 {
603 static char const *const buildobj[] =
604 {
605 #include "buildobj.h"
606 };
607 int i = ARRAYELTS (buildobj);
608 while (0 <= --i)
609 Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
610 Vbuild_files = Fpurecopy (Vbuild_files);
611 }
612 652
613 fd = emacs_open (name, O_RDONLY, 0); 653 fd = emacs_open (name, O_RDONLY, 0);
614 if (fd < 0) 654 if (fd < 0)
@@ -618,7 +658,6 @@ the same file name is found in the `doc-directory'. */)
618 open_errno); 658 open_errno);
619 } 659 }
620 record_unwind_protect_int (close_file_unwind, fd); 660 record_unwind_protect_int (close_file_unwind, fd);
621 Vdoc_file_name = filename;
622 filled = 0; 661 filled = 0;
623 pos = 0; 662 pos = 0;
624 while (1) 663 while (1)
@@ -641,18 +680,13 @@ the same file name is found in the `doc-directory'. */)
641 if (p[1] == 'S') 680 if (p[1] == 'S')
642 { 681 {
643 skip_file = 0; 682 skip_file = 0;
644 if (end - p > 4 && end[-2] == '.' 683 if (NILP (module)
645 && (end[-1] == 'o' || end[-1] == 'c')) 684 && end - p > 4
685 && end[-2] == '.'
686 && (end[-1] == 'o' || end[-1] == 'c')
687 && build_file_p (&p[2], end - p - 2))
646 { 688 {
647 ptrdiff_t len = end - p - 2; 689 skip_file = 1;
648 char *fromfile = SAFE_ALLOCA (len + 1);
649 memcpy (fromfile, &p[2], len);
650 fromfile[len] = 0;
651 if (fromfile[len-1] == 'c')
652 fromfile[len-1] = 'o';
653
654 skip_file = NILP (Fmember (build_string (fromfile),
655 Vbuild_files));
656 } 690 }
657 } 691 }
658 692
@@ -672,6 +706,7 @@ the same file name is found in the `doc-directory'. */)
672 /* Install file-position as variable-documentation property 706 /* Install file-position as variable-documentation property
673 and make it negative for a user-variable 707 and make it negative for a user-variable
674 (doc starts with a `*'). */ 708 (doc starts with a `*'). */
709 /* TODO: handle module var */
675 if (!NILP (Fboundp (sym)) 710 if (!NILP (Fboundp (sym))
676 || !NILP (Fmemq (sym, delayed_init))) 711 || !NILP (Fmemq (sym, delayed_init)))
677 Fput (sym, Qvariable_documentation, 712 Fput (sym, Qvariable_documentation,
@@ -683,7 +718,7 @@ the same file name is found in the `doc-directory'. */)
683 else if (p[1] == 'F') 718 else if (p[1] == 'F')
684 { 719 {
685 if (!NILP (Ffboundp (sym))) 720 if (!NILP (Ffboundp (sym)))
686 store_function_docstring (sym, pos + end + 1 - buf); 721 store_function_docstring (sym, filename, pos + end + 1 - buf, !NILP (module));
687 } 722 }
688 else if (p[1] == 'S') 723 else if (p[1] == 'S')
689 ; /* Just a source file name boundary marker. Ignore it. */ 724 ; /* Just a source file name boundary marker. Ignore it. */
diff --git a/src/lisp.h b/src/lisp.h
index a56c4a73bf8..dc855f5e2bf 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1513,7 +1513,7 @@ struct Lisp_Subr
1513 short min_args, max_args; 1513 short min_args, max_args;
1514 const char *symbol_name; 1514 const char *symbol_name;
1515 const char *intspec; 1515 const char *intspec;
1516 const char *doc; 1516 Lisp_Object doc;
1517 }; 1517 };
1518 1518
1519enum char_table_specials 1519enum char_table_specials
diff --git a/src/lread.c b/src/lread.c
index 6f71ff5f468..3a2c29a616b 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -64,6 +64,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
64#define file_tell ftell 64#define file_tell ftell
65#endif 65#endif
66 66
67#ifdef HAVE_LTDL
68#include <ltdl.h>
69#endif
70
67/* Hash table read constants. */ 71/* Hash table read constants. */
68static Lisp_Object Qhash_table, Qdata; 72static Lisp_Object Qhash_table, Qdata;
69static Lisp_Object Qtest; 73static Lisp_Object Qtest;
@@ -982,7 +986,15 @@ required.
982This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) 986This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */)
983 (void) 987 (void)
984{ 988{
985 Lisp_Object lst = Qnil, suffixes = Vload_suffixes, suffix, ext; 989 Lisp_Object lst = Qnil, suffixes, suffix, ext;
990
991 /* module suffixes, then regular elisp suffixes */
992
993 Lisp_Object args[2];
994 args[0] = Vload_module_suffixes;
995 args[1] = Vload_suffixes;
996 suffixes = Fappend (2, args);
997
986 while (CONSP (suffixes)) 998 while (CONSP (suffixes))
987 { 999 {
988 Lisp_Object exts = Vload_file_rep_suffixes; 1000 Lisp_Object exts = Vload_file_rep_suffixes;
@@ -998,6 +1010,86 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */)
998 return Fnreverse (lst); 1010 return Fnreverse (lst);
999} 1011}
1000 1012
1013DEFUN ("load-module", Fload_module, Sload_module, 1, 1, 0,
1014 doc: /* Dymamically load a compiled module. */)
1015 (Lisp_Object file)
1016{
1017#ifdef HAVE_LTDL
1018 static int lt_init_done = 0;
1019 lt_dlhandle handle;
1020 void (*module_init) ();
1021 void *gpl_sym;
1022 Lisp_Object doc_name, args[2];
1023
1024 /* init libtool once per emacs process */
1025 if (!lt_init_done)
1026 {
1027 int ret = lt_dlinit ();
1028 if (ret)
1029 {
1030 const char* s = lt_dlerror ();
1031 error ("ltdl init fail: %s", s);
1032 }
1033 lt_init_done = 1;
1034 }
1035
1036 CHECK_STRING (file);
1037
1038 handle = lt_dlopen (SDATA (file));
1039 if (!handle)
1040 error ("Cannot load file %s", SDATA (file));
1041
1042 gpl_sym = lt_dlsym (handle, "plugin_is_GPL_compatible");
1043 if (!gpl_sym)
1044 error ("Module %s is not GPL compatible", SDATA (file));
1045
1046 module_init = (void (*) ()) lt_dlsym (handle, "init");
1047 if (!module_init)
1048 error ("Module %s does not have an init function.", SDATA (file));
1049
1050 module_init ();
1051
1052 /* build doc file path and install it */
1053 args[0] = Fsubstring (file, make_number (0), make_number (-3));
1054 args[1] = build_string (".doc");
1055 doc_name = Fconcat (2, args);
1056 Fsnarf_documentation (doc_name, Qt);
1057
1058 return Qt;
1059#else
1060 return Qnil;
1061#endif
1062}
1063
1064
1065/* Return true if STRING ends with SUFFIX. */
1066static bool string_suffix_p (Lisp_Object string, const char *suffix)
1067{
1068 const ptrdiff_t len = strlen (suffix);
1069 return memcmp (SDATA (string) + SBYTES (string) - len, suffix, len) == 0;
1070}
1071
1072/* Return true if STRING ends with any element of SUFFIXES. */
1073static bool string_suffixes_p (Lisp_Object string, Lisp_Object suffixes)
1074{
1075 ptrdiff_t length = SBYTES (string), suflen;
1076 Lisp_Object tail, suffix;
1077
1078 for (tail = suffixes; CONSP (tail); tail = XCDR (tail))
1079 {
1080 suffix = XCAR (tail);
1081 suflen = SBYTES (suffix);
1082
1083 if (suflen <= length)
1084 {
1085 if (memcmp (SDATA (string) + length - suflen, SDATA (suffix), suflen) == 0)
1086 return true;
1087 }
1088 }
1089
1090 return false;
1091}
1092
1001DEFUN ("load", Fload, Sload, 1, 5, 0, 1093DEFUN ("load", Fload, Sload, 1, 5, 0,
1002 doc: /* Execute a file of Lisp code named FILE. 1094 doc: /* Execute a file of Lisp code named FILE.
1003First try FILE with `.elc' appended, then try with `.el', 1095First try FILE with `.elc' appended, then try with `.el',
@@ -1055,6 +1147,8 @@ Return t if the file exists and loads successfully. */)
1055 bool newer = 0; 1147 bool newer = 0;
1056 /* True means we are loading a compiled file. */ 1148 /* True means we are loading a compiled file. */
1057 bool compiled = 0; 1149 bool compiled = 0;
1150 /* True means we are loading a dynamic module. */
1151 bool module = 0;
1058 Lisp_Object handler; 1152 Lisp_Object handler;
1059 bool safe_p = 1; 1153 bool safe_p = 1;
1060 const char *fmode = "r"; 1154 const char *fmode = "r";
@@ -1105,18 +1199,14 @@ Return t if the file exists and loads successfully. */)
1105 1199
1106 if (! NILP (must_suffix)) 1200 if (! NILP (must_suffix))
1107 { 1201 {
1108 /* Don't insist on adding a suffix if FILE already ends with one. */ 1202 /* Don't insist on adding a suffix if FILE already ends with
1109 ptrdiff_t size = SBYTES (file); 1203 one or if FILE includes a directory name. */
1110 if (size > 3 1204 if (string_suffixes_p (file, Vload_module_suffixes)
1111 && !strcmp (SSDATA (file) + size - 3, ".el")) 1205 || string_suffixes_p (file, Vload_suffixes)
1112 must_suffix = Qnil; 1206 || ! NILP (Ffile_name_directory (file)))
1113 else if (size > 4 1207 {
1114 && !strcmp (SSDATA (file) + size - 4, ".elc")) 1208 must_suffix = Qnil;
1115 must_suffix = Qnil; 1209 }
1116 /* Don't insist on adding a suffix
1117 if the argument includes a directory name. */
1118 else if (! NILP (Ffile_name_directory (file)))
1119 must_suffix = Qnil;
1120 } 1210 }
1121 1211
1122 if (!NILP (nosuffix)) 1212 if (!NILP (nosuffix))
@@ -1227,7 +1317,7 @@ Return t if the file exists and loads successfully. */)
1227 specbind (Qold_style_backquotes, Qnil); 1317 specbind (Qold_style_backquotes, Qnil);
1228 record_unwind_protect (load_warn_old_style_backquotes, file); 1318 record_unwind_protect (load_warn_old_style_backquotes, file);
1229 1319
1230 if (!memcmp (SDATA (found) + SBYTES (found) - 4, ".elc", 4) 1320 if (string_suffix_p (found, ".elc")
1231 || (fd >= 0 && (version = safe_to_load_version (fd)) > 0)) 1321 || (fd >= 0 && (version = safe_to_load_version (fd)) > 0))
1232 /* Load .elc files directly, but not when they are 1322 /* Load .elc files directly, but not when they are
1233 remote and have no handler! */ 1323 remote and have no handler! */
@@ -1289,6 +1379,12 @@ Return t if the file exists and loads successfully. */)
1289 UNGCPRO; 1379 UNGCPRO;
1290 } 1380 }
1291 } 1381 }
1382#ifdef HAVE_LTDL
1383 else if (string_suffixes_p (found, Vload_module_suffixes))
1384 {
1385 module = 1;
1386 }
1387#endif
1292 else 1388 else
1293 { 1389 {
1294 /* We are loading a source file (*.el). */ 1390 /* We are loading a source file (*.el). */
@@ -1338,7 +1434,9 @@ Return t if the file exists and loads successfully. */)
1338 1434
1339 if (NILP (nomessage) || force_load_messages) 1435 if (NILP (nomessage) || force_load_messages)
1340 { 1436 {
1341 if (!safe_p) 1437 if (module)
1438 message_with_string ("Loading %s (dymamic module)...", file, 1);
1439 else if (!safe_p)
1342 message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...", 1440 message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...",
1343 file, 1); 1441 file, 1);
1344 else if (!compiled) 1442 else if (!compiled)
@@ -1358,7 +1456,14 @@ Return t if the file exists and loads successfully. */)
1358 if (lisp_file_lexically_bound_p (Qget_file_char)) 1456 if (lisp_file_lexically_bound_p (Qget_file_char))
1359 Fset (Qlexical_binding, Qt); 1457 Fset (Qlexical_binding, Qt);
1360 1458
1361 if (! version || version >= 22) 1459#ifdef HAVE_LTDL
1460 if (module)
1461 {
1462 /* XXX: should the fd/stream be closed before loading the module? */
1463 Fload_module (found);
1464 }
1465#endif
1466 else if (! version || version >= 22)
1362 readevalloop (Qget_file_char, stream, hist_file_name, 1467 readevalloop (Qget_file_char, stream, hist_file_name,
1363 0, Qnil, Qnil, Qnil, Qnil); 1468 0, Qnil, Qnil, Qnil, Qnil);
1364 else 1469 else
@@ -1387,7 +1492,9 @@ Return t if the file exists and loads successfully. */)
1387 1492
1388 if (!noninteractive && (NILP (nomessage) || force_load_messages)) 1493 if (!noninteractive && (NILP (nomessage) || force_load_messages))
1389 { 1494 {
1390 if (!safe_p) 1495 if (module)
1496 message_with_string ("Loading %s (dymamic module)...done", file, 1);
1497 else if (!safe_p)
1391 message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...done", 1498 message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...done",
1392 file, 1); 1499 file, 1);
1393 else if (!compiled) 1500 else if (!compiled)
@@ -3837,9 +3944,6 @@ intern_c_string_1 (const char *str, ptrdiff_t len)
3837 3944
3838 if (!SYMBOLP (tem)) 3945 if (!SYMBOLP (tem))
3839 { 3946 {
3840 /* Creating a non-pure string from a string literal not implemented yet.
3841 We could just use make_string here and live with the extra copy. */
3842 eassert (!NILP (Vpurify_flag));
3843 tem = intern_driver (make_pure_c_string (str, len), obarray, XINT (tem)); 3947 tem = intern_driver (make_pure_c_string (str, len), obarray, XINT (tem));
3844 } 3948 }
3845 return tem; 3949 return tem;
@@ -4094,6 +4198,7 @@ void
4094defsubr (struct Lisp_Subr *sname) 4198defsubr (struct Lisp_Subr *sname)
4095{ 4199{
4096 Lisp_Object sym, tem; 4200 Lisp_Object sym, tem;
4201 sname->doc = Qnil;
4097 sym = intern_c_string (sname->symbol_name); 4202 sym = intern_c_string (sname->symbol_name);
4098 XSETPVECTYPE (sname, PVEC_SUBR); 4203 XSETPVECTYPE (sname, PVEC_SUBR);
4099 XSETSUBR (tem, sname); 4204 XSETSUBR (tem, sname);
@@ -4491,6 +4596,7 @@ syms_of_lread (void)
4491 defsubr (&Sget_file_char); 4596 defsubr (&Sget_file_char);
4492 defsubr (&Smapatoms); 4597 defsubr (&Smapatoms);
4493 defsubr (&Slocate_file_internal); 4598 defsubr (&Slocate_file_internal);
4599 defsubr (&Sload_module);
4494 4600
4495 DEFVAR_LISP ("obarray", Vobarray, 4601 DEFVAR_LISP ("obarray", Vobarray,
4496 doc: /* Symbol table for use by `intern' and `read'. 4602 doc: /* Symbol table for use by `intern' and `read'.
@@ -4551,8 +4657,22 @@ Initialized during startup as described in Info node `(elisp)Library Search'. *
4551This list should not include the empty string. 4657This list should not include the empty string.
4552`load' and related functions try to append these suffixes, in order, 4658`load' and related functions try to append these suffixes, in order,
4553to the specified file name if a Lisp suffix is allowed or required. */); 4659to the specified file name if a Lisp suffix is allowed or required. */);
4660
4554 Vload_suffixes = list2 (build_pure_c_string (".elc"), 4661 Vload_suffixes = list2 (build_pure_c_string (".elc"),
4555 build_pure_c_string (".el")); 4662 build_pure_c_string (".el"));
4663
4664 DEFVAR_LISP ("load-module-suffixes", Vload_module_suffixes,
4665 doc: /* List of suffixes for modules files.
4666This list should not include the empty string. See `load-suffixes'. */);
4667
4668#ifdef HAVE_LTDL
4669 Vload_module_suffixes = list3 (build_pure_c_string (".dll"),
4670 build_pure_c_string (".so"),
4671 build_pure_c_string (".dylib"));
4672#else
4673 Vload_module_suffixes = Qnil;
4674#endif
4675
4556 DEFVAR_LISP ("load-file-rep-suffixes", Vload_file_rep_suffixes, 4676 DEFVAR_LISP ("load-file-rep-suffixes", Vload_file_rep_suffixes,
4557 doc: /* List of suffixes that indicate representations of \ 4677 doc: /* List of suffixes that indicate representations of \
4558the same file. 4678the same file.