1 /* Record indices of function doc strings stored in a file.
2 Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 #include <sys/types.h>
25 #include <sys/file.h> /* Must be after sys/types.h for USG*/
44 #include "character.h"
49 extern char *index (const char *, int);
52 Lisp_Object Vdoc_file_name
;
54 Lisp_Object Qfunction_documentation
;
56 /* A list of files used to build this Emacs binary. */
57 static Lisp_Object Vbuild_files
;
59 extern Lisp_Object Voverriding_local_map
;
61 extern Lisp_Object Qremap
;
63 /* Buffer used for reading from documentation file. */
64 static char *get_doc_string_buffer
;
65 static int get_doc_string_buffer_size
;
67 static unsigned char *read_bytecode_pointer
;
68 Lisp_Object
Fsnarf_documentation (Lisp_Object
);
70 /* readchar in lread.c calls back here to fetch the next byte.
71 If UNREADFLAG is 1, we unread a byte. */
74 read_bytecode_char (int unreadflag
)
78 read_bytecode_pointer
--;
81 return *read_bytecode_pointer
++;
84 /* Extract a doc string from a file. FILEPOS says where to get it.
85 If it is an integer, use that position in the standard DOC-... file.
86 If it is (FILE . INTEGER), use FILE as the file name
87 and INTEGER as the position in that file.
88 But if INTEGER is negative, make it positive.
89 (A negative integer is used for user variables, so we can distinguish
90 them without actually fetching the doc string.)
92 If the location does not point to the beginning of a docstring
93 (e.g. because the file has been modified and the location is stale),
96 If UNIBYTE is nonzero, always make a unibyte string.
98 If DEFINITION is nonzero, assume this is for reading
99 a dynamic function definition; convert the bytestring
100 and the constants vector with appropriate byte handling,
101 and return a cons cell. */
104 get_doc_string (Lisp_Object filepos
, int unibyte
, int definition
)
109 register char *p
, *p1
;
111 int offset
, position
;
112 Lisp_Object file
, tem
;
114 if (INTEGERP (filepos
))
116 file
= Vdoc_file_name
;
117 position
= XINT (filepos
);
119 else if (CONSP (filepos
))
121 file
= XCAR (filepos
);
122 position
= XINT (XCDR (filepos
));
128 position
= - position
;
130 if (!STRINGP (Vdoc_directory
))
136 /* Put the file name in NAME as a C string.
137 If it is relative, combine it with Vdoc_directory. */
139 tem
= Ffile_name_absolute_p (file
);
142 minsize
= SCHARS (Vdoc_directory
);
143 /* sizeof ("../etc/") == 8 */
146 name
= (char *) alloca (minsize
+ SCHARS (file
) + 8);
147 strcpy (name
, SDATA (Vdoc_directory
));
148 strcat (name
, SDATA (file
));
152 name
= (char *) SDATA (file
);
155 fd
= emacs_open (name
, O_RDONLY
, 0);
159 if (!NILP (Vpurify_flag
))
161 /* Preparing to dump; DOC file is probably not installed.
162 So check in ../etc. */
163 strcpy (name
, "../etc/");
164 strcat (name
, SDATA (file
));
166 fd
= emacs_open (name
, O_RDONLY
, 0);
170 error ("Cannot open doc string file \"%s\"", name
);
173 /* Seek only to beginning of disk block. */
174 /* Make sure we read at least 1024 bytes before `position'
175 so we can check the leading text for consistency. */
176 offset
= min (position
, max (1024, position
% (8 * 1024)));
177 if (0 > lseek (fd
, position
- offset
, 0))
180 error ("Position %ld out of range in doc string file \"%s\"",
184 /* Read the doc string into get_doc_string_buffer.
185 P points beyond the data just read. */
187 p
= get_doc_string_buffer
;
190 int space_left
= (get_doc_string_buffer_size
191 - (p
- get_doc_string_buffer
));
194 /* Allocate or grow the buffer if we need to. */
197 int in_buffer
= p
- get_doc_string_buffer
;
198 get_doc_string_buffer_size
+= 16 * 1024;
199 get_doc_string_buffer
200 = (char *) xrealloc (get_doc_string_buffer
,
201 get_doc_string_buffer_size
+ 1);
202 p
= get_doc_string_buffer
+ in_buffer
;
203 space_left
= (get_doc_string_buffer_size
204 - (p
- get_doc_string_buffer
));
207 /* Read a disk block at a time.
208 If we read the same block last time, maybe skip this? */
209 if (space_left
> 1024 * 8)
210 space_left
= 1024 * 8;
211 nread
= emacs_read (fd
, p
, space_left
);
215 error ("Read error on documentation file");
220 if (p
== get_doc_string_buffer
)
221 p1
= (char *) index (p
+ offset
, '\037');
223 p1
= (char *) index (p
, '\037');
234 /* Sanity checking. */
238 if (get_doc_string_buffer
[offset
- test
++] != ' ')
240 while (get_doc_string_buffer
[offset
- test
] >= '0'
241 && get_doc_string_buffer
[offset
- test
] <= '9')
243 if (get_doc_string_buffer
[offset
- test
++] != '@'
244 || get_doc_string_buffer
[offset
- test
] != '#')
250 if (get_doc_string_buffer
[offset
- test
++] != '\n')
252 while (get_doc_string_buffer
[offset
- test
] > ' ')
254 if (get_doc_string_buffer
[offset
- test
] != '\037')
258 /* Scan the text and perform quoting with ^A (char code 1).
259 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
260 from
= get_doc_string_buffer
+ offset
;
261 to
= get_doc_string_buffer
+ offset
;
277 error ("Invalid data in documentation file -- ^A followed by code 0%o", c
);
283 /* If DEFINITION, read from this buffer
284 the same way we would read bytes from a file. */
287 read_bytecode_pointer
= get_doc_string_buffer
+ offset
;
288 return Fread (Qlambda
);
292 return make_unibyte_string (get_doc_string_buffer
+ offset
,
293 to
- (get_doc_string_buffer
+ offset
));
296 /* Let the data determine whether the string is multibyte,
297 even if Emacs is running in --unibyte mode. */
298 int nchars
= multibyte_chars_in_text (get_doc_string_buffer
+ offset
,
299 to
- (get_doc_string_buffer
+ offset
));
300 return make_string_from_bytes (get_doc_string_buffer
+ offset
,
302 to
- (get_doc_string_buffer
+ offset
));
306 /* Get a string from position FILEPOS and pass it through the Lisp reader.
307 We use this for fetching the bytecode string and constants vector
308 of a compiled function from the .elc file. */
311 read_doc_string (Lisp_Object filepos
)
313 return get_doc_string (filepos
, 0, 1);
317 reread_doc_file (Lisp_Object file
)
320 Lisp_Object reply
, prompt
[3];
323 prompt
[0] = build_string ("File ");
324 prompt
[1] = NILP (file
) ? Vdoc_file_name
: file
;
325 prompt
[2] = build_string (" is out of sync. Reload? ");
326 reply
= Fy_or_n_p (Fconcat (3, prompt
));
333 Fsnarf_documentation (Vdoc_file_name
);
335 Fload (file
, Qt
, Qt
, Qt
, Qnil
);
340 DEFUN ("documentation", Fdocumentation
, Sdocumentation
, 1, 2, 0,
341 doc
: /* Return the documentation string of FUNCTION.
342 Unless a non-nil second argument RAW is given, the
343 string is passed through `substitute-command-keys'. */)
344 (Lisp_Object function
, Lisp_Object raw
)
348 Lisp_Object tem
, doc
;
355 if (SYMBOLP (function
)
356 && (tem
= Fget (function
, Qfunction_documentation
),
358 return Fdocumentation_property (function
, Qfunction_documentation
, raw
);
360 fun
= Findirect_function (function
, Qnil
);
363 if (XSUBR (fun
)->doc
== 0)
365 else if ((EMACS_INT
) XSUBR (fun
)->doc
>= 0)
366 doc
= build_string (XSUBR (fun
)->doc
);
368 doc
= make_number ((EMACS_INT
) XSUBR (fun
)->doc
);
370 else if (COMPILEDP (fun
))
372 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) <= COMPILED_DOC_STRING
)
374 tem
= AREF (fun
, COMPILED_DOC_STRING
);
377 else if (NATNUMP (tem
) || CONSP (tem
))
382 else if (STRINGP (fun
) || VECTORP (fun
))
384 return build_string ("Keyboard macro.");
386 else if (CONSP (fun
))
389 if (!SYMBOLP (funcar
))
390 xsignal1 (Qinvalid_function
, fun
);
391 else if (EQ (funcar
, Qkeymap
))
392 return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
393 else if (EQ (funcar
, Qlambda
)
394 || EQ (funcar
, Qautoload
))
397 tem1
= Fcdr (Fcdr (fun
));
401 /* Handle a doc reference--but these never come last
402 in the function body, so reject them if they are last. */
403 else if ((NATNUMP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
404 && !NILP (XCDR (tem1
)))
409 else if (EQ (funcar
, Qmacro
))
410 return Fdocumentation (Fcdr (fun
), raw
);
417 xsignal1 (Qinvalid_function
, fun
);
420 /* Check for an advised function. Its doc string
421 has an `ad-advice-info' text property. */
424 Lisp_Object innerfunc
;
425 innerfunc
= Fget_text_property (make_number (0),
426 intern ("ad-advice-info"),
428 if (! NILP (innerfunc
))
429 doc
= call1 (intern ("ad-make-advised-docstring"), innerfunc
);
432 /* If DOC is 0, it's typically because of a dumped file missing
433 from the DOC file (bug in src/Makefile.in). */
434 if (EQ (doc
, make_number (0)))
436 if (INTEGERP (doc
) || CONSP (doc
))
439 tem
= get_doc_string (doc
, 0, 0);
440 if (NILP (tem
) && try_reload
)
442 /* The file is newer, we need to reset the pointers. */
443 struct gcpro gcpro1
, gcpro2
;
444 GCPRO2 (function
, raw
);
445 try_reload
= reread_doc_file (Fcar_safe (doc
));
458 doc
= Fsubstitute_command_keys (doc
);
462 DEFUN ("documentation-property", Fdocumentation_property
,
463 Sdocumentation_property
, 2, 3, 0,
464 doc
: /* Return the documentation string that is SYMBOL's PROP property.
465 Third argument RAW omitted or nil means pass the result through
466 `substitute-command-keys' if it is a string.
468 This differs from `get' in that it can refer to strings stored in the
469 `etc/DOC' file; and that it evaluates documentation properties that
471 (Lisp_Object symbol
, Lisp_Object prop
, Lisp_Object raw
)
476 documentation_property
:
478 tem
= Fget (symbol
, prop
);
479 if (EQ (tem
, make_number (0)))
481 if (INTEGERP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
483 Lisp_Object doc
= tem
;
484 tem
= get_doc_string (tem
, 0, 0);
485 if (NILP (tem
) && try_reload
)
487 /* The file is newer, we need to reset the pointers. */
488 struct gcpro gcpro1
, gcpro2
, gcpro3
;
489 GCPRO3 (symbol
, prop
, raw
);
490 try_reload
= reread_doc_file (Fcar_safe (doc
));
495 goto documentation_property
;
499 else if (!STRINGP (tem
))
500 /* Feval protects its argument. */
503 if (NILP (raw
) && STRINGP (tem
))
504 tem
= Fsubstitute_command_keys (tem
);
508 /* Scanning the DOC files and placing docstring offsets into functions. */
511 store_function_docstring (Lisp_Object fun
, EMACS_INT offset
)
512 /* Use EMACS_INT because we get offset from pointer subtraction. */
514 fun
= indirect_function (fun
);
516 /* The type determines where the docstring is stored. */
518 /* Lisp_Subrs have a slot for it. */
520 XSUBR (fun
)->doc
= (char *) - offset
;
522 /* If it's a lisp form, stick it in the form. */
523 else if (CONSP (fun
))
528 if (EQ (tem
, Qlambda
) || EQ (tem
, Qautoload
))
530 tem
= Fcdr (Fcdr (fun
));
531 if (CONSP (tem
) && INTEGERP (XCAR (tem
)))
532 XSETCAR (tem
, make_number (offset
));
534 else if (EQ (tem
, Qmacro
))
535 store_function_docstring (XCDR (fun
), offset
);
538 /* Bytecode objects sometimes have slots for it. */
539 else if (COMPILEDP (fun
))
541 /* This bytecode object must have a slot for the
542 docstring, since we've found a docstring for it. */
543 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) > COMPILED_DOC_STRING
)
544 ASET (fun
, COMPILED_DOC_STRING
, make_number (offset
));
548 static const char buildobj
[] = BUILDOBJ
;
550 DEFUN ("Snarf-documentation", Fsnarf_documentation
, Ssnarf_documentation
,
552 doc
: /* Used during Emacs initialization to scan the `etc/DOC...' file.
553 This searches the `etc/DOC...' file for doc strings and
554 records them in function and variable definitions.
555 The function takes one argument, FILENAME, a string;
556 it specifies the file name (without a directory) of the DOC file.
557 That file is found in `../etc' now; later, when the dumped Emacs is run,
558 the same file name is found in the `doc-directory'. */)
559 (Lisp_Object filename
)
565 register char *p
, *end
;
570 CHECK_STRING (filename
);
574 (!NILP (Vpurify_flag
))
575 #else /* CANNOT_DUMP */
577 #endif /* CANNOT_DUMP */
579 name
= (char *) alloca (SCHARS (filename
) + 14);
580 strcpy (name
, "../etc/");
584 CHECK_STRING (Vdoc_directory
);
585 name
= (char *) alloca (SCHARS (filename
)
586 + SCHARS (Vdoc_directory
) + 1);
587 strcpy (name
, SDATA (Vdoc_directory
));
589 strcat (name
, SDATA (filename
)); /*** Add this line ***/
591 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
592 if (NILP (Vbuild_files
))
594 const char *beg
, *end
;
596 for (beg
= buildobj
; *beg
; beg
= end
)
600 while (*beg
&& isspace (*beg
)) ++beg
;
602 for (end
= beg
; *end
&& ! isspace (*end
); ++end
)
603 if (*end
== '/') beg
= end
+1; /* skip directory part */
606 if (len
> 4 && end
[-4] == '.' && end
[-3] == 'o')
607 len
-= 2; /* Just take .o if it ends in .obj */
610 Vbuild_files
= Fcons (make_string (beg
, len
), Vbuild_files
);
612 Vbuild_files
= Fpurecopy (Vbuild_files
);
615 fd
= emacs_open (name
, O_RDONLY
, 0);
617 report_file_error ("Opening doc string file",
618 Fcons (build_string (name
), Qnil
));
619 Vdoc_file_name
= filename
;
625 filled
+= emacs_read (fd
, &buf
[filled
], sizeof buf
- 1 - filled
);
631 end
= buf
+ (filled
< 512 ? filled
: filled
- 128);
632 while (p
!= end
&& *p
!= '\037') p
++;
633 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
636 end
= (char *) index (p
, '\n');
638 /* See if this is a file name, and if it is a file in build-files. */
639 if (p
[1] == 'S' && end
- p
> 4 && end
[-2] == '.'
640 && (end
[-1] == 'o' || end
[-1] == 'c'))
642 int len
= end
- p
- 2;
643 char *fromfile
= alloca (len
+ 1);
644 strncpy (fromfile
, &p
[2], len
);
646 if (fromfile
[len
-1] == 'c')
647 fromfile
[len
-1] = 'o';
649 skip_file
= NILP (Fmember (build_string (fromfile
),
653 sym
= oblookup (Vobarray
, p
+ 2,
654 multibyte_chars_in_text (p
+ 2, end
- p
- 2),
656 /* Check skip_file so that when a function is defined several
657 times in different files (typically, once in xterm, once in
658 w32term, ...), we only pay attention to the one that
660 if (! skip_file
&& SYMBOLP (sym
))
662 /* Attach a docstring to a variable? */
665 /* Install file-position as variable-documentation property
666 and make it negative for a user-variable
667 (doc starts with a `*'). */
668 Fput (sym
, Qvariable_documentation
,
669 make_number ((pos
+ end
+ 1 - buf
)
670 * (end
[1] == '*' ? -1 : 1)));
673 /* Attach a docstring to a function? */
674 else if (p
[1] == 'F')
675 store_function_docstring (sym
, pos
+ end
+ 1 - buf
);
677 else if (p
[1] == 'S')
678 ; /* Just a source file name boundary marker. Ignore it. */
681 error ("DOC file invalid at position %d", pos
);
686 memcpy (buf
, end
, filled
);
692 DEFUN ("substitute-command-keys", Fsubstitute_command_keys
,
693 Ssubstitute_command_keys
, 1, 1, 0,
694 doc
: /* Substitute key descriptions for command names in STRING.
695 Substrings of the form \\=\\[COMMAND] replaced by either: a keystroke
696 sequence that will invoke COMMAND, or "M-x COMMAND" if COMMAND is not
698 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
699 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
700 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
701 as the keymap for future \\=\\[COMMAND] substrings.
702 \\=\\= quotes the following character and is discarded;
703 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
705 Returns original STRING if no substitutions were made. Otherwise,
706 a new string, without any text properties, is returned. */)
711 register unsigned char *strp
;
712 register unsigned char *bufp
;
717 unsigned char *start
;
718 int length
, length_byte
;
720 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
727 CHECK_STRING (string
);
731 GCPRO4 (string
, tem
, keymap
, name
);
733 multibyte
= STRING_MULTIBYTE (string
);
736 /* KEYMAP is either nil (which means search all the active keymaps)
737 or a specified local map (which means search just that and the
738 global map). If non-nil, it might come from Voverriding_local_map,
739 or from a \\<mapname> construct in STRING itself.. */
740 keymap
= current_kboard
->Voverriding_terminal_local_map
;
742 keymap
= Voverriding_local_map
;
744 bsize
= SBYTES (string
);
745 bufp
= buf
= (unsigned char *) xmalloc (bsize
);
747 strp
= SDATA (string
);
748 while (strp
< SDATA (string
) + SBYTES (string
))
750 if (strp
[0] == '\\' && strp
[1] == '=')
752 /* \= quotes the next character;
753 thus, to put in \[ without its special meaning, use \=\[. */
760 STRING_CHAR_AND_LENGTH (strp
, len
);
764 memcpy (bufp
, strp
, len
);
770 *bufp
++ = *strp
++, nchars
++;
772 else if (strp
[0] == '\\' && strp
[1] == '[')
775 int follow_remap
= 1;
778 strp
+= 2; /* skip \[ */
780 start_idx
= start
- SDATA (string
);
782 while ((strp
- SDATA (string
)
786 length_byte
= strp
- start
;
790 /* Save STRP in IDX. */
791 idx
= strp
- SDATA (string
);
792 name
= Fintern (make_string (start
, length_byte
), Qnil
);
795 tem
= Fwhere_is_internal (name
, keymap
, Qt
, Qnil
, Qnil
);
797 if (VECTORP (tem
) && XVECTOR (tem
)->size
> 1
798 && EQ (AREF (tem
, 0), Qremap
) && SYMBOLP (AREF (tem
, 1))
801 name
= AREF (tem
, 1);
806 /* Note the Fwhere_is_internal can GC, so we have to take
807 relocation of string contents into account. */
808 strp
= SDATA (string
) + idx
;
809 start
= SDATA (string
) + start_idx
;
811 if (NILP (tem
)) /* but not on any keys */
813 int offset
= bufp
- buf
;
814 buf
= (unsigned char *) xrealloc (buf
, bsize
+= 4);
816 memcpy (bufp
, "M-x ", 4);
820 length
= multibyte_chars_in_text (start
, length_byte
);
822 length
= length_byte
;
826 { /* function is on a key */
827 tem
= Fkey_description (tem
, Qnil
);
831 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
832 \<foo> just sets the keymap used for \[cmd]. */
833 else if (strp
[0] == '\\' && (strp
[1] == '{' || strp
[1] == '<'))
835 struct buffer
*oldbuf
;
837 /* This is for computing the SHADOWS arg for describe_map_tree. */
838 Lisp_Object active_maps
= Fcurrent_active_maps (Qnil
, Qnil
);
839 Lisp_Object earlier_maps
;
842 strp
+= 2; /* skip \{ or \< */
844 start_idx
= start
- SDATA (string
);
846 while ((strp
- SDATA (string
) < SBYTES (string
))
847 && *strp
!= '}' && *strp
!= '>')
850 length_byte
= strp
- start
;
851 strp
++; /* skip } or > */
853 /* Save STRP in IDX. */
854 idx
= strp
- SDATA (string
);
856 /* Get the value of the keymap in TEM, or nil if undefined.
857 Do this while still in the user's current buffer
858 in case it is a local variable. */
859 name
= Fintern (make_string (start
, length_byte
), Qnil
);
860 tem
= Fboundp (name
);
863 tem
= Fsymbol_value (name
);
866 tem
= get_keymap (tem
, 0, 1);
867 /* Note that get_keymap can GC. */
868 strp
= SDATA (string
) + idx
;
869 start
= SDATA (string
) + start_idx
;
873 /* Now switch to a temp buffer. */
874 oldbuf
= current_buffer
;
875 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer
));
879 name
= Fsymbol_name (name
);
880 insert_string ("\nUses keymap \"");
881 insert_from_string (name
, 0, 0,
884 insert_string ("\", which is not currently defined.\n");
885 if (start
[-1] == '<') keymap
= Qnil
;
887 else if (start
[-1] == '<')
891 /* Get the list of active keymaps that precede this one.
892 If this one's not active, get nil. */
893 earlier_maps
= Fcdr (Fmemq (tem
, Freverse (active_maps
)));
894 describe_map_tree (tem
, 1, Fnreverse (earlier_maps
),
895 Qnil
, (char *)0, 1, 0, 0, 1);
897 tem
= Fbuffer_string ();
899 set_buffer_internal (oldbuf
);
903 length
= SCHARS (tem
);
904 length_byte
= SBYTES (tem
);
907 int offset
= bufp
- buf
;
908 buf
= (unsigned char *) xrealloc (buf
, bsize
+= length_byte
);
910 memcpy (bufp
, start
, length_byte
);
913 /* Check STRING again in case gc relocated it. */
914 strp
= (unsigned char *) SDATA (string
) + idx
;
917 else if (! multibyte
) /* just copy other chars */
918 *bufp
++ = *strp
++, nchars
++;
923 STRING_CHAR_AND_LENGTH (strp
, len
);
927 memcpy (bufp
, strp
, len
);
934 if (changed
) /* don't bother if nothing substituted */
935 tem
= make_string_from_bytes (buf
, nchars
, bufp
- buf
);
939 RETURN_UNGCPRO (tem
);
945 Qfunction_documentation
= intern_c_string ("function-documentation");
946 staticpro (&Qfunction_documentation
);
948 DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name
,
949 doc
: /* Name of file containing documentation strings of built-in symbols. */);
950 Vdoc_file_name
= Qnil
;
952 DEFVAR_LISP ("build-files", &Vbuild_files
,
953 doc
: /* A list of files used to build this Emacs binary. */);
956 defsubr (&Sdocumentation
);
957 defsubr (&Sdocumentation_property
);
958 defsubr (&Ssnarf_documentation
);
959 defsubr (&Ssubstitute_command_keys
);
962 /* arch-tag: 56281d4d-6949-43e2-be2e-f6517de744ba
963 (do not change this comment) */