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
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*/
43 #include "character.h"
47 extern char *index
P_ ((const char *, int));
50 Lisp_Object Vdoc_file_name
;
52 Lisp_Object Qfunction_documentation
;
54 /* A list of files used to build this Emacs binary. */
55 static Lisp_Object Vbuild_files
;
57 extern Lisp_Object Voverriding_local_map
;
59 extern Lisp_Object Qremap
;
61 /* Buffer used for reading from documentation file. */
62 static char *get_doc_string_buffer
;
63 static int get_doc_string_buffer_size
;
65 static unsigned char *read_bytecode_pointer
;
66 Lisp_Object Fsnarf_documentation
P_ ((Lisp_Object
));
68 /* readchar in lread.c calls back here to fetch the next byte.
69 If UNREADFLAG is 1, we unread a byte. */
72 read_bytecode_char (unreadflag
)
77 read_bytecode_pointer
--;
80 return *read_bytecode_pointer
++;
83 /* Extract a doc string from a file. FILEPOS says where to get it.
84 If it is an integer, use that position in the standard DOC-... file.
85 If it is (FILE . INTEGER), use FILE as the file name
86 and INTEGER as the position in that file.
87 But if INTEGER is negative, make it positive.
88 (A negative integer is used for user variables, so we can distinguish
89 them without actually fetching the doc string.)
91 If the location does not point to the beginning of a docstring
92 (e.g. because the file has been modified and the location is stale),
95 If UNIBYTE is nonzero, always make a unibyte string.
97 If DEFINITION is nonzero, assume this is for reading
98 a dynamic function definition; convert the bytestring
99 and the constants vector with appropriate byte handling,
100 and return a cons cell. */
103 get_doc_string (filepos
, unibyte
, definition
)
105 int unibyte
, definition
;
110 register char *p
, *p1
;
112 int offset
, position
;
113 Lisp_Object file
, tem
;
115 if (INTEGERP (filepos
))
117 file
= Vdoc_file_name
;
118 position
= XINT (filepos
);
120 else if (CONSP (filepos
))
122 file
= XCAR (filepos
);
123 position
= XINT (XCDR (filepos
));
129 position
= - position
;
131 if (!STRINGP (Vdoc_directory
))
137 /* Put the file name in NAME as a C string.
138 If it is relative, combine it with Vdoc_directory. */
140 tem
= Ffile_name_absolute_p (file
);
143 minsize
= SCHARS (Vdoc_directory
);
144 /* sizeof ("../etc/") == 8 */
147 name
= (char *) alloca (minsize
+ SCHARS (file
) + 8);
148 strcpy (name
, SDATA (Vdoc_directory
));
149 strcat (name
, SDATA (file
));
153 name
= (char *) SDATA (file
);
156 fd
= emacs_open (name
, O_RDONLY
, 0);
160 if (!NILP (Vpurify_flag
))
162 /* Preparing to dump; DOC file is probably not installed.
163 So check in ../etc. */
164 strcpy (name
, "../etc/");
165 strcat (name
, SDATA (file
));
167 fd
= emacs_open (name
, O_RDONLY
, 0);
171 error ("Cannot open doc string file \"%s\"", name
);
174 /* Seek only to beginning of disk block. */
175 /* Make sure we read at least 1024 bytes before `position'
176 so we can check the leading text for consistency. */
177 offset
= min (position
, max (1024, position
% (8 * 1024)));
178 if (0 > lseek (fd
, position
- offset
, 0))
181 error ("Position %ld out of range in doc string file \"%s\"",
185 /* Read the doc string into get_doc_string_buffer.
186 P points beyond the data just read. */
188 p
= get_doc_string_buffer
;
191 int space_left
= (get_doc_string_buffer_size
192 - (p
- get_doc_string_buffer
));
195 /* Allocate or grow the buffer if we need to. */
198 int in_buffer
= p
- get_doc_string_buffer
;
199 get_doc_string_buffer_size
+= 16 * 1024;
200 get_doc_string_buffer
201 = (char *) xrealloc (get_doc_string_buffer
,
202 get_doc_string_buffer_size
+ 1);
203 p
= get_doc_string_buffer
+ in_buffer
;
204 space_left
= (get_doc_string_buffer_size
205 - (p
- get_doc_string_buffer
));
208 /* Read a disk block at a time.
209 If we read the same block last time, maybe skip this? */
210 if (space_left
> 1024 * 8)
211 space_left
= 1024 * 8;
212 nread
= emacs_read (fd
, p
, space_left
);
216 error ("Read error on documentation file");
221 if (p
== get_doc_string_buffer
)
222 p1
= (char *) index (p
+ offset
, '\037');
224 p1
= (char *) index (p
, '\037');
235 /* Sanity checking. */
239 if (get_doc_string_buffer
[offset
- test
++] != ' ')
241 while (get_doc_string_buffer
[offset
- test
] >= '0'
242 && get_doc_string_buffer
[offset
- test
] <= '9')
244 if (get_doc_string_buffer
[offset
- test
++] != '@'
245 || get_doc_string_buffer
[offset
- test
] != '#')
251 if (get_doc_string_buffer
[offset
- test
++] != '\n')
253 while (get_doc_string_buffer
[offset
- test
] > ' ')
255 if (get_doc_string_buffer
[offset
- test
] != '\037')
259 /* Scan the text and perform quoting with ^A (char code 1).
260 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
261 from
= get_doc_string_buffer
+ offset
;
262 to
= get_doc_string_buffer
+ offset
;
278 error ("Invalid data in documentation file -- ^A followed by code 0%o", c
);
284 /* If DEFINITION, read from this buffer
285 the same way we would read bytes from a file. */
288 read_bytecode_pointer
= get_doc_string_buffer
+ offset
;
289 return Fread (Qlambda
);
293 return make_unibyte_string (get_doc_string_buffer
+ offset
,
294 to
- (get_doc_string_buffer
+ offset
));
297 /* Let the data determine whether the string is multibyte,
298 even if Emacs is running in --unibyte mode. */
299 int nchars
= multibyte_chars_in_text (get_doc_string_buffer
+ offset
,
300 to
- (get_doc_string_buffer
+ offset
));
301 return make_string_from_bytes (get_doc_string_buffer
+ offset
,
303 to
- (get_doc_string_buffer
+ offset
));
307 /* Get a string from position FILEPOS and pass it through the Lisp reader.
308 We use this for fetching the bytecode string and constants vector
309 of a compiled function from the .elc file. */
312 read_doc_string (filepos
)
315 return get_doc_string (filepos
, 0, 1);
319 reread_doc_file (file
)
323 Lisp_Object reply
, prompt
[3];
326 prompt
[0] = build_string ("File ");
327 prompt
[1] = NILP (file
) ? Vdoc_file_name
: file
;
328 prompt
[2] = build_string (" is out of sync. Reload? ");
329 reply
= Fy_or_n_p (Fconcat (3, prompt
));
336 Fsnarf_documentation (Vdoc_file_name
);
338 Fload (file
, Qt
, Qt
, Qt
, Qnil
);
343 DEFUN ("documentation", Fdocumentation
, Sdocumentation
, 1, 2, 0,
344 doc
: /* Return the documentation string of FUNCTION.
345 Unless a non-nil second argument RAW is given, the
346 string is passed through `substitute-command-keys'. */)
348 Lisp_Object function
, raw
;
352 Lisp_Object tem
, doc
;
359 if (SYMBOLP (function
)
360 && (tem
= Fget (function
, Qfunction_documentation
),
362 return Fdocumentation_property (function
, Qfunction_documentation
, raw
);
364 fun
= Findirect_function (function
, Qnil
);
367 if (XSUBR (fun
)->doc
== 0)
369 else if ((EMACS_INT
) XSUBR (fun
)->doc
>= 0)
370 doc
= build_string (XSUBR (fun
)->doc
);
372 doc
= make_number ((EMACS_INT
) XSUBR (fun
)->doc
);
374 else if (COMPILEDP (fun
))
376 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) <= COMPILED_DOC_STRING
)
378 tem
= AREF (fun
, COMPILED_DOC_STRING
);
381 else if (NATNUMP (tem
) || CONSP (tem
))
386 else if (STRINGP (fun
) || VECTORP (fun
))
388 return build_string ("Keyboard macro.");
390 else if (CONSP (fun
))
393 if (!SYMBOLP (funcar
))
394 xsignal1 (Qinvalid_function
, fun
);
395 else if (EQ (funcar
, Qkeymap
))
396 return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
397 else if (EQ (funcar
, Qlambda
)
398 || EQ (funcar
, Qautoload
))
401 tem1
= Fcdr (Fcdr (fun
));
405 /* Handle a doc reference--but these never come last
406 in the function body, so reject them if they are last. */
407 else if ((NATNUMP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
408 && !NILP (XCDR (tem1
)))
413 else if (EQ (funcar
, Qmacro
))
414 return Fdocumentation (Fcdr (fun
), raw
);
421 xsignal1 (Qinvalid_function
, fun
);
424 /* Check for an advised function. Its doc string
425 has an `ad-advice-info' text property. */
428 Lisp_Object innerfunc
;
429 innerfunc
= Fget_text_property (make_number (0),
430 intern ("ad-advice-info"),
432 if (! NILP (innerfunc
))
433 doc
= call1 (intern ("ad-make-advised-docstring"), innerfunc
);
436 /* If DOC is 0, it's typically because of a dumped file missing
437 from the DOC file (bug in src/Makefile.in). */
438 if (EQ (doc
, make_number (0)))
440 if (INTEGERP (doc
) || CONSP (doc
))
443 tem
= get_doc_string (doc
, 0, 0);
444 if (NILP (tem
) && try_reload
)
446 /* The file is newer, we need to reset the pointers. */
447 struct gcpro gcpro1
, gcpro2
;
448 GCPRO2 (function
, raw
);
449 try_reload
= reread_doc_file (Fcar_safe (doc
));
462 doc
= Fsubstitute_command_keys (doc
);
466 DEFUN ("documentation-property", Fdocumentation_property
,
467 Sdocumentation_property
, 2, 3, 0,
468 doc
: /* Return the documentation string that is SYMBOL's PROP property.
469 Third argument RAW omitted or nil means pass the result through
470 `substitute-command-keys' if it is a string.
472 This differs from `get' in that it can refer to strings stored in the
473 `etc/DOC' file; and that it evaluates documentation properties that
476 Lisp_Object symbol
, prop
, raw
;
481 documentation_property
:
483 tem
= Fget (symbol
, prop
);
484 if (EQ (tem
, make_number (0)))
486 if (INTEGERP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
488 Lisp_Object doc
= tem
;
489 tem
= get_doc_string (tem
, 0, 0);
490 if (NILP (tem
) && try_reload
)
492 /* The file is newer, we need to reset the pointers. */
493 struct gcpro gcpro1
, gcpro2
, gcpro3
;
494 GCPRO3 (symbol
, prop
, raw
);
495 try_reload
= reread_doc_file (Fcar_safe (doc
));
500 goto documentation_property
;
504 else if (!STRINGP (tem
))
505 /* Feval protects its argument. */
508 if (NILP (raw
) && STRINGP (tem
))
509 tem
= Fsubstitute_command_keys (tem
);
513 /* Scanning the DOC files and placing docstring offsets into functions. */
516 store_function_docstring (fun
, offset
)
518 /* Use EMACS_INT because we get this from pointer subtraction. */
521 fun
= indirect_function (fun
);
523 /* The type determines where the docstring is stored. */
525 /* Lisp_Subrs have a slot for it. */
527 XSUBR (fun
)->doc
= (char *) - offset
;
529 /* If it's a lisp form, stick it in the form. */
530 else if (CONSP (fun
))
535 if (EQ (tem
, Qlambda
) || EQ (tem
, Qautoload
))
537 tem
= Fcdr (Fcdr (fun
));
538 if (CONSP (tem
) && INTEGERP (XCAR (tem
)))
539 XSETCARFASTINT (tem
, offset
);
541 else if (EQ (tem
, Qmacro
))
542 store_function_docstring (XCDR (fun
), offset
);
545 /* Bytecode objects sometimes have slots for it. */
546 else if (COMPILEDP (fun
))
548 /* This bytecode object must have a slot for the
549 docstring, since we've found a docstring for it. */
550 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) > COMPILED_DOC_STRING
)
551 ASET (fun
, COMPILED_DOC_STRING
, make_number (offset
));
556 DEFUN ("Snarf-documentation", Fsnarf_documentation
, Ssnarf_documentation
,
558 doc
: /* Used during Emacs initialization to scan the `etc/DOC...' file.
559 This searches the `etc/DOC...' file for doc strings and
560 records them in function and variable definitions.
561 The function takes one argument, FILENAME, a string;
562 it specifies the file name (without a directory) of the DOC file.
563 That file is found in `../etc' now; later, when the dumped Emacs is run,
564 the same file name is found in the `doc-directory'. */)
566 Lisp_Object filename
;
572 register char *p
, *end
;
577 CHECK_STRING (filename
);
581 (!NILP (Vpurify_flag
))
582 #else /* CANNOT_DUMP */
584 #endif /* CANNOT_DUMP */
586 name
= (char *) alloca (SCHARS (filename
) + 14);
587 strcpy (name
, "../etc/");
591 CHECK_STRING (Vdoc_directory
);
592 name
= (char *) alloca (SCHARS (filename
)
593 + SCHARS (Vdoc_directory
) + 1);
594 strcpy (name
, SDATA (Vdoc_directory
));
596 strcat (name
, SDATA (filename
)); /*** Add this line ***/
598 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
599 if (NILP (Vbuild_files
))
607 fd
= emacs_open ("buildobj.lst", O_RDONLY
, 0);
609 report_file_error ("Opening file buildobj.lst", Qnil
);
615 to_read
= cp_size
- 1 - filled
;
616 cp
= xrealloc (cp
, cp_size
);
617 nr_read
= emacs_read (fd
, &cp
[filled
], to_read
);
619 if (nr_read
< to_read
)
626 for (beg
= cp
; *beg
; beg
= end
)
630 while (*beg
&& isspace (*beg
)) ++beg
;
632 for (end
= beg
; *end
&& ! isspace (*end
); ++end
)
633 if (*end
== '/') beg
= end
+1; /* skip directory part */
636 if (len
> 4 && end
[-4] == '.' && end
[-3] == 'o')
637 len
-= 2; /* Just take .o if it ends in .obj */
640 Vbuild_files
= Fcons (make_string (beg
, len
), Vbuild_files
);
646 fd
= emacs_open (name
, O_RDONLY
, 0);
648 report_file_error ("Opening doc string file",
649 Fcons (build_string (name
), Qnil
));
650 Vdoc_file_name
= filename
;
656 filled
+= emacs_read (fd
, &buf
[filled
], sizeof buf
- 1 - filled
);
662 end
= buf
+ (filled
< 512 ? filled
: filled
- 128);
663 while (p
!= end
&& *p
!= '\037') p
++;
664 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
667 end
= (char *) index (p
, '\n');
669 /* See if this is a file name, and if it is a file in build-files. */
670 if (p
[1] == 'S' && end
- p
> 4 && end
[-2] == '.'
671 && (end
[-1] == 'o' || end
[-1] == 'c'))
673 int len
= end
- p
- 2;
674 char *fromfile
= alloca (len
+ 1);
675 strncpy (fromfile
, &p
[2], len
);
677 if (fromfile
[len
-1] == 'c')
678 fromfile
[len
-1] = 'o';
680 skip_file
= NILP (Fmember (build_string (fromfile
),
684 sym
= oblookup (Vobarray
, p
+ 2,
685 multibyte_chars_in_text (p
+ 2, end
- p
- 2),
687 /* Check skip_file so that when a function is defined several
688 times in different files (typically, once in xterm, once in
689 w32term, ...), we only pay attention to the one that
691 if (! skip_file
&& SYMBOLP (sym
))
693 /* Attach a docstring to a variable? */
696 /* Install file-position as variable-documentation property
697 and make it negative for a user-variable
698 (doc starts with a `*'). */
699 Fput (sym
, Qvariable_documentation
,
700 make_number ((pos
+ end
+ 1 - buf
)
701 * (end
[1] == '*' ? -1 : 1)));
704 /* Attach a docstring to a function? */
705 else if (p
[1] == 'F')
706 store_function_docstring (sym
, pos
+ end
+ 1 - buf
);
708 else if (p
[1] == 'S')
709 ; /* Just a source file name boundary marker. Ignore it. */
712 error ("DOC file invalid at position %d", pos
);
717 bcopy (end
, buf
, filled
);
723 DEFUN ("substitute-command-keys", Fsubstitute_command_keys
,
724 Ssubstitute_command_keys
, 1, 1, 0,
725 doc
: /* Substitute key descriptions for command names in STRING.
726 Substrings of the form \\=\\[COMMAND] replaced by either: a keystroke
727 sequence that will invoke COMMAND, or "M-x COMMAND" if COMMAND is not
729 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
730 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
731 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
732 as the keymap for future \\=\\[COMMAND] substrings.
733 \\=\\= quotes the following character and is discarded;
734 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
736 Returns original STRING if no substitutions were made. Otherwise,
737 a new string, without any text properties, is returned. */)
743 register unsigned char *strp
;
744 register unsigned char *bufp
;
749 unsigned char *start
;
750 int length
, length_byte
;
752 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
759 CHECK_STRING (string
);
763 GCPRO4 (string
, tem
, keymap
, name
);
765 multibyte
= STRING_MULTIBYTE (string
);
768 /* KEYMAP is either nil (which means search all the active keymaps)
769 or a specified local map (which means search just that and the
770 global map). If non-nil, it might come from Voverriding_local_map,
771 or from a \\<mapname> construct in STRING itself.. */
772 keymap
= current_kboard
->Voverriding_terminal_local_map
;
774 keymap
= Voverriding_local_map
;
776 bsize
= SBYTES (string
);
777 bufp
= buf
= (unsigned char *) xmalloc (bsize
);
779 strp
= SDATA (string
);
780 while (strp
< SDATA (string
) + SBYTES (string
))
782 if (strp
[0] == '\\' && strp
[1] == '=')
784 /* \= quotes the next character;
785 thus, to put in \[ without its special meaning, use \=\[. */
791 int maxlen
= SDATA (string
) + SBYTES (string
) - strp
;
793 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
797 bcopy (strp
, bufp
, len
);
803 *bufp
++ = *strp
++, nchars
++;
805 else if (strp
[0] == '\\' && strp
[1] == '[')
808 int follow_remap
= 1;
811 strp
+= 2; /* skip \[ */
813 start_idx
= start
- SDATA (string
);
815 while ((strp
- SDATA (string
)
819 length_byte
= strp
- start
;
823 /* Save STRP in IDX. */
824 idx
= strp
- SDATA (string
);
825 name
= Fintern (make_string (start
, length_byte
), Qnil
);
828 /* Ignore remappings unless there are no ordinary bindings. */
829 tem
= Fwhere_is_internal (name
, keymap
, Qt
, Qnil
, Qt
);
831 tem
= Fwhere_is_internal (name
, keymap
, Qt
, Qnil
, Qnil
);
833 if (VECTORP (tem
) && XVECTOR (tem
)->size
> 1
834 && EQ (AREF (tem
, 0), Qremap
) && SYMBOLP (AREF (tem
, 1))
837 name
= AREF (tem
, 1);
842 /* Note the Fwhere_is_internal can GC, so we have to take
843 relocation of string contents into account. */
844 strp
= SDATA (string
) + idx
;
845 start
= SDATA (string
) + start_idx
;
847 if (NILP (tem
)) /* but not on any keys */
849 int offset
= bufp
- buf
;
850 buf
= (unsigned char *) xrealloc (buf
, bsize
+= 4);
852 bcopy ("M-x ", bufp
, 4);
856 length
= multibyte_chars_in_text (start
, length_byte
);
858 length
= length_byte
;
862 { /* function is on a key */
863 tem
= Fkey_description (tem
, Qnil
);
867 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
868 \<foo> just sets the keymap used for \[cmd]. */
869 else if (strp
[0] == '\\' && (strp
[1] == '{' || strp
[1] == '<'))
871 struct buffer
*oldbuf
;
873 /* This is for computing the SHADOWS arg for describe_map_tree. */
874 Lisp_Object active_maps
= Fcurrent_active_maps (Qnil
, Qnil
);
875 Lisp_Object earlier_maps
;
878 strp
+= 2; /* skip \{ or \< */
880 start_idx
= start
- SDATA (string
);
882 while ((strp
- SDATA (string
) < SBYTES (string
))
883 && *strp
!= '}' && *strp
!= '>')
886 length_byte
= strp
- start
;
887 strp
++; /* skip } or > */
889 /* Save STRP in IDX. */
890 idx
= strp
- SDATA (string
);
892 /* Get the value of the keymap in TEM, or nil if undefined.
893 Do this while still in the user's current buffer
894 in case it is a local variable. */
895 name
= Fintern (make_string (start
, length_byte
), Qnil
);
896 tem
= Fboundp (name
);
899 tem
= Fsymbol_value (name
);
902 tem
= get_keymap (tem
, 0, 1);
903 /* Note that get_keymap can GC. */
904 strp
= SDATA (string
) + idx
;
905 start
= SDATA (string
) + start_idx
;
909 /* Now switch to a temp buffer. */
910 oldbuf
= current_buffer
;
911 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer
));
915 name
= Fsymbol_name (name
);
916 insert_string ("\nUses keymap \"");
917 insert_from_string (name
, 0, 0,
920 insert_string ("\", which is not currently defined.\n");
921 if (start
[-1] == '<') keymap
= Qnil
;
923 else if (start
[-1] == '<')
927 /* Get the list of active keymaps that precede this one.
928 If this one's not active, get nil. */
929 earlier_maps
= Fcdr (Fmemq (tem
, Freverse (active_maps
)));
930 describe_map_tree (tem
, 1, Fnreverse (earlier_maps
),
931 Qnil
, (char *)0, 1, 0, 0, 1);
933 tem
= Fbuffer_string ();
935 set_buffer_internal (oldbuf
);
939 length
= SCHARS (tem
);
940 length_byte
= SBYTES (tem
);
943 int offset
= bufp
- buf
;
944 buf
= (unsigned char *) xrealloc (buf
, bsize
+= length_byte
);
946 bcopy (start
, bufp
, length_byte
);
949 /* Check STRING again in case gc relocated it. */
950 strp
= (unsigned char *) SDATA (string
) + idx
;
953 else if (! multibyte
) /* just copy other chars */
954 *bufp
++ = *strp
++, nchars
++;
958 int maxlen
= SDATA (string
) + SBYTES (string
) - strp
;
960 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
964 bcopy (strp
, bufp
, len
);
971 if (changed
) /* don't bother if nothing substituted */
972 tem
= make_string_from_bytes (buf
, nchars
, bufp
- buf
);
976 RETURN_UNGCPRO (tem
);
982 Qfunction_documentation
= intern ("function-documentation");
983 staticpro (&Qfunction_documentation
);
985 DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name
,
986 doc
: /* Name of file containing documentation strings of built-in symbols. */);
987 Vdoc_file_name
= Qnil
;
989 DEFVAR_LISP ("build-files", &Vbuild_files
,
990 doc
: /* A list of files used to build this Emacs binary. */);
993 defsubr (&Sdocumentation
);
994 defsubr (&Sdocumentation_property
);
995 defsubr (&Ssnarf_documentation
);
996 defsubr (&Ssubstitute_command_keys
);
999 /* arch-tag: 56281d4d-6949-43e2-be2e-f6517de744ba
1000 (do not change this comment) */