1 /* Record indices of function doc strings stored in a file.
2 Copyright (C) 1985, 86,93,94,95,97,98,99, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 #include <sys/types.h>
25 #include <sys/file.h> /* Must be after sys/types.h for USG and BSD4_1*/
42 #include "character.h"
46 extern char *index
P_ ((const char *, int));
49 Lisp_Object Vdoc_file_name
;
51 Lisp_Object Qfunction_documentation
;
53 extern Lisp_Object Voverriding_local_map
;
55 /* For VMS versions with limited file name syntax,
56 convert the name to something VMS will allow. */
58 munge_doc_file_name (name
)
63 /* For VMS versions with limited file name syntax,
64 convert the name to something VMS will allow. */
72 #endif /* not VMS4_4 */
74 strcpy (name
, sys_translate_unix (name
));
79 /* Buffer used for reading from documentation file. */
80 static char *get_doc_string_buffer
;
81 static int get_doc_string_buffer_size
;
83 static unsigned char *read_bytecode_pointer
;
84 Lisp_Object Fsnarf_documentation
P_ ((Lisp_Object
));
86 /* readchar in lread.c calls back here to fetch the next byte.
87 If UNREADFLAG is 1, we unread a byte. */
90 read_bytecode_char (unreadflag
)
95 read_bytecode_pointer
--;
98 return *read_bytecode_pointer
++;
101 /* Extract a doc string from a file. FILEPOS says where to get it.
102 If it is an integer, use that position in the standard DOC-... file.
103 If it is (FILE . INTEGER), use FILE as the file name
104 and INTEGER as the position in that file.
105 But if INTEGER is negative, make it positive.
106 (A negative integer is used for user variables, so we can distinguish
107 them without actually fetching the doc string.)
109 If UNIBYTE is nonzero, always make a unibyte string.
111 If DEFINITION is nonzero, assume this is for reading
112 a dynamic function definition; convert the bytestring
113 and the constants vector with appropriate byte handling,
114 and return a cons cell. */
117 get_doc_string (filepos
, unibyte
, definition
)
119 int unibyte
, definition
;
124 register char *p
, *p1
;
126 int offset
, position
;
127 Lisp_Object file
, tem
;
129 if (INTEGERP (filepos
))
131 file
= Vdoc_file_name
;
132 position
= XINT (filepos
);
134 else if (CONSP (filepos
))
136 file
= XCAR (filepos
);
137 position
= XINT (XCDR (filepos
));
143 position
= - position
;
145 if (!STRINGP (Vdoc_directory
))
151 /* Put the file name in NAME as a C string.
152 If it is relative, combine it with Vdoc_directory. */
154 tem
= Ffile_name_absolute_p (file
);
157 minsize
= XSTRING (Vdoc_directory
)->size
;
158 /* sizeof ("../etc/") == 8 */
161 name
= (char *) alloca (minsize
+ XSTRING (file
)->size
+ 8);
162 strcpy (name
, XSTRING (Vdoc_directory
)->data
);
163 strcat (name
, XSTRING (file
)->data
);
164 munge_doc_file_name (name
);
168 name
= (char *) XSTRING (file
)->data
;
171 fd
= emacs_open (name
, O_RDONLY
, 0);
175 if (!NILP (Vpurify_flag
))
177 /* Preparing to dump; DOC file is probably not installed.
178 So check in ../etc. */
179 strcpy (name
, "../etc/");
180 strcat (name
, XSTRING (file
)->data
);
181 munge_doc_file_name (name
);
183 fd
= emacs_open (name
, O_RDONLY
, 0);
187 error ("Cannot open doc string file \"%s\"", name
);
190 /* Seek only to beginning of disk block. */
191 offset
= position
% (8 * 1024);
192 if (0 > lseek (fd
, position
- offset
, 0))
195 error ("Position %ld out of range in doc string file \"%s\"",
199 /* Read the doc string into get_doc_string_buffer.
200 P points beyond the data just read. */
202 p
= get_doc_string_buffer
;
205 int space_left
= (get_doc_string_buffer_size
206 - (p
- get_doc_string_buffer
));
209 /* Allocate or grow the buffer if we need to. */
212 int in_buffer
= p
- get_doc_string_buffer
;
213 get_doc_string_buffer_size
+= 16 * 1024;
214 get_doc_string_buffer
215 = (char *) xrealloc (get_doc_string_buffer
,
216 get_doc_string_buffer_size
+ 1);
217 p
= get_doc_string_buffer
+ in_buffer
;
218 space_left
= (get_doc_string_buffer_size
219 - (p
- get_doc_string_buffer
));
222 /* Read a disk block at a time.
223 If we read the same block last time, maybe skip this? */
224 if (space_left
> 1024 * 8)
225 space_left
= 1024 * 8;
226 nread
= emacs_read (fd
, p
, space_left
);
230 error ("Read error on documentation file");
235 if (p
== get_doc_string_buffer
)
236 p1
= (char *) index (p
+ offset
, '\037');
238 p1
= (char *) index (p
, '\037');
249 /* Scan the text and perform quoting with ^A (char code 1).
250 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
251 from
= get_doc_string_buffer
+ offset
;
252 to
= get_doc_string_buffer
+ offset
;
268 error ("Invalid data in documentation file -- ^A followed by code 0%o", c
);
274 /* If DEFINITION, read from this buffer
275 the same way we would read bytes from a file. */
278 read_bytecode_pointer
= get_doc_string_buffer
+ offset
;
279 return Fread (Qlambda
);
283 return make_unibyte_string (get_doc_string_buffer
+ offset
,
284 to
- (get_doc_string_buffer
+ offset
));
287 /* Let the data determine whether the string is multibyte,
288 even if Emacs is running in --unibyte mode. */
289 int nchars
= multibyte_chars_in_text (get_doc_string_buffer
+ offset
,
290 to
- (get_doc_string_buffer
+ offset
));
291 return make_string_from_bytes (get_doc_string_buffer
+ offset
,
293 to
- (get_doc_string_buffer
+ offset
));
297 /* Get a string from position FILEPOS and pass it through the Lisp reader.
298 We use this for fetching the bytecode string and constants vector
299 of a compiled function from the .elc file. */
302 read_doc_string (filepos
)
305 return get_doc_string (filepos
, 0, 1);
308 DEFUN ("documentation", Fdocumentation
, Sdocumentation
, 1, 2, 0,
309 doc
: /* Return the documentation string of FUNCTION.
310 Unless a non-nil second argument RAW is given, the
311 string is passed through `substitute-command-keys'. */)
313 Lisp_Object function
, raw
;
317 Lisp_Object tem
, doc
;
321 if (SYMBOLP (function
)
322 && (tem
= Fget (function
, Qfunction_documentation
),
324 return Fdocumentation_property (function
, Qfunction_documentation
, raw
);
326 fun
= Findirect_function (function
);
329 if (XSUBR (fun
)->doc
== 0)
331 else if ((EMACS_INT
) XSUBR (fun
)->doc
>= 0)
332 doc
= build_string (XSUBR (fun
)->doc
);
334 doc
= make_number ((EMACS_INT
) XSUBR (fun
)->doc
);
336 else if (COMPILEDP (fun
))
338 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) <= COMPILED_DOC_STRING
)
340 tem
= AREF (fun
, COMPILED_DOC_STRING
);
343 else if (NATNUMP (tem
) || CONSP (tem
))
348 else if (STRINGP (fun
) || VECTORP (fun
))
350 return build_string ("Keyboard macro.");
352 else if (CONSP (fun
))
355 if (!SYMBOLP (funcar
))
356 return Fsignal (Qinvalid_function
, Fcons (fun
, Qnil
));
357 else if (EQ (funcar
, Qkeymap
))
358 return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
359 else if (EQ (funcar
, Qlambda
)
360 || EQ (funcar
, Qautoload
))
363 tem1
= Fcdr (Fcdr (fun
));
367 /* Handle a doc reference--but these never come last
368 in the function body, so reject them if they are last. */
369 else if ((NATNUMP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
370 && !NILP (XCDR (tem1
)))
375 else if (EQ (funcar
, Qmacro
))
376 return Fdocumentation (Fcdr (fun
), raw
);
383 Fsignal (Qinvalid_function
, Fcons (fun
, Qnil
));
386 if (INTEGERP (doc
) || CONSP (doc
))
387 doc
= get_doc_string (doc
, 0, 0);
390 doc
= Fsubstitute_command_keys (doc
);
394 DEFUN ("documentation-property", Fdocumentation_property
,
395 Sdocumentation_property
, 2, 3, 0,
396 doc
: /* Return the documentation string that is SYMBOL's PROP property.
397 Third argument RAW omitted or nil means pass the result through
398 `substitute-command-keys' if it is a string.
400 This differs from `get' in that it can refer to strings stored in the
401 `etc/DOC' file; and that it evaluates documentation properties that
404 Lisp_Object symbol
, prop
, raw
;
408 tem
= Fget (symbol
, prop
);
409 if (INTEGERP (tem
) || (CONSP (tem
) && INTEGERP (XCDR (tem
))))
410 tem
= get_doc_string (tem
, 0, 0);
411 else if (!STRINGP (tem
))
412 /* Feval protects its argument. */
415 if (NILP (raw
) && STRINGP (tem
))
416 tem
= Fsubstitute_command_keys (tem
);
420 /* Scanning the DOC files and placing docstring offsets into functions. */
423 store_function_docstring (fun
, offset
)
425 /* Use EMACS_INT because we get this from pointer subtraction. */
428 fun
= indirect_function (fun
);
430 /* The type determines where the docstring is stored. */
432 /* Lisp_Subrs have a slot for it. */
434 XSUBR (fun
)->doc
= (char *) - offset
;
436 /* If it's a lisp form, stick it in the form. */
437 else if (CONSP (fun
))
442 if (EQ (tem
, Qlambda
) || EQ (tem
, Qautoload
))
444 tem
= Fcdr (Fcdr (fun
));
445 if (CONSP (tem
) && INTEGERP (XCAR (tem
)))
446 XSETCARFASTINT (tem
, offset
);
448 else if (EQ (tem
, Qmacro
))
449 store_function_docstring (XCDR (fun
), offset
);
452 /* Bytecode objects sometimes have slots for it. */
453 else if (COMPILEDP (fun
))
455 /* This bytecode object must have a slot for the
456 docstring, since we've found a docstring for it. */
457 if ((ASIZE (fun
) & PSEUDOVECTOR_SIZE_MASK
) > COMPILED_DOC_STRING
)
458 XSETFASTINT (AREF (fun
, COMPILED_DOC_STRING
), offset
);
463 DEFUN ("Snarf-documentation", Fsnarf_documentation
, Ssnarf_documentation
,
465 doc
: /* Used during Emacs initialization to scan the `etc/DOC...' file.
466 This searches the `etc/DOC...' file for doc strings and
467 records them in function and variable definitions.
468 The function takes one argument, FILENAME, a string;
469 it specifies the file name (without a directory) of the DOC file.
470 That file is found in `../etc' now; later, when the dumped Emacs is run,
471 the same file name is found in the `data-directory'. */)
473 Lisp_Object filename
;
479 register char *p
, *end
;
484 if (NILP (Vpurify_flag
))
485 error ("Snarf-documentation can only be called in an undumped Emacs");
488 CHECK_STRING (filename
);
491 name
= (char *) alloca (XSTRING (filename
)->size
+ 14);
492 strcpy (name
, "../etc/");
493 #else /* CANNOT_DUMP */
494 CHECK_STRING (Vdoc_directory
);
495 name
= (char *) alloca (XSTRING (filename
)->size
496 + XSTRING (Vdoc_directory
)->size
+ 1);
497 strcpy (name
, XSTRING (Vdoc_directory
)->data
);
498 #endif /* CANNOT_DUMP */
499 strcat (name
, XSTRING (filename
)->data
); /*** Add this line ***/
502 /* For VMS versions with limited file name syntax,
503 convert the name to something VMS will allow. */
511 #endif /* not VMS4_4 */
513 strcpy (name
, sys_translate_unix (name
));
517 fd
= emacs_open (name
, O_RDONLY
, 0);
519 report_file_error ("Opening doc string file",
520 Fcons (build_string (name
), Qnil
));
521 Vdoc_file_name
= filename
;
527 filled
+= emacs_read (fd
, &buf
[filled
], sizeof buf
- 1 - filled
);
533 end
= buf
+ (filled
< 512 ? filled
: filled
- 128);
534 while (p
!= end
&& *p
!= '\037') p
++;
535 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
538 end
= (char *) index (p
, '\n');
539 sym
= oblookup (Vobarray
, p
+ 2,
540 multibyte_chars_in_text (p
+ 2, end
- p
- 2),
544 /* Attach a docstring to a variable? */
547 /* Install file-position as variable-documentation property
548 and make it negative for a user-variable
549 (doc starts with a `*'). */
550 Fput (sym
, Qvariable_documentation
,
551 make_number ((pos
+ end
+ 1 - buf
)
552 * (end
[1] == '*' ? -1 : 1)));
555 /* Attach a docstring to a function? */
556 else if (p
[1] == 'F')
557 store_function_docstring (sym
, pos
+ end
+ 1 - buf
);
560 error ("DOC file invalid at position %d", pos
);
565 bcopy (end
, buf
, filled
);
571 DEFUN ("substitute-command-keys", Fsubstitute_command_keys
,
572 Ssubstitute_command_keys
, 1, 1, 0,
573 doc
: /* Substitute key descriptions for command names in STRING.
574 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]
575 replaced by either: a keystroke sequence that will invoke COMMAND,
576 or "M-x COMMAND" if COMMAND is not on any keys.
577 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
578 \(made by describe-bindings) of the value of MAPVAR, taken as a keymap.
579 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
580 as the keymap for future \\=\\[COMMAND] substrings.
581 \\=\\= quotes the following character and is discarded;
582 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output. */)
588 register unsigned char *strp
;
589 register unsigned char *bufp
;
594 unsigned char *start
;
595 int length
, length_byte
;
597 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
604 CHECK_STRING (string
);
608 GCPRO4 (string
, tem
, keymap
, name
);
610 multibyte
= STRING_MULTIBYTE (string
);
613 /* KEYMAP is either nil (which means search all the active keymaps)
614 or a specified local map (which means search just that and the
615 global map). If non-nil, it might come from Voverriding_local_map,
616 or from a \\<mapname> construct in STRING itself.. */
617 keymap
= current_kboard
->Voverriding_terminal_local_map
;
619 keymap
= Voverriding_local_map
;
621 bsize
= STRING_BYTES (XSTRING (string
));
622 bufp
= buf
= (unsigned char *) xmalloc (bsize
);
624 strp
= (unsigned char *) XSTRING (string
)->data
;
625 while (strp
< XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)))
627 if (strp
[0] == '\\' && strp
[1] == '=')
629 /* \= quotes the next character;
630 thus, to put in \[ without its special meaning, use \=\[. */
637 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
641 bcopy (strp
, bufp
, len
);
647 *bufp
++ = *strp
++, nchars
++;
649 else if (strp
[0] == '\\' && strp
[1] == '[')
651 Lisp_Object firstkey
;
655 strp
+= 2; /* skip \[ */
657 start_idx
= start
- XSTRING (string
)->data
;
659 while ((strp
- (unsigned char *) XSTRING (string
)->data
660 < STRING_BYTES (XSTRING (string
)))
663 length_byte
= strp
- start
;
667 /* Save STRP in IDX. */
668 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
669 tem
= Fintern (make_string (start
, length_byte
), Qnil
);
671 /* Note the Fwhere_is_internal can GC, so we have to take
672 relocation of string contents into account. */
673 tem
= Fwhere_is_internal (tem
, keymap
, Qt
, Qnil
, Qnil
);
674 strp
= XSTRING (string
)->data
+ idx
;
675 start
= XSTRING (string
)->data
+ start_idx
;
677 /* Disregard menu bar bindings; it is positively annoying to
678 mention them when there's no menu bar, and it isn't terribly
679 useful even when there is a menu bar. */
682 firstkey
= Faref (tem
, make_number (0));
683 if (EQ (firstkey
, Qmenu_bar
))
687 if (NILP (tem
)) /* but not on any keys */
689 int offset
= bufp
- buf
;
690 buf
= (unsigned char *) xrealloc (buf
, bsize
+= 4);
692 bcopy ("M-x ", bufp
, 4);
696 length
= multibyte_chars_in_text (start
, length_byte
);
698 length
= length_byte
;
702 { /* function is on a key */
703 tem
= Fkey_description (tem
);
707 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
708 \<foo> just sets the keymap used for \[cmd]. */
709 else if (strp
[0] == '\\' && (strp
[1] == '{' || strp
[1] == '<'))
711 struct buffer
*oldbuf
;
715 strp
+= 2; /* skip \{ or \< */
717 start_idx
= start
- XSTRING (string
)->data
;
719 while ((strp
- (unsigned char *) XSTRING (string
)->data
720 < XSTRING (string
)->size
)
721 && *strp
!= '}' && *strp
!= '>')
724 length_byte
= strp
- start
;
725 strp
++; /* skip } or > */
727 /* Save STRP in IDX. */
728 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
730 /* Get the value of the keymap in TEM, or nil if undefined.
731 Do this while still in the user's current buffer
732 in case it is a local variable. */
733 name
= Fintern (make_string (start
, length_byte
), Qnil
);
734 tem
= Fboundp (name
);
737 tem
= Fsymbol_value (name
);
740 tem
= get_keymap (tem
, 0, 1);
741 /* Note that get_keymap can GC. */
742 strp
= XSTRING (string
)->data
+ idx
;
743 start
= XSTRING (string
)->data
+ start_idx
;
747 /* Now switch to a temp buffer. */
748 oldbuf
= current_buffer
;
749 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer
));
753 name
= Fsymbol_name (name
);
754 insert_string ("\nUses keymap \"");
755 insert_from_string (name
, 0, 0,
756 XSTRING (name
)->size
,
757 STRING_BYTES (XSTRING (name
)), 1);
758 insert_string ("\", which is not currently defined.\n");
759 if (start
[-1] == '<') keymap
= Qnil
;
761 else if (start
[-1] == '<')
764 describe_map_tree (tem
, 1, Qnil
, Qnil
, (char *)0, 1, 0, 0);
765 tem
= Fbuffer_string ();
767 set_buffer_internal (oldbuf
);
770 start
= XSTRING (tem
)->data
;
771 length
= XSTRING (tem
)->size
;
772 length_byte
= STRING_BYTES (XSTRING (tem
));
775 int offset
= bufp
- buf
;
776 buf
= (unsigned char *) xrealloc (buf
, bsize
+= length_byte
);
778 bcopy (start
, bufp
, length_byte
);
781 /* Check STRING again in case gc relocated it. */
782 strp
= (unsigned char *) XSTRING (string
)->data
+ idx
;
785 else if (! multibyte
) /* just copy other chars */
786 *bufp
++ = *strp
++, nchars
++;
791 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
795 bcopy (strp
, bufp
, len
);
802 if (changed
) /* don't bother if nothing substituted */
803 tem
= make_string_from_bytes (buf
, nchars
, bufp
- buf
);
807 RETURN_UNGCPRO (tem
);
813 Qfunction_documentation
= intern ("function-documentation");
814 staticpro (&Qfunction_documentation
);
816 DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name
,
817 doc
: /* Name of file containing documentation strings of built-in symbols. */);
818 Vdoc_file_name
= Qnil
;
820 defsubr (&Sdocumentation
);
821 defsubr (&Sdocumentation_property
);
822 defsubr (&Ssnarf_documentation
);
823 defsubr (&Ssubstitute_command_keys
);