aboutsummaryrefslogtreecommitdiffstats
path: root/src/doc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc.c')
-rw-r--r--src/doc.c139
1 files changed, 87 insertions, 52 deletions
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. */