1 /* Record indices of function doc strings stored in a file.
2 Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995
3 Free Software Foundation, Inc.
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: FSF 19.30. */
24 /* This file has been Mule-ized except as noted. */
35 Lisp_Object Vinternal_doc_file_name;
37 Lisp_Object QSsubstitute;
39 /* Read and return doc string from open file descriptor FD
40 at position POSITION. Does not close the file. Returns
41 string; or if error, returns a cons holding the error
42 data to pass to Fsignal. NAME_NONRELOC and NAME_RELOC
43 are only used for the error messages. */
46 unparesseuxify_doc_string (int fd, EMACS_INT position,
47 char *name_nonreloc, Lisp_Object name_reloc)
49 char buf[512 * 32 + 1];
51 int buffer_size = sizeof (buf);
53 REGISTER char *p = buffer;
54 Lisp_Object return_me;
56 if (0 > lseek (fd, position, 0))
59 name_reloc = build_string (name_nonreloc);
60 return_me = list3 (build_string
61 ("Position out of range in doc string file"),
62 name_reloc, make_int (position));
66 /* Read the doc string into a buffer.
67 Use the fixed buffer BUF if it is big enough; otherwise allocate one.
68 We store the buffer in use in BUFFER and its size in BUFFER_SIZE. */
72 int space_left = buffer_size - (p - buffer);
75 /* Switch to a bigger buffer if we need one. */
78 char * old_buffer = buffer;
80 buffer = (char *) xmalloc (buffer_size *= 2);
81 memcpy (buffer, old_buffer, p - old_buffer);
83 buffer = (char *) xrealloc (buffer, buffer_size *= 2);
85 p += buffer - old_buffer;
86 space_left = buffer_size - (p - buffer);
89 /* Don't read too much at one go. */
90 if (space_left > 1024 * 8)
91 space_left = 1024 * 8;
92 nread = read (fd, p, space_left);
95 return_me = list1 (build_string
96 ("Read error on documentation file"));
103 char *p1 = strchr (p, '\037'); /* End of doc string marker */
114 /* Scan the text and remove quoting with ^A (char code 1).
115 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
119 if (*from != 1 /*^A*/)
128 case 1: *to++ = c; break;
129 case '0': *to++ = '\0'; break;
130 case '_': *to++ = '\037'; break;
132 return_me = list2 (build_string
133 ("Invalid data in documentation file -- ^A followed by weird code"),
140 /* #### mrb: following STILL completely broken */
141 return_me = make_ext_string (buffer, to - buffer, Qbinary);
144 if (buffer != buf) /* We must have allocated buffer above */
149 #define string_join(dest, s1, s2) \
150 memcpy ((void *) dest, (void *) XSTRING_DATA (s1), XSTRING_LENGTH (s1)); \
151 memcpy ((void *) ((Bufbyte *) dest + XSTRING_LENGTH (s1)), \
152 (void *) XSTRING_DATA (s2), XSTRING_LENGTH (s2)); \
153 dest[XSTRING_LENGTH (s1) + XSTRING_LENGTH (s2)] = '\0'
155 /* Extract a doc string from a file. FILEPOS says where to get it.
156 (This could actually be byte code instructions/constants instead
158 If it is an integer, use that position in the standard DOC file.
159 If it is (FILE . INTEGER), use FILE as the file name
160 and INTEGER as the position in that file.
161 But if INTEGER is negative, make it positive.
162 (A negative integer is used for user variables, so we can distinguish
163 them without actually fetching the doc string.) */
166 get_doc_string (Lisp_Object filepos)
168 /* !!#### This function has not been Mule-ized */
170 REGISTER char *name_nonreloc = 0;
172 Lisp_Object file, tem;
173 Lisp_Object name_reloc = Qnil;
177 file = Vinternal_doc_file_name;
178 position = XINT (filepos);
180 else if (CONSP (filepos) && INTP (XCDR (filepos)))
182 file = XCAR (filepos);
183 position = XINT (XCDR (filepos));
185 position = - position;
193 /* Put the file name in NAME as a C string.
194 If it is relative, combine it with Vdoc_directory. */
196 tem = Ffile_name_absolute_p (file);
200 /* XEmacs: Move this check here. OK if called during loadup to
201 load byte code instructions. */
202 if (!STRINGP (Vdoc_directory))
205 minsize = XSTRING_LENGTH (Vdoc_directory);
206 /* sizeof ("../lib-src/") == 12 */
209 name_nonreloc = (char *) alloca (minsize + XSTRING_LENGTH (file) + 8);
210 string_join (name_nonreloc, Vdoc_directory, file);
215 fd = open (name_nonreloc ? name_nonreloc :
216 (char *) XSTRING_DATA (name_reloc), O_RDONLY | OPEN_BINARY, 0);
222 /* sizeof ("../lib-src/") == 12 */
223 name_nonreloc = (char *) alloca (12 + XSTRING_LENGTH (file) + 8);
224 /* Preparing to dump; DOC file is probably not installed.
225 So check in ../lib-src. */
226 strcpy (name_nonreloc, "../lib-src/");
227 strcat (name_nonreloc, (char *) XSTRING_DATA (file));
229 fd = open (name_nonreloc, O_RDONLY | OPEN_BINARY, 0);
231 #endif /* CANNOT_DUMP */
234 error ("Cannot open doc string file \"%s\"",
235 name_nonreloc ? name_nonreloc :
236 (char *) XSTRING_DATA (name_reloc));
239 tem = unparesseuxify_doc_string (fd, position, name_nonreloc, name_reloc);
243 signal_error (Qerror, tem);
248 /* Get a string from position FILEPOS and pass it through the Lisp reader.
249 We use this for fetching the bytecode string and constants vector
250 of a compiled function from the .elc file. */
253 read_doc_string (Lisp_Object filepos)
255 Lisp_Object string = get_doc_string (filepos);
257 if (!STRINGP (string))
258 signal_simple_error ("loading bytecode failed to return string", string);
259 return Fread (string);
262 DEFUN ("documentation", Fdocumentation, 1, 2, 0, /*
263 Return the documentation string of FUNCTION.
264 Unless a non-nil second argument RAW is given, the
265 string is passed through `substitute-command-keys'.
269 /* This function can GC */
273 fun = Findirect_function (function);
277 if (XSUBR (fun)->doc == 0)
279 if ((EMACS_INT) XSUBR (fun)->doc >= 0)
280 doc = build_string (XSUBR (fun)->doc);
282 doc = get_doc_string (make_int (- (EMACS_INT) XSUBR (fun)->doc));
284 else if (COMPILED_FUNCTIONP (fun))
287 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
288 if (! (f->flags.documentationp))
290 tem = compiled_function_documentation (f);
293 else if (NATNUMP (tem) || CONSP (tem))
294 doc = get_doc_string (tem);
298 else if (KEYMAPP (fun))
299 return build_translated_string ("Prefix command (definition is a keymap of subcommands).");
300 else if (STRINGP (fun) || VECTORP (fun))
301 return build_translated_string ("Keyboard macro.");
302 else if (CONSP (fun))
304 Lisp_Object funcar = Fcar (fun);
306 if (!SYMBOLP (funcar))
307 return Fsignal (Qinvalid_function, list1 (fun));
308 else if (EQ (funcar, Qlambda)
309 || EQ (funcar, Qautoload))
311 Lisp_Object tem, tem1;
312 tem1 = Fcdr (Fcdr (fun));
316 /* Handle a doc reference--but these never come last
317 in the function body, so reject them if they are last. */
318 else if ((NATNUMP (tem) || CONSP (tem))
319 && ! NILP (XCDR (tem1)))
320 doc = get_doc_string (tem);
324 else if (EQ (funcar, Qmacro))
325 return Fdocumentation (Fcdr (fun), raw);
332 return Fsignal (Qinvalid_function, list1 (fun));
339 Lisp_Object domain = Qnil;
340 if (COMPILED_FUNCTIONP (fun))
341 domain = compiled_function_domain (XCOMPILED_FUNCTION (fun));
343 doc = Fgettext (doc);
345 doc = Fdgettext (domain, doc);
349 doc = Fsubstitute_command_keys (doc);
355 DEFUN ("documentation-property", Fdocumentation_property, 2, 3, 0, /*
356 Return the documentation string that is SYMBOL's PROP property.
357 This is like `get', but it can refer to strings stored in the
358 `doc-directory/DOC' file; and if the value is a string, it is passed
359 through `substitute-command-keys'. A non-nil third argument avoids this
364 /* This function can GC */
365 REGISTER Lisp_Object doc = Qnil;
367 REGISTER Lisp_Object domain;
373 doc = Fget (symbol, prop, Qnil);
375 doc = get_doc_string (XINT (doc) > 0 ? doc : make_int (- XINT (doc)));
376 else if (CONSP (doc))
377 doc = get_doc_string (doc);
381 domain = Fget (symbol, Qvariable_domain, Qnil);
383 doc = Fgettext (doc);
385 doc = Fdgettext (domain, doc);
388 if (NILP (raw) && STRINGP (doc))
389 doc = Fsubstitute_command_keys (doc);
395 weird_doc (Lisp_Object sym, const char *weirdness, const char *type, int pos)
397 if (!strcmp (weirdness, GETTEXT ("duplicate"))) return;
398 message ("Note: Strange doc (%s) for %s %s @ %d",
399 weirdness, type, string_data (XSYMBOL (sym)->name), pos);
403 DEFUN ("Snarf-documentation", Fsnarf_documentation, 1, 1, 0, /*
404 Used during Emacs initialization, before dumping runnable Emacs,
405 to find pointers to doc strings stored in `.../lib-src/DOC' and
406 record them in function definitions.
407 One arg, FILENAME, a string which does not include a directory.
408 The file is written to `../lib-src', and later found in `exec-directory'
409 when doc strings are referred to in the dumped Emacs.
413 /* !!#### This function has not been Mule-ized */
418 REGISTER char *p, *end;
419 Lisp_Object sym, fun, tem;
424 error ("Snarf-documentation can only be called in an undumped Emacs");
427 CHECK_STRING (filename);
430 if (!NILP(Vdoc_directory))
432 CHECK_STRING (Vdoc_directory);
433 name = (char *) alloca (XSTRING_LENGTH (filename)
434 + XSTRING_LENGTH (Vdoc_directory)
436 strcpy (name, (char *) XSTRING_DATA (Vdoc_directory));
439 #endif /* CANNOT_DUMP */
441 name = (char *) alloca (XSTRING_LENGTH (filename) + 14);
442 strcpy (name, "../lib-src/");
445 strcat (name, (char *) XSTRING_DATA (filename));
447 fd = open (name, O_RDONLY | OPEN_BINARY, 0);
449 report_file_error ("Opening doc string file",
450 Fcons (build_string (name), Qnil));
451 Vinternal_doc_file_name = filename;
457 filled += read (fd, &buf[filled], sizeof buf - 1 - filled);
463 end = buf + (filled < 512 ? filled : filled - 128);
464 while (p != end && *p != '\037') p++;
465 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
468 end = strchr (p, '\n');
469 sym = oblookup (Vobarray, (Bufbyte *) p + 2, end - p - 2);
472 Lisp_Object offset = make_int (pos + end + 1 - buf);
473 /* Attach a docstring to a variable */
476 /* Install file-position as variable-documentation property
477 and make it negative for a user-variable
478 (doc starts with a `*'). */
479 Lisp_Object old = Fget (sym, Qvariable_documentation, Qzero);
482 weird_doc (sym, GETTEXT ("duplicate"),
483 GETTEXT ("variable"), pos);
484 /* In the case of duplicate doc file entries, always
485 take the later one. But if the doc is not an int
486 (a string, say) leave it alone. */
490 Fput (sym, Qvariable_documentation,
492 ? make_int (- XINT (offset))
495 /* Attach a docstring to a function.
496 The type determines where the docstring is stored. */
497 else if (p[1] == 'F')
499 fun = indirect_function (sym,0);
501 if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
506 /* May have been #if'ed out or something */
507 weird_doc (sym, GETTEXT ("not fboundp"),
508 GETTEXT ("function"), pos);
511 else if (SUBRP (fun))
513 /* Lisp_Subrs have a slot for it. */
514 if (XSUBR (fun)->doc)
516 weird_doc (sym, GETTEXT ("duplicate"),
517 GETTEXT ("subr"), pos);
520 XSUBR (fun)->doc = (char *) (- XINT (offset));
522 else if (CONSP (fun))
524 /* If it's a lisp form, stick it in the form. */
526 if (EQ (tem, Qlambda) || EQ (tem, Qautoload))
528 tem = Fcdr (Fcdr (fun));
532 Lisp_Object old = XCAR (tem);
535 weird_doc (sym, GETTEXT ("duplicate"),
538 : GETTEXT ("autoload")),
540 /* In the case of duplicate doc file entries,
541 always take the later one. But if the doc
542 is not an int (a string, say) leave it
549 else if (!CONSP (tem))
551 weird_doc (sym, GETTEXT ("!CONSP(tem)"),
552 GETTEXT ("function"), pos);
557 /* DOC string is a string not integer 0 */
559 weird_doc (sym, GETTEXT ("!INTP(XCAR(tem))"),
560 GETTEXT ("function"), pos);
567 weird_doc (sym, GETTEXT ("not lambda or autoload"),
568 GETTEXT ("function"), pos);
572 else if (COMPILED_FUNCTIONP (fun))
574 /* Compiled-Function objects sometimes have
576 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
578 /* This compiled-function object must have a
579 slot for the docstring, since we've found a
580 docstring for it. Unless there were multiple
581 definitions of it, and the latter one didn't
582 have any doc, which is a legal if slightly
583 bogus situation, so don't blow up. */
585 if (! (f->flags.documentationp))
587 weird_doc (sym, GETTEXT ("no doc slot"),
588 GETTEXT ("bytecode"), pos);
594 compiled_function_documentation (f);
597 weird_doc (sym, GETTEXT ("duplicate"),
598 GETTEXT ("bytecode"), pos);
599 /* In the case of duplicate doc file entries,
600 always take the later one. But if the doc is
601 not an int (a string, say) leave it alone. */
605 set_compiled_function_documentation (f, offset);
610 /* Otherwise the function is undefined or
611 otherwise weird. Ignore it. */
612 weird_doc (sym, GETTEXT ("weird function"),
613 GETTEXT ("function"), pos);
620 error ("DOC file invalid at position %d", pos);
629 memmove (buf, end, filled);
636 #if 1 /* Don't warn about functions whose doc was lost because they were
637 wrapped by advice-freeze.el... */
639 kludgily_ignore_lost_doc_p (Lisp_Object sym)
641 # define kludge_prefix "ad-Orig-"
642 Lisp_String *name = XSYMBOL (sym)->name;
643 return (string_length (name) > (Bytecount) (sizeof (kludge_prefix)) &&
644 !strncmp ((char *) string_data (name), kludge_prefix,
645 sizeof (kludge_prefix) - 1));
646 # undef kludge_prefix
649 # define kludgily_ignore_lost_doc_p(sym) 0
654 verify_doc_mapper (Lisp_Object sym, void *arg)
656 Lisp_Object closure = *(Lisp_Object *)arg;
658 if (!NILP (Ffboundp (sym)))
661 Lisp_Object fun = XSYMBOL (sym)->function;
663 EQ (XCAR (fun), Qmacro))
667 doc = (EMACS_INT) XSUBR (fun)->doc;
668 else if (SYMBOLP (fun))
670 else if (KEYMAPP (fun))
672 else if (CONSP (fun))
674 Lisp_Object tem = XCAR (fun);
675 if (EQ (tem, Qlambda) || EQ (tem, Qautoload))
678 tem = Fcdr (Fcdr (fun));
681 doc = XINT (XCAR (tem));
684 else if (COMPILED_FUNCTIONP (fun))
686 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
687 if (! (f->flags.documentationp))
691 Lisp_Object tem = compiled_function_documentation (f);
697 if (doc == 0 && !kludgily_ignore_lost_doc_p (sym))
699 message ("Warning: doc lost for function %s.",
700 string_data (XSYMBOL (sym)->name));
704 if (!NILP (Fboundp (sym)))
706 Lisp_Object doc = Fget (sym, Qvariable_documentation, Qnil);
709 message ("Warning: doc lost for variable %s.",
710 string_data (XSYMBOL (sym)->name));
714 return 0; /* Never stop */
717 DEFUN ("Verify-documentation", Fverify_documentation, 0, 0, 0, /*
718 Used to make sure everything went well with Snarf-documentation.
719 Writes to stderr if not.
723 Lisp_Object closure = Fcons (Qnil, Qnil);
726 map_obarray (Vobarray, verify_doc_mapper, &closure);
727 if (!NILP (Fcdr (closure)))
729 "This is usually because some files were preloaded by loaddefs.el or\n"
730 "site-load.el, but were not passed to make-docfile by Makefile.\n");
732 return NILP (Fcdr (closure)) ? Qt : Qnil;
736 DEFUN ("substitute-command-keys", Fsubstitute_command_keys, 1, 1, 0, /*
737 Substitute key descriptions for command names in STRING.
738 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]
739 replaced by either: a keystroke sequence that will invoke COMMAND,
740 or "M-x COMMAND" if COMMAND is not on any keys.
741 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
742 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
743 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
744 as the keymap for future \\=\\[COMMAND] substrings.
745 \\=\\= quotes the following character and is discarded;
746 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
750 /* This function can GC */
753 REGISTER Bufbyte *strdata;
754 REGISTER Bufbyte *bufp;
759 Lisp_Object tem = Qnil;
760 Lisp_Object keymap = Qnil;
761 Lisp_Object name = Qnil;
764 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
769 CHECK_STRING (string);
770 GCPRO4 (string, tem, keymap, name);
772 /* There is the possibility that the string is not destined for a
773 translating stream, and it could be argued that we should do the
774 same thing here as in Fformat(), but there are very few times
775 when this will be the case and many calls to this function
776 would have to have `gettext' calls added. (I18N3) */
777 string = LISP_GETTEXT (string);
779 /* KEYMAP is either nil (which means search all the active keymaps)
780 or a specified local map (which means search just that and the
781 global map). If non-nil, it might come from Voverriding_local_map,
782 or from a \\<mapname> construct in STRING itself.. */
784 /* This is really weird and garbagey. If keymap is nil and there's
785 an overriding-local-map, `where-is-internal' will correctly note
786 this, so there's no reason to do it here. Maybe FSFmacs
787 `where-is-internal' is broken. */
789 keymap = current_kboard->Voverriding_terminal_local_map;
791 keymap = Voverriding_local_map;
795 strlength = XSTRING_LENGTH (string);
796 bsize = 1 + strlength;
797 buf = (Bufbyte *) xmalloc (bsize);
800 /* Have to reset strdata every time GC might be called */
801 strdata = XSTRING_DATA (string);
802 for (idx = 0; idx < strlength; )
804 Bufbyte *strp = strdata + idx;
808 /* just copy other chars */
809 /* As it happens, this will work with Mule even if the
810 character quoted is multi-byte; the remaining multi-byte
811 characters will just be copied by this loop. */
815 else switch (strp[1])
819 /* just copy unknown escape sequences */
826 /* \= quotes the next character;
827 thus, to put in \[ without its special meaning, use \=\[. */
828 /* As it happens, this will work with Mule even if the
829 character quoted is multi-byte; the remaining multi-byte
830 characters will just be copied by this loop. */
839 idx += 2; /* skip \[ */
843 while ((idx < strlength)
849 length = strp - start;
852 tem = Fintern (make_string (start, length), Qnil);
853 tem = Fwhere_is_internal (tem, keymap, Qt, Qnil, Qnil);
856 /* Disregard menu bar bindings; it is positively annoying to
857 mention them when there's no menu bar, and it isn't terribly
858 useful even when there is a menu bar. */
861 firstkey = Faref (tem, Qzero);
862 if (EQ (firstkey, Qmenu_bar))
867 if (NILP (tem)) /* but not on any keys */
869 new = (Bufbyte *) xrealloc (buf, bsize += 4);
872 memcpy (bufp, "M-x ", 4);
877 { /* function is on a key */
878 tem = Fkey_description (tem);
885 Lisp_Object buffer = Fget_buffer_create (QSsubstitute);
886 struct buffer *buf_ = XBUFFER (buffer);
888 Fbuffer_disable_undo (buffer);
889 Ferase_buffer (buffer);
891 /* \{foo} is replaced with a summary of keymap (symbol-value foo).
892 \<foo> just sets the keymap used for \[cmd]. */
894 idx += 2; /* skip \{ or \< */
898 while ((idx < strlength)
899 && *strp != '}' && *strp != '>')
904 length = strp - start;
905 idx++; /* skip } or > */
907 /* Get the value of the keymap in TEM, or nil if undefined.
908 Do this while still in the user's current buffer
909 in case it is a local variable. */
910 name = Fintern (make_string (start, length), Qnil);
911 tem = Fboundp (name);
914 tem = Fsymbol_value (name);
916 tem = get_keymap (tem, 0, 1);
921 buffer_insert_c_string (buf_, "(uses keymap \"");
922 buffer_insert_lisp_string (buf_, Fsymbol_name (name));
923 buffer_insert_c_string (buf_, "\", which is not currently defined) ");
925 if (start[-1] == '<') keymap = Qnil;
927 else if (start[-1] == '<')
930 describe_map_tree (tem, 1, Qnil, Qnil, 0, buffer);
932 tem = make_string_from_buffer (buf_, BUF_BEG (buf_),
933 BUF_Z (buf_) - BUF_BEG (buf_));
934 Ferase_buffer (buffer);
939 start = XSTRING_DATA (tem);
940 length = XSTRING_LENGTH (tem);
943 new = (Bufbyte *) xrealloc (buf, bsize);
946 memcpy (bufp, start, length);
949 /* Reset STRDATA in case gc relocated it. */
950 strdata = XSTRING_DATA (string);
956 if (changed) /* don't bother if nothing substituted */
957 tem = make_string (buf, bufp - buf);
966 /************************************************************************/
968 /************************************************************************/
973 DEFSUBR (Fdocumentation);
974 DEFSUBR (Fdocumentation_property);
975 DEFSUBR (Fsnarf_documentation);
976 DEFSUBR (Fverify_documentation);
977 DEFSUBR (Fsubstitute_command_keys);
983 DEFVAR_LISP ("internal-doc-file-name", &Vinternal_doc_file_name /*
984 Name of file containing documentation strings of built-in symbols.
986 Vinternal_doc_file_name = Qnil;
988 QSsubstitute = build_string (" *substitute*");
989 staticpro (&QSsubstitute);