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
)
61 #ifndef NO_HYPHENS_IN_FILENAMES
62 strcpy (name
, sys_translate_unix (name
));
63 #else /* NO_HYPHENS_IN_FILENAMES */
71 #endif /* NO_HYPHENS_IN_FILENAMES */
75 /* Buffer used for reading from documentation file. */
76 static char *get_doc_string_buffer
;
77 static int get_doc_string_buffer_size
;
79 static unsigned char *read_bytecode_pointer
;
81 /* readchar in lread.c calls back here to fetch the next byte.
82 If UNREADFLAG is 1, we unread a byte. */
85 read_bytecode_char (unreadflag
)
90 read_bytecode_pointer
--;
93 return *read_bytecode_pointer
++;
96 /* Extract a doc string from a file. FILEPOS says where to get it.
97 If it is an integer, use that position in the standard DOC-... file.
98 If it is (FILE . INTEGER), use FILE as the file name
99 and INTEGER as the position in that file.
100 But if INTEGER is negative, make it positive.
101 (A negative integer is used for user variables, so we can distinguish
102 them without actually fetching the doc string.)
104 If UNIBYTE is nonzero, always make a unibyte string.
106 If DEFINITION is nonzero, assume this is for reading
107 a dynamic function definition; convert the bytestring
108 and the constants vector with appropriate byte handling,
109 and return a cons cell. */
112 get_doc_string (filepos
, unibyte
, definition
)
114 int unibyte
, definition
;
119 register char *p
, *p1
;
121 int offset
, position
;
122 Lisp_Object file
, tem
;
124 if (INTEGERP (filepos
))
126 file
= Vdoc_file_name
;
127 position
= XINT (filepos
);
129 else if (CONSP (filepos
))
131 file
= XCAR (filepos
);
132 position
= XINT (XCDR (filepos
));
134 position
= - position
;
139 if (!STRINGP (Vdoc_directory
))
145 /* Put the file name in NAME as a C string.
146 If it is relative, combine it with Vdoc_directory. */
148 tem
= Ffile_name_absolute_p (file
);
151 minsize
= XSTRING (Vdoc_directory
)->size
;
152 /* sizeof ("../etc/") == 8 */
155 name
= (char *) alloca (minsize
+ XSTRING (file
)->size
+ 8);
156 strcpy (name
, XSTRING (Vdoc_directory
)->data
);
157 strcat (name
, XSTRING (file
)->data
);
158 munge_doc_file_name (name
);
162 name
= (char *) XSTRING (file
)->data
;
165 fd
= emacs_open (name
, O_RDONLY
, 0);
169 if (!NILP (Vpurify_flag
))
171 /* Preparing to dump; DOC file is probably not installed.
172 So check in ../etc. */
173 strcpy (name
, "../etc/");
174 strcat (name
, XSTRING (file
)->data
);
175 munge_doc_file_name (name
);
177 fd
= emacs_open (name
, O_RDONLY
, 0);
181 error ("Cannot open doc string file \"%s\"", name
);
184 /* Seek only to beginning of disk block. */
185 offset
= position
% (8 * 1024);
186 if (0 > lseek (fd
, position
- offset
, 0))
189 error ("Position %ld out of range in doc string file \"%s\"",
193 /* Read the doc string into get_doc_string_buffer.
194 P points beyond the data just read. */
196 p
= get_doc_string_buffer
;
199 int space_left
= (get_doc_string_buffer_size
200 - (p
- get_doc_string_buffer
));
203 /* Allocate or grow the buffer if we need to. */
206 int in_buffer
= p
- get_doc_string_buffer
;
207 get_doc_string_buffer_size
+= 16 * 1024;
208 get_doc_string_buffer
209 = (char *) xrealloc (get_doc_string_buffer
,
210 get_doc_string_buffer_size
+ 1);
211 p
= get_doc_string_buffer
+ in_buffer
;
212 space_left
= (get_doc_string_buffer_size
213 - (p
- get_doc_string_buffer
));
216 /* Read a disk block at a time.
217 If we read the same block last time, maybe skip this? */
218 if (space_left
> 1024 * 8)
219 space_left
= 1024 * 8;
220 nread
= emacs_read (fd
, p
, space_left
);
224 error ("Read error on documentation file");
229 if (p
== get_doc_string_buffer
)
230 p1
= (char *) index (p
+ offset
, '\037');
232 p1
= (char *) index (p
, '\037');
243 /* Scan the text and perform quoting with ^A (char code 1).
244 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
245 from
= get_doc_string_buffer
+ offset
;
246 to
= get_doc_string_buffer
+ offset
;
262 error ("Invalid data in documentation file -- ^A followed by code 0%o", c
);
268 /* If DEFINITION, read from this buffer
269 the same way we would read bytes from a file. */
272 read_bytecode_pointer
= get_doc_string_buffer
+ offset
;
273 return Fread (Qlambda
);
277 return make_unibyte_string (get_doc_string_buffer
+ offset
,
278 to
- (get_doc_string_buffer
+ offset
));
281 /* Let the data determine whether the string is multibyte,
282 even if Emacs is running in --unibyte mode. */
283 int nchars
= multibyte_chars_in_text (get_doc_string_buffer
+ offset
,
284 to
- (get_doc_string_buffer
+ offset
));
285 return make_string_from_bytes (get_doc_string_buffer
+ offset
,
287 to
- (get_doc_string_buffer
+ offset
));
291 /* Get a string from position FILEPOS and pass it through the Lisp reader.
292 We use this for fetching the bytecode string and constants vector
293 of a compiled function from the .elc file. */
296 read_doc_string (filepos
)
299 return get_doc_string (filepos
, 0, 1);
302 DEFUN ("documentation", Fdocumentation
, Sdocumentation
, 1, 2, 0,
303 "Return the documentation string of FUNCTION.\n\
304 Unless a non-nil second argument RAW is given, the\n\
305 string is passed through `substitute-command-keys'.")
307 Lisp_Object function
, raw
;
311 Lisp_Object tem
, doc
;
315 if (SYMBOLP (function
)
316 && (tem
= Fget (function
, Qfunction_documentation
),
318 return Fdocumentation_property (function
, Qfunction_documentation
, raw
);
320 fun
= Findirect_function (function
);
323 if (XSUBR (fun
)->doc
== 0)
325 else if ((EMACS_INT
) XSUBR (fun
)->doc
>= 0)
326 doc
= build_string (XSUBR (fun
)->doc
);
328 doc
= get_doc_string (make_number (- (EMACS_INT
) XSUBR (fun
)->doc
),
330 if (! NILP (tem
= Fassq (function
, Vhelp_manyarg_func_alist
)))
331 doc
= concat3 (doc
, build_string ("\n"), Fcdr (tem
));
333 else if (COMPILEDP (fun
))
335 if ((XVECTOR (fun
)->size
& PSEUDOVECTOR_SIZE_MASK
) <= COMPILED_DOC_STRING
)
337 tem
= XVECTOR (fun
)->contents
[COMPILED_DOC_STRING
];
340 else if (NATNUMP (tem
) || CONSP (tem
))
341 doc
= get_doc_string (tem
, 0, 0);
345 else if (STRINGP (fun
) || VECTORP (fun
))
347 return build_string ("Keyboard macro.");
349 else if (CONSP (fun
))
352 if (!SYMBOLP (funcar
))
353 return Fsignal (Qinvalid_function
, Fcons (fun
, Qnil
));
354 else if (EQ (funcar
, Qkeymap
))
355 return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
356 else if (EQ (funcar
, Qlambda
)
357 || EQ (funcar
, Qautoload
))
360 tem1
= Fcdr (Fcdr (fun
));
364 /* Handle a doc reference--but these never come last
365 in the function body, so reject them if they are last. */
366 else if ((NATNUMP (tem
) || CONSP (tem
))
367 && ! NILP (XCDR (tem1
)))
368 doc
= get_doc_string (tem
, 0, 0);
372 else if (EQ (funcar
, Qmocklisp
))
374 else if (EQ (funcar
, Qmacro
))
375 return Fdocumentation (Fcdr (fun
), raw
);
382 Fsignal (Qinvalid_function
, Fcons (fun
, Qnil
));
386 doc
= Fsubstitute_command_keys (doc
);
390 DEFUN ("documentation-property", Fdocumentation_property
,
391 Sdocumentation_property
, 2, 3, 0,
392 "Return the documentation string that is SYMBOL's PROP property.\n\
393 Third argument RAW omitted or nil means pass the result through\n\
394 `substitute-command-keys' if it is a string.\n\
396 This is differs from `get' in that it can refer to strings stored in the\n\
397 `etc/DOC' file; and that it evaluates documentation properties that\n\
400 Lisp_Object symbol
, prop
, raw
;
404 tem
= Fget (symbol
, prop
);
406 tem
= get_doc_string (XINT (tem
) > 0 ? tem
: make_number (- XINT (tem
)), 0, 0);
407 else if (CONSP (tem
) && INTEGERP (XCDR (tem
)))
408 tem
= get_doc_string (tem
, 0, 0);
409 else if (!STRINGP (tem
))
410 /* Feval protects its argument. */
413 if (NILP (raw
) && STRINGP (tem
))
414 tem
= Fsubstitute_command_keys (tem
);
418 /* Scanning the DOC files and placing docstring offsets into functions. */
421 store_function_docstring (fun
, offset
)
423 /* Use EMACS_INT because we get this from pointer subtraction. */
426 fun
= indirect_function (fun
);
428 /* The type determines where the docstring is stored. */
430 /* Lisp_Subrs have a slot for it. */
432 XSUBR (fun
)->doc
= (char *) - offset
;
434 /* If it's a lisp form, stick it in the form. */
435 else if (CONSP (fun
))
440 if (EQ (tem
, Qlambda
) || EQ (tem
, Qautoload
))
442 tem
= Fcdr (Fcdr (fun
));
443 if (CONSP (tem
) && INTEGERP (XCAR (tem
)))
444 XSETFASTINT (XCAR (tem
), offset
);
446 else if (EQ (tem
, Qmacro
))
447 store_function_docstring (XCDR (fun
), offset
);
450 /* Bytecode objects sometimes have slots for it. */
451 else if (COMPILEDP (fun
))
453 /* This bytecode object must have a slot for the
454 docstring, since we've found a docstring for it. */
455 if ((XVECTOR (fun
)->size
& PSEUDOVECTOR_SIZE_MASK
) > COMPILED_DOC_STRING
)
456 XSETFASTINT (XVECTOR (fun
)->contents
[COMPILED_DOC_STRING
], offset
);
461 DEFUN ("Snarf-documentation", Fsnarf_documentation
, Ssnarf_documentation
,
463 "Used during Emacs initialization, before dumping runnable Emacs,\n\
464 to find pointers to doc strings stored in `etc/DOC...' and\n\
465 record them in function definitions.\n\
466 One arg, FILENAME, a string which does not include a directory.\n\
467 The file is found in `../etc' now; found in the `data-directory'\n\
468 when doc strings are referred to later in the dumped Emacs.")
470 Lisp_Object filename
;
476 register char *p
, *end
;
481 if (NILP (Vpurify_flag
))
482 error ("Snarf-documentation can only be called in an undumped Emacs");
485 CHECK_STRING (filename
, 0);
488 name
= (char *) alloca (XSTRING (filename
)->size
+ 14);
489 strcpy (name
, "../etc/");
490 #else /* CANNOT_DUMP */
491 CHECK_STRING (Vdoc_directory
, 0);
492 name
= (char *) alloca (XSTRING (filename
)->size
+
493 XSTRING (Vdoc_directory
)->size
+ 1);
494 strcpy (name
, XSTRING (Vdoc_directory
)->data
);
495 #endif /* CANNOT_DUMP */
496 strcat (name
, XSTRING (filename
)->data
); /*** Add this line ***/
497 munge_doc_file_name (name
);
499 fd
= emacs_open (name
, O_RDONLY
, 0);
501 report_file_error ("Opening doc string file",
502 Fcons (build_string (name
), Qnil
));
503 Vdoc_file_name
= filename
;
509 filled
+= emacs_read (fd
, &buf
[filled
], sizeof buf
- 1 - filled
);
515 end
= buf
+ (filled
< 512 ? filled
: filled
- 128);
516 while (p
!= end
&& *p
!= '\037') p
++;
517 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
520 end
= (char *) index (p
, '\n');
521 sym
= oblookup (Vobarray
, p
+ 2,
522 multibyte_chars_in_text (p
+ 2, end
- p
- 2),
526 /* Attach a docstring to a variable? */
529 /* Install file-position as variable-documentation property
530 and make it negative for a user-variable
531 (doc starts with a `*'). */
532 Fput (sym
, Qvariable_documentation
,
533 make_number ((pos
+ end
+ 1 - buf
)
534 * (end
[1] == '*' ? -1 : 1)));
537 /* Attach a docstring to a function? */
538 else if (p
[1] == 'F')
539 store_function_docstring (sym
, pos
+ end
+ 1 - buf
);
542 error ("DOC file invalid at position %d", pos
);
547 bcopy (end
, buf
, filled
);
553 DEFUN ("substitute-command-keys", Fsubstitute_command_keys
,
554 Ssubstitute_command_keys
, 1, 1, 0,
555 "Substitute key descriptions for command names in STRING.\n\
556 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]\n\
557 replaced by either: a keystroke sequence that will invoke COMMAND,\n\
558 or \"M-x COMMAND\" if COMMAND is not on any keys.\n\
559 Substrings of the form \\=\\{MAPVAR} are replaced by summaries\n\
560 \(made by describe-bindings) of the value of MAPVAR, taken as a keymap.\n\
561 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR\n\
562 as the keymap for future \\=\\[COMMAND] substrings.\n\
563 \\=\\= quotes the following character and is discarded;\n\
564 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.")
570 register unsigned char *strp
;
571 register unsigned char *bufp
;
576 unsigned char *start
;
577 int length
, length_byte
;
579 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
586 CHECK_STRING (string
, 0);
590 GCPRO4 (string
, tem
, keymap
, name
);
592 multibyte
= STRING_MULTIBYTE (string
);
595 /* KEYMAP is either nil (which means search all the active keymaps)
596 or a specified local map (which means search just that and the
597 global map). If non-nil, it might come from Voverriding_local_map,
598 or from a \\<mapname> construct in STRING itself.. */
599 keymap
= current_kboard
->Voverriding_terminal_local_map
;
601 keymap
= Voverriding_local_map
;
603 bsize
= STRING_BYTES (XSTRING (string
));
604 bufp
= buf
= (unsigned char *) xmalloc (bsize
);
606 strp
= (unsigned char *) XSTRING (string
)->data
;
607 while (strp
< XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)))
609 if (strp
[0] == '\\' && strp
[1] == '=')
611 /* \= quotes the next character;
612 thus, to put in \[ without its special meaning, use \=\[. */
618 int maxlen
= XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)) - strp
;
620 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
624 bcopy (strp
, bufp
, len
);
630 *bufp
++ = *strp
++, nchars
++;
632 else if (strp
[0] == '\\' && strp
[1] == '[')
634 Lisp_Object firstkey
;
638 strp
+= 2; /* skip \[ */
640 start_idx
= start
- XSTRING (string
)->data
;
642 while ((strp
- (unsigned char *) XSTRING (string
)->data
643 < STRING_BYTES (XSTRING (string
)))
646 length_byte
= strp
- start
;
650 /* Save STRP in IDX. */
651 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
652 tem
= Fintern (make_string (start
, length_byte
), Qnil
);
654 /* Note the Fwhere_is_internal can GC, so we have to take
655 relocation of string contents into account. */
656 tem
= Fwhere_is_internal (tem
, keymap
, Qt
, Qnil
);
657 strp
= XSTRING (string
)->data
+ idx
;
658 start
= XSTRING (string
)->data
+ start_idx
;
660 /* Disregard menu bar bindings; it is positively annoying to
661 mention them when there's no menu bar, and it isn't terribly
662 useful even when there is a menu bar. */
665 firstkey
= Faref (tem
, make_number (0));
666 if (EQ (firstkey
, Qmenu_bar
))
670 if (NILP (tem
)) /* but not on any keys */
672 int offset
= bufp
- buf
;
673 buf
= (unsigned char *) xrealloc (buf
, bsize
+= 4);
675 bcopy ("M-x ", bufp
, 4);
679 length
= multibyte_chars_in_text (start
, length_byte
);
681 length
= length_byte
;
685 { /* function is on a key */
686 tem
= Fkey_description (tem
);
690 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
691 \<foo> just sets the keymap used for \[cmd]. */
692 else if (strp
[0] == '\\' && (strp
[1] == '{' || strp
[1] == '<'))
694 struct buffer
*oldbuf
;
698 strp
+= 2; /* skip \{ or \< */
700 start_idx
= start
- XSTRING (string
)->data
;
702 while ((strp
- (unsigned char *) XSTRING (string
)->data
703 < XSTRING (string
)->size
)
704 && *strp
!= '}' && *strp
!= '>')
707 length_byte
= strp
- start
;
708 strp
++; /* skip } or > */
710 /* Save STRP in IDX. */
711 idx
= strp
- (unsigned char *) XSTRING (string
)->data
;
713 /* Get the value of the keymap in TEM, or nil if undefined.
714 Do this while still in the user's current buffer
715 in case it is a local variable. */
716 name
= Fintern (make_string (start
, length_byte
), Qnil
);
717 tem
= Fboundp (name
);
720 tem
= Fsymbol_value (name
);
723 tem
= get_keymap (tem
, 0, 1);
724 /* Note that get_keymap can GC. */
725 strp
= XSTRING (string
)->data
+ idx
;
726 start
= XSTRING (string
)->data
+ start_idx
;
730 /* Now switch to a temp buffer. */
731 oldbuf
= current_buffer
;
732 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer
));
736 name
= Fsymbol_name (name
);
737 insert_string ("\nUses keymap \"");
738 insert_from_string (name
, 0, 0,
739 XSTRING (name
)->size
,
740 STRING_BYTES (XSTRING (name
)), 1);
741 insert_string ("\", which is not currently defined.\n");
742 if (start
[-1] == '<') keymap
= Qnil
;
744 else if (start
[-1] == '<')
747 describe_map_tree (tem
, 1, Qnil
, Qnil
, (char *)0, 1, 0, 0);
748 tem
= Fbuffer_string ();
750 set_buffer_internal (oldbuf
);
753 start
= XSTRING (tem
)->data
;
754 length
= XSTRING (tem
)->size
;
755 length_byte
= STRING_BYTES (XSTRING (tem
));
758 int offset
= bufp
- buf
;
759 buf
= (unsigned char *) xrealloc (buf
, bsize
+= length_byte
);
761 bcopy (start
, bufp
, length_byte
);
764 /* Check STRING again in case gc relocated it. */
765 strp
= (unsigned char *) XSTRING (string
)->data
+ idx
;
768 else if (! multibyte
) /* just copy other chars */
769 *bufp
++ = *strp
++, nchars
++;
773 int maxlen
= XSTRING (string
)->data
+ STRING_BYTES (XSTRING (string
)) - strp
;
775 STRING_CHAR_AND_LENGTH (strp
, maxlen
, len
);
779 bcopy (strp
, bufp
, len
);
786 if (changed
) /* don't bother if nothing substituted */
787 tem
= make_string_from_bytes (buf
, nchars
, bufp
- buf
);
791 RETURN_UNGCPRO (tem
);
797 Qfunction_documentation
= intern ("function-documentation");
798 staticpro (&Qfunction_documentation
);
800 DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name
,
801 "Name of file containing documentation strings of built-in symbols.");
802 Vdoc_file_name
= Qnil
;
803 DEFVAR_LISP ("help-manyarg-func-alist", &Vhelp_manyarg_func_alist
,
804 "Alist of primitive functions and descriptions of their arg lists.\n\
805 All special forms and primitives which effectively have &rest args\n\
806 should have an entry here so that `documentation' can provide their\n\
808 Vhelp_manyarg_func_alist
= Qnil
;
810 defsubr (&Sdocumentation
);
811 defsubr (&Sdocumentation_property
);
812 defsubr (&Ssnarf_documentation
);
813 defsubr (&Ssubstitute_command_keys
);