diff options
| author | Aurélien Aptel | 2014-12-02 16:17:10 -0500 |
|---|---|---|
| committer | Ted Zlatanov | 2014-12-04 19:54:16 -0500 |
| commit | ae901ddbfff04e8b1b0d63c452a6ca3f4c81fb17 (patch) | |
| tree | b806504944c633be45255321d1203bbcc2504781 /src | |
| parent | dd601050e7db69f322eea09d99751d8e6363b153 (diff) | |
| download | emacs-old-branches/dynamic-modules-rc2.tar.gz emacs-old-branches/dynamic-modules-rc2.zip | |
Add external modulesold-branches/dynamic-modules-rc2
* 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/ChangeLog | 17 | ||||
| -rw-r--r-- | src/Makefile.in | 4 | ||||
| -rw-r--r-- | src/alloc.c | 1 | ||||
| -rw-r--r-- | src/doc.c | 139 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/lread.c | 162 |
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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-12-02 Eli Zaretskii <eliz@gnu.org> | 18 | 2014-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 | ||
| 225 | LIBZ = @LIBZ@ | 225 | LIBZ = @LIBZ@ |
| 226 | 226 | ||
| 227 | LIBLTDL = @LIBLTDL@ | ||
| 228 | |||
| 227 | XRANDR_LIBS = @XRANDR_LIBS@ | 229 | XRANDR_LIBS = @XRANDR_LIBS@ |
| 228 | XRANDR_CFLAGS = @XRANDR_CFLAGS@ | 230 | XRANDR_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 | ||
| 430 | all: emacs$(EXEEXT) $(OTHER_FILES) | 432 | all: 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: |
| @@ -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 */ | ||
| 60 | static bool | ||
| 61 | doc_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 | ||
| 497 | static void | 508 | static void |
| 498 | store_function_docstring (Lisp_Object obj, ptrdiff_t offset) | 509 | store_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 | ||
| 556 | static bool | ||
| 557 | build_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 | ||
| 546 | DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation, | 572 | DEFUN ("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. |
| 549 | This searches the `etc/DOC...' file for doc strings and | 575 | This searches the `etc/DOC...' file for doc strings and |
| 550 | records them in function and variable definitions. | 576 | records them in function and variable definitions. |
| @@ -552,7 +578,7 @@ The function takes one argument, FILENAME, a string; | |||
| 552 | it specifies the file name (without a directory) of the DOC file. | 578 | it specifies the file name (without a directory) of the DOC file. |
| 553 | That file is found in `../etc' now; later, when the dumped Emacs is run, | 579 | That file is found in `../etc' now; later, when the dumped Emacs is run, |
| 554 | the same file name is found in the `doc-directory'. */) | 580 | the 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 | ||
| 1519 | enum char_table_specials | 1519 | enum 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. */ |
| 68 | static Lisp_Object Qhash_table, Qdata; | 72 | static Lisp_Object Qhash_table, Qdata; |
| 69 | static Lisp_Object Qtest; | 73 | static Lisp_Object Qtest; |
| @@ -982,7 +986,15 @@ required. | |||
| 982 | This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) | 986 | This 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 | ||
| 1013 | DEFUN ("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. */ | ||
| 1066 | static 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. */ | ||
| 1073 | static 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 | |||
| 1001 | DEFUN ("load", Fload, Sload, 1, 5, 0, | 1093 | DEFUN ("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. |
| 1003 | First try FILE with `.elc' appended, then try with `.el', | 1095 | First 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 | |||
| 4094 | defsubr (struct Lisp_Subr *sname) | 4198 | defsubr (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'. * | |||
| 4551 | This list should not include the empty string. | 4657 | This 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, |
| 4553 | to the specified file name if a Lisp suffix is allowed or required. */); | 4659 | to 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. | ||
| 4666 | This 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 \ |
| 4558 | the same file. | 4678 | the same file. |