summaryrefslogtreecommitdiff
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)
return *read_bytecode_pointer++;
}
+/* A module doc file must have a doc extension */
+static bool
+doc_is_from_module_p (const char* path)
+{
+ int len = strlen (path);
+ return len > 4 && (strcmp (path + len - 4, ".doc") == 0
+ || (strcmp (path + len - 4, ".DOC") == 0));
+}
+
/* Extract a doc string from a file. FILEPOS says where to get it.
If it is an integer, use that position in the standard DOC file.
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)
return Qnil;
/* Put the file name in NAME as a C string.
- If it is relative, combine it with Vdoc_directory. */
+ If it is relative and not from a module, combine it with Vdoc_directory. */
tem = Ffile_name_absolute_p (file);
file = ENCODE_FILE (file);
- if (NILP (tem))
+ if (NILP (tem) && !doc_is_from_module_p (SSDATA (file)))
{
Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
minsize = SCHARS (docdir);
@@ -211,7 +220,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
SAFE_FREE ();
/* Sanity checking. */
- if (CONSP (filepos))
+ if (CONSP (filepos) && !doc_is_from_module_p (name))
{
int test = 1;
/* A dynamic docstring should be either at the very beginning of a "#@
@@ -321,7 +330,7 @@ reread_doc_file (Lisp_Object file)
#endif
if (NILP (file))
- Fsnarf_documentation (Vdoc_file_name);
+ Fsnarf_documentation (Vdoc_file_name, Qnil);
else
Fload (file, Qt, Qt, Qt, Qnil);
@@ -356,14 +365,16 @@ string is passed through `substitute-command-keys'. */)
fun = XCDR (fun);
if (SUBRP (fun))
{
- if (XSUBR (fun)->doc == 0)
- return Qnil;
- /* FIXME: This is not portable, as it assumes that string
- pointers have the top bit clear. */
- else if ((intptr_t) XSUBR (fun)->doc >= 0)
- doc = build_string (XSUBR (fun)->doc);
+ Lisp_Object subrdoc = XSUBR (fun)->doc;
+
+ if (NILP (subrdoc))
+ return Qnil;
+ else if (STRINGP (subrdoc))
+ return subrdoc;
+ else if (INTEGERP (subrdoc) || CONSP (subrdoc))
+ doc = subrdoc;
else
- doc = make_number ((intptr_t) XSUBR (fun)->doc);
+ error ("invalid value in subr doc field");
}
else if (COMPILEDP (fun))
{
@@ -495,7 +506,7 @@ aren't strings. */)
/* Scanning the DOC files and placing docstring offsets into functions. */
static void
-store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
+store_function_docstring (Lisp_Object obj, Lisp_Object filename, ptrdiff_t offset, bool module)
{
/* Don't use indirect_function here, or defaliases will apply their
docstrings to the base functions (Bug#2603). */
@@ -506,8 +517,8 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
/* Lisp_Subrs have a slot for it. */
if (SUBRP (fun))
{
- intptr_t negative_offset = - offset;
- XSUBR (fun)->doc = (char *) negative_offset;
+ Lisp_Object neg = make_number (-offset); /* XXX: no sure why.. */
+ XSUBR (fun)->doc = module ? Fcons (filename, neg) : neg;
}
/* If it's a lisp form, stick it in the form. */
@@ -526,7 +537,7 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
XSETCAR (tem, make_number (offset));
}
else if (EQ (tem, Qmacro))
- store_function_docstring (XCDR (fun), offset);
+ store_function_docstring (XCDR (fun), filename, offset, module);
}
/* Bytecode objects sometimes have slots for it. */
@@ -542,9 +553,24 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
}
}
+static bool
+build_file_p (const char* file, ptrdiff_t len)
+{
+ /* file can be longer than len, can't use xstrdup */
+ char *ofile = xmalloc (len + 1);
+ memcpy (ofile, file, len);
+ ofile[len] = 0;
+
+ if (ofile[len-1] == 'c')
+ ofile[len-1] = 'o';
+
+ bool res = NILP (Fmember (build_string (ofile), Vbuild_files));
+ xfree (ofile);
+ return res;
+}
DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation,
- 1, 1, 0,
+ 1, 2, 0,
doc: /* Used during Emacs initialization to scan the `etc/DOC...' file.
This searches the `etc/DOC...' file for doc strings and
records them in function and variable definitions.
@@ -552,7 +578,7 @@ The function takes one argument, FILENAME, a string;
it specifies the file name (without a directory) of the DOC file.
That file is found in `../etc' now; later, when the dumped Emacs is run,
the same file name is found in the `doc-directory'. */)
- (Lisp_Object filename)
+ (Lisp_Object filename, Lisp_Object module)
{
int fd;
char buf[1024 + 1];
@@ -573,22 +599,48 @@ the same file name is found in the `doc-directory'. */)
CHECK_STRING (filename);
- if
+ /* Vbuild_files is nil when temacs is run, and non-nil after that. */
+ if (NILP (Vbuild_files))
+ {
+ static char const *const buildobj[] =
+ {
+ #include "buildobj.h"
+ };
+ int i = ARRAYELTS (buildobj);
+ while (0 <= --i)
+ Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
+ Vbuild_files = Fpurecopy (Vbuild_files);
+ }
+
+ if (NILP (module))
+ {
+ /* If we're not processing a module doc, the doc file becomes
+ the "global" DOC file */
+ Vdoc_file_name = filename;
+
+ if
#ifndef CANNOT_DUMP
- (!NILP (Vpurify_flag))
+ (!NILP (Vpurify_flag))
#else /* CANNOT_DUMP */
- (0)
+ (0)
#endif /* CANNOT_DUMP */
- {
- static char const sibling_etc[] = "../etc/";
- dirname = sibling_etc;
- dirlen = sizeof sibling_etc - 1;
+ {
+ static char const sibling_etc[] = "../etc/";
+ dirname = sibling_etc;
+ dirlen = sizeof sibling_etc - 1;
+ }
+ else
+ {
+ CHECK_STRING (Vdoc_directory);
+ dirname = SSDATA (Vdoc_directory);
+ dirlen = SBYTES (Vdoc_directory);
+ }
}
else
{
- CHECK_STRING (Vdoc_directory);
- dirname = SSDATA (Vdoc_directory);
- dirlen = SBYTES (Vdoc_directory);
+ static char const empty_prefix_dir[] = "";
+ dirname = empty_prefix_dir;
+ dirlen = 0;
}
count = SPECPDL_INDEX ();
@@ -597,18 +649,6 @@ the same file name is found in the `doc-directory'. */)
strcpy (name, dirname);
strcat (name, SSDATA (filename)); /*** Add this line ***/
- /* Vbuild_files is nil when temacs is run, and non-nil after that. */
- if (NILP (Vbuild_files))
- {
- static char const *const buildobj[] =
- {
- #include "buildobj.h"
- };
- int i = ARRAYELTS (buildobj);
- while (0 <= --i)
- Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
- Vbuild_files = Fpurecopy (Vbuild_files);
- }
fd = emacs_open (name, O_RDONLY, 0);
if (fd < 0)
@@ -618,7 +658,6 @@ the same file name is found in the `doc-directory'. */)
open_errno);
}
record_unwind_protect_int (close_file_unwind, fd);
- Vdoc_file_name = filename;
filled = 0;
pos = 0;
while (1)
@@ -641,18 +680,13 @@ the same file name is found in the `doc-directory'. */)
if (p[1] == 'S')
{
skip_file = 0;
- if (end - p > 4 && end[-2] == '.'
- && (end[-1] == 'o' || end[-1] == 'c'))
+ if (NILP (module)
+ && end - p > 4
+ && end[-2] == '.'
+ && (end[-1] == 'o' || end[-1] == 'c')
+ && build_file_p (&p[2], end - p - 2))
{
- ptrdiff_t len = end - p - 2;
- char *fromfile = SAFE_ALLOCA (len + 1);
- memcpy (fromfile, &p[2], len);
- fromfile[len] = 0;
- if (fromfile[len-1] == 'c')
- fromfile[len-1] = 'o';
-
- skip_file = NILP (Fmember (build_string (fromfile),
- Vbuild_files));
+ skip_file = 1;
}
}
@@ -672,6 +706,7 @@ the same file name is found in the `doc-directory'. */)
/* Install file-position as variable-documentation property
and make it negative for a user-variable
(doc starts with a `*'). */
+ /* TODO: handle module var */
if (!NILP (Fboundp (sym))
|| !NILP (Fmemq (sym, delayed_init)))
Fput (sym, Qvariable_documentation,
@@ -683,7 +718,7 @@ the same file name is found in the `doc-directory'. */)
else if (p[1] == 'F')
{
if (!NILP (Ffboundp (sym)))
- store_function_docstring (sym, pos + end + 1 - buf);
+ store_function_docstring (sym, filename, pos + end + 1 - buf, !NILP (module));
}
else if (p[1] == 'S')
; /* Just a source file name boundary marker. Ignore it. */