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*/
45 extern char *index
P_ ((const char *, int));
48 Lisp_Object Vdoc_file_name
, Vhelp_manyarg_func_alist
;
50 Lisp_Object Qfunction_documentation
;
52 extern Lisp_Object Voverriding_local_map
;
54 /* For VMS versions with limited file name syntax,
55 convert the name to something VMS will allow. */
57 munge_doc_file_name (name
)
62 /* For VMS versions with limited file name syntax,
63 convert the name to something VMS will allow. */
71 #endif /* not VMS4_4 */
73 strcpy (name
, sys_translate_unix (name
));
78 /* Buffer used for reading from documentation file. */
79 static char *get_doc_string_buffer
;
80 static int get_doc_string_buffer_size
;
82 static unsigned char *read_bytecode_pointer
;
84 /* readchar in lread.c calls back here to fetch the next byte.
85 If UNREADFLAG is 1, we unread a byte. */
88 read_bytecode_char (unreadflag
)
93 read_bytecode_pointer
--;
96 return *read_bytecode_pointer
++;
99 /* Extract a doc string from a file. FILEPOS says where to get it.
100 If it is an integer, use that position in the standard DOC-... file.
101 If it is (FILE . INTEGER), use FILE as the file name
102 and INTEGER as the position in that file.
103 But if INTEGER is negative, make it positive.
104 (A negative integer is used for user variables, so we can distinguish
105 them without actually fetching the doc string.)
107 If UNIBYTE is nonzero, always make a unibyte string.
109 If DEFINITION is nonzero, assume this is for reading
110 a dynamic function definition; convert the bytestring
111 and the constants vector with appropriate byte handling,
112 and return a cons cell. */
115 get_doc_string (filepos
, unibyte
, definition
)
117 int unibyte
, definition
;
122 register char *p
, *p1
;
124 int offset
, position
;
125 Lisp_Object file
, tem
;
127 if (INTEGERP (filepos
))
129 file
= Vdoc_file_name
;
130 position
= XINT (filepos
);
132 else if (CONSP (filepos
))
134 file
= XCAR (filepos
);
135 position
= XINT (XCDR (filepos
));
137 position
= - position
;
142 if (!STRINGP (Vdoc_directory
))
148 /* Put the file name in NAME as a C string.
149 If it is relative, combine it with Vdoc_directory. */
151 tem
= Ffile_name_absolute_p (file
);
154 minsize
= XSTRING (Vdoc_directory
)->size
;
155 /* sizeof ("../etc/") == 8 */
158 name
= (char *) alloca (minsize
+ XSTRING (file
)->size
+ 8);
159 strcpy (name
, XSTRING (Vdoc_directory
)->data
);
160 strcat (name
, XSTRING (file
)->data
);
161 munge_doc_file_name (name
);
165 name
= (char *) XSTRING (file
)->data
;
168 fd
= emacs_open (name
, O_RDONLY
, 0);
172 if (!NILP (Vpurify_flag
))
174 /* Preparing to dump; DOC file is probably not installed.
175 So check in ../etc. */
176 strcpy (name
, "../etc/");
177 strcat (name
, XSTRING (file
)->data
);
178 munge_doc_file_name (name
);
180 fd
= emacs_open (name
, O_RDONLY
, 0);
184 error ("Cannot open doc string file \"%s\"", name
);
187 /* Seek only to beginning of disk block. */
188 offset
= position
% (8 * 1024);
189 if (0 > lseek (fd
, position
- offset
, 0))
192 error ("Position %ld out of range in doc string file \"%s\"",
196 /* Read the doc string into get_doc_string_buffer.
197 P points beyond the data just read. */
199 p
= get_doc_string_buffer
;
202 int space_left
= (get_doc_string_buffer_size
203 - (p
- get_doc_string_buffer
));
206 /* Allocate or grow the buffer if we need to. */
209 int in_buffer
= p
- get_doc_string_buffer
;
210 get_doc_string_buffer_size
+= 16 * 1024;
211 get_doc_string_buffer
212 = (char *) xrealloc (get_doc_string_buffer
,
213 get_doc_string_buffer_size
+ 1);
214 p
= get_doc_string_buffer
+ in_buffer
;
215 space_left
= (get_doc_string_buffer_size
216 - (p
- get_doc_string_buffer
));
219 /* Read a disk block at a time.
220 If we read the same block last time, maybe skip this? */
221 if (space_left
> 1024 * 8)
222 space_left
= 1024 * 8;
223 nread
= emacs_read (fd
, p
, space_left
);
227 error ("Read error on documentation file");
232 if (p
== get_doc_string_buffer
)
233 p1
= (char *) index (p
+ offset
, '\037');
235 p1
= (char *) index (p
, '\037');
246 /* Scan the text and perform quoting with ^A (char code 1).
247 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
248 from
= get_doc_string_buffer
+ offset
;
249 to
= get_doc_string_buffer
+ offset
;
265 error ("Invalid data in documentation file -- ^A followed by code 0%o", c
);
271 /* If DEFINITION, read from this buffer
272 the same way we would read bytes from a file. */
275 read_bytecode_pointer
= get_doc_string_buffer
+ offset
;
276 return Fread (Qlambda
);
280 return make_unibyte_string (get_doc_string_buffer
+ offset
,
281 to
- (get_doc_string_buffer
+ offset
));
284 /* Let the data determine whether the string is multibyte,
285 even if Emacs is running in --unibyte mode. */
286 int nchars
= multibyte_chars_in_text (get_doc_string_buffer
+ offset
,
287 to
- (get_doc_string_buffer
+ offset
));
288 return make_string_from_bytes (get_doc_string_buffer
+ offset
,
290 to
- (get_doc_string_buffer
+ offset
));
294 /* Get a string from position FILEPOS and pass it through the Lisp reader.
295 We use this for fetching the bytecode string and constants vector
296 of a compiled function from the .elc file. */
299 read_doc_string (filepos
)
302 return get_doc_string (filepos
, 0, 1);
305 DEFUN ("documentation", Fdocumentation
, Sdocumentation
, 1, 2, 0,
306 "Return the documentation string of FUNCTION.\n\
307 Unless a non-nil second argument RAW is given, the\n\
308 string is passed through `substitute-command-keys'.")
310 Lisp_Object function
, raw
;
314 Lisp_Object tem
, doc
;
318 if (SYMBOLP (function
)
319 && (tem
= Fget (function
, Qfunction_documentation
),
321 return Fdocumentation_property (function
, Qfunction_documentation
, raw
);
323 fun
= Findirect_function (function
);
326 if (XSUBR (fun
)->doc
== 0)
328 else if ((EMACS_INT
) XSUBR (fun
)->doc
>= 0)
329 doc
= build_string (XSUBR (fun
)->doc
);
331 doc
= get_doc_string (make_number (- (EMACS_INT
) XSUBR (fun
)->doc
),
333 if (! NILP (tem
= Fassq (function
, Vhelp_manyarg_func_alist
)))
334 doc
= concat3 (doc
, build_string ("\n"), Fcdr (tem
));
336 else if (COMPILEDP (fun
))
338 if ((XVECTOR (fun
)->size
& PSEUDOVECTOR_SIZE_MASK
) <= COMPILED_DOC_STRING
)
340 tem
= XVECTOR (fun
)->contents
[COMPILED_DOC_STRING
];
343 else if (NATNUMP (tem
) || CONSP (tem
))
344 doc
= get_doc_string (tem
, 0, 0);
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
))
370 && ! NILP (XCDR (tem1
)))
371 doc
= get_doc_string (tem
, 0, 0);
375 else if (EQ (funcar
, Qmocklisp
))
377 else if (EQ (funcar
, Qmacro
))
378 return Fdocumentation (Fcdr (fun
), raw
);
385 Fsignal (Qinvalid_function
, Fcons (fun
, Qnil
));
389 doc
= Fsubstitute_command_keys (doc
);
393 DEFUN ("documentation-property", Fdocumentation_property
,
394 Sdocumentation_property
, 2, 3, 0,
395 "Return the documentation string that is SYMBOL's PROP property.\n\
396 Third argument RAW omitted or nil means pass the result through\n\
397 `substitute-command-keys' if it is a string.\n\
399 This is differs from `get' in that it can refer to strings stored in the\n\
400 `etc/DOC' file; and that it evaluates documentation properties that\n\
403 Lisp_Object symbol
, prop
, raw
;
407 tem
= Fget (symbol
, prop
);
409 tem
= get_doc_string (XINT (tem
) > 0 ? tem
: make_number (- XINT (tem
)), 0, 0);
410 else if (CONSP (tem
) && INTEGERP (XCDR (tem
)))
411 tem
= get_doc_string (tem
, 0, 0);
412 else if (!STRINGP (tem
))
413 /* Feval protects its argument. */
416 if (NILP (raw
) && STRINGP (tem
))
417 tem
= Fsubstitute_command_keys (tem
);
421 /* Scanning the DOC files and placing docstring offsets into functions. */
424 store_function_docstring (fun
, offset
)
426 /* Use EMACS_INT because we get this from pointer subtraction. */
429 fun
= indirect_function (fun
);
431 /* The type determines where the docstring is stored. */
433 /* Lisp_Subrs have a slot for it. */
435 XSUBR (fun
)->doc
= (char *) - offset
;
437 /* If it's a lisp form, stick it in the form. */
438 else if (CONSP (fun
))
443 if (EQ (tem
, Qlambda
) || EQ (tem
, Qautoload
))
445 tem
= Fcdr (Fcdr (fun
));
446 if (CONSP (tem
) && INTEGERP (XCAR (tem
)))
447 XSETFASTINT (XCAR (tem
), offset
);
449 else if (EQ (tem
, Qmacro
))
450 store_function_docstring (XCDR (fun
), offset
);
453 /* Bytecode objects sometimes have slots for it. */
454 else if (COMPILEDP (fun
))
456 /* This bytecode object must have a slot for the
457 docstring, since we've found a docstring for it. */
458 if ((XVECTOR (fun
)->size
& PSEUDOVECTOR_SIZE_MASK
) > COMPILED_DOC_STRING
)
459 XSETFASTINT (XVECTOR (fun
)->contents
[COMPILED_DOC_STRING
], offset
);
464 DEFUN ("Snarf-documentation", Fsnarf_documentation
, Ssnarf_documentation
,
466 "Used during Emacs initialization, before dumping runnable Emacs,\n\
467 to find pointers to doc strings stored in `etc/DOC...' and\n\
468 record them in function definitions.\n\
469 One arg, FILENAME, a string which does not include a directory.\n\
470 The file is found in `../etc' now; found in the `data-directory'\n\
471 when doc strings are referred to later in the dumped Emacs.")
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
, 0);
491 name
= (char *) alloca (XSTRING (filename
)->size
+ 14);
492 strcpy (name
, "../etc/");
493 #else /* CANNOT_DUMP */
494 CHECK_STRING (Vdoc_directory
, 0);
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 "Substitute key descriptions for command names in STRING.\n\
574 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]\n\
575 replaced by either: a keystroke sequence that will invoke COMMAND,\n\
576 or \"M-x COMMAND\" if COMMAND is not on any keys.\n\
577 Substrings of the form \\=\\{MAPVAR} are replaced by summaries\n\
578 \(made by describe-bindings) of the value of MAPVAR, taken as a keymap.\n\
579 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR\n\
580 as the keymap for future \\=\\[COMMAND] substrings.\n\
581 \\=\\= quotes the following character and is discarded;\n\
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
, 0);
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 \=\[. */
636 int maxlen
= XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)) - strp
;
638 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
642 bcopy (strp
, bufp
, len
);
648 *bufp
++ = *strp
++, nchars
++;
650 else if (strp
[0] == '\\' && strp
[1] == '[')
652 Lisp_Object firstkey
;
656 strp
+= 2; /* skip \[ */
658 start_idx
= start
- XSTRING (string
)->data
;
660 while ((strp
- (unsigned char *) XSTRING (string
)->data
661 < STRING_BYTES (XSTRING (string
)))
664 length_byte
= strp
- start
;
668 /* Save STRP in IDX. */
669 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
670 tem
= Fintern (make_string (start
, length_byte
), Qnil
);
672 /* Note the Fwhere_is_internal can GC, so we have to take
673 relocation of string contents into account. */
674 tem
= Fwhere_is_internal (tem
, keymap
, Qt
, Qnil
);
675 strp
= XSTRING (string
)->data
+ idx
;
676 start
= XSTRING (string
)->data
+ start_idx
;
678 /* Disregard menu bar bindings; it is positively annoying to
679 mention them when there's no menu bar, and it isn't terribly
680 useful even when there is a menu bar. */
683 firstkey
= Faref (tem
, make_number (0));
684 if (EQ (firstkey
, Qmenu_bar
))
688 if (NILP (tem
)) /* but not on any keys */
690 int offset
= bufp
- buf
;
691 buf
= (unsigned char *) xrealloc (buf
, bsize
+= 4);
693 bcopy ("M-x ", bufp
, 4);
697 length
= multibyte_chars_in_text (start
, length_byte
);
699 length
= length_byte
;
703 { /* function is on a key */
704 tem
= Fkey_description (tem
);
708 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
709 \<foo> just sets the keymap used for \[cmd]. */
710 else if (strp
[0] == '\\' && (strp
[1] == '{' || strp
[1] == '<'))
712 struct buffer
*oldbuf
;
716 strp
+= 2; /* skip \{ or \< */
718 start_idx
= start
- XSTRING (string
)->data
;
720 while ((strp
- (unsigned char *) XSTRING (string
)->data
721 < XSTRING (string
)->size
)
722 && *strp
!= '}' && *strp
!= '>')
725 length_byte
= strp
- start
;
726 strp
++; /* skip } or > */
728 /* Save STRP in IDX. */
729 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
731 /* Get the value of the keymap in TEM, or nil if undefined.
732 Do this while still in the user's current buffer
733 in case it is a local variable. */
734 name
= Fintern (make_string (start
, length_byte
), Qnil
);
735 tem
= Fboundp (name
);
738 tem
= Fsymbol_value (name
);
741 tem
= get_keymap (tem
, 0, 1);
742 /* Note that get_keymap can GC. */
743 strp
= XSTRING (string
)->data
+ idx
;
744 start
= XSTRING (string
)->data
+ start_idx
;
748 /* Now switch to a temp buffer. */
749 oldbuf
= current_buffer
;
750 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer
));
754 name
= Fsymbol_name (name
);
755 insert_string ("\nUses keymap \"");
756 insert_from_string (name
, 0, 0,
757 XSTRING (name
)->size
,
758 STRING_BYTES (XSTRING (name
)), 1);
759 insert_string ("\", which is not currently defined.\n");
760 if (start
[-1] == '<') keymap
= Qnil
;
762 else if (start
[-1] == '<')
765 describe_map_tree (tem
, 1, Qnil
, Qnil
, (char *)0, 1, 0, 0);
766 tem
= Fbuffer_string ();
768 set_buffer_internal (oldbuf
);
771 start
= XSTRING (tem
)->data
;
772 length
= XSTRING (tem
)->size
;
773 length_byte
= STRING_BYTES (XSTRING (tem
));
776 int offset
= bufp
- buf
;
777 buf
= (unsigned char *) xrealloc (buf
, bsize
+= length_byte
);
779 bcopy (start
, bufp
, length_byte
);
782 /* Check STRING again in case gc relocated it. */
783 strp
= (unsigned char *) XSTRING (string
)->data
+ idx
;
786 else if (! multibyte
) /* just copy other chars */
787 *bufp
++ = *strp
++, nchars
++;
791 int maxlen
= XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)) - strp
;
793 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
797 bcopy (strp
, bufp
, len
);
804 if (changed
) /* don't bother if nothing substituted */
805 tem
= make_string_from_bytes (buf
, nchars
, bufp
- buf
);
809 RETURN_UNGCPRO (tem
);
815 Qfunction_documentation
= intern ("function-documentation");
816 staticpro (&Qfunction_documentation
);
818 DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name
,
819 "Name of file containing documentation strings of built-in symbols.");
820 Vdoc_file_name
= Qnil
;
821 DEFVAR_LISP ("help-manyarg-func-alist", &Vhelp_manyarg_func_alist
,
822 "Alist of primitive functions and descriptions of their arg lists.\n\
823 All special forms and primitives which effectively have &rest args\n\
824 should have an entry here so that `documentation' can provide their\n\
826 Vhelp_manyarg_func_alist
= Qnil
;
828 defsubr (&Sdocumentation
);
829 defsubr (&Sdocumentation_property
);
830 defsubr (&Ssnarf_documentation
);
831 defsubr (&Ssubstitute_command_keys
);